Иконка ресурса

FREE Crosshair : 1.0.0 1.0.0

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Oxide.Core;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using Oxide.Game.Rust.Cui;
using System.Text.RegularExpressions;
using UnityEngine;

/*	This plugin is originally based off of MisterPixie's Crosshair 3.1.0 and credit is given per the MIT License Agreement.*
 *	Drastic overhaul and rewrite have occurred to allow customization of the crosshair and storing toggle state per user.*
 *	Future plans:
 *		- create on-screen UI for managing customization.*		- make sure that all of the "using" inheritances above are needed.*		- Add support-for and use-of Carbon's CUI
 *		- Add an outline or dropshadow to the cursor (and make it customizable, too)
 *
 *	(c) 2024 TheAlchemist
 */
 
namespace Oxide.Plugins
{
    [Info("Crosshair", "TheAlchemist", "1.0.0")]
    [Description("Allows the user to toggle a crosshair.Also allows for minimal customization of the crosshair and if it loads automatically for each player.")]

    class Crosshair : RustPlugin
    {
		private bool DebugEnabled = true;

		#region Fields

        private const string _usePerm = "crosshair.use";

        private string mainUI = "UI_MAIN";
        private CuiElementContainer _ui;
       		
		private static string DetermineDataFilePath() => $"{nameof(Crosshair)}/";
		private static string PreferencesFilePath() => DetermineDataFilePath() + "/Preferences";
		private PreferenceData preferenceData;		
        private UserPreferences userPreferences;

		private HashSet<string> _playersWithCrosshairEnabled = new HashSet<string>();
		
		#endregion Fields
				
        #region Classes for UI
 
		private class UI
        {
            public static CuiElementContainer CreateElementContainer(string panelName, string color, string aMin, string aMax, bool cursor = false)
            {
                var newElement = new CuiElementContainer
                {
                    {
                        new CuiPanel
                        {
                            Image = {Color = color},
                            RectTransform = {AnchorMin = aMin, AnchorMax = aMax},
                            CursorEnabled = cursor
                        },
                        new CuiElement().Parent = "Hud",
                        panelName
                    }
                };

                return newElement;
            }

            public static void CreateLabel(ref CuiElementContainer container, string panel, string color, string text, int size, string aMin, string aMax, TextAnchor align = TextAnchor.MiddleCenter, float fadein = 1f)
            {
                container.Add(new CuiLabel
                {
                    Text = { Color = color, FontSize = size, Align = align, FadeIn = fadein, Text = text },
                    RectTransform = { AnchorMin = aMin, AnchorMax = aMax }
                }, panel, CuiHelper.GetGuid());
            }
        }
 
        #endregion Classes for UI

        #region Methods

        private void CreateUI()
        {			 
            var container = UI.CreateElementContainer(mainUI, $"{HexToColor("000000")} 0", "0.4692 0.4672", "0.5292 0.5272");
			UI.CreateLabel(ref container, mainUI, $"{HexToColor(configData.CrosshairColor)} 0.9", configData.CrosshairText, 25, "0 0", "1 1");            
			_ui = container;
        }
		
        private void CreateUI(BasePlayer player)
        {			
			if (player == null) return;
			
			DestroyCrosshair(player);
			_ui = null;
			
            var container = UI.CreateElementContainer(mainUI, $"{HexToColor("000000")} 0", "0.4692 0.4672", "0.5292 0.5272");
			
			string color = ( string.IsNullOrEmpty(GetUsersPreference(player, "color")) ) ? configData.CrosshairColor : GetUsersPreference(player, "color");
			string text = ( string.IsNullOrEmpty(GetUsersPreference(player, "text")) ) ? configData.CrosshairText : GetUsersPreference(player, "text");

			UI.CreateLabel(ref container, mainUI, $"{HexToColor(color)} 0.9", text, 25, "0 0", "1 1");            

			_ui = container;
			
			if( GetUsersPreference(player, "auto").ToLower() == "true" )
				CrosshairOn(player);
        }

		//
		// This toggle is based solely on whether or not the user currently exists in the HashSet _playersWithCrosshairEnabled that is in memory (not from a file)
		//
        private void ToggleCrosshair(BasePlayer player, string command, string[] args)
        {
            if (_playersWithCrosshairEnabled.Contains(player.UserIDString))
            {
				CrosshairOff(player);    
            } 
			else 
			{
				CrosshairOn(player);				
			}
        }
		
		private void CrosshairOn(BasePlayer player)
		{
			CrosshairOff(player); 									// just making sure we don't double up memory on the HashSet or the UI
            CuiHelper.AddUi(player, _ui); 							// displays whatever ui elements are currently saved in _ui
            _playersWithCrosshairEnabled.Add(player.UserIDString);
		}

		private void CrosshairOff(BasePlayer player)
		{
			DestroyCrosshair(player);
			_playersWithCrosshairEnabled.Remove(player.UserIDString);
		}

        private void DestroyCrosshair(BasePlayer player)
        {
			if (player == null) return;
            CuiHelper.DestroyUi(player, mainUI);
        }
						
        private void DetermineCrosshairPreference(BasePlayer player)
        {
            if (player == null || player.IsNpc || !player.IsAlive() || player.IsSleeping())
                return;

            if (!permission.UserHasPermission(player.UserIDString, _usePerm))
                return;

			if (GetUsersPreference(player, "auto").ToLower() == "true")
				CreateUI(player);
        }

        #endregion Methods

        #region Hooks
		
        private void Init()
        {
            permission.RegisterPermission("crosshair.use", this);

            LoadConfigVariables();			
			LoadPreferenceData();
		
            foreach (var player in BasePlayer.activePlayerList)
            {
				DetermineCrosshairPreference(player);
            }

			if (_ui == null)
				CreateUI();
        }

        private void Unload()
        {
            foreach (var player in BasePlayer.activePlayerList)
            {
                DestroyCrosshair(player);
				_playersWithCrosshairEnabled.Remove(player.UserIDString);
            }
        }

        private void OnPlayerDisconnected(BasePlayer player)
        {
			if (player.IsNpc) return;
			
            DestroyCrosshair(player);
        }
		
		private void OnPlayerConnected(BasePlayer player) => DetermineCrosshairPreference(player);
		private void OnPlayerRespawned(BasePlayer player) => DetermineCrosshairPreference(player);
        private void OnPlayerSleepEnded(BasePlayer player) => OnPlayerRespawned(player);
        private void OnPlayerSleep(BasePlayer player) => OnPlayerDisconnected(player);		
        private void OnEntityKill(BasePlayer player) => OnPlayerDisconnected(player);
        private void OnEntityDeath(BasePlayer player, HitInfo info) => OnPlayerDisconnected(player);
		
        #endregion Hooks

        #region Config
		
        private ConfigData configData;
        private class ConfigData
        {
			public string CrosshairEnabled;
            public string CrosshairColor;
            public string CrosshairText;
        }

        private void LoadConfigData() => configData = Config.ReadObject<ConfigData>();
        private void SaveConfig(ConfigData config) => Config.WriteObject(config, true);
        private void SaveConfig() => Config.WriteObject(configData, true);

        private void LoadConfigVariables()
        {
            LoadConfigData();
            SaveConfig();
        }

        protected override void LoadDefaultConfig()				// CrosshairText = "◎"
        {
            var config = new ConfigData
            {
				CrosshairEnabled = "true",
                CrosshairColor = "#FFFFFF",
                CrosshairText = "◎"
            };
            SaveConfig(config);
        }
		
        #endregion Config

        #region Config Data File - User Preferences

		//
		// Global fields are located in Fields region at top of program
		//
		 
		private class PreferenceData // the preference data of all players in the preference data file
		{
			public HashSet<PlayerInfo> Players = new HashSet<PlayerInfo>();
		}
	
        private class UserPreferences // an individual player's preferences
        {
			public bool CrosshairEnabled;
            public string CrosshairColor;
            public string CrosshairText;

			public UserPreferences()
			{
			}
        }

		private class PlayerInfo
		{
			public string Id;
			public string Name;
			public UserPreferences Preferences = new UserPreferences();
			
			public PlayerInfo()
			{
			}

			public PlayerInfo(BasePlayer player)
			{
				Id = player.UserIDString;
				Name = player.displayName;
				Preferences = this.Preferences;
			}

		}
		
		private string GetUsersPreference(BasePlayer player, string key)																// TO-DO:  should we just get the ones in memory, or re-read from the file?
		{
			string val = "";
			
			PlayerInfo playerPreferences = preferenceData.Players.Where(x => x.Id.Equals(player.UserIDString)).FirstOrDefault();
			
			if (playerPreferences != null)
			{
				switch (key)
				{
					case "auto":
						val = playerPreferences.Preferences.CrosshairEnabled.ToString();
						break;
					case "color":
						val = playerPreferences.Preferences.CrosshairColor;
						break;
					case "text":
						val = playerPreferences.Preferences.CrosshairText;
						break;
					default:
						break;
				}
			}
			
			return val;
		}
		
		private void SetUsersPreference(BasePlayer player, string key, string val)
		{
			PlayerInfo playerPreferences = preferenceData.Players.Where(x => x.Id.Equals(player.UserIDString)).FirstOrDefault();
			
			if (playerPreferences != null)
			{
				switch (key)
				{
					case "auto":
						playerPreferences.Preferences.CrosshairEnabled = bool.Parse(ProcessAutoValue(val, player));
						break;
					case "color":
						playerPreferences.Preferences.CrosshairColor = ProcessColorValue(val, player);
						break;
					case "text":
						playerPreferences.Preferences.CrosshairText = ProcessTextValue(val, player);
						break;
					case "default":
						playerPreferences.Preferences.CrosshairEnabled = bool.Parse(configData.CrosshairEnabled);
						playerPreferences.Preferences.CrosshairColor = configData.CrosshairColor;
						playerPreferences.Preferences.CrosshairText = configData.CrosshairText;
						break;
					default:
						break;
				}
			}


// TO-DO                                     Need to reload the file into memory after setting preferences?                        TO-DO						
			return;
		}
			
        private void LoadPreferenceData() => preferenceData = Interface.Oxide.DataFileSystem.ReadObject<PreferenceData>(PreferencesFilePath());
		
        #endregion Data File - User Preferences

		#region Commands

		[Command("crosshair")]
		private void CrosshairCommand(BasePlayer player, string command, string[] args)
		{
            if (!permission.UserHasPermission(player.UserIDString, _usePerm))
                return;
			
			if (args.Length == 0)
			{
				ToggleCrosshair(player, command, args);
				return;
			}
			
			string key = "";
			string valAuto = "";
			string valColor = "";
			string valText = "";
			
			bool refreshUI = false;

			if (args.Length == 1)
			{
				key = args[0].ToLower();
				
				if (key != "auto" && key != "color" && key != "text" && key != "default")
				{
					player.ChatMessage("'" + key + "' is not a valid command or configurable parameter for the Crosshair");
					return;
				}

				switch (key)
				{
					case "auto":
						player.ChatMessage("Current preference setting for Crosshair's auto-enable setting 'auto' is: " + GetUsersPreference(player, key));
						break;
					case "color":
						player.ChatMessage("Current preference setting for Crosshair's color is: " + GetUsersPreference(player, key));
						break;
					case "text":
						player.ChatMessage("Current preference setting for Crosshair's text is: " + GetUsersPreference(player, key));
						break;					
					case "default":
						player.ChatMessage("Resetting the Crosshair to the server's default settings");
						SetUsersPreference(player, key, "");
						refreshUI = true;
						break;					
					default:
						break;
				}

				//return;
			}
			else
			{				
				key = args[0];
				string val = args[1].ToLower();
				
				switch (key)
				{
					case "auto":
						valAuto = ProcessAutoValue(val, player);
						if (valAuto == "") {
							player.ChatMessage("Invalid value for Crosshair's 'auto' setting");
							return;
						}
						break;
					case "color":
						valColor = ProcessColorValue(val, player);
						if (valColor == "") {
							player.ChatMessage("Invalid value for Crosshair's 'color' setting");
							return;
						}
						break;
					case "text":
						valText = ProcessTextValue(val, player);
						if (valText == "") {
							player.ChatMessage("Invalid value for Crosshair's 'text' setting");
							return;
						}
						break;
					default:
						player.ChatMessage("'" + key + "' is not a configurable parameter for the Crosshair");
						return;
						break;
				}
				
				refreshUI = true;
			}

			if (refreshUI)
			{
			
//			PlayerInfo playerInfo = new PlayerInfo(player);
				PlayerInfo playerInfo = new PlayerInfo(player);
				PlayerInfo playerPreferences = preferenceData.Players.Where(x => x.Id.Equals(playerInfo.Id)).FirstOrDefault();
				
				if (playerPreferences != null)
				{				
					player.ChatMessage("Updating your existing preferences...");
					
					playerInfo.Preferences.CrosshairEnabled = (valAuto == "") ? playerPreferences.Preferences.CrosshairEnabled : (valAuto == "true") ? true : false;
					playerInfo.Preferences.CrosshairColor = (valColor == "") ? playerPreferences.Preferences.CrosshairColor : valColor;
					playerInfo.Preferences.CrosshairText = (valText == "") ? playerPreferences.Preferences.CrosshairText : valText;

					preferenceData.Players.Remove(playerPreferences);
				}
				else
				{
					player.ChatMessage("Saving your Crosshair preference to the data file...");
					
					playerInfo.Preferences.CrosshairEnabled = (valAuto == "") ? bool.Parse(configData.CrosshairEnabled) : (valAuto == "true") ? true : false;
					playerInfo.Preferences.CrosshairColor = (valColor == "") ? configData.CrosshairColor: valColor;
					playerInfo.Preferences.CrosshairText = (valText == "") ? configData.CrosshairText : valText;	
				}

				preferenceData.Players.Add(playerInfo);
				Interface.Oxide.DataFileSystem.WriteObject(PreferencesFilePath(), preferenceData);
				
				if (playerInfo.Preferences.CrosshairEnabled || _playersWithCrosshairEnabled.Contains(player.UserIDString) )
				{
					CreateUI(player);
					CrosshairOn(player);
				}
				
				if (!playerInfo.Preferences.CrosshairEnabled && _playersWithCrosshairEnabled.Contains(player.UserIDString) )
				{
					CrosshairOff(player);
				}
			}
		}		
		
		#endregion Commands

		#region Helpers
		
		private string ProcessAutoValue(string val, BasePlayer player)
		{
			string vval = "";
			
			switch (val)
			{
				case "true":
				case "1":
				case "on":
				case "enable":
				case "enabled":
					vval = "true";
					break;
				case "false":
				case "0":
				case "off":
				case "disable":
				case "disabled":
					vval = "false";
					break;
				case "default":
				default:
					player.ChatMessage("'" + val + "' is not a valid value for the 'auto' setting.Resetting to server default value: " + configData.CrosshairEnabled);			
					vval = configData.CrosshairEnabled;
					break;
				
			}
			
			return vval;
		}

		private string ProcessColorValue(string val, BasePlayer player)
		{
			string vval = "";
			
			if (IsValidHexaCode(val) || IsValidHexaCode("#" + val))
			{
				if (val.Length == 6) val = "#" + val;
				vval = val;
			}
			else
			{			
				switch (val)
				{
					case "red":
						vval = "#FF0000";
						break;
					case "green":
						vval = "#00FF00";
						break;
					case "blue":
						vval = "#0000FF";
						break;
					case "white":
						vval = "#FFFFFF";
						break;
					case "black":
						vval = "#000000";
						break;
					case "gray":
					case "grey":
						vval = "#888888";
						break;
					case "default":
					default:
						player.ChatMessage("'" + val + "' is not a valid value for the 'color' setting.Resetting to server default value: " + configData.CrosshairColor);			
						vval = configData.CrosshairColor;
						break;
				}
			}
			
			return vval;
		}

		private string ProcessTextValue(string val, BasePlayer player)   //  Default Text: "◎"
		{
			string vval = "";
			
			if (val == "default" )
			{
				vval = configData.CrosshairText;
			}
			else
			{
				vval = val.Substring(0,1);
			}
			
			return vval;
		}

        private static string HexToColor(string hexColor)
        {
            if (hexColor.IndexOf('#') != -1) hexColor = hexColor.Replace("#", "");

            var red = 0;
            var green = 0;
            var blue = 0;

            if (hexColor.Length == 6)
            {
                red = int.Parse(hexColor.Substring(0, 2), NumberStyles.AllowHexSpecifier);
                green = int.Parse(hexColor.Substring(2, 2), NumberStyles.AllowHexSpecifier);
                blue = int.Parse(hexColor.Substring(4, 2), NumberStyles.AllowHexSpecifier);
            }
            else if (hexColor.Length == 3)
            {
                red = int.Parse(hexColor[0] + hexColor[0].ToString(), NumberStyles.AllowHexSpecifier);
                green = int.Parse(hexColor[1] + hexColor[1].ToString(), NumberStyles.AllowHexSpecifier);
                blue = int.Parse(hexColor[2] + hexColor[2].ToString(), NumberStyles.AllowHexSpecifier);
            }

            return $"{(double)red / 255} {(double)green / 255} {(double)blue / 255}";
        }
		
		public static bool IsValidHexaCode(string str)
		{
			string strRegex = @"^#([A-Fa-f0-9]{6})$";
			
			Regex re = new Regex(strRegex);
			if (re.IsMatch(str))
				return true;
			else
				return false;
		}

		#endregion Helpers
		
		#region Debug
		
        private void PrintDebug(string message, bool warning = false, bool error = false)
        {
            if (DebugEnabled)
            {
                if (error)
                {
                    PrintError(message);
                }
                else if (warning)
                {
                    PrintWarning(message);
                }
                else
                {
                    Puts(message);
                }
            }
        }
		
        #endregion Debug

    }
}

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху