C#:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using Oxide.Core;
using Oxide.Game.Rust.Cui;
using System.Linq;
using Random = UnityEngine.Random;
namespace Oxide.Plugins
{
[Info("Falling Tiles", "Vic", "23.0.0")]
public class FallingTiles : RustPlugin
{
private List<BuildingBlock> _tiles = new List<BuildingBlock>();
private bool _gameActive = false;
private string _currentSong = "Waiting for Request...";
private string _lastLyric = "FALLING TILES";
private string _ngrokLink = "https://gael-supersolar-elenora.ngrok-free.dev";
private Timer _touchTimer;
private const string MetalFloorPrefab = "assets/prefabs/building core/floor/floor.prefab";
private const string ExplodeEffect = "assets/content/effects/explosions/explosion piercing.prefab";
void Init() => permission.RegisterPermission("fallingtiles.admin", this);
// --- COMMANDS ---
[ChatCommand("sr")]
private void CmdSongRequest(BasePlayer player, string cmd, string[] args) {
if (args.Length == 0) return;
string query = UnityWebRequest.EscapeURL(string.Join(" ", args));
webrequest.Enqueue($"{_ngrokLink}/request-song?q={query}", null, (code, res) => {}, this);
}
[ChatCommand("srl")]
private void CmdLink(BasePlayer player) {
Item n = ItemManager.CreateByName("note", 1);
if (n == null) return;
n.name = "Falling Tiles Access Pass";
n.text = _ngrokLink;
if (!n.MoveToContainer(player.inventory.containerBelt)) n.MoveToContainer(player.inventory.containerMain);
player.ChatMessage("<color=#1DB954>[FALLING TILES]</color> Link forced to your hotbar!");
}
[ChatCommand("tiles")]
private void CmdMenu(BasePlayer player) {
CuiHelper.DestroyUi(player, "FT_Menu");
var container = new CuiElementContainer();
container.Add(new CuiPanel { Image = { Color = "0 0 0 0.96" }, RectTransform = { AnchorMin = "0.35 0.35", AnchorMax = "0.65 0.65" }, CursorEnabled = true }, "Overlay", "FT_Menu");
container.Add(new CuiLabel { Text = { Text = "FALLING TILES", FontSize = 18, Align = TextAnchor.MiddleCenter, Color = "0 1 0 1" }, RectTransform = { AnchorMin = "0 0.85", AnchorMax = "1 1" } }, "FT_Menu");
container.Add(new CuiButton { Button = { Command = "tiles.close", Color = "0.6 0.1 0.1 1" }, RectTransform = { AnchorMin = "0.9 0.88", AnchorMax = "0.98 0.98" }, Text = { Text = "X" } }, "FT_Menu");
if (player.IsAdmin) {
AddBtn(ref container, "1. SETUP ARENA", "tiles.setup", "0.1 0.6", "0.9 0.75", "0.2 0.2 0.2 1");
AddBtn(ref container, "2. START GAME", "tiles.start", "0.1 0.4", "0.9 0.55", "0.1 0.5 0.1 1");
AddBtn(ref container, "3. STOP & CLEAR", "tiles.stop", "0.1 0.2", "0.9 0.35", "0.5 0.1 0.1 1");
}
CuiHelper.AddUi(player, container);
}
private void AddBtn(ref CuiElementContainer c, string t, string cmd, string min, string max, string clr) {
c.Add(new CuiButton { Button = { Command = cmd, Color = clr }, RectTransform = { AnchorMin = min, AnchorMax = max }, Text = { Text = t, Align = TextAnchor.MiddleCenter } }, "FT_Menu");
}
[ConsoleCommand("tiles.close")] private void ConsoleClose(ConsoleSystem.Arg arg) => CuiHelper.DestroyUi(arg.Player(), "FT_Menu");
// --- CORE LOGIC ---
[ConsoleCommand("tiles.setup")]
private void ConsoleSetup(ConsoleSystem.Arg arg) {
ClearArena(); BasePlayer p = arg.Player();
for (int l = 0; l < 3; l++) {
for (int x = -3; x < 3; x++) {
for (int z = -3; z < 3; z++) {
Vector3 pos = p.transform.position + new Vector3(x * 3, -(l * 3.5f), z * 3);
BuildingBlock b = GameManager.server.CreateEntity(MetalFloorPrefab, pos) as BuildingBlock;
b.Spawn(); b.SetGrade(BuildingGrade.Enum.Stone); b.grounded = true;
if (l == 2 && x >= -1 && x <= 0 && z >= -1 && z <= 0) b.gameObject.name = "CenterTile";
_tiles.Add(b);
}
}
}
}
[ConsoleCommand("tiles.start")] private void ConsoleStart(ConsoleSystem.Arg arg) { _gameActive = true; StartTouchEngine(); UpdateHUD(); }
[ConsoleCommand("tiles.stop")] private void ConsoleStop(ConsoleSystem.Arg arg) { _gameActive = false; _touchTimer?.Destroy(); ClearArena(); }
[ConsoleCommand("tiles.pulse")]
private void ConsolePulse(ConsoleSystem.Arg arg) { if (_gameActive && arg.Args[0] == "bass") DropRandomTile(); }
private void DropRandomTile() {
if (_tiles.Count <= 4) return;
var t = _tiles[Random.Range(0, _tiles.Count)];
if (t != null && t.gameObject.name != "CenterTile") DegradeTile(t);
}
private void StartTouchEngine() {
_touchTimer = timer.Every(0.25f, () => {
if (!_gameActive) return;
foreach (var p in BasePlayer.activePlayerList) {
RaycastHit hit;
if (Physics.Raycast(p.transform.position + Vector3.up, Vector3.down, out hit, 1.5f)) {
var b = hit.GetEntity() as BuildingBlock;
if (b != null && _tiles.Contains(b) && b.gameObject.name != "CenterTile") DegradeTile(b);
}
}
});
}
private void DegradeTile(BuildingBlock b) {
if (b.grade == BuildingGrade.Enum.Twigs) {
foreach(var p in BasePlayer.activePlayerList) p.SendConsoleCommand("ddraw.text", 1.5f, Color.green, b.transform.position + Vector3.up, $"<b>{_lastLyric}</b>");
_tiles.Remove(b); Effect.server.Run(ExplodeEffect, b.transform.position); b.Kill();
} else { b.SetGrade((BuildingGrade.Enum)((int)b.grade - 1)); b.SendNetworkUpdate(); }
}
[ConsoleCommand("tiles.lyrics")]
private void ConsoleLyrics(ConsoleSystem.Arg arg) {
_lastLyric = string.Join(" ", arg.Args).ToUpper();
foreach (var p in BasePlayer.activePlayerList) {
CuiHelper.DestroyUi(p, "FT_LYR");
var c = new CuiElementContainer();
c.Add(new CuiPanel { Image = { Color = "0 0 0 0.8" }, RectTransform = { AnchorMin = "0.2 0.93", AnchorMax = "0.8 0.98" } }, "Overlay", "FT_LYR");
c.Add(new CuiLabel { Text = { Text = _lastLyric, FontSize = 22, Align = TextAnchor.MiddleCenter, Color = "0 1 0 1" }, RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" } }, "FT_LYR");
CuiHelper.AddUi(p, c);
}
}
[ConsoleCommand("tiles.updateui")]
private void ConsoleUpdateUI(ConsoleSystem.Arg arg) { _currentSong = string.Join(" ", arg.Args); UpdateHUD(); }
private void UpdateHUD() {
foreach (var p in BasePlayer.activePlayerList) {
CuiHelper.DestroyUi(p, "FT_HUD");
var c = new CuiElementContainer();
c.Add(new CuiPanel { Image = { Color = "0 0 0 0.7" }, RectTransform = { AnchorMin = "0.75 0.93", AnchorMax = "0.99 0.99" } }, "HUD", "FT_HUD");
c.Add(new CuiLabel { Text = { Text = $"SONG: {_currentSong}\nBY: VIC", FontSize = 10, Align = TextAnchor.MiddleLeft, Color = "0 1 0 1" }, RectTransform = { AnchorMin = "0.05 0", AnchorMax = "1 1" } }, "FT_HUD");
CuiHelper.AddUi(p, c);
}
}
private void ClearArena() { foreach (var t in _tiles.Where(x => x != null)) t.Kill(); _tiles.Clear(); }
void Unload() => ClearArena();
}
}