C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Effects Panel", "Mevent", "1.1.0")]
[Description("Displaying effects in the interface with the ability to play it and output it to the console")]
public class EffectsPanel : RustPlugin
{
#region Fields
[PluginReference] private Plugin Notify;
private const string Layer = "UI.Effects";
private readonly List<string> _effects = new List<string>();
private const string PermUse = "effects.use";
#endregion
#region Config
private Configuration _config;
private class Configuration
{
[JsonProperty(PropertyName = "Commands", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public string[] Commands = { "effects", "efui" };
[JsonProperty(PropertyName = "Work with Notify?")]
public bool UseNotify = true;
[JsonProperty(PropertyName = "Interface Settings")]
public InterfaceConf UI = new InterfaceConf
{
AmountOnPage = 8,
ItemHeight = 50f,
ItemsMargin = 5f
};
}
private class InterfaceConf
{
[JsonProperty(PropertyName = "Amount on page")]
public int AmountOnPage;
[JsonProperty(PropertyName = "Item Height")]
public float ItemHeight;
[JsonProperty(PropertyName = "Items Margin")]
public float ItemsMargin;
}
protected override void LoadConfig()
{
base.LoadConfig();
try
{
_config = Config.ReadObject<Configuration>();
if (_config == null) throw new Exception();
SaveConfig();
}
catch
{
PrintError("Your configuration file contains an error.Using default configuration values.");
LoadDefaultConfig();
}
}
protected override void SaveConfig()
{
Config.WriteObject(_config);
}
protected override void LoadDefaultConfig()
{
_config = new Configuration();
}
#endregion
#region Hooks
private void OnServerInitialized()
{
permission.RegisterPermission(PermUse, this);
foreach (var asset in GameManifest.Current.pooledStrings.Where(asset =>
(asset.str.StartsWith("assets/content/") || asset.str.StartsWith("assets/bundled/") ||
asset.str.StartsWith("assets/prefabs/")) && asset.str.EndsWith(".prefab") &&
asset.str.Contains("/fx/")))
_effects.Add(asset.str);
AddCovalenceCommand(_config.Commands, nameof(CmdOpenEffects));
}
private void Unload()
{
foreach (var player in BasePlayer.activePlayerList)
{
CuiHelper.DestroyUi(player, Layer);
}
}
#endregion
#region Commands
private void CmdOpenEffects(IPlayer cov, string command, string[] args)
{
var player = cov?.Object as BasePlayer;
if (player == null) return;
if (!cov.HasPermission(PermUse))
{
SendNotify(player, NoPermission, 1);
return;
}
MainUi(player, first: true);
}
[ConsoleCommand("UI_Effects")]
private void CmdConsoleEffects(ConsoleSystem.Arg arg)
{
var player = arg?.Player();
if (player == null || !arg.HasArgs()) return;
switch (arg.Args[0])
{
case "page":
{
int page;
if (!arg.HasArgs(2) || !int.TryParse(arg.Args[1], out page)) return;
var search = string.Empty;
if (arg.HasArgs(3))
search = string.Join(" ", arg.Args.Skip(2));
MainUi(player, page, search);
break;
}
case "play":
{
var effect = string.Join(" ", arg.Args.Skip(1));
if (string.IsNullOrEmpty(effect)) return;
SendEffect(player, effect);
break;
}
case "debug":
{
var effect = string.Join(" ", arg.Args.Skip(1));
if (string.IsNullOrEmpty(effect)) return;
PrintWarning(Msg(player, ShowEffect, effect));
break;
}
}
}
#endregion
#region Interface
private void MainUi(BasePlayer player, int page = 0, string search = "", bool first = false)
{
var container = new CuiElementContainer();
#region Background
if (first)
{
CuiHelper.DestroyUi(player, Layer);
container.Add(new CuiPanel
{
RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" },
Image =
{
Color = "0 0 0 0.9",
Material = "assets/content/ui/uibackgroundblur.mat"
},
CursorEnabled = true
}, "Overlay", Layer);
container.Add(new CuiButton
{
RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" },
Text = { Text = "" },
Button =
{
Color = "0 0 0 0",
Close = Layer
}
}, Layer);
}
#endregion
#region Main
container.Add(new CuiPanel
{
RectTransform =
{
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5",
OffsetMin = "-310 -250",
OffsetMax = "310 250"
},
Image =
{
Color = HexToCuiColor("#0E0E10")
}
}, Layer, Layer + ".Main");
#region Header
container.Add(new CuiPanel
{
RectTransform =
{
AnchorMin = "0 1", AnchorMax = "1 1",
OffsetMin = "0 -50",
OffsetMax = "0 0"
},
Image = { Color = HexToCuiColor("#161617") }
}, Layer + ".Main", Layer + ".Header");
container.Add(new CuiLabel
{
RectTransform =
{
AnchorMin = "0 0", AnchorMax = "1 1",
OffsetMin = "30 0",
OffsetMax = "0 0"
},
Text =
{
Text = Msg(player, TitleMenu),
Align = TextAnchor.MiddleLeft,
Font = "robotocondensed-bold.ttf",
FontSize = 14,
Color = HexToCuiColor("#FFFFFF")
}
}, Layer + ".Header");
float xSwitch = -25;
float width = 25;
float margin = 5;
container.Add(new CuiButton
{
RectTransform =
{
AnchorMin = "1 1", AnchorMax = "1 1",
OffsetMin = $"{xSwitch - width} -37.5",
OffsetMax = $"{xSwitch} -12.5"
},
Text =
{
Text = Msg(player, CloseButton),
Align = TextAnchor.MiddleCenter,
Font = "robotocondensed-bold.ttf",
FontSize = 10,
Color = HexToCuiColor("#FFFFFF")
},
Button =
{
Close = Layer,
Color = HexToCuiColor("#4B68FF")
}
}, Layer + ".Header");
xSwitch = xSwitch - margin - width;
width = 25;
container.Add(new CuiButton
{
RectTransform =
{
AnchorMin = "1 1", AnchorMax = "1 1",
OffsetMin = $"{xSwitch - width} -37.5",
OffsetMax = $"{xSwitch} -12.5"
},
Text =
{
Text = Msg(player, BtnNext),
Align = TextAnchor.MiddleCenter,
Font = "robotocondensed-regular.ttf",
FontSize = 12,
Color = HexToCuiColor("#FFFFFF")
},
Button =
{
Color = HexToCuiColor("#4B68FF"),
Command = _effects.Count > (page + 1) * _config.UI.AmountOnPage
? $"UI_Effects page {page + 1} {search}"
: ""
}
}, Layer + ".Header");
xSwitch = xSwitch - margin - width;
container.Add(new CuiButton
{
RectTransform =
{
AnchorMin = "1 1", AnchorMax = "1 1",
OffsetMin = $"{xSwitch - width} -37.5",
OffsetMax = $"{xSwitch} -12.5"
},
Text =
{
Text = Msg(player, BtnBack),
Align = TextAnchor.MiddleCenter,
Font = "robotocondensed-regular.ttf",
FontSize = 12,
Color = HexToCuiColor("#FFFFFF")
},
Button =
{
Color = HexToCuiColor("#4B68FF", 33),
Command = page != 0 ? $"UI_Effects page {page - 1} {search}" : ""
}
}, Layer + ".Header");
#region Search
xSwitch = xSwitch - margin - width;
width = 140;
container.Add(new CuiPanel
{
RectTransform =
{
AnchorMin = "1 1", AnchorMax = "1 1",
OffsetMin = $"{xSwitch - width} -37.5",
OffsetMax = $"{xSwitch} -12.5"
},
Image =
{
Color = HexToCuiColor("#000000")
}
}, Layer + ".Header", Layer + ".Header.Search");
container.Add(new CuiLabel
{
RectTransform =
{
AnchorMin = "0 0", AnchorMax = "1 1",
OffsetMin = "10 0", OffsetMax = "-10 0"
},
Text =
{
Text = string.IsNullOrEmpty(search) ? Msg(player, SearchTitle) : $"{search}",
Align = TextAnchor.MiddleLeft,
Font = "robotocondensed-regular.ttf",
FontSize = 12,
Color = "1 1 1 0.65"
}
}, Layer + ".Header.Search");
container.Add(new CuiElement
{
Parent = Layer + ".Header.Search",
Components =
{
new CuiInputFieldComponent
{
FontSize = 12,
Align = TextAnchor.MiddleCenter,
Font = "robotocondensed-regular.ttf",
Command = $"UI_Effects page {page} ",
Color = "1 1 1 0.95",
CharsLimit = 32
},
new CuiRectTransformComponent
{
AnchorMin = "0 0", AnchorMax = "1 1"
}
}
});
#endregion
#endregion
#region List
var ySwitch = -60f;
foreach (var effect in _effects.Skip(page * _config.UI.AmountOnPage).Take(_config.UI.AmountOnPage))
{
container.Add(new CuiPanel
{
RectTransform =
{
AnchorMin = "0.5 1", AnchorMax = "0.5 1",
OffsetMin = $"-300 {ySwitch - _config.UI.ItemHeight}",
OffsetMax = $"300 {ySwitch}"
},
Image =
{
Color = HexToCuiColor("#161617")
}
}, Layer + ".Main", Layer + $".Effect.{ySwitch}");
#region Name
container.Add(new CuiLabel
{
RectTransform =
{
AnchorMin = "0 0", AnchorMax = "1 1",
OffsetMin = "10 0", OffsetMax = "0 0"
},
Text =
{
Text = $"{effect}",
Align = TextAnchor.MiddleLeft,
Font = "robotocondensed-regular.ttf",
FontSize = 14,
Color = "1 1 1 1"
}
}, Layer + $".Effect.{ySwitch}");
#endregion
#region Buttons
container.Add(new CuiButton
{
RectTransform =
{
AnchorMin = "1 0.5", AnchorMax = "1 0.5",
OffsetMin = "-110 -15", OffsetMax = "-10 15"
},
Text =
{
Text = Msg(player, DebugTitle),
Align = TextAnchor.MiddleCenter,
Font = "robotocondensed-regular.ttf",
FontSize = 14,
Color = "1 1 1 1"
},
Button =
{
Color = HexToCuiColor("#B43D3D"),
Command = $"UI_Effects debug {effect}"
}
}, Layer + $".Effect.{ySwitch}");
container.Add(new CuiButton
{
RectTransform =
{
AnchorMin = "1 0.5", AnchorMax = "1 0.5",
OffsetMin = "-220 -15", OffsetMax = "-120 15"
},
Text =
{
Text = Msg(player, PlayTitle),
Align = TextAnchor.MiddleCenter,
Font = "robotocondensed-regular.ttf",
FontSize = 14,
Color = "1 1 1 1"
},
Button =
{
Color = HexToCuiColor("#4B68FF"),
Command = $"UI_Effects play {effect}"
}
}, Layer + $".Effect.{ySwitch}");
#endregion
ySwitch = ySwitch - _config.UI.ItemHeight - _config.UI.ItemsMargin;
}
#endregion
#endregion
CuiHelper.DestroyUi(player, Layer + ".Main");
CuiHelper.AddUi(player, container);
}
#endregion
#region Utils
private static string HexToCuiColor(string hex, float alpha = 100)
{
if (string.IsNullOrEmpty(hex)) hex = "#FFFFFF";
var str = hex.Trim('#');
if (str.Length != 6) throw new Exception(hex);
var r = byte.Parse(str.Substring(0, 2), NumberStyles.HexNumber);
var g = byte.Parse(str.Substring(2, 2), NumberStyles.HexNumber);
var b = byte.Parse(str.Substring(4, 2), NumberStyles.HexNumber);
return $"{(double)r / 255} {(double)g / 255} {(double)b / 255} {alpha / 100f}";
}
private static void SendEffect(BasePlayer player, string effect)
{
EffectNetwork.Send(new Effect(effect, player, 0, new Vector3(), new Vector3()), player.Connection);
}
#endregion
#region Lang
private const string
ShowEffect = "ShowEffect",
NoPermission = "NoPermission",
PlayTitle = "PlayTitle",
DebugTitle = "DebugTitle",
SearchTitle = "SearchTitle",
BtnBack = "BtnBack",
BtnNext = "BtnNext",
CloseButton = "CloseButton",
TitleMenu = "TitleMenu";
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
[NoPermission] = "You don't have the required permission",
[TitleMenu] = "Effects",
[CloseButton] = "✕",
[BtnBack] = "◀",
[BtnNext] = "▶",
[SearchTitle] = "Search...",
[DebugTitle] = "DEBUG",
[PlayTitle] = "PLAY",
[ShowEffect] = "Effect: {0}"
}, this);
}
private string Msg(BasePlayer player, string key, params object[] obj)
{
return string.Format(lang.GetMessage(key, this, player.UserIDString), obj);
}
private void Reply(BasePlayer player, string key, params object[] obj)
{
SendReply(player, Msg(player, key, obj));
}
private void SendNotify(BasePlayer player, string key, int type, params object[] obj)
{
if (Notify.IsLoaded && _config.UseNotify)
Notify?.Call("SendNotify", player, type, Msg(player, key, obj));
else
Reply(player, key, obj);
}
#endregion
}
}