using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Oxide.Core; using Oxide.Core.Plugins; using Oxide.Game.Rust; using Oxide.Game.Rust.Cui; using UnityEngine; /* ToDo: https://umod.org/community/info-panel/35582-feature-for-dangerous-treasure-event Add support for dangerous-treasure-event */ namespace Oxide.Plugins { [Info("InfoPanel", "Gonzi", "1.0.6")] [Description("A little panel with useful information.")] public class InfoPanel : RustPlugin { #region DefaultConfigs private static string DefaultFontColor = "1 1 1 1"; public bool IsReady; #endregion private Timer TestTimer; private Dictionary> PlayerPanels = new Dictionary>(); private Dictionary> PlayerDockPanels = new Dictionary>(); private Dictionary> LoadedPluginPanels = new Dictionary>(); #region DefaultConfig private static PluginConfig Settings; private readonly List TimeFormats = new List { "H:mm", "HH:mm", "h:mm", "h:mm tt", }; PluginConfig DefaultConfig() { var DefaultConfig = new PluginConfig { ThirdPartyPanels = new Dictionary>(), Messages = Messages, TimeFormats = TimeFormats, CoordType = 2, CompassDirections = new Dictionary { {"n", "North"}, {"ne", "Northeast"}, {"e", "East"}, {"se", "Southeast"}, {"s", "South"}, {"sw", "Southwest"}, {"w", "West"}, {"nw", "Northwest"}, }, Docks = new Dictionary { { "BottomLeftDock", new DockConfig { Available = true, Width = 0.18f, Height = 0.03f, AnchorX = "Left", AnchorY = "Bottom", Margin = "0.005 0.165 0.005 0.005", BackgroundColor = "0 0 0 0.4", } }, { "BottomRightDock", new DockConfig { Available = true, Width = 0.19f, Height = 0.03f, AnchorX = "Right", AnchorY = "Bottom", Margin = "0.005 0.005 0.005 0.165", BackgroundColor = "0 0 0 0.4", } }, { "TopLeftDock", new DockConfig { Available = true, Width = 0.175f, Height = 0.03f, AnchorX = "Left", AnchorY = "Top", Margin = "0.005 0.005 0.005 0.005", BackgroundColor = "0 0 0 0.4", } }, { "TopRightDock", new DockConfig { Available = true, Width = 0.29f, Height = 0.03f, AnchorX = "Right", AnchorY = "Top", Margin = "0.005 0.005 0.005 0.005", BackgroundColor = "0 0 0 0.4", } } }, Panels = new Dictionary { { "Clock", new PanelConfig { Available = true, Permission = null, Dock = "BottomLeftDock", Order = 1, AnchorX = "Left", AnchorY = "Bottom", Margin = "0 0 0 0.01", Width = 0.2f, Height = 0.95f, BackgroundColor = "0.1 0.1 0.1 0", Text = new PanelTextConfig { Align = TextAnchor.MiddleCenter, FontColor = DefaultFontColor, FontSize = 14, Margin = "0 0.01 0 0.01", }, PanelSettings = new Dictionary { {"ClockUpdateFrequency (seconds)", ClockUpdateFrequency}, {"TimeFormat", "HH:mm"} } } }, { "MessageBox", new PanelConfig { Available = true, Permission = null, Dock = "TopRightDock", Order = 7, AnchorX = "Right", AnchorY = "Bottom", Margin = "0 0 0 0.005", Width = 1f, Height = 0.95f, BackgroundColor = "0 0 0 0.4", Text = new PanelTextConfig { Align = TextAnchor.MiddleCenter, FontColor = DefaultFontColor, FontSize = 14, }, PanelSettings = new Dictionary { {"MessageUpdateFrequency (seconds)", MessageUpdateFrequency}, {"MsgOrder", "normal"} } } }, { "Balance", new PanelConfig { Available = true, Permission = null, Dock = "BottomLeftDock", Order = 7, AnchorX = "Left", AnchorY = "Bottom", Margin = "0 0 0 0.01", Width = 0.4f, Height = 0.95f, BackgroundColor = "0 0 0 0.4", Image = new PanelImageConfig { Order = 1, Width = 0.2f, Height = 0.8f, Margin = "0 0.01 0.1 0.01", Url = "http://i.imgur.com/HhL5TvU.png", }, Text = new PanelTextConfig { Order = 2, Width = 0.848f, Height = 1f, Align = TextAnchor.MiddleCenter, FontColor = DefaultFontColor, FontSize = 12, Margin = "0 0.02 0 0", }, PanelSettings = new Dictionary { {"RefreshRate(s)", "5"}, } } }, { "Points", new PanelConfig { Available = true, Permission = null, Dock = "BottomLeftDock", Order = 8, AnchorX = "Left", AnchorY = "Bottom", Margin = "0 0 0 0.01", Width = 0.4f, Height = 0.95f, BackgroundColor = "0 0 0 0.4", Image = new PanelImageConfig { Order = 1, Width = 0.2f, Height = 0.8f, Margin = "0 0.01 0.1 0.01", Url = "http://i.imgur.com/dwzul4T.png", }, Text = new PanelTextConfig { Order = 2, Width = 0.848f, Height = 1f, Align = TextAnchor.MiddleCenter, FontColor = DefaultFontColor, FontSize = 12, Margin = "0 0.02 0 0", }, PanelSettings = new Dictionary { {"RefreshRate(s)", "5"}, } } }, { "Coordinates", new PanelConfig { Available = true, Permission = null, Dock = "TopLeftDock", Order = 7, AnchorX = "Left", AnchorY = "Bottom", Margin = "0 0 0 0.01", Width = 0.8f, Height = 0.95f, BackgroundColor = "0 0 0 0.4", Image = new PanelImageConfig { Order = 1, Width = 0.13f, Height = 0.8f, Margin = "0 0.01 0.1 0.01", Url = "http://i.imgur.com/Kr1pQ5b.png", }, Text = new PanelTextConfig { Order = 2, Width = 0.848f, Height = 1f, Align = TextAnchor.MiddleCenter, FontColor = DefaultFontColor, FontSize = 12, Margin = "0 0.02 0 0", }, PanelSettings = new Dictionary { {"RefreshRate(s)", "3"}, } } }, { "Compass", new PanelConfig { Available = false, Permission = null, Dock = "BottomRightDock", Order = 8, AnchorX = "Left", AnchorY = "Bottom", Margin = "0 0 0 0.01", Width = 0.5f, Height = 0.95f, BackgroundColor = "0 0 0 0.4", Image = new PanelImageConfig { Order = 1, Width = 0.188f, Height = 0.8f, Margin = "0 0.01 0.1 0.03", Url = "http://i.imgur.com/dG5nOOJ.png", }, Text = new PanelTextConfig { Order = 2, Width = 0.76f, Height = 1f, Align = TextAnchor.MiddleCenter, FontColor = DefaultFontColor, FontSize = 12, Margin = "0 0.02 0 0", }, PanelSettings = new Dictionary { {"RefreshRate(s)", "1"}, {"TextOrAngle", "text"} } } }, { "OPlayers", new PanelConfig { Available = true, Permission = null, Dock = "TopLeftDock", Order = 2, AnchorX = "Left", AnchorY = "Bottom", Margin = "0 0 0 0.01", Width = 0.31f, Height = 0.95f, BackgroundColor = "0 0 0 0.4", Image = new PanelImageConfig { Order = 1, Width = 0.35f, Height = 0.8f, Margin = "0 0.05 0.1 0.05", Url = "http://i.imgur.com/n9EYIWi.png", }, Text = new PanelTextConfig { Order = 2, Width = 0.68f, Height = 1f, Align = TextAnchor.MiddleCenter, FontColor = DefaultFontColor, FontSize = 14, } } }, { "Sleepers", new PanelConfig { Available = true, Permission = null, Dock = "TopLeftDock", Order = 3, AnchorX = "Left", AnchorY = "Bottom", Margin = "0 0 0 0.01", Width = 0.225f, Height = 0.95f, BackgroundColor = "0 0 0 0.4", Image = new PanelImageConfig { Order = 1, Width = 0.4f, Height = 0.8f, Margin = "0 0.05 0.1 0.05", Url = "http://i.imgur.com/XIIZkqD.png", }, Text = new PanelTextConfig { Order = 2, Width = 0.63f, Height = 1f, Align = TextAnchor.MiddleCenter, FontColor = DefaultFontColor, FontSize = 14, } } }, { "AirdropEvent", new PanelConfig { Available = true, Permission = null, Dock = "TopLeftDock", Order = 4, AnchorX = "Left", AnchorY = "Bottom", Margin = "0 0 0 0.01", Width = 0.1f, Height = 0.95f, BackgroundColor = "0 0 0 0.4", Image = new PanelImageConfig { Order = 1, Width = 0.8f, Height = 0.8f, Margin = "0 0.1 0.1 0.1", Url = "http://i.imgur.com/dble6vf.png", }, PanelSettings = new Dictionary { {"InactiveColor", "1 1 1 0.1"}, {"ActiveColor", "0 1 0 1"}, } } }, { "HelicopterEvent", new PanelConfig { Available = true, Permission = null, Dock = "TopLeftDock", Order = 5, AnchorX = "Left", AnchorY = "Bottom", Margin = "0 0 0 0.01", Width = 0.1f, Height = 0.95f, BackgroundColor = "0 0 0 0.5", Image = new PanelImageConfig { Order = 1, Width = 0.75f, Height = 0.8f, Margin = "0 0.15 0.1 0.1", Url = "http://i.imgur.com/hTTyTTx.png", }, PanelSettings = new Dictionary { {"InactiveColor", "1 1 1 0.1"}, {"ActiveColor", "0.7 0.2 0.2 1"}, } } }, { "ChinookEvent", new PanelConfig { Available = true, Permission = null, Dock = "TopLeftDock", Order = 5, AnchorX = "Left", AnchorY = "Bottom", Margin = "0 0 0 0.01", Width = 0.1f, Height = 0.95f, BackgroundColor = "0 0 0 0.5", Image = new PanelImageConfig { Order = 1, Width = 0.75f, Height = 0.8f, Margin = "0 0.15 0.1 0.1", Url = "https://i.imgur.com/49d8ZcK.png", }, PanelSettings = new Dictionary { {"InactiveColor", "1 1 1 0.1"}, {"ActiveColor", "0.7 0.2 0.2 1"}, } } }, { "CargoShipEvent", new PanelConfig { Available = true, Permission = null, Dock = "TopLeftDock", Order = 5, AnchorX = "Left", AnchorY = "Bottom", Margin = "0 0 0 0.01", Width = 0.1f, Height = 0.95f, BackgroundColor = "0 0 0 0.4", Image = new PanelImageConfig { Order = 1, Width = 0.75f, Height = 0.8f, Margin = "0 0.15 0.1 0.1", Url = "https://i.imgur.com/WQiNxyM.png", }, PanelSettings = new Dictionary { {"InactiveColor", "1 1 1 0.1"}, {"ActiveColor", "0 1 0 1"}, } } }, { "Radiation", new PanelConfig { Available = false, Permission = null, Dock = "TopLeftDock", Order = 6, AnchorX = "Left", AnchorY = "Bottom", Margin = "0 0 0 0.01", Width = 0.1f, Height = 0.95f, BackgroundColor = "0 0 0 0.4", Image = new PanelImageConfig { Order = 1, Width = 0.75f, Height = 0.8f, Margin = "0 0.15 0.1 0.1", Url = "http://i.imgur.com/owVdFsK.png", }, PanelSettings = new Dictionary { {"InactiveColor", "1 1 1 0.1"}, {"ActiveColor", "1 1 0 1"}, {"RefreshRate(s)", "3"} } } }, { "BradleyEvent", new PanelConfig { Available = false, Permission = null, Dock = "TopLeftDock", Order = 5, AnchorX = "Left", AnchorY = "Bottom", Margin = "0 0 0 0.01", Width = 0.1f, Height = 0.95f, BackgroundColor = "0 0 0 0.4", Image = new PanelImageConfig { Order = 1, Width = 0.75f, Height = 0.8f, Margin = "0 0.15 0.1 0.1", Url = "https://i.imgur.com/7mSjIwl.png", }, PanelSettings = new Dictionary { {"InactiveColor", "1 1 1 0.1"}, {"ActiveColor", "0.7 0.2 0.2 1"} } } } } }; return DefaultConfig; } class PluginConfig { //public Dictionary Settings { get; set; } public Dictionary Docks { get; set; } public Dictionary Panels { get; set; } public int CoordType { get; set; } public Dictionary> ThirdPartyPanels { get; set; } public List Messages { get; set; } public List TimeFormats { get; set; } public Dictionary CompassDirections { get; set; } public T GetPanelSettingsValue(string Panel, string Setting, T defaultValue) { PanelConfig panelConfig; if (!Panels.TryGetValue(Panel, out panelConfig)) return defaultValue; if (panelConfig.PanelSettings == null) return defaultValue; object value; if (!panelConfig.PanelSettings.TryGetValue(Setting, out value)) return defaultValue; return (T)Convert.ChangeType(value, typeof(T)); } public bool CheckPanelAvailability(string Panel) { PanelConfig panelConfig; if (!Panels.TryGetValue(Panel, out panelConfig)) return false; if (!panelConfig.Available) return false; DockConfig dockConfig; return Docks.TryGetValue(panelConfig.Dock, out dockConfig) && dockConfig.Available; } } class DockConfig { [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public bool Available { get; set; } = true; [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string AnchorX { get; set; } = "Left"; [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string AnchorY { get; set; } = "Bottom"; [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public float Width { get; set; } = 0.05f; [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public float Height { get; set; } = 0.95f; [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string BackgroundColor { get; set; } = "0 0 0 0.4"; [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string Margin { get; set; } = "0 0 0 0.005"; [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public PanelImageConfig Image { get; set; } } class BasePanelConfig { [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public bool Available { get; set; } = true; [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string AnchorX { get; set; } = "Left"; [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string AnchorY { get; set; } = "Bottom"; [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public float Width { get; set; } = 0.05f; [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public float Height { get; set; } = 0.95f; [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public int Order { get; set; } [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string BackgroundColor { get; set; } = "0 0 0 0.4"; [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string Margin { get; set; } = "0 0 0 0.005"; } class PanelConfig : BasePanelConfig { [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public bool Autoload { get; set; } = true; [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string Dock { get; set; } = "BottomLeftDock"; [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public Dictionary PanelSettings { get; set; } [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public PanelImageConfig Image { get; set; } [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public PanelTextConfig Text { get; set; } [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public float FadeOut { get; set; } public string Permission { get; set; } } class PanelTextConfig : BasePanelConfig { [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public new float Width { get; set; } = 1f; [JsonConverter(typeof(StringEnumConverter))] [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public TextAnchor Align { get; set; } = TextAnchor.MiddleCenter; [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string FontColor { get; set; } = "1 1 1 1"; [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public int FontSize { get; set; } = 14; [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string Content { get; set; } = "No Content"; [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public float FadeIn { get; set; } [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public float FadeOut { get; set; } } class PanelImageConfig : BasePanelConfig { [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public new float Width { get; set; } = 1f; [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string Url { get; set; } [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string Color { get; set; } = null; } protected void LoadConfigValues() { Settings = Config.ReadObject(); var UnOrderPanels = Settings.Panels.Where(p => p.Value.Order == 0).ToDictionary(s => s.Key, s => s.Value); var all = Settings.Panels.ToDictionary(s => s.Key, s => s.Value); foreach (var pan in all) { if (Settings.Panels[pan.Key].Permission != null) permission.RegisterPermission("infopanel." + Settings.Panels[pan.Key].Permission, this); } if (UnOrderPanels.Count == 0) return; PrintWarning("Reordering Panels."); foreach (var PanelCfg in UnOrderPanels) { //int HighestSiblingOrder = Settings.Panels.Where(p => p.Value.Dock == Settings.Panels[PanelName].Dock && p.Value.AnchorX == Settings.Panels[PanelName].AnchorX).Max(m => m.Value.Order); Settings.Panels[PanelCfg.Key].Order = PanelReOrder(PanelCfg.Value.Dock, PanelCfg.Value.AnchorX); } Config.WriteObject(Settings, true); PrintWarning("Config Saved."); } int PanelReOrder(string DockName, string AnchorX) { var SiblingPanels = Settings.Panels.Where(p => p.Value.Dock == DockName && p.Value.AnchorX == AnchorX); var Max = 0; if (SiblingPanels.Any()) Max = SiblingPanels.Max(m => m.Value.Order); foreach (var pPanelCfg in Settings.ThirdPartyPanels) { if (pPanelCfg.Value.Count == 0) continue; var SiblingPluginPAnels = pPanelCfg.Value.Where(p => p.Value.Dock == DockName && p.Value.AnchorX == AnchorX); if (SiblingPluginPAnels.Any()) { var PluginMax = pPanelCfg.Value.Where(p => p.Value.Dock == DockName && p.Value.AnchorX == AnchorX).Max(m => m.Value.Order); if (PluginMax > Max) Max = PluginMax; } } return Max + 1; } #endregion #region Hooks protected override void LoadDefaultConfig() { Config.Clear(); Config.WriteObject(DefaultConfig(), true); PrintWarning("Default configuration file created."); } void Init() { LoadConfigValues(); LoadData(); } void OnServerInitialized() { Clock = new Watch ( Settings.GetPanelSettingsValue("Clock", "ClockUpdateFrequency (seconds)", ClockUpdateFrequency), Settings.CheckPanelAvailability("Clock") ); MessageBox = new Messenger ( Settings.Messages, Settings.GetPanelSettingsValue("MessageBox", "MessageUpdateFrequency (seconds)", MessageUpdateFrequency), Settings.GetPanelSettingsValue("MessageBox", "MsgOrder", "normal") ); Airplane = new AirplaneEvent(); Helicopter = new HelicopterEvent(); Cargoship = new CargoshipEvent(); Chinook = new ChinookEvent(); Bradley = new BradleyEvent(); CompassObj = new Compass ( Settings.GetPanelSettingsValue("Compass", "RefreshRate(s)", 1) ); Rad = new Radiation ( Settings.GetPanelSettingsValue("Radiation", "RefreshRate(s)", 3) ); Poi = new Points ( Settings.GetPanelSettingsValue("Points", "RefreshRate(s)", 3) ); Bala = new Balance ( Settings.GetPanelSettingsValue("Balance", "RefreshRate(s)", 3) ); Coord = new Coordinates ( Settings.GetPanelSettingsValue("Coordinates", "RefreshRate(s)", 3) ); foreach (var player in BasePlayer.activePlayerList) { LoadPanels(player); InitializeGUI(player); } if (Settings.CheckPanelAvailability("Radiation")) { RadiationUpdater = timer.Repeat(Rad.RefreshRate, 0, () => Rad.Refresh(storedData, PlayerPanels)); } if (Settings.CheckPanelAvailability("Points")) { PointsUpdater = timer.Repeat(Poi.RefreshRate, 0, () => Poi.Refresh(storedData, PlayerPanels)); } if (Settings.CheckPanelAvailability("Balance")) { BalanceUpdater = timer.Repeat(Bala.RefreshRate, 0, () => Bala.Refresh(storedData, PlayerPanels)); } if (Settings.CheckPanelAvailability("Coordinates")) { CoordUpdater = timer.Repeat(Coord.RefreshRate, 0, () => Coord.Refresh(storedData, PlayerPanels)); } if (Settings.CheckPanelAvailability("MessageBox")) { MsgUpdater = timer.Repeat(MessageBox.RefreshRate, 0, () => MessageBox.Refresh(storedData, PlayerPanels)); } if (Settings.CheckPanelAvailability("Clock")) { TimeUpdater = timer.Repeat(Clock.RefresRate, 0, () => Clock.Refresh(storedData, PlayerPanels)); } if (Settings.CheckPanelAvailability("Compass")) { CompassUpdater = timer.Repeat(CompassObj.RefreshRate, 0, () => CompassObj.Refresh(storedData, PlayerPanels)); } //TestTimer = timer.Repeat(5, 0, () => TestSH()); ActivePlanes = UnityEngine.Object.FindObjectsOfType().ToList(); if (ActivePlanes.Count > 0) { CheckAirplane(); } else { Airplane.Refresh(storedData, PlayerPanels); } ActiveHelicopters = UnityEngine.Object.FindObjectsOfType().ToList(); if (ActiveHelicopters.Count > 0) { CheckHelicopter(); } else { Helicopter.Refresh(storedData, PlayerPanels); } ActiveBradleys = UnityEngine.Object.FindObjectsOfType().ToList(); if (ActiveBradleys.Count > 0) { CheckBradley(); } else { Bradley.Refresh(storedData, PlayerPanels); } ActiveChinooks = UnityEngine.Object.FindObjectsOfType().ToList(); if (ActiveChinooks.Count > 0) { CheckChinook(); } else { Chinook.Refresh(storedData, PlayerPanels); } ActiveCargoships = UnityEngine.Object.FindObjectsOfType().ToList(); if (ActiveCargoships.Count > 0) { CheckCargoship(); } else { Cargoship.Refresh(storedData, PlayerPanels); } IsReady = true; } void OnPlayerConnected(BasePlayer player) { if (player.HasPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot)) { timer.Once(2, () => OnPlayerConnected(player)); return; } if (PlayerPanels.ContainsKey(player.UserIDString)) { PlayerPanels.Remove(player.UserIDString); } if (PlayerDockPanels.ContainsKey(player.UserIDString)) { PlayerDockPanels.Remove(player.UserIDString); } timer.In(1, () => GUITimerInit(player)); } void OnPlayerDisconnected(BasePlayer player) { PlayerPanels.Remove(player.UserIDString); PlayerDockPanels.Remove(player.UserIDString); timer.Once(2, RefreshOnlinePlayers); timer.Once(2, RefreshSleepers); } void OnPlayerSleepEnded(BasePlayer player) { timer.Once(2, RefreshSleepers); } private void OnEntitySpawned(BaseEntity Entity) { if (!IsReady) { timer.In(10, () => OnEntitySpawned(Entity)); return; } if (Entity == null) return; if (Entity is BaseHelicopter && Settings.Panels["HelicopterEvent"].Available) { ActiveHelicopters.Add((BaseHelicopter)Entity); if (HelicopterTimer == false) { CheckHelicopter(); } } if (Entity is CargoPlane && Settings.Panels["AirdropEvent"].Available) { ActivePlanes.Add((CargoPlane)Entity); if (AirplaneTimer == false) { CheckAirplane(); } } if (Entity is CargoShip && Settings.Panels["CargoShipEvent"].Available) { ActiveCargoships.Add((CargoShip)Entity); if (CargoshipTimer == false) { CheckCargoship(); } } if (Entity is CH47Helicopter && Settings.Panels["ChinookEvent"].Available) { ActiveChinooks.Add((CH47Helicopter)Entity); if (ChinookTimer == false) { CheckChinook(); } } if (Entity is BradleyAPC && Settings.CheckPanelAvailability("BradleyEvent") && Settings.Panels["BradleyEvent"].Available) { ActiveBradleys.Add((BradleyAPC)Entity); if (BradleyTimer == false) { CheckBradley(); } } } private void Unload() { foreach (var player in BasePlayer.activePlayerList) DestroyGUI(player); SaveData(); PlayerPanels.Clear(); PlayerDockPanels.Clear(); Err.Clear(); ErrD.Clear(); ErrB.Clear(); ErrA.Clear(); storedData = null; Settings = null; } void OnPluginUnloaded(Plugin plugin) { if (!Settings.ThirdPartyPanels.ContainsKey(plugin.Title)) return; var PluginPanels = LoadedPluginPanels[plugin.Title]; foreach (var PanelName in PluginPanels) { foreach (var pair in PlayerPanels) { pair.Value[PanelName].DestroyPanel(); pair.Value[PanelName].Remover(); } } LoadedPluginPanels.Remove(plugin.Title); } void OnServerSave() { SaveData(); } void OnServerShutdown() { SaveData(); } #endregion #region PanelLoad /// /// /// private void LoadPanels(BasePlayer Player) { foreach (var Docks in Settings.Docks) { if (!Settings.Docks[Docks.Key].Available) continue; LoadDockPanel(Docks.Key, Player); } var playerDockPanel = PlayerDockPanels[Player.UserIDString]; foreach (var grouppedByDock in Settings.Panels.GroupBy(g => g.Value.Dock).ToDictionary(gd => gd.Key, gd => gd.Select(p => p).ToDictionary(gk => gk.Key, gk => gk.Value))) { if (!Settings.Docks[grouppedByDock.Key].Available) continue; foreach (var panelCfg in grouppedByDock.Value) { if (!Settings.CheckPanelAvailability(panelCfg.Key)) continue; if (panelCfg.Value.Permission == null || permission.UserHasPermission(Player.UserIDString, panelCfg.Value.Permission)) LoadPanel(playerDockPanel[grouppedByDock.Key], panelCfg.Key, panelCfg.Value); } } foreach (var loadedPluginPanel in LoadedPluginPanels) { foreach (var panelName in loadedPluginPanel.Value) { Dictionary panelConfigs; PanelConfig panelConfig; if (!Settings.ThirdPartyPanels.TryGetValue(loadedPluginPanel.Key, out panelConfigs) || !panelConfigs.TryGetValue(panelName, out panelConfig) || !panelConfig.Available) continue; if (panelConfig.Permission == null || permission.UserHasPermission(Player.UserIDString, panelConfig.Permission)) LoadPanel(playerDockPanel[panelConfig.Dock], panelName, panelConfig); } } } private IPanel LoadDockPanel(string DockName, BasePlayer Player) { var dockConfig = Settings.Docks[DockName]; var DockPanel = new IPanel(DockName, Player, PlayerPanels, PlayerDockPanels) { Width = dockConfig.Width, Height = dockConfig.Height, AnchorX = dockConfig.AnchorX, AnchorY = dockConfig.AnchorY, Margin = Vector4Parser(dockConfig.Margin), BackgroundColor = ColorEx.Parse(dockConfig.BackgroundColor), IsDock = true }; //LoadedDocks.Add(DockName, DockPanel); Dictionary panels; if (!PlayerDockPanels.TryGetValue(Player.UserIDString, out panels)) PlayerDockPanels.Add(Player.UserIDString, panels = new Dictionary()); panels.Add(DockName, DockPanel); return DockPanel; } private void LoadPanel(IPanel Dock, string PanelName, PanelConfig PCfg) { var Panel = Dock.AddPanel(PanelName); Panel.Width = PCfg.Width; Panel.Height = PCfg.Height; Panel.AnchorX = PCfg.AnchorX; Panel.AnchorY = PCfg.AnchorY; Panel.Margin = Vector4Parser(PCfg.Margin); Panel.BackgroundColor = ColorEx.Parse(PCfg.BackgroundColor); Panel.Order = PCfg.Order; Panel.Autoload = PCfg.Autoload; Panel.IsPanel = true; Panel.DockName = Dock.Name; Panel.FadeOut = Dock.FadeOut; if (PCfg.Text != null) { var Text = Panel.AddText(PanelName + "Text"); Text.Width = PCfg.Text.Width; Text.Height = PCfg.Text.Height; Text.Margin = Vector4Parser(PCfg.Text.Margin); Text.Content = PCfg.Text.Content; Text.FontColor = ColorEx.Parse(PCfg.Text.FontColor); Text.FontSize = PCfg.Text.FontSize; Text.Align = PCfg.Text.Align; Text.Order = PCfg.Text.Order; Text.FadeOut = PCfg.Text.FadeOut; Text.TextComponent.FadeIn = PCfg.Text.FadeIn; } if (PCfg.Image != null) { var Image = Panel.AddImage(PanelName + "Image"); Image.Width = PCfg.Image.Width; Image.Height = PCfg.Image.Height; Image.Margin = Vector4Parser(PCfg.Image.Margin); Image.Url = PCfg.Image.Url; Image.Order = PCfg.Image.Order; if (PCfg.Image.Color != null) Image.Color = ColorEx.Parse(PCfg.Image.Color); } } #endregion #region Clock private Watch Clock; private int ClockUpdateFrequency = 4; private Timer TimeUpdater; public class Watch { string ClockFormat = "HH:mm"; public int RefresRate = 4; public bool Available = true; TOD_Sky Sky = TOD_Sky.Instance; public Watch(int RefreshRate, bool Available) { RefresRate = RefreshRate; this.Available = Available; } public string GetServerTime(string PlayerID, StoredData storedData) { return DateTime.Now.AddHours(storedData.GetPlayerPanelSettings(PlayerID, "Clock", "Offset", 0)) .ToString(storedData.GetPlayerPanelSettings(PlayerID, "Clock", "TimeFormat", ClockFormat), CultureInfo.InvariantCulture); } public string GetSkyTime(string PlayerID, StoredData storedData) { return Sky.Cycle.DateTime.ToString( storedData.GetPlayerPanelSettings(PlayerID, "Clock", "TimeFormat", ClockFormat), CultureInfo.InvariantCulture); } public string ShowTime(string PlayerID, StoredData storedData) { if (storedData.GetPlayerPanelSettings(PlayerID, "Clock", "Type", "Game") == "Server") return GetServerTime(PlayerID, storedData); return GetSkyTime(PlayerID, storedData); } public void Refresh(StoredData storedData, Dictionary> panels) { if (!Settings.CheckPanelAvailability("Clock")) return; foreach (var panel in panels) { IPanel iPanel; if (!panel.Value.TryGetValue("ClockText", out iPanel)) continue; var showTime = ShowTime(panel.Key, storedData); var panelText = (IPanelText)iPanel; if (!showTime.Equals(panelText.Content)) { panelText.Content = showTime; panelText.Refresh(); } } } } #endregion #region MessageBox private Messenger MessageBox; private Timer MsgUpdater; private int MessageUpdateFrequency = 20; private List Messages = new List {"Welcome!", "Beware! You Are Not Alone!", "Leeeeeeeeeeeroy Jenkins"}; private bool MessageBoxAvailable = true; public class Messenger { List Messages; public int RefreshRate = 20; private int Counter = 0; private string MsgOrder = "normal"; public Messenger(List msgs, int RefreshRate, string MsgOrder) { Messages = msgs; this.RefreshRate = RefreshRate; this.MsgOrder = MsgOrder; if (MsgOrder == "random") { Counter = Core.Random.Range(0, Messages.Count - 1); } } public string GetMessage() { return Messages[Counter]; } private void RefreshCounter() { if (MsgOrder == "random") { var OldCounter = Counter; var NewCounter = Core.Random.Range(0, Messages.Count - 1); if (OldCounter == NewCounter) { if (NewCounter + 1 <= Messages.Count - 1) { Counter = NewCounter + 1; return; } else if (NewCounter - 1 >= 0) { Counter = NewCounter - 1; return; } } Counter = NewCounter; return; } Counter++; if (Counter >= Messages.Count) Counter = 0; } public void Refresh(StoredData storedData, Dictionary> panels) { if (!Settings.CheckPanelAvailability("MessageBox")) return; foreach (var panel in panels) { IPanel iPanel; if (!panel.Value.TryGetValue("MessageBoxText", out iPanel)) continue; var message = GetMessage(); var panelText = (IPanelText)iPanel; if (!message.Equals(panelText.Content)) { panelText.Content = message; panelText.Refresh(); } } RefreshCounter(); } } #endregion #region Events private Timer HeliAttack; private Timer RadiationUpdater; private AirplaneEvent Airplane; private List ActivePlanes; private bool AirplaneTimer = false; private HelicopterEvent Helicopter; private List ActiveHelicopters; private bool HelicopterTimer = false; private CargoshipEvent Cargoship; private List ActiveCargoships; private bool CargoshipTimer = false; private ChinookEvent Chinook; private List ActiveChinooks; private bool ChinookTimer = false; private Radiation Rad; private BaseHelicopter ActiveHelicopter; private CH47Helicopter ActiveChinook; private CargoShip ActiveCargoship; private BradleyEvent Bradley; private List ActiveBradleys; private bool BradleyTimer = false; public class AirplaneEvent { public bool isActive = false; public Color ImageColor; public AirplaneEvent() { ImageColor = ColorEx.Parse(Settings.GetPanelSettingsValue("AirdropEvent", "InactiveColor", "1 1 1 0.1")); } public void SetActivity(bool active) { isActive = active; if (isActive) { ImageColor = ColorEx.Parse(Settings.GetPanelSettingsValue("AirdropEvent", "ActiveColor", "0 1 0 1")); return; } ImageColor = ColorEx.Parse(Settings.GetPanelSettingsValue("AirdropEvent", "InactiveColor", "1 1 1 0.1")); return; } public void Refresh(StoredData storedData, Dictionary> panels) { if (!Settings.CheckPanelAvailability("AirdropEvent")) return; foreach (var panel in panels) { IPanel iPanel; if (!panel.Value.TryGetValue("AirdropEventImage", out iPanel)) continue; var panelRawImage = (IPanelRawImage)iPanel; if (panelRawImage.Color != ImageColor) { panelRawImage.Color = ImageColor; panelRawImage.Refresh(); } } } } public class HelicopterEvent { public bool isActive = false; public Color ImageColor; public HelicopterEvent() { ImageColor = ColorEx.Parse(Settings.GetPanelSettingsValue("HelicopterEvent", "InactiveColor", "1 1 1 0.1")); } public void SetActivity(bool active) { isActive = active; if (isActive) { ImageColor = ColorEx.Parse(Settings.GetPanelSettingsValue("HelicopterEvent", "ActiveColor", "1 0 0 1")); return; } ImageColor = ColorEx.Parse(Settings.GetPanelSettingsValue("HelicopterEvent", "InactiveColor", "1 1 1 0.1")); } public void Refresh(StoredData storedData, Dictionary> panels) { if (!Settings.CheckPanelAvailability("HelicopterEvent")) return; foreach (var panel in panels) { IPanel iPanel; if (!panel.Value.TryGetValue("HelicopterEventImage", out iPanel)) continue; var panelRawImage = (IPanelRawImage)iPanel; if (panelRawImage.Color != ImageColor) { panelRawImage.Color = ImageColor; panelRawImage.Refresh(); } } } } public class CargoshipEvent { public bool isActive = false; public Color ImageColor; public CargoshipEvent() { ImageColor = ColorEx.Parse(Settings.GetPanelSettingsValue("CargoShipEvent", "InactiveColor", "1 1 1 0.1")); } public void SetActivity(bool active) { isActive = active; if (isActive) { ImageColor = ColorEx.Parse(Settings.GetPanelSettingsValue("CargoShipEvent", "ActiveColor", "1 0 0 1")); return; } ImageColor = ColorEx.Parse(Settings.GetPanelSettingsValue("CargoShipEvent", "InactiveColor", "1 1 1 0.1")); } public void Refresh(StoredData storedData, Dictionary> panels) { if (!Settings.CheckPanelAvailability("CargoShipEvent")) return; foreach (var panel in panels) { IPanel iPanel; if (!panel.Value.TryGetValue("CargoShipEventImage", out iPanel)) continue; var panelRawImage = (IPanelRawImage)iPanel; if (panelRawImage.Color != ImageColor) { panelRawImage.Color = ImageColor; panelRawImage.Refresh(); } } } } public class ChinookEvent { public bool isActive = false; public Color ImageColor; public ChinookEvent() { ImageColor = ColorEx.Parse(Settings.GetPanelSettingsValue("ChinookEvent", "InactiveColor", "1 1 1 0.1")); } public void SetActivity(bool active) { isActive = active; if (isActive) { ImageColor = ColorEx.Parse(Settings.GetPanelSettingsValue("ChinookEvent", "ActiveColor", "1 0 0 1")); return; } ImageColor = ColorEx.Parse(Settings.GetPanelSettingsValue("ChinookEvent", "InactiveColor", "1 1 1 0.1")); } public void Refresh(StoredData storedData, Dictionary> panels) { if (!Settings.CheckPanelAvailability("ChinookEvent")) return; foreach (var panel in panels) { IPanel iPanel; if (!panel.Value.TryGetValue("ChinookEventImage", out iPanel)) continue; var panelRawImage = (IPanelRawImage)iPanel; if (panelRawImage.Color != ImageColor) { panelRawImage.Color = ImageColor; panelRawImage.Refresh(); } } } } public class Radiation { bool isActive = false; public Color ImageColor; public int RefreshRate = 3; public Radiation(int RefreshRate) { isActive = ConVar.Server.radiation; this.RefreshRate = RefreshRate; if (isActive) { ImageColor = ColorEx.Parse(Settings.GetPanelSettingsValue("Radiation", "ActiveColor", "1 1 0 1")); } else { ImageColor = ColorEx.Parse(Settings.GetPanelSettingsValue("Radiation", "InactiveColor", "1 1 1 0.1")); } } public void SetActivity(bool active) { isActive = active; if (isActive) { ImageColor = ColorEx.Parse(Settings.GetPanelSettingsValue("Radiation", "ActiveColor", "1 0 0 1")); return; } ImageColor = ColorEx.Parse(Settings.GetPanelSettingsValue("Radiation", "InactiveColor", "1 1 1 0.1")); } public void Refresh(StoredData storedData, Dictionary> panels) { if (isActive == ConVar.Server.radiation) return; SetActivity(ConVar.Server.radiation); if (!Settings.CheckPanelAvailability("Radiation")) return; foreach (var panel in panels) { IPanel iPanel; if (!panel.Value.TryGetValue("RadiationImage", out iPanel)) continue; var panelRawImage = (IPanelRawImage)iPanel; if (panelRawImage.Color != ImageColor) { panelRawImage.Color = ImageColor; panelRawImage.Refresh(); } } } } public class BradleyEvent { public bool isActive = false; public Color ImageColor; public BradleyEvent() { ImageColor = ColorEx.Parse(Settings.GetPanelSettingsValue("BradleyEvent", "InactiveColor", "1 1 1 0.1")); } public void SetActivity(bool active) { isActive = active; if (isActive) { ImageColor = ColorEx.Parse(Settings.GetPanelSettingsValue("BradleyEvent", "ActiveColor", "0.7 0.2 0.2 1")); return; } ImageColor = ColorEx.Parse(Settings.GetPanelSettingsValue("BradleyEvent", "InactiveColor", "1 1 1 0.1")); } public void Refresh(StoredData storedData, Dictionary> panels) { if (!Settings.CheckPanelAvailability("BradleyEvent")) return; foreach (var panel in panels) { IPanel iPanel; if (!panel.Value.TryGetValue("BradleyEventImage", out iPanel)) continue; var panelRawImage = (IPanelRawImage)iPanel; if (panelRawImage.Color != ImageColor) { panelRawImage.Color = ImageColor; panelRawImage.Refresh(); } } } } public void CheckAirplane() { ActivePlanes.RemoveAll(p => !p.IsValid() || !p.gameObject.activeInHierarchy); if (ActivePlanes.Count > 0) { if (Airplane.isActive == false) { Airplane.SetActivity(true); Airplane.Refresh(storedData, PlayerPanels); } AirplaneTimer = true; timer.In(10, CheckAirplane); return; } Airplane.SetActivity(false); Airplane.Refresh(storedData, PlayerPanels); AirplaneTimer = false; } public void CheckHelicopter() { ActiveHelicopters.RemoveAll(p => !p.IsValid() || !p.gameObject.activeInHierarchy); if (ActiveHelicopters.Count > 0) { if (Helicopter.isActive == false) { Helicopter.SetActivity(true); Helicopter.Refresh(storedData, PlayerPanels); } HelicopterTimer = true; timer.In(5, CheckHelicopter); return; } Helicopter.SetActivity(false); Helicopter.Refresh(storedData, PlayerPanels); HelicopterTimer = false; } public void CheckCargoship() { ActiveCargoships.RemoveAll(p => !p.IsValid() || !p.gameObject.activeInHierarchy); if (ActiveCargoships.Count > 0) { if (Cargoship.isActive == false) { Cargoship.SetActivity(true); Cargoship.Refresh(storedData, PlayerPanels); } CargoshipTimer = true; timer.In(5, CheckCargoship); return; } Cargoship.SetActivity(false); Cargoship.Refresh(storedData, PlayerPanels); CargoshipTimer = false; } public void CheckBradley() { ActiveBradleys.RemoveAll(p => !p.IsValid() || !p.gameObject.activeInHierarchy); if (ActiveBradleys.Count > 0) { if (Bradley.isActive == false) { Bradley.SetActivity(true); Bradley.Refresh(storedData, PlayerPanels); } BradleyTimer = true; timer.In(5, CheckBradley); return; } Bradley.SetActivity(false); Bradley.Refresh(storedData, PlayerPanels); BradleyTimer = false; } public void CheckChinook() { ActiveChinooks.RemoveAll(p => !p.IsValid() || !p.gameObject.activeInHierarchy); if (ActiveChinooks.Count > 0) { if (Chinook.isActive == false) { Chinook.SetActivity(true); Chinook.Refresh(storedData, PlayerPanels); } ChinookTimer = true; timer.In(5, CheckChinook); return; } Chinook.SetActivity(false); Chinook.Refresh(storedData, PlayerPanels); ChinookTimer = false; } #endregion #region Balance private Balance Bala; private Timer BalanceUpdater; public class Balance { public int RefreshRate = 3; public Balance(int RefreshRate) { this.RefreshRate = RefreshRate; } public double GetBalance(string PlayerID) { var player = RustCore.FindPlayerByIdString(PlayerID); if (player == null) return 0.0; return Convert.ToDouble(Interface.Oxide.CallHook("Balance", player.UserIDString) ?? 0.0); } public void Refresh(StoredData storedData, Dictionary> panels) { if (!Settings.CheckPanelAvailability("Balance")) return; foreach (var panel in panels) { IPanel iPanel; if (!panel.Value.TryGetValue("BalanceText", out iPanel)) continue; var balance = $"{GetBalance(panel.Key):N}"; var panelText = (IPanelText)iPanel; if (!balance.Equals(panelText.Content)) { panelText.Content = balance; panelText.Refresh(); } } } } #endregion #region Points private Points Poi; private Timer PointsUpdater; public class Points { public int RefreshRate = 3; public Points(int RefreshRate) { this.RefreshRate = RefreshRate; } public int GetPoints(string PlayerID) { var player = RustCore.FindPlayerByIdString(PlayerID); if (player == null) return 0; return (int)(Interface.Oxide.CallHook("CheckPoints", player.userID) ?? 0); } public void Refresh(StoredData storedData, Dictionary> panels) { if (!Settings.CheckPanelAvailability("Points")) return; foreach (var panel in panels) { IPanel iPanel; if (!panel.Value.TryGetValue("PointsText", out iPanel)) continue; var points = $"{GetPoints(panel.Key)}"; var panelText = (IPanelText)iPanel; if (!points.Equals(panelText.Content)) { panelText.Content = points; panelText.Refresh(); } } } } #endregion #region Coordinates private Coordinates Coord; private Timer CoordUpdater; public class Coordinates { public int RefreshRate = 3; public Coordinates(int RefreshRate) { this.RefreshRate = RefreshRate; } public string GetCoord(string PlayerID) { var player = RustCore.FindPlayerByIdString(PlayerID); var type = Settings.CoordType; if (player == null) return string.Empty; switch (type) { case 0: return $"X: {player.transform.position.x.ToString("0")} | Z: {player.transform.position.z.ToString("0")}"; case 1: return FormatGridReference(player.ServerPosition); case 2: return $"X: {player.transform.position.x.ToString("0")} | Z: {player.transform.position.z.ToString("0")} | {FormatGridReference(player.ServerPosition)}"; default: return FormatGridReference(player.ServerPosition); } } public void Refresh(StoredData storedData, Dictionary> panels) { if (!Settings.CheckPanelAvailability("Coordinates")) return; foreach (var panel in panels) { IPanel iPanel; if (!panel.Value.TryGetValue("CoordinatesText", out iPanel)) continue; var coord = GetCoord(panel.Key); var panelText = (IPanelText)iPanel; if (!coord.Equals(panelText.Content)) { panelText.Content = coord; panelText.Refresh(); } } } } #endregion #region Compass private Compass CompassObj; private Timer CompassUpdater; public class Compass { public int RefreshRate = 3; public Compass(int RefreshRate) { this.RefreshRate = RefreshRate; } public string GetDirection(string PlayerID) { var player = RustCore.FindPlayerByIdString(PlayerID); if (player == null) return string.Empty; var PCurrent = player.eyes.rotation.eulerAngles; string str = $"{PCurrent.y.ToString("0")}\u00B0"; if (Settings.GetPanelSettingsValue("Compass", "TextOrAngle", "text") == "text") { if (PCurrent.y > 337.5 || PCurrent.y < 22.5) str = Settings.CompassDirections["n"]; else if (PCurrent.y > 22.5 && PCurrent.y < 67.5) str = Settings.CompassDirections["ne"]; else if (PCurrent.y > 67.5 && PCurrent.y < 112.5) str = Settings.CompassDirections["e"]; else if (PCurrent.y > 112.5 && PCurrent.y < 157.5) str = Settings.CompassDirections["se"]; else if (PCurrent.y > 157.5 && PCurrent.y < 202.5) str = Settings.CompassDirections["s"]; else if (PCurrent.y > 202.5 && PCurrent.y < 247.5) str = Settings.CompassDirections["sw"]; else if (PCurrent.y > 247.5 && PCurrent.y < 292.5) str = Settings.CompassDirections["w"]; else if (PCurrent.y > 292.5 && PCurrent.y < 337.5) str = Settings.CompassDirections["nw"]; } return str; } public void Refresh(StoredData storedData, Dictionary> panels) { if (!Settings.CheckPanelAvailability("Compass")) { return; } foreach (var panel in panels) { if (panel.Value.ContainsKey("CompassText")) { var direction = GetDirection(panel.Key); var panelText = (IPanelText)panel.Value["CompassText"]; if (!direction.Equals(panelText.Content)) { panelText.Content = direction; panelText.Refresh(); } } } } } #endregion #region Commands [ChatCommand("ipanel")] private void IPanelCommand(BasePlayer player, string command, string[] args) { if (args.Length == 0) { var Str = "InfoPanel Available Commands:\n"; Str += "/ipanel - Chat Command list \n"; Str += "/ipanel - To hide or show the panel. \n"; Str += "/ipanel clock game - Change to game time. \n"; Str += "/ipanel clock server - Change to server time.\n Offset: Add hours to the clock. (-23 - 23) \n"; Str += "/ipanel timeformat - To change time format. \n"; PrintToChat(player, Str); return; } switch (args[0]) { case "hide": if (!storedData.GetPlayerSettings(player.UserIDString, "enable", true)) { break; } ChangePlayerSettings(player, "enable", "false"); DestroyGUI(player); break; case "show": if (storedData.GetPlayerSettings(player.UserIDString, "enable", true)) { break; } ChangePlayerSettings(player, "enable", "true"); RevealGUI(player); break; case "clock": if (args[1] == "server") { ChangePlayerPanelSettings(player, "Clock", "Type", "Server"); if (args.Length == 3) { var offset = 0; if (int.TryParse(args[2], out offset) && offset > -23 && offset < 23) { ChangePlayerPanelSettings(player, "Clock", "Offset", offset.ToString()); } } } else if (args[1] == "game") { ChangePlayerPanelSettings(player, "Clock", "Type", "Game"); } break; case "timeformat": if (args.Length == 1) { var Str = "Available Time Formats:\n"; for (var index = 0; index < Settings.TimeFormats.Count; index++) { Str += $"[{index}] - {DateTime.Now.ToString(Settings.TimeFormats[index])}\n"; } PrintToChat(player, Str + "Usage: /ipanel timeformat NUMBER "); } else if (args.Length == 2) { var TimeFormat = 0; if (int.TryParse(args[1], out TimeFormat) && TimeFormat >= 0 && TimeFormat < Settings.TimeFormats.Count) { ChangePlayerPanelSettings(player, "Clock", "TimeFormat", TimeFormats[TimeFormat]); } } break; default: PrintToChat(player, "Wrong Command!"); break; } ; } [ChatCommand("iptest")] private void IPaCommand(BasePlayer player, string command, string[] args) { } [ChatCommand("iperr")] private void IPCommand(BasePlayer player, string command, string[] args) { /* foreach (string item in Err) { Puts(item); }*/ /*foreach (KeyValuePair> item in PlayerDockPanels) { foreach (KeyValuePair itemm in item.Value) { Puts(itemm.Key); } }*/ /* foreach (KeyValuePair item in ErrB.OrderBy(k => k.Key)) { Puts(item.Key + " - " + item.Value); }*/ /* foreach (KeyValuePair> item in ErrA) { Puts(item.Key + " -> "); foreach (string itemm in item.Value) { Puts(itemm); } Puts("--------"); }*/ Err.Clear(); ErrA.Clear(); ErrB.Clear(); } #endregion #region StoredData public static StoredData storedData; public class StoredData { public Dictionary Players; public StoredData() { Players = new Dictionary(); } public bool CheckPlayerData(BasePlayer Player) { return Players.ContainsKey(Player.UserIDString); } public T GetPlayerSettings(string PlayerID, string Key, T DefaultValue) { PlayerSettings playerSettings; if (Players.TryGetValue(PlayerID, out playerSettings)) return playerSettings.GetSetting(Key, DefaultValue); return DefaultValue; } public T GetPlayerPanelSettings(BasePlayer Player, string Panel, string Key, T DefaultValue) { PlayerSettings playerSettings; if (Players.TryGetValue(Player.UserIDString, out playerSettings)) return playerSettings.GetPanelSetting(Panel, Key, DefaultValue); return DefaultValue; } public T GetPlayerPanelSettings(string PlayerID, string Panel, string Key, T DefaultValue) { PlayerSettings playerSettings; if (Players.TryGetValue(PlayerID, out playerSettings)) return playerSettings.GetPanelSetting(Panel, Key, DefaultValue); return DefaultValue; } } public class PlayerSettings { public string UserId; public Dictionary Settings; public Dictionary> PanelSettings; public PlayerSettings() { Settings = new Dictionary(); PanelSettings = new Dictionary>(); } public PlayerSettings(BasePlayer player) { UserId = player.UserIDString; Settings = new Dictionary(); PanelSettings = new Dictionary>(); } public void SetSetting(string Key, string Value) { Settings[Key] = Value; } public void SetPanelSetting(string Panel, string Key, string Value) { Dictionary settings; if (!PanelSettings.TryGetValue(Panel, out settings)) PanelSettings.Add(Panel, settings = new Dictionary()); settings[Key] = Value; } public T GetPanelSetting(string Panel, string Key, T DefaultValue) { Dictionary PanelConfig; if (!PanelSettings.TryGetValue(Panel, out PanelConfig)) return DefaultValue; string value; if (!PanelConfig.TryGetValue(Key, out value)) return DefaultValue; if (value == null) return DefaultValue; return (T)Convert.ChangeType(value, typeof(T)); } public T GetSetting(string Key, T DefaultValue) { string value; if (!Settings.TryGetValue(Key, out value)) return DefaultValue; if (value == null) return DefaultValue; return (T)Convert.ChangeType(value, typeof(T)); } } public void LoadData() { storedData = Interface.Oxide.DataFileSystem.ReadObject("InfoPanel_db"); if (storedData == null) { storedData = new StoredData(); SaveData(); } } public void SaveData() { Interface.Oxide.DataFileSystem.WriteObject("InfoPanel_db", storedData); } public void ChangePlayerSettings(BasePlayer player, string Key, string Value) { PlayerSettings playerSettings; if (!storedData.Players.TryGetValue(player.UserIDString, out playerSettings)) storedData.Players[player.UserIDString] = playerSettings = new PlayerSettings(player); playerSettings.SetSetting(Key, Value); } public void ChangePlayerPanelSettings(BasePlayer player, string Panel, string Key, string Value) { PlayerSettings playerSettings; if (!storedData.Players.TryGetValue(player.UserIDString, out playerSettings)) storedData.Players[player.UserIDString] = playerSettings = new PlayerSettings(player); playerSettings.SetPanelSetting(Panel, Key, Value); } #endregion public List Err = new List(); public Dictionary> ErrA = new Dictionary>(); public Dictionary ErrB = new Dictionary(); public Dictionary ErrD = new Dictionary(); #region IPanelClass [JsonObject(MemberSerialization.OptIn)] public class IPanel { #region Class Variables [JsonProperty("name")] public string Name { get; set; } [JsonProperty("parent")] public string ParentName { get; set; } = "Hud"; [JsonProperty("components")] public List Components = new List(); [JsonProperty("fadeOut")] public float FadeOut { get; set; } //Left-Right public Vector2 HorizontalPosition { get; set; } = new Vector2(0f, 1f); //Bottom-Top public Vector2 VerticalPosition { get; set; } = new Vector2(0f, 1f); public string AnchorX { get; set; } = "Left"; public string AnchorY { get; set; } = "Bottom"; public Vector4 Padding = Vector4.zero; public Vector4 Margin { get; set; } = Vector4.zero; public float Width { get; set; } = 1f; public float Height { get; set; } = 1f; public Color _BGColor = Color.black; public Color BackgroundColor { get { return _BGColor; } set { _BGColor = value; if (ImageComponent == null) { ImageComponent = new CuiImageComponent(); Components.Insert(0, ImageComponent); } ImageComponent.Color = $"{value.r} {value.g} {value.b} {value.a}"; } } public int Order = 0; public float _VerticalOffset = 0f; public float VerticalOffset { get { return _VerticalOffset; } set { _VerticalOffset = value; SetVerticalPosition(); } } //public Dictionary Childs = new Dictionary(); public List Childs = new List(); //Components public CuiRectTransformComponent RecTransform; public CuiImageComponent ImageComponent; //public bool ChildsChanged = false; BasePlayer Owner = null; public string DockName = null; public bool IsActive = false; public bool IsHidden = false; public bool IsPanel = false; public bool IsDock = false; public bool Autoload = true; private Dictionary> playerPanels; private Dictionary> playerDockPanels; #endregion public IPanel(string name, BasePlayer Player, Dictionary> playerPanels, Dictionary> playerDockPanels) { Name = name; Owner = Player; this.playerPanels = playerPanels; this.playerDockPanels = playerDockPanels; //LoadedPanels.Add(this._Name, this); Dictionary playerPanel; if (!playerPanels.TryGetValue(Player.UserIDString, out playerPanel)) playerPanels.Add(Player.UserIDString, playerPanel = new Dictionary()); playerPanel.Add(name, this); RecTransform = new CuiRectTransformComponent(); Components.Add(RecTransform); } public void SetAnchorXY(string Horizontal, string Vertical) { AnchorX = Horizontal; AnchorY = Vertical; } #region Positioning //x,y,z,w public void SetHorizontalPosition() { float Left; float Right; var Offset = GetOffset(); if (AnchorX == "Right") { Right = 1f - Margin.w; Left = Right - Width; HorizontalPosition = new Vector2(Left, Right) - new Vector2(Offset, Offset); } else { Left = 0f + Margin.y; Right = Left + Width; HorizontalPosition = new Vector2(Left, Right) + new Vector2(Offset, Offset); } RecTransform.AnchorMin = $"{HorizontalPosition.x} {VerticalPosition.x}"; RecTransform.AnchorMax = $"{HorizontalPosition.y} {VerticalPosition.y}"; } public void SetVerticalPosition() { float Top; float Bottom; if (AnchorY == "Top") { Top = 1f - Margin.x; Bottom = Top - Height; VerticalPosition = new Vector2(Bottom, Top) + new Vector2(_VerticalOffset, _VerticalOffset); } else { Bottom = 0f + Margin.z; Top = Bottom + Height; VerticalPosition = new Vector2(Bottom, Top) + new Vector2(_VerticalOffset, _VerticalOffset); } RecTransform.AnchorMin = $"{HorizontalPosition.x} {VerticalPosition.x}"; RecTransform.AnchorMax = $"{HorizontalPosition.y} {VerticalPosition.y}"; } float FullWidth() { return Width + Margin.y + Margin.w; } float GetSiblingsFullWidth() { return 1f; } #endregion #region Json public string ToJson() { SetHorizontalPosition(); SetVerticalPosition(); return JsonConvert.SerializeObject( this, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore } ); } public float GetOffset() { var Offset = 0f; var Parent = GetPanel(ParentName); if (Parent == null) return Offset; var Siblings = Parent.GetChilds() .Where(c => c.Value.AnchorX == AnchorX && c.Value.Order <= Order && c.Value.IsActive && c.Value.Name != Name).Select(c => c.Value).OrderBy(s => s.Order); foreach (var Sibling in Siblings) Offset += Sibling.Width + Sibling.Margin.y + Sibling.Margin.w; return Offset; } public string GetJson(bool Brackets = true) { var Panel = ToJson(); return Brackets ? $"[{Panel}]" : Panel; } #endregion #region Childs public int GetLastChild() { if (Childs.Count == 0) { return 0; } else { return GetChilds().Max(p => p.Value.Order); } } public IPanelText AddText(string Name) { var Text = new IPanelText(Name, Owner, playerPanels, playerDockPanels) { ParentName = this.Name }; Childs.Add(Name); return Text; } public IPanelRawImage AddImage(string Name) { var Image = new IPanelRawImage(Name, Owner, playerPanels, playerDockPanels) { ParentName = this.Name }; Childs.Add(Name); return Image; } public IPanel AddPanel(string Name) { var Panel = new IPanel(Name, Owner, playerPanels, playerDockPanels) { ParentName = this.Name }; Childs.Add(Name); return Panel; } #endregion #region Selectors List GetActiveAfterThis() { var Panels = playerPanels[Owner.UserIDString] .Where(p => p.Value.IsActive && p.Value.Order > Order && p.Value.ParentName == ParentName && p.Value.AnchorX == AnchorX) .OrderBy(s => s.Value.Order) .Select(k => k.Key) .ToList(); return Panels; } public Dictionary GetChilds() { return playerPanels[Owner.UserIDString].Where(x => Childs.Contains(x.Key)) .ToDictionary(se => se.Key, se => se.Value); } public IPanel GetParent() { return GetPanel(ParentName); } public List GetSiblings() { return GetPanel(ParentName)?.GetChilds().Where(c => c.Value.AnchorX == AnchorX && c.Value.Name != Name) .Select(c => c.Value).OrderBy(s => s.Order).ToList() ?? new List(); } public IPanel GetPanel(string PName) { Dictionary panels; IPanel panel; if (playerPanels.TryGetValue(Owner.UserIDString, out panels) && panels.TryGetValue(PName, out panel)) return panel; return null; } public IPanel GetDock() { if (DockName == null) return null; Dictionary panels; IPanel panel; if (playerDockPanels.TryGetValue(Owner.UserIDString, out panels) && panels.TryGetValue(DockName, out panel)) return panel; return null; } #endregion #region GUI public void Hide() { foreach (var Panel in GetChilds().Where(p => p.Value.IsActive)) Panel.Value.Hide(); CuiHelper.DestroyUi(Owner, Name); //CommunityEntity.ServerInstance.ClientRPCEx(new Network.SendInfo(this.Owner.net.connection), null, "DestroyUI", new Facepunch.ObjectList(this._Name)); } public void Reveal() { //Interface.Oxide.LogInfo(GetJson()); //TODO CuiHelper.AddUi(Owner, GetJson()); //CommunityEntity.ServerInstance.ClientRPCEx(new Network.SendInfo(this.Owner.net.connection), null, "AddUI", new Facepunch.ObjectList(GetJson())); IsActive = true; IsHidden = false; foreach (var Child in GetChilds().Where(p => p.Value.Autoload || p.Value.IsActive) .OrderBy(s => s.Value.Order)) Child.Value.Reveal(); } void ReDrawPanels(List PanelsName) { foreach (var PanelName in PanelsName) GetPanel(PanelName)?.DestroyPanel(false); foreach (var PanelName in PanelsName) GetPanel(PanelName)?.ShowPanel(); } public void ShowPanel(bool Childs = true) { if (storedData.GetPlayerSettings(Owner.UserIDString, "enable", true)) { var Dock = GetDock(); if (Dock != null && Dock.IsActive == false) Dock.ShowPanel(false); var ActivePanelsAfterThis = GetActiveAfterThis(); foreach (var PanelName in ActivePanelsAfterThis) GetPanel(PanelName)?.DestroyPanel(false); //ErrB.Add(this.Name + ErrB.Count,ActivePanelsAfterThis.Count); if (storedData.GetPlayerSettings(Owner.UserIDString, "enable", true)) { //Interface.Oxide.LogInfo(GetJson()); //TODO CuiHelper.AddUi(Owner, GetJson()); //CommunityEntity.ServerInstance.ClientRPCEx(new Network.SendInfo(this.Owner.net.connection), null, "AddUI", new Facepunch.ObjectList(GetJson())); } IsActive = true; IsHidden = false; if (Childs) { foreach (var Child in GetChilds().Where(p => p.Value.Autoload || p.Value.IsActive) .OrderBy(s => s.Value.Order)) Child.Value.ShowPanel(); } foreach (var PanelName in ActivePanelsAfterThis) GetPanel(PanelName)?.ShowPanel(); } else { ShowPanelIfHidden(); } } void ShowPanelIfHidden(bool Childs = true) { IsActive = true; IsHidden = true; if (Childs) { foreach (var Child in GetChilds().Where(p => p.Value.Autoload || p.Value.IsActive) .OrderBy(s => s.Value.Order)) Child.Value.ShowPanel(); } } public void DestroyPanel(bool Redraw = true) { foreach (var Panel in GetChilds().Where(p => p.Value.IsActive)) Panel.Value.DestroyPanel(false); CuiHelper.DestroyUi(Owner, Name); //CommunityEntity.ServerInstance.ClientRPCEx(new Network.SendInfo(this.Owner.net.connection), null, "DestroyUI", new Facepunch.ObjectList(this._Name)); IsActive = false; if (Redraw) ReDrawPanels(GetActiveAfterThis()); var Dock = GetDock(); if (Dock?.GetChilds().Count(p => p.Value.IsActive) == 0) Dock.DestroyPanel(); } public virtual void Refresh() { DestroyPanel(); ShowPanel(); } #endregion #region Util public void Remover() { foreach (var Child in GetChilds()) Child.Value.Remover(); GetPanel(ParentName).Childs.Remove(Name); playerPanels[Owner.UserIDString].Remove(Name); } protected string ColorToString(Color color) { return $"{color.r} {color.g} {color.b} {color.a}"; } #endregion } public class IPanelText : IPanel { public string Content { get { return TextComponent.Text; } set { TextComponent.Text = value; } } public TextAnchor Align { get { return TextComponent.Align; } set { TextComponent.Align = value; } } public int FontSize { get { return TextComponent.FontSize; } set { TextComponent.FontSize = value; } } public Color _FontColor = Color.white; public Color FontColor { get { return _FontColor; } set { _FontColor = value; TextComponent.Color = $"{value.r} {value.g} {value.b} {value.a}"; } } public CuiTextComponent TextComponent; public IPanelText(string Name, BasePlayer Player, Dictionary> playerPanels, Dictionary> playerDockPanels) : base(Name, Player, playerPanels, playerDockPanels) { TextComponent = new CuiTextComponent(); Components.Insert(0, TextComponent); } public void RefreshText(BasePlayer player, string text) { DestroyPanel(); Content = text; ShowPanel(); } } public class IPanelRawImage : IPanel { public string Url { get { return RawImageComponent.Url; } set { RawImageComponent.Url = value; } } public Color _Color; public Color Color { get { return _Color; } set { _Color = value; RawImageComponent.Color = ColorToString(value); } } public CuiRawImageComponent RawImageComponent; public IPanelRawImage(string Name, BasePlayer Player, Dictionary> playerPanels, Dictionary> playerDockPanels) : base(Name, Player, playerPanels, playerDockPanels) { RawImageComponent = new CuiRawImageComponent(); Components.Insert(0, RawImageComponent); } } #endregion #region GUI private void DestroyGUI(BasePlayer player) { foreach (var Dock in PlayerDockPanels[player.UserIDString]) { Dock.Value.DestroyPanel(false); } } void GUITimerInit(BasePlayer player) { if (player == null) return; if (player.HasPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot)) { timer.In(2, () => GUITimerInit(player)); } else if (!PlayerDockPanels.ContainsKey(player.UserIDString)) { LoadPanels(player); InitializeGUI(player); RefreshOnlinePlayers(); } } private void InitializeGUI(BasePlayer player) { if (!storedData.GetPlayerSettings(player.UserIDString, "enable", true)) return; foreach (var Panel in PlayerPanels[player.UserIDString]) { switch (Panel.Key) { case "ClockText": ((IPanelText)Panel.Value).Content = Clock.ShowTime(player.UserIDString, storedData); break; case "OPlayersText": ((IPanelText)Panel.Value).Content = BasePlayer.activePlayerList.Count + "/" + ConVar.Server.maxplayers; break; case "SleepersText": ((IPanelText)Panel.Value).Content = BasePlayer.sleepingPlayerList.Count.ToString(); break; case "MessageBoxText": ((IPanelText)Panel.Value).Content = MessageBox.GetMessage(); break; case "CoordinatesText": ((IPanelText)Panel.Value).Content = Coord.GetCoord(player.UserIDString); break; case "BalanceText": ((IPanelText)Panel.Value).Content = $"{Bala.GetBalance(player.UserIDString):N}"; break; case "RadiationImage": ((IPanelRawImage)Panel.Value).Color = Rad.ImageColor; break; case "AirdropEventImage": ((IPanelRawImage)Panel.Value).Color = Airplane.ImageColor; break; case "HelicopterEventImage": ((IPanelRawImage)Panel.Value).Color = Helicopter.ImageColor; break; case "ChinookEventImage": ((IPanelRawImage)Panel.Value).Color = Chinook.ImageColor; break; case "BradleyEventImage": ((IPanelRawImage)Panel.Value).Color = Bradley.ImageColor; break; case "CargoShipEventImage": ((IPanelRawImage)Panel.Value).Color = Cargoship.ImageColor; break; case "CompassText": ((IPanelText)Panel.Value).Content = CompassObj.GetDirection(player.UserIDString); break; } } foreach (var Dock in PlayerDockPanels[player.UserIDString]) { if (Dock.Value.Childs.Count != 0) Dock.Value.ShowPanel(); } } private void RevealGUI(BasePlayer player) { foreach (var Dock in PlayerDockPanels[player.UserIDString]) { if (Dock.Value.Childs.Count != 0) Dock.Value.ShowPanel(); } } private void RefreshOnlinePlayers() { foreach (var panel in PlayerPanels) { if (Settings.GetPanelSettingsValue("OPlayers", "Available", true) && panel.Value.ContainsKey("OPlayersText")) { var panelText = (IPanelText)panel.Value["OPlayersText"]; panelText.Content = $"{BasePlayer.activePlayerList.Count}/{ConVar.Server.maxplayers}"; panelText.Refresh(); } } } private void RefreshSleepers() { foreach (var panel in PlayerPanels) { if (Settings.GetPanelSettingsValue("Sleepers", "Available", true) && panel.Value.ContainsKey("SleepersText")) { var panelText = (IPanelText)panel.Value["SleepersText"]; panelText.Content = BasePlayer.sleepingPlayerList.Count.ToString(); panelText.Refresh(); } } } #endregion #region API private bool PanelRegister(string PluginName, string PanelName, string json) { List loadedPlugin; if (LoadedPluginPanels.TryGetValue(PluginName, out loadedPlugin) && loadedPlugin.Contains(PanelName)) return true; var Cfg = JsonConvert.DeserializeObject(json); Dictionary thirdPartyPanel; if (!Settings.ThirdPartyPanels.TryGetValue(PluginName, out thirdPartyPanel)) Settings.ThirdPartyPanels.Add(PluginName, thirdPartyPanel = new Dictionary()); if (!thirdPartyPanel.ContainsKey(PanelName)) { Cfg.Order = PanelReOrder(Cfg.Dock, Cfg.AnchorX); thirdPartyPanel.Add(PanelName, Cfg); Config.WriteObject(Settings, true); PrintWarning($"New panel added to the config file: {PanelName}"); } foreach (var Docks in PlayerDockPanels) { if (Docks.Value.ContainsKey(Cfg.Dock)) LoadPanel(Docks.Value[Cfg.Dock], PanelName, Cfg); } if (!LoadedPluginPanels.TryGetValue(PluginName, out loadedPlugin)) LoadedPluginPanels.Add(PluginName, loadedPlugin = new List()); loadedPlugin.Add(PanelName); return true; } private bool ShowPanel(string PluginName, string PanelName, string PlayerId = null) { if (!Settings.ThirdPartyPanels[PluginName][PanelName].Available) return false; if (PlayerId != null && PlayerPanels.ContainsKey(PlayerId)) { PlayerPanels[PlayerId][PanelName].ShowPanel(); return true; } foreach (var PlayerID in PlayerPanels.Keys) PlayerPanels[PlayerID][PanelName].ShowPanel(); return true; } private bool HidePanel(string PluginName, string PanelName, string PlayerId = null) { if (!Settings.ThirdPartyPanels[PluginName][PanelName].Available) return false; if (PlayerId != null && PlayerPanels.ContainsKey(PlayerId)) { PlayerPanels[PlayerId][PanelName].DestroyPanel(); return true; } foreach (var PlayerID in PlayerPanels.Keys) PlayerPanels[PlayerID][PanelName].DestroyPanel(); return true; } private bool RefreshPanel(string PluginName, string PanelName, string PlayerId = null) { if (!Settings.ThirdPartyPanels[PluginName][PanelName].Available) return false; if (PlayerId != null && PlayerPanels.ContainsKey(PlayerId)) { PlayerPanels[PlayerId][PanelName].DestroyPanel(); PlayerPanels[PlayerId][PanelName].ShowPanel(); return true; } foreach (var PlayerID in PlayerPanels.Keys) { PlayerPanels[PlayerID][PanelName].DestroyPanel(); PlayerPanels[PlayerID][PanelName].ShowPanel(); } return true; } private void SetPanelAttribute(string PluginName, string PanelName, string Attribute, string Value, string PlayerId = null) { if (PlayerId != null && PlayerPanels.ContainsKey(PlayerId)) { var Panel = PlayerPanels[PlayerId][PanelName]; var PropInfo = Panel.GetType().GetProperty(Attribute); if (PropInfo == null) { PrintWarning("Wrong Attribute name: " + Attribute); return; } if (Attribute == "FontColor" || Attribute == "BackgroundColor") { PropInfo.SetValue(Panel, ColorEx.Parse(Value), null); } else if (Attribute == "Margin") { PropInfo.SetValue(Panel, Vector4Parser(Value), null); } else { var ConvertedValue = Convert.ChangeType(Value, PropInfo.PropertyType); PropInfo.SetValue(Panel, ConvertedValue, null); } return; } foreach (var playerID in PlayerPanels.Keys) { var Panel = PlayerPanels[playerID][PanelName]; var PropInfo = Panel.GetType().GetProperty(Attribute); if (PropInfo == null) { PrintWarning("Wrong Attribute name: " + Attribute); return; } if (Attribute == "FontColor" || Attribute == "BackgroundColor") { PropInfo.SetValue(Panel, ColorEx.Parse(Value), null); } else if (Attribute == "Margin") { PropInfo.SetValue(Panel, Vector4Parser(Value), null); } else { var ConvertedValue = Convert.ChangeType(Value, PropInfo.PropertyType); PropInfo.SetValue(Panel, ConvertedValue, null); } } } private bool SendPanelInfo(string PluginName, List Panels) { Dictionary panelConfig; if (!Settings.ThirdPartyPanels.TryGetValue(PluginName, out panelConfig)) { return false; } var Removable = panelConfig.Keys.Except(Panels).ToList(); foreach (var item in Removable) { panelConfig.Remove(item); } if (Removable.Count > 0) { Config.WriteObject(Settings, true); PrintWarning($"Config File refreshed! {Removable.Count} panel removed!"); } return true; } private bool IsPlayerGUILoaded(string PlayerId) { return PlayerPanels.ContainsKey(PlayerId); } #endregion #region Utility internal static Vector4 Vector4Parser(string p) { var strArrays = p.Split(' '); if (strArrays.Length != 4) return Vector4.zero; return new Vector4(float.Parse(strArrays[0]), float.Parse(strArrays[1]), float.Parse(strArrays[2]), float.Parse(strArrays[3])); } public static string FormatGridReference(Vector3 position) { Vector2 roundedPos = new Vector2(World.Size / 2 + position.x, World.Size / 2 - position.z); string grid = $"{NumberToLetter((int)(roundedPos.x / 150))}:{(int)(roundedPos.y / 150)}"; return grid; } public static string NumberToLetter(int num) { int num2 = Mathf.FloorToInt(num / 26); int num3 = num % 26; string text = string.Empty; if (num2 > 0) { for (int i = 0; i < num2; i++) { text += Convert.ToChar(65 + i); } } return text + Convert.ToChar(65 + num3).ToString(); } #endregion } }