C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using HarmonyLib;
using Oxide.Core.Plugins;
using System;
using System.Collections.Generic;
using System.Reflection;
using Network;
using Newtonsoft.Json;
using System.Collections;
using System.ComponentModel;
using System.Linq;
using UnityEngine;
using Oxide.Game.Rust.Cui;
using UnityEngine.UI;
using Facepunch;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Rust;
using System.Text.RegularExpressions;
using Oxide.Core.Libraries;
using Oxide.Game.Rust.Libraries;
using System.Xml;
using System.IO;
using System.Text;
using System.Globalization;
using Newtonsoft.Json.Linq;
namespace Oxide.Plugins {
/*ПЛАГИН БЫЛ ПОФИКШЕН С ПОМОЩЬЮ ПРОГРАММЫ СКАЧАНОЙ С https://discord.gg/dNGbxafuJn */
/*ПЛАГИН БЫЛ ПОФИКШЕН С ПОМОЩЬЮ ПРОГРАММЫ СКАЧАНОЙ С https://discord.gg/dNGbxafuJn */
/*ПЛАГИН БЫЛ ПОФИКШЕН С ПОМОЩЬЮ ПРОГРАММЫ СКАЧАНОЙ С https://discord.gg/dNGbxafuJn */
/*ПЛАГИН БЫЛ ПОФИКШЕН С ПОМОЩЬЮ ПРОГРАММЫ СКАЧАНОЙ С https://discord.gg/dNGbxafuJn */
[Info("AdminMenu", "https://discord.gg/dNGbxafuJn", "1.1.8")]
[Description("Multifunctional in-game admin menu.")]
public class AdminMenu : RustPlugin {
[PluginReference]
private Plugin ImageLibrary, Economics, ServerRewards, Clans;
private const string PERMISSION_USE = "adminmenu.use";
private const string PERMISSION_FULLACCESS = "adminmenu.fullaccess";
private const string PERMISSION_CONVARS = "adminmenu.convars";
private const string PERMISSION_PERMISSIONMANAGER = "adminmenu.permissionmanager";
private const string PERMISSION_PLUGINMANAGER = "adminmenu.pluginmanager";
private const string PERMISSION_GIVE = "adminmenu.give";
private const string PERMISSION_USERINFO_IP = "adminmenu.userinfo.ip";
private const string PERMISSION_USERINFO_STEAMINFO = "adminmenu.userinfo.steaminfo";
private const string ADMINMENU_IMAGEBASE64 = "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";
private static Dictionary<string, string> HEADERS = new Dictionary<string, string> {
{
"Content-Type", "application/json"
}
}
;
#if !CARBON
private static FieldInfo PERMISSIONS_DICTIONARY_FIELD = typeof(Oxide.Core.Libraries.Permission).GetField("registeredPermissions", BindingFlags.NonPublic | BindingFlags.Instance);
private static FieldInfo CONSOLECOMMANDS_DICTIONARY_FIELD = typeof(Oxide.Game.Rust.Libraries.Command).GetField("consoleCommands", BindingFlags.NonPublic | BindingFlags.Instance);
private static FieldInfo CONSOLECOMMAND_CALLBACK_FIELD = CONSOLECOMMANDS_DICTIONARY_FIELD.FieldType.GetGenericArguments()[1].GetField("Callback", BindingFlags.Public | BindingFlags.Instance);
private static FieldInfo PLUGINCALLBACK_PLUGIN_FIELD = CONSOLECOMMAND_CALLBACK_FIELD.FieldType.GetField("Plugin", BindingFlags.Public | BindingFlags.Instance);
private static FieldInfo CHATCOMMANDS_DICTIONARY_FIELD = typeof(Oxide.Game.Rust.Libraries.Command).GetField("chatCommands", BindingFlags.NonPublic | BindingFlags.Instance);
private static FieldInfo CHATCOMMAND_PLUGIN_FIELD = CHATCOMMANDS_DICTIONARY_FIELD.FieldType.GetGenericArguments()[1].GetField("Plugin", BindingFlags.Public | BindingFlags.Instance);
#endif
private static AdminMenu Instance;
private static Dictionary<string, Panel> panelList;
private static Dictionary<ulong, SteamInfo> cachedSteamInfo = new Dictionary<ulong, SteamInfo>();
private static string ADMINMENU_IMAGECRC;
private MainMenu mainMenu;
private Dictionary<string, string> defaultLang = new Dictionary<string, string>();
private Dictionary<PlayerLoot, Item> viewingBackpacks = new Dictionary<PlayerLoot, Item>();
static Configuration config;
public AdminMenu() {
Instance = this;
}
public class ButtonArray<T> : List<T> where T : Button {
public ButtonArray() : base() {
}
public ButtonArray(IEnumerable<T> collection) : base(collection) {
}
public IEnumerable<T> GetAllowedButtons(Connection connection) {
return GetAllowedButtons(connection.userid.ToString());
}
public IEnumerable<T> GetAllowedButtons(string userId) {
return this.Where(b => b == null || b.UserHasPermission(userId));
}
}
public class ButtonGrid<T> : List<ButtonGrid<T>.Item> where T : Button {
public class Item {
public int row;
public int column;
public T button;
public Item(int row, int column, T button) {
this.row = row;
this.column = column;
this.button = button;
}
}
public IEnumerable<Item> GetAllowedButtons(Connection connection) {
return GetAllowedButtons(connection.userid.ToString());
}
public IEnumerable<Item> GetAllowedButtons(string userId) {
return this.Where(b => b.button == null || b.button.UserHasPermission(userId));
}
}
public class ButtonArray : ButtonArray<Button> {
}
public class Button {
public enum State {
None, Normal, Pressed, Toggled
}
private string label = null;
private string permission = null;
public string Command {
get;
set;
}
public string[] Args {
get;
set;
}
public Label Label {
get;
set;
}
public virtual int FontSize {
get;
set;
}
= 14;
public ButtonStyle Style {
get;
set;
}
= ButtonStyle.Default;
public string Permission {
get {
return permission;
}
set {
if (string.IsNullOrEmpty(value)) return;
permission = string.Format("adminmenu.{0}", value);
if (!Instance.permission.PermissionExists(permission)) Instance.permission.RegisterPermission(permission, Instance);
}
}
public string FullCommand {
get {
return $"{Command} {string.Join(" ", Args)}";
}
}
public Button() {
}
public Button(string label, string command, params string[] args) {
Label = new Label(label);
Command = command;
Args = args;
if (!all.ContainsKey(FullCommand)) all.Add(FullCommand, this);
}
public virtual Button.State GetState(ConnectionData connectionData) {
if (connectionData.userData.TryGetValue($"button_{this.GetHashCode()}.state", out object state)) return (Button.State)state;
return Button.State.None;
}
public virtual void SetState(ConnectionData connectionData, Button.State state) {
connectionData.userData[$"button_{this.GetHashCode()}.state"] = state;
}
public bool UserHasPermission(Connection connection) {
return UserHasPermission(connection.userid.ToString());
}
public bool UserHasPermission(string userId) {
return Permission == null || Instance.UserHasPermission(userId, Permission);
}
public virtual bool IsPressed(ConnectionData connectionData) {
return GetState(connectionData) == State.Pressed;
}
public virtual bool IsHidden(ConnectionData connectionData) {
return false;
}
internal static Dictionary<string, Button> all = new Dictionary<string, Button>();
}
public class ButtonStyle : ICloneable {
public string BackgroundColor {
get;
set;
}
public string ActiveBackgroundColor {
get;
set;
}
public string TextColor {
get;
set;
}
public object Clone() {
return this.MemberwiseClone();
}
public static ButtonStyle Default => new ButtonStyle {
BackgroundColor = "0.3 0.3 0.3 0.6", ActiveBackgroundColor = "0.2 0.4 0.2 0.6", TextColor = "1 1 1 1",
}
;
}
public class CategoryButton : Button {
public override int FontSize {
get;
set;
}
= 22;
public CategoryButton(string label, string command, params string[] args) : base(label, command, args) {
}
}
public class HideButton : Button {
public HideButton(string label, string command, params string[] args) : base(label, command, args) {
}
public override bool IsHidden(ConnectionData connectionData) {
return connectionData.userData["backcommand"] == null;
}
}
public class ToggleButton : Button {
public ToggleButton(string label, string command, params string[] args) : base(label, command, args) {
}
public virtual void Toggle(ConnectionData connectionData) {
Button.State currentState = GetState(connectionData);
SetState(connectionData, (currentState == State.Normal || currentState == State.None ? Button.State.Toggled : Button.State.Normal));
}
}
public class ConditionToggleButton : ToggleButton {
public Func<ConnectionData, bool> Condition {
get;
set;
}
public ConditionToggleButton(string label, string command, params string[] args) : base(label, command, args) {
}
public override State GetState(ConnectionData connectionData) {
if (Condition == null) return State.Normal;
return Condition(connectionData) ? State.Toggled : State.Normal;
}
public override void Toggle(ConnectionData connectionData) {
}
}
[JsonObject(MemberSerialization.OptIn)]
public class BaseCustomButton {
[JsonProperty]
public string Label {
get;
set;
}
= string.Empty;
[JsonProperty("Execution as server")]
public bool ExecutionAsServer {
get;
set;
}
[JsonProperty]
public string[] Commands {
get;
set;
}
= new string[0];
[JsonProperty]
public string Permission {
get;
set;
}
= string.Empty;
[JsonProperty]
public ButtonStyle Style {
get;
set;
}
= ButtonStyle.Default;
[JsonProperty]
public int[] Position {
get;
set;
}
= new int[2] {
0, 0
}
;
protected virtual string BaseCommand => "custombutton";
private Button _button;
public Button Button {
get {
if (_button == null) _button = GetButton();
return _button;
}
}
private Button GetButton() {
return new Button(Label, BaseCommand, "cb.exec", this.GetHashCode().ToString()) {
Permission = Permission.ToLower(), Style = Style
}
;
;
}
}
public class QMCustomButton : BaseCustomButton {
public enum Recievers {
None, Online, Offline, Everyone
}
protected override string BaseCommand => "quickmenu.action";
[JsonProperty("Bulk sending of command to each player.Available values: None, Online, Offline, Everyone")]
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
public Recievers PlayerReceivers {
get;
set;
}
}
public class UserInfoCustomButton : BaseCustomButton {
protected override string BaseCommand => "userinfo.action";
}
public class Configuration {
[JsonProperty(PropertyName = "Text under the ADMIN MENU")]
public string Subtext {
get;
set;
}
= "BY 0XF";
[JsonProperty(PropertyName = "Button to hook (X | F | OFF)")]
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
public ButtonHook ButtonToHook {
get;
set;
}
= ButtonHook.X;
[JsonProperty(PropertyName = "Chat command to show admin menu")]
public string ChatCommand {
get;
set;
}
= "admin";
[JsonProperty(PropertyName = "Theme")]
[JsonConverter(typeof(ThemeConverter))]
public Theme Theme {
get => Themes.CurrentTheme;
set => Themes.CurrentTheme = value;
}
[JsonProperty(PropertyName = "Custom Quick Buttons")]
public List<QMCustomButton> CustomQuickButtons {
get;
set;
}
= new List<QMCustomButton>();
[JsonProperty(PropertyName = "User Custom Buttons")]
public List<UserInfoCustomButton> UserInfoCustomButtons {
get;
set;
}
= new List<UserInfoCustomButton>();
[JsonProperty(PropertyName = "Give menu item presets (add your custom items for easy give)")]
public List<ItemPreset> GiveItemPresets {
get;
set;
}
= new List<ItemPreset>();
[JsonProperty(PropertyName = "Logs Properties")]
public LogsProperties Logs {
get;
set;
}
= new LogsProperties();
[JsonIgnore]
public Dictionary<int, string[]> HashedCommands {
get;
set;
}
= new Dictionary<int, string[]>();
public static Configuration DefaultConfig() {
return new Configuration() {
CustomQuickButtons = new List<QMCustomButton> {
new QMCustomButton {
Label = "Custom Button", Commands = new[] {
"chat.say \"/custom\"", "adminmenu openinfopanel custom_buttons"
}
, Permission = "fullaccess", Style = new ButtonStyle() {
BackgroundColor = "1 0.2 0.2 0.6", TextColor = "0.95 0.6 0 1",
}
, Position = new int[2] {
0, 4
}
}
}
, UserInfoCustomButtons = new List<UserInfoCustomButton> {
new UserInfoCustomButton {
Label = "Custom Button", Commands = new[] {
"chat.say \"/custom {steamID}\"", "adminmenu openinfopanel custom_buttons"
}
, Permission = "fullaccess", Position = new int[2] {
9, 0
}
}
}
, GiveItemPresets = new List<ItemPreset>() {
ItemPreset.Example
}
}
;
}
public class ItemPreset {
[JsonProperty(PropertyName = "Short Name")]
public string ShortName {
get;
set;
}
[JsonProperty(PropertyName = "Skin Id")]
public ulong SkinId {
get;
set;
}
[JsonProperty(PropertyName = "Name")]
public string Name {
get;
set;
}
[JsonProperty(PropertyName = "Category Name")]
public string Category {
get;
set;
}
[JsonIgnore]
public static ItemPreset Example {
get {
return new ItemPreset {
ShortName = "chocolate", SkinId = 3161523786, Name = "Delicious cookies with chocolate", Category = "Food",
}
;
}
}
}
public class LogsProperties {
[JsonProperty(PropertyName = "Discord Webhook URL for logs (https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks)")]
public string WebhookURL {
get;
set;
}
= string.Empty;
[JsonProperty(PropertyName = "Give")]
public bool Give {
get;
set;
}
= true;
[JsonProperty(PropertyName = "Admin teleports")]
public bool AdminTeleport {
get;
set;
}
= true;
[JsonProperty(PropertyName = "Spectate")]
public bool Spectate {
get;
set;
}
= true;
[JsonProperty(PropertyName = "Heal")]
public bool Heal {
get;
set;
}
= true;
[JsonProperty(PropertyName = "Kill")]
public bool Kill {
get;
set;
}
= true;
[JsonProperty(PropertyName = "Look inventory")]
public bool LookInventory {
get;
set;
}
= true;
[JsonProperty(PropertyName = "Strip inventory")]
public bool StripInventory {
get;
set;
}
= true;
[JsonProperty(PropertyName = "Blueprints")]
public bool Blueprints {
get;
set;
}
= true;
[JsonProperty(PropertyName = "Mute/Unmute")]
public bool MuteUnmute {
get;
set;
}
= true;
[JsonProperty(PropertyName = "Toggle Creative")]
public bool ToggleCreative {
get;
set;
}
= true;
[JsonProperty(PropertyName = "Cuff")]
public bool Cuff {
get;
set;
}
= true;
[JsonProperty(PropertyName = "Kick the player")]
public bool Kick {
get;
set;
}
= true;
[JsonProperty(PropertyName = "Ban the player")]
public bool Ban {
get;
set;
}
= true;
[JsonProperty(PropertyName = "Using custom buttons")]
public bool CustomButtons {
get;
set;
}
= true;
[JsonProperty(PropertyName = "Spawn entities")]
public bool SpawnEntities {
get;
set;
}
= true;
[JsonProperty(PropertyName = "Set time")]
public bool SetTime {
get;
set;
}
= true;
[JsonProperty(PropertyName = "ConVars")]
public bool ConVars {
get;
set;
}
= true;
[JsonProperty(PropertyName = "Plugin Manager")]
public bool PluginManager {
get;
set;
}
= true;
}
}
public class ConnectionData {
public Connection connection;
public MainMenu currentMainMenu;
public Panel currentPanel;
public Sidebar currentSidebar;
public Content currentContent;
public Translator15 translator;
public Dictionary<string, object> userData;
public ConnectionData(BasePlayer player) : this(player.Connection) {
}
public ConnectionData(Connection connection) {
this.connection = connection;
this.translator = new Translator15(connection.userid);
this.translator.Get("test");
this.userData = new Dictionary<string, object>() {
{
"userId", connection.userid
}
, {
"userinfo.lastuserid", connection.userid
}
, {
"backcommand", null
}
,
}
;
this.UI = new ConnectionUI(this);
try {
Init();
}
catch (Exception ex) {
UnityEngine.Debug.LogException(ex);
}
}
public ConnectionUI UI {
get;
private set;
}
public bool IsAdminMenuDisplay {
get;
set;
}
public bool IsDestroyed {
get;
set;
}
public void Init() {
UI.RenderMainMenu(Instance.mainMenu);
this.currentMainMenu = Instance.mainMenu;
}
public void ShowAdminMenu() {
UI.ShowAdminMenu();
IsAdminMenuDisplay = true;
}
public void HideAdminMenu() {
UI.HideAdminMenu();
IsAdminMenuDisplay = false;
}
public ConnectionData OpenPanel(string panelName) {
if (panelList.TryGetValue(panelName, out Panel panel)) {
if (currentPanel == panel) return null;
if (currentContent != null) currentContent.RestoreUserData(userData);
currentContent = null;
if (currentPanel != null) currentPanel.OnClose(this);
currentPanel = panel;
currentSidebar = currentPanel.Sidebar;
UI.RenderPanel(currentPanel);
currentPanel.OnOpen(this);
Content defaultPanelContent = panel.DefaultContent;
if (defaultPanelContent != null) ShowPanelContent(defaultPanelContent);
if (panel.Sidebar != null && panel.Sidebar.AutoActivateCategoryButtonIndex.HasValue) Instance.HandleCommand(connection, "uipanel.sidebar.button_pressed", panel.Sidebar.AutoActivateCategoryButtonIndex.Value.ToString(), panel.Sidebar.CategoryButtons.GetAllowedButtons(connection).Count().ToString());
return this;
}
else {
Instance.PrintError($"Panel with name \"{panelName}\" not founded!");
return null;
}
}
public void SetSidebar(Sidebar sidebar) {
bool needsChangeContentSize = (currentSidebar != sidebar);
currentSidebar = sidebar;
CUI.Root root = new CUI.Root("AdminMenu_Panel");
if (sidebar != null) UI.AddSidebar(root, sidebar);
else root.Add(new CUI.Element {
DestroyUi = "AdminMenu_Panel_Sidebar"
}
);
root.Render(connection);
if (needsChangeContentSize) {
CUI.Root updateRoot = new CUI.Root();
updateRoot.Add(new CUI.Element {
Components = {
new CuiRectTransformComponent {
OffsetMin = $"{(sidebar != null ? 250 : 0)} 0",
}
}
, Name = "AdminMenu_Panel_Content"
}
);
updateRoot.Update(connection);
}
}
public void ShowPanelContent(Content content) {
if (content == null) {
CUI.Root root = new CUI.Root();
root.Add(new CUI.Element {
DestroyUi = "AdminMenu_Panel_TempContent"
}
);
root.Render(connection);
return;
}
if (currentContent != null) currentContent.RestoreUserData(userData);
currentContent = content;
currentContent.LoadDefaultUserData(userData);
UI.RenderContent(content);
}
public void ShowPanelContent(string contentId) {
ShowPanelContent(currentPanel.TryGetContent(contentId));
}
public void Dispose() {
all.Remove(connection);
}
public static Dictionary<Connection, ConnectionData> all = new Dictionary<Connection, ConnectionData>();
public static ConnectionData Get(Connection connection) {
if (connection == null) return null;
ConnectionData data;
if (all.TryGetValue(connection, out data)) return data;
return null;
}
public static ConnectionData Get(BasePlayer player) {
return Get(player.Connection);
}
public static ConnectionData GetOrCreate(Connection connection) {
if (connection == null) return null;
ConnectionData data = Get(connection);
if (data == null) data = all[connection] = new ConnectionData(connection);
return data;
}
public static ConnectionData GetOrCreate(BasePlayer player) {
return GetOrCreate(player.Connection);
}
}
public class ConnectionUI {
Connection connection;
ConnectionData connectionData;
public ConnectionUI(ConnectionData connectionData) {
this.connectionData = connectionData;
this.connection = connectionData.connection;
}
public void ShowAdminMenu() {
CUI.Root root = new CUI.Root();
root.Add(new CUI.Element {
Components = {
new CuiRectTransformComponent {
AnchorMin = "0 0.00001", AnchorMax = "1 1.00001"
}
}
, Name = "AdminMenu", Update = true
}
);
root.Add(new CUI.Element {
Components = {
new CuiNeedsCursorComponent()
}
, Parent = "AdminMenu", Name = "AdminMenu_Cursor"
}
);
root.Render(connection);
}
public void HideAdminMenu() {
CUI.Root root = new CUI.Root();
root.Add(new CUI.Element {
Components = {
new CuiRectTransformComponent {
AnchorMin = "1000 1000", AnchorMax = "1001 1001"
}
}
, DestroyUi = "AdminMenu_Cursor", Name = "AdminMenu", Update = true
}
);
root.Render(connection);
}
public void DestroyAdminMenu() {
CuiHelper.DestroyUi(connection.player as BasePlayer, "AdminMenu");
CuiHelper.DestroyUi(connection.player as BasePlayer, "AdminMenu_Cursor");
connectionData.IsDestroyed = true;
}
public void DestroyAll() {
DestroyAdminMenu();
CuiHelper.DestroyUi(connection.player as BasePlayer, "AdminMenu_OpenButton");
}
public void AddSidebar(CUI.Element element, Sidebar sidebar) {
if (sidebar == null) return;
var sidebarPanel = element.AddPanel(color : Themes.CurrentTheme.GetColorString(Theme.KeyCollection.PANEL_SIDEBAR_BACKGROUND), material : "assets/content/ui/uibackgroundblur-ingamemenu.mat", imageType : Image.Type.Tiled, anchorMin : "0 0", anchorMax : "0 1", offsetMin : "0 0", offsetMax : "250 0", name : "AdminMenu_Panel_Sidebar").AddDestroySelfAttribute();
sidebarPanel.AddPanel(color : "0.217 0.217 0.217 0.796", sprite : "assets/content/ui/ui.background.transparent.linear.psd", material : "assets/content/ui/namefontmaterial.mat", anchorMin : "0 0", anchorMax : "1 1", name : "UIPanel_SideBar_Linear");
IEnumerable<CategoryButton> categoryButtons = sidebar.CategoryButtons.GetAllowedButtons(connection);
if (categoryButtons != null) {
int categoryButtonsCount = categoryButtons.Count();
if (categoryButtonsCount == 0) return;
var sidebarButtonGroup = sidebarPanel.AddPanel(color : "0 0 0 0", name : "UIPanel_SideBar_Scrollview");
sidebarButtonGroup.Components.AddScrollView(vertical : true, anchorMin : "0 1", offsetMin : $"0 -{categoryButtonsCount * 48}");
for (int i = 0; i < categoryButtonsCount; i++) {
CategoryButton categoryButton = categoryButtons.ElementAt(i);
sidebarButtonGroup.AddButton(command : $"adminmenu uipanel.sidebar.button_pressed {i} {categoryButtonsCount}", color : $"0 0 0 0", anchorMin : "0 1", anchorMax : "1 1", offsetMin : $"16 -{(i + 1) * 48}", offsetMax : $"0 -{i * 48}", name : $"UIPanel_SideBar_Button{i}").AddText(text : categoryButton.Label.Localize(connection), color : "0.969 0.922 0.882 1", font : CUI.Font.RobotoCondensedBold, fontSize : categoryButton.FontSize, align : TextAnchor.MiddleRight, offsetMin : "16 0", offsetMax : "-16 0");
}
}
}
private void AddNavButtons(CUI.Element element, MainMenu mainMenu) {
IEnumerable<Button> navButtons = mainMenu.NavButtons.GetAllowedButtons(connection);
int navButtonsCount = navButtons.Count();
var navButtonGroup = element.AddContainer(anchorMin : "0 0", anchorMax : "1 0", offsetMin : "64 64", offsetMax : $"0 {64 + navButtonsCount * 42}", name : "Navigation ButtonGroup").AddDestroySelfAttribute();
for (int i = 0; i < navButtonsCount; i++) {
Button navButton = navButtons.ElementAtOrDefault(i);
if (navButton == null) continue;
navButtonGroup.AddButton(command : navButton.IsHidden(connectionData) ? null : $"adminmenu navigation.button_pressed {i} {navButtonsCount}", color : "0 0 0 0", anchorMin : "0 1", anchorMax : "1 1", offsetMin : $"0 -{(i + 1) * 42}", offsetMax : $"0 -{i * 42}").AddText(text : navButton.Label.Localize(connection).ToUpper(), color : $"0.969 0.922 0.882 {(navButton.IsHidden(connectionData) ? 0 : (navButton.IsPressed(connectionData) ? 1 : 0.180f))}", fontSize : 28, font : CUI.Font.RobotoCondensedBold, align : TextAnchor.LowerLeft, overflow : VerticalWrapMode.Truncate, offsetMin : "10 5", name : $"NavigationButtonText{i}");
}
}
public void UpdateNavButtons(MainMenu mainMenu) {
CUI.Root root = new CUI.Root("AdminMenu_Navigation");
AddNavButtons(root, mainMenu);
root.Render(connection);
}
public void RenderOverlayOpenButton() {
CUI.Root root = new CUI.Root("Overlay");
root.AddButton(command : "adminmenu", color : "0.969 0.922 0.882 0.035", material : "assets/icons/greyout.mat", anchorMin : "0 0", anchorMax : "0 0", offsetMin : "0 0", offsetMax : "100 30", name : "AdminMenu_OpenButton").AddDestroySelfAttribute().AddText(text : "ADMIN MENU", color : "0.969 0.922 0.882 0.45", font : CUI.Font.RobotoCondensedBold, fontSize : 14, align : TextAnchor.MiddleCenter);
root.Render(connection);
}
public void RenderMainMenu(MainMenu mainMenu) {
if (mainMenu == null) return;
CUI.Root root = new CUI.Root("Overlay");
var container = root.AddPanel(color : "0.169 0.162 0.143 1", material : "assets/content/ui/uibackgroundblur-mainmenu.mat", imageType : Image.Type.Tiled, anchorMin : "1000 1000", anchorMax : "1001 1001", name : "AdminMenu").AddDestroySelfAttribute();
container.AddPanel(color : "0.301 0.283 0.235 1", sprite : "assets/content/ui/ui.background.transparent.radial.psd", material : "assets/content/ui/namefontmaterial.mat", anchorMin : "0 0", anchorMax : "1 1");
container.AddPanel(color : "0.169 0.162 0.143 0.384", sprite : "assets/content/ui/ui.background.transparent.radial.psd", material : "assets/content/ui/namefontmaterial.mat", anchorMin : "0 0", anchorMax : "1 1");
var navigation = container.AddContainer(anchorMin : "0 0", anchorMax : "0 1", offsetMin : "0 0", offsetMax : "350 0", name : "AdminMenu_Navigation");
var homeButton = navigation.AddContainer( //command: "adminmenu homebutton",
anchorMin : "0 1", anchorMax : "1 1", offsetMin : $"64 -{102f + 32}", offsetMax : "0 -32");
homeButton.AddImage(content : ADMINMENU_IMAGECRC, color : "0.811 0.811 0.811 1", material : "assets/content/ui/namefontmaterial.mat", anchorMin : "0 0", anchorMax : "0 1", offsetMax : $"146.4 0");
homeButton.AddText(text : config.Subtext, color : "0.824 0.824 0.824 1", font : CUI.Font.RobotoCondensedBold, fontSize : 16, anchorMin : "0 0", anchorMax : "0 0", offsetMin : "0 -35", offsetMax : "146.4 -10");
container.AddText(text : $"v{Instance.Version}", color : "0.5 0.5 0.5 0.2", font : CUI.Font.RobotoCondensedBold, fontSize : 12, align : TextAnchor.MiddleRight, anchorMin : "1 0", anchorMax : "1 0", offsetMin : "-100 0", offsetMax : "-10 20");
AddNavButtons(navigation, mainMenu);
var body = container.AddContainer(anchorMin : "0 0", anchorMax : "1 1", offsetMin : "350 0", offsetMax : "-64 0", name : "AdminMenu_Body");
var right = container.AddContainer(anchorMin : "1 0", anchorMax : "1 1", offsetMin : "-64 0", offsetMax : "0 0");
root.Render(connection);
connectionData.IsDestroyed = false;
}
public void RenderPanel(Panel panel) {
if (panel == null) return;
CUI.Root root = new CUI.Root("AdminMenu_Body");
var container = root.AddContainer(anchorMin : "0 0", anchorMax : "1 1", name : "AdminMenu_Panel").AddDestroySelfAttribute();
Sidebar sidebar = panel.Sidebar;
if (sidebar != null) AddSidebar(container, sidebar);
CUI.Element panelBackground = container.AddContainer(anchorMin : "0 0", anchorMax : "1 1", offsetMin : $"{(sidebar != null ? 250 : 0)} 0", offsetMax : "0 0", name : "AdminMenu_Panel_Content");
if (true) {
panelBackground = panelBackground.AddPanel(color : "1 1 1 1", material : "assets/content/ui/menuui/mainmenu.panel.mat", imageType : Image.Type.Tiled);
}
root.Render(connection);
}
public void RenderContent(Content content) {
if (content == null) return;
CUI.Root root = new CUI.Root("AdminMenu_Panel_Content");
var container = root.AddContainer(name : "AdminMenu_Panel_TempContent").AddDestroySelfAttribute();
root.Render(connection);
content.Render(connectionData);
}
}
public static class Extensions {
public static string ToCuiString(Color color) {
return string.Format("{0} {1} {2} {3}", new object[] {
color.r, color.g, color.b, color.a
}
);
}
}
[HarmonyPatch(typeof(BasePlayer), "Tick_Spectator")]
private static class SpectatorStaff {
private static bool Prefix(BasePlayer __instance) {
if (__instance.serverInput.WasJustPressed(BUTTON.RELOAD)) {
__instance.Respawn();
return false;
}
int num = 0;
if (__instance.serverInput.WasJustPressed(BUTTON.LEFT)) {
num--;
}
else if (__instance.serverInput.WasJustPressed(BUTTON.RIGHT)) {
num++;
}
if (num != 0) {
__instance.SpectateOffset += num;
using (TimeWarning.New("UpdateSpectateTarget", 0)) __instance.UpdateSpectateTarget(__instance.spectateFilter);
}
return true;
}
}
public class Label {
private static readonly Regex richTextRegex = new Regex(@"<[^>]*>");
string label;
string langKey;
public Label(string label) {
this.label = label;
if (!string.IsNullOrEmpty(label)) {
this.langKey = richTextRegex.Replace(label.ToPrintable(), string.Empty).Trim();
if (!Instance.defaultLang.ContainsKey(this.langKey)) Instance.defaultLang.Add(this.langKey, label);
}
}
public override string ToString() {
return label;
}
public string Localize(string userId) {
return this.langKey != null ? Instance.lang.GetMessage(this.langKey, Instance, userId) : this.label;
}
public string Localize(Connection connection) {
return Localize(connection.userid.ToString());
}
}
public class MainMenu {
public ButtonArray NavButtons {
get;
set;
}
}
public class Panel {
public virtual Sidebar Sidebar {
get;
set;
}
public virtual Dictionary<string, Content> Content {
get;
set;
}
public Content DefaultContent {
get => TryGetContent("default");
}
public Content TryGetContent(string id) {
if (Content == null) return null;
if (Content.TryGetValue(id, out Content content)) return content;
return null;
}
public virtual void OnOpen(ConnectionData connectionData) {
connectionData.UI.UpdateNavButtons(connectionData.currentMainMenu);
}
public virtual void OnClose(ConnectionData connectionData) {
connectionData.userData["backcommand"] = null;
}
}
public class UserInfoPanel : Panel {
}
public class PermissionPanel : Panel {
public override Sidebar Sidebar {
get => null;
}
public override void OnClose(ConnectionData connectionData) {
connectionData.userData["backcommand"] = null;
}
}
public class Sidebar {
public ButtonArray<CategoryButton> CategoryButtons {
get;
set;
}
public int? AutoActivateCategoryButtonIndex {
get;
set;
}
= 0;
}
public class SteamInfo {
public string Location {
get;
set;
}
public string[] Avatars {
get;
set;
}
public string RegistrationDate {
get;
set;
}
public string RustHours {
get;
set;
}
public override string ToString() {
return string.Join(", ", Location, RegistrationDate, RustHours);
}
}
public class Translator15 {
public static void Init(string language) {
Dictionary<string, string> lang = new Dictionary<string, string>();
TextAsset textAsset = FileSystem.Load<TextAsset>($"assets/localization/{language}/engine.json", true);
if (textAsset == null) return;
Dictionary<string, string> @object = JsonConvert.DeserializeObject<Dictionary<string, string>>(textAsset.text);
if (@object == null) return;
foreach (ItemDefinition itemDefinition in ItemManager.itemList) {
string key = itemDefinition.displayName.token;
if (@object.ContainsKey(key)) lang[key] = @object[key];
}
translations[language] = lang;
}
private static Dictionary<string, Dictionary<string, string>> translations = new Dictionary<string, Dictionary<string, string>>();
public class Phrase : Translate.Phrase {
private Translator15 translator;
public Phrase(Translator15 translator) {
this.translator = translator;
}
public override string translated {
get {
if (string.IsNullOrEmpty(this.token)) {
return this.english;
}
return translator.Get(this.token, this.english);
}
}
}
protected ulong userID;
public Translator15(ulong userID) {
this.userID = userID;
}
public Translator15.Phrase Convert(Translate.Phrase phrase) {
if (phraseCache.TryGetValue(phrase, out Translator15.Phrase phrase1)) return phrase1;
else return phraseCache[phrase] = new Translator15.Phrase(this) {
english = phrase.english, token = phrase.token
}
;
}
private string GetLanguage() {
return Instance.lang.GetLanguage(userID.ToString());
}
public string Get(string key, string def = null) {
if (def == null) def = "#" + key;
if (string.IsNullOrEmpty(key)) return def;
string language = GetLanguage();
if (!Translator15.translations.ContainsKey(language)) Translator15.Init(language);
if (Translator15.translations[language].TryGetValue(key, out string result)) return result;
return def;
}
private Dictionary<Translat
// ... [Code preview truncated due to length. Full source in attached file] ...