using System.Collections.Generic; using Oxide.Game.Rust.Cui; using System.Linq; using UnityEngine; using System; using Oxide.Core; using System.Globalization; //make alias a list namespace Oxide.Plugins { [Info("InfoScreens", "Steenamaroo", "1.0.5", ResourceId = 75)] [Description("Server info screens, with navigation.")] class InfoScreens : RustPlugin { Dictionary users = new Dictionary(); public Dictionary Pages = new Dictionary(); const string permAllowed = "infoscreens.show"; bool HasPermission(string id, string perm) => permission.UserHasPermission(id, perm); void OnServerInitialized() { permission.RegisterPermission(permAllowed, this); if (!LoadConfigVariables()) { Interface.Oxide.UnloadPlugin(Name); return; } cmd.AddChatCommand($"{config.Global.CommandAlias}", this, "InfoScreen"); if (config.Global.NumberOfPages == 0) config.Global.NumberOfPages = 1; for (int i = 1; i <= Mathf.Max(config.Global.NumberOfPages, config.Pages.Count); i++) { if (config.Pages.Count >= i) Pages.Add(config.Pages.ElementAt(i - 1).Key, config.Pages.ElementAt(i - 1).Value); else if (!Pages.ContainsKey($"Page{i}")) Pages.Add($"Page{i}", DefaultPage()); } foreach (var page in config.Pages.ToDictionary(x => x.Key, x => x.Value)) if (page.Value.ImageElements.Count == 0 && page.Value.TextElements.Count == 0) Pages[page.Key] = DefaultPage(); config.Pages = Pages; SaveConfig(config); foreach (var player in BasePlayer.activePlayerList) if (config.Global.PermaUIButton) ISPermaUI(player); } void Unload() { foreach (BasePlayer player in BasePlayer.activePlayerList) DestroyMenu(player, true); SaveData(); } void OnPlayerConnected(BasePlayer player) { if (player.IsReceivingSnapshot) { timer.Once(1f, () => { if (player?.net?.connection != null) OnPlayerConnected(player); }); return; } if (config.Global.PermaUIButton) ISPermaUI(player); if (config.Global.NeverAutoShow) return; if (config.Global.OnlyShowOnce) { if (!storedData.DisplayedTo.Contains(player.userID)) { OpenUI(player); storedData.DisplayedTo.Add(player.userID.Get()); } } else OpenUI(player); } void OnPlayerDisconnected(BasePlayer player) { if (users.ContainsKey(player.userID)) DestroyMenu(player, true); } void OnPlayerDeath(BasePlayer player, HitInfo info) { if (users.ContainsKey(player.userID)) DestroyMenu(player, false); } void DestroyMenu(BasePlayer player, bool all) { if (all) CuiHelper.DestroyUi(player, "ISPermaUI"); CuiHelper.DestroyUi(player, "ISUI"); users.Remove(player.userID); } static BasePlayer FindPlayerByName(string name) { BasePlayer result = null; foreach (BasePlayer current in BasePlayer.activePlayerList) { if (current.displayName.Equals(name, StringComparison.OrdinalIgnoreCase) || current.UserIDString.Contains(name, CompareOptions.OrdinalIgnoreCase) || current.displayName.Contains(name, CompareOptions.OrdinalIgnoreCase)) result = current; } return result; } [ChatCommand("infoscreen")] void InfoScreen(BasePlayer player, string command, string[] args) { if (args == null) return; if (args.Length == 2 && args[0] == "ui") { DestroyMenu(player, true); if (args[1] == "on") ISPermaUI(player); return; } if ((player.IsAdmin || HasPermission(player.UserIDString, permAllowed)) && args?.Length > 0) { BasePlayer target = FindPlayerByName(args[0]); if (target == null) { SendReply(player, $"Target player {args[0]} not found."); return; } else { SendReply(player, $"Opened infoscreens for player {target.displayName}."); if (args.Length == 2) { if (config.Pages.ContainsKey(args[1])) ISUI(player, config.Pages.Keys.ToList().IndexOf(args[1]), 0); else SendReply(player, $"No page found for '{args[1]}'."); return; } else { OpenUI(target); return; } } } OpenUI(player); } void OpenUI(BasePlayer player) => ISUI(player, 0, 0); [ConsoleCommand("ISWipe")] private void ISWipe(ConsoleSystem.Arg arg) { if (arg.Player() == null || arg.Player()?.IsAdmin == true) { storedData.DisplayedTo.Clear(); SaveData(); Puts("InfoScreens displayed-to records have been cleared."); } } [ConsoleCommand("ISRefreshUI")] private void ISRefreshUI(ConsoleSystem.Arg arg) { if (arg.Player() == null) return; ISUI(arg.Player(), Convert.ToInt32(arg.Args[0]), Convert.ToInt32(arg.Args[1])); } void ISPermaUI(BasePlayer player) { var elements = new CuiElementContainer(); var mainName = elements.Add(new CuiPanel { Image = { Color = $"0.1 0.1 0.1 0" }, RectTransform = { AnchorMin = "0.97 0.97", AnchorMax = "0.995 0.995" }, CursorEnabled = false, FadeOut = 0.1f }, "Overlay", "ISPermaUI"); elements.Add(new CuiButton { Button = { Command = "ISRefreshUI 0 0", Color = GetColour(config.Global.ButtonColour) }, RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" }, Text = { Text = "i", FontSize = 11, Align = TextAnchor.MiddleCenter } }, mainName); CuiHelper.AddUi(player, elements); } void ISUI(BasePlayer player, int page, int subpage) { DestroyMenu(player, false); Dictionary VisiblePages = new Dictionary(); foreach (var storedpage in config.Pages) { foreach (var group in permission.GetUserGroups(player.UserIDString)) if (storedpage.Value.VisibleTo.Split(',').Contains(group)) if (!VisiblePages.ContainsKey(storedpage.Key)) VisiblePages.Add(storedpage.Key, storedpage.Value); } if (VisiblePages.Count == 0) { SendReply(player, "InfoScreens has no pages"); return; } users[player.userID] = page; var elements = new CuiElementContainer(); var mainName = elements.Add(new CuiPanel { Image = { Color = $"0.1 0.1 0.1 {config.Global.GuiTransparency}" }, RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" }, CursorEnabled = true, FadeOut = 0.1f }, "Overlay", "ISUI"); var pageInfo = VisiblePages.ElementAt(page); int subPages = GetSubPages(pageInfo.Value); foreach (var image in pageInfo.Value.ImageElements.Where(x => x.Value.ShowOnSubPages.Split(',').Contains(subpage.ToString()))) { string[] pos = GetPosition(image.Key, image.Value); elements.Add(new CuiElement { Parent = "ISUI", Components = { new CuiRawImageComponent { Url = $"{image.Value.URL}" , FadeIn = 0.8f}, new CuiRectTransformComponent { AnchorMin = $"{pos[0]} {pos[1]}", AnchorMax = $"{pos[2]} {pos[3]}" } } }); } foreach (var text in pageInfo.Value.TextElements.Where(x => x.Value.ShowOnSubPages.Split(',').Contains(subpage.ToString()))) { string[] pos = GetPosition(text.Key, text.Value); elements.Add(new CuiLabel { Text = { Text = $"{text.Value.Content}", FontSize = text.Value.FontSize, Color = GetColour(text.Value.FontColour), Align = GetAnchor(text.Key, text.Value) }, RectTransform = { AnchorMin = $"{pos[0]} {pos[1]}", AnchorMax = $"{pos[2]} {pos[3]}" } }, mainName); } if (config.Global.SideNav) elements.Add(new CuiButton { Button = { Color = $"0 0 0 {config.Global.GuiTransparency}" }, RectTransform = { AnchorMin = $"0 0", AnchorMax = $"0.1 1" }, Text = { Text = string.Empty } }, mainName); else elements.Add(new CuiButton { Button = { Color = $"0 0 0 {config.Global.GuiTransparency}" }, RectTransform = { AnchorMin = $"0 0.965", AnchorMax = $"1 1" }, Text = { Text = string.Empty } }, mainName); int num = (VisiblePages.Count * 2) + 1; double unit = 1.0 / num; for (int i = 1; i <= VisiblePages.Count; i++) { int fontsize = VisiblePages.Count > 8 ? 12 : 18; string bc = i - 1 == page ? GetColour(config.Global.ButtonColourSelected) : GetColour(config.Global.ButtonColour); if (config.Global.SideNav) elements.Add(new CuiButton { Button = { Command = $"ISRefreshUI {i - 1} 0", Color = bc }, RectTransform = { AnchorMin = $"0 {1-(unit * ((i * 2) - 0.5))}", AnchorMax = $"0.1 {1-(unit * ((i * 2) - 1))}" }, Text = { Text = $"{VisiblePages.ElementAt(i - 1).Key}", FontSize = fontsize, Align = TextAnchor.MiddleCenter } }, mainName); else elements.Add(new CuiButton { Button = { Command = $"ISRefreshUI {i - 1} 0", Color = bc }, RectTransform = { AnchorMin = $"{unit * ((i * 2) - 1)} 0.965", AnchorMax = $"{unit * (i * 2)} 1" }, Text = { Text = $"{VisiblePages.ElementAt(i - 1).Key}", FontSize = fontsize, Align = TextAnchor.MiddleCenter } }, mainName); } if (subpage < subPages) elements.Add(new CuiButton { Button = { Command = $"ISRefreshUI {page} {subpage + 1}", Color = GetColour(config.Global.ButtonColour) }, RectTransform = { AnchorMin = "0.8 0.01", AnchorMax = "0.895 0.05" }, Text = { Text = "->", FontSize = 24, Align = TextAnchor.MiddleCenter } }, mainName); if (subpage > 0) elements.Add(new CuiButton { Button = { Command = $"ISRefreshUI {page} {subpage - 1}", Color = GetColour(config.Global.ButtonColour) }, RectTransform = { AnchorMin = "0.105 0.01", AnchorMax = "0.2 0.05" }, Text = { Text = "<-", FontSize = 24, Align = TextAnchor.MiddleCenter } }, mainName); elements.Add(new CuiButton { Button = { Command = "CloseIS", Color = GetColour(config.Global.ButtonColour) }, RectTransform = { AnchorMin = "0.97 0.97", AnchorMax = "0.995 0.995" }, Text = { Text = "X", FontSize = 11, Align = TextAnchor.MiddleCenter } }, mainName); CuiHelper.AddUi(player, elements); } public int GetSubPages(Page page) { string source = string.Empty; foreach (var image in page.ImageElements) source += $",{image.Value.ShowOnSubPages}"; foreach (var text in page.TextElements) source += $",{text.Value.ShowOnSubPages}"; string[] subs = source.Split(','); int maxsub = 0; foreach (var sub in subs) if (sub.IsNumeric() && Convert.ToInt16(sub) > maxsub) maxsub = Convert.ToInt16(sub); return maxsub; } public bool IsFloat(string input) { float num; return float.TryParse(input, out num); } public string[] GetPosition(string name, Element element) { var LR = element.PosLeftToRight.Split(','); var BT = element.PosBottomToTop.Split(','); if (BT == null || LR == null || BT.Length != 2 || LR.Length != 2 || !IsFloat(BT[0]) || !IsFloat(BT[1]) || !IsFloat(LR[0]) || !IsFloat(LR[1])) { Puts($"Error in config for {name}."); return new string[] { "0", "1", "0", "1" }; } if (!element.GoBehindNav) if (config.Global.SideNav) LR[0] = (float.Parse(LR[0]) + 0.1f).ToString(); else BT[1] = ((float.Parse(BT[1]) / 100f) * 96.5).ToString(); return new string[] { LR[0], BT[0], LR[1], BT[1] }; } public TextAnchor GetAnchor(string name, Text text) { int tAnchor = text.AlignTopMiddleBottom.ToLower() == "top" ? 0 : text.AlignTopMiddleBottom.ToLower() == "middle" ? 3 : 6; tAnchor += text.AlignLeftMiddleRight.ToLower() == "middle" ? 1 : text.AlignLeftMiddleRight.ToLower() == "right" ? 2 : 0; return (TextAnchor)tAnchor; } string GetColour(string colour) { var cols = colour.Replace(" ","").Split(','); if (cols == null || cols.Length != 4 || !IsFloat(cols[0]) || !IsFloat(cols[1]) || !IsFloat(cols[2]) || !IsFloat(cols[3])) return "0, 0, 0, 1"; for (int i = 0; i < 3; i++) cols[i] = (float.Parse(cols[i]) / 255).ToString(); return $"{cols[0]} {cols[1]} {cols[2]} {cols[3]}"; } [ConsoleCommand("CloseIS")] private void CloseIS(ConsoleSystem.Arg arg) { if (arg.Player() == null) return; DestroyMenu(arg.Player(), false); } #region Config private ConfigData config; public class ConfigData { public Global Global = new Global(); public Dictionary Pages = new Dictionary(); } public class Global { public bool PermaUIButton = false; public bool SideNav = false; public bool OnlyShowOnce = false; public bool NeverAutoShow = false; public int NumberOfPages = 4; public double GuiTransparency = 0.95; public string ButtonColour = "0,100,0,1"; public string ButtonColourSelected = "0,200,0,1"; public string CommandAlias = "is"; } public class Page { public Dictionary ImageElements = new Dictionary(); public Dictionary TextElements = new Dictionary(); public string VisibleTo = "default,somegroup"; } public Page DefaultPage() => new Page(){ImageElements = new Dictionary(){{ "BackGround", new Image () }},TextElements = new Dictionary(){{ "Title", new Text() },{ "Content", new Text() { PosBottomToTop = "0.0,0.5" } },}}; public class Element { public bool GoBehindNav = false; public string ShowOnSubPages = "0"; public string PosBottomToTop = "0.0,1.0"; public string PosLeftToRight = "0.0,1.0"; } public class Text : Element { public string Content = "Default Text"; public int FontSize = 16; public string AlignTopMiddleBottom = "top"; public string AlignLeftMiddleRight = "middle"; public string FontColour = "255,255,255,1"; } public class Image : Element { public string URL = string.Empty ; } private bool LoadConfigVariables() { try { config = Config.ReadObject(); } catch { return false; } SaveConfig(config); return true; } protected override void LoadDefaultConfig() { Puts("Creating new config file."); var config = new ConfigData(); SaveConfig(config); } void SaveConfig(ConfigData config) => Config.WriteObject(config, true); #endregion #region Data StoredData storedData; class StoredData { public List DisplayedTo = new List(); } void Loaded() { storedData = Interface.Oxide.DataFileSystem.ReadObject("InfoScreens"); Interface.Oxide.DataFileSystem.WriteObject("InfoScreens", storedData); } void SaveData()=>Interface.Oxide.DataFileSystem.WriteObject("InfoScreens", storedData); #endregion } }