using Oxide.Core; using System.Collections.Generic; namespace Oxide.Plugins { [Info("PlayerEventStates", "Flutes", "1.0.0")] [Description("Useful for developers who wish to create conditional gameplay mechanics based on specific events or states.")] public class PlayerEventStates : RustPlugin { #region Fields public static PlayerEventStates Instance { get; private set; } public static PlayerEventStatesManager Core { get; private set; } #endregion #region Core public class PlayerEventStatesManager { public readonly GlobalEventStatesData GlobalEventStates; private Dictionary m_players = new Dictionary(); public IReadOnlyDictionary Players => m_players; public PlayerEventStatesManager() { GlobalEventStates = GlobalEventStatesData.Load(); } public void SaveData() { foreach(var player in m_players) { player.Value.PlayerData.Save(); } GlobalEventStates.Save(); } public PlayerController GetOrCreatePlayerController(ulong playerId) { PlayerController playerController = null; if (m_players.TryGetValue(playerId, out playerController) == false) { PlayerData playerData = PlayerData.Load(playerId); playerController = new PlayerController(playerData); m_players.Add(playerId, playerController); } return playerController; } public bool GetGlobalEventState(string eventName) { EventStateData eventStateData = null; if (GlobalEventStates.EventStates.TryGetValue(eventName, out eventStateData) == false) { eventStateData = new EventStateData(); eventStateData.Name = eventName; GlobalEventStates.EventStates.Add(eventName, eventStateData); GlobalEventStates.OnChange(); } return eventStateData.State; } public void SetGlobalEventState(string eventName, bool value) { if (GlobalEventStates.EventStates.ContainsKey(eventName) == false) { Instance.Puts($"Global EventState with name {eventName} not found"); return; } GlobalEventStates.EventStates[eventName].State = value; GlobalEventStates.OnChange(); } } public class PlayerController { public readonly PlayerData PlayerData; public PlayerController(PlayerData playerData) { PlayerData = playerData; } public bool GetEventState(string eventName) { EventStateData eventStateData = null; if (PlayerData.EventStates.TryGetValue(eventName, out eventStateData) == false) { return false; } return eventStateData.State; } public bool HasRecquiredStates(Dictionary eventStates) { foreach(var kvp in eventStates) { var eventName = kvp.Key; var state = kvp.Value; if (GetEventState(eventName) != state) { return false; } } return true; } public void SetEventState(string eventName, bool value) { EventStateData eventStateData = null; if (PlayerData.EventStates.ContainsKey(eventName)) { eventStateData = PlayerData.EventStates[eventName]; } else { eventStateData = new EventStateData(); eventStateData.Name = eventName; PlayerData.EventStates.Add(eventName, eventStateData); } eventStateData.State = value; PlayerData.OnChange(); } } #endregion #region Startup private void Init() { Instance = this; LoadConfig(); Core = new PlayerEventStatesManager(); } private void Unload() { Core?.SaveData(); } private void OnServerSave() => Core?.SaveData(); #endregion #region API private bool GetEventStatePlayer_API(ulong playerId, string eventName) { var player = Core.GetOrCreatePlayerController(playerId); return player.GetEventState(eventName); } private bool GetEventStateGlobal_API(string eventName) { return Core.GetGlobalEventState(eventName); } private void SetEventStatePlayer_API(ulong playerId, string eventName, bool value) { var player = Core.GetOrCreatePlayerController(playerId); player.SetEventState(eventName, value); } private void SetEventStateGlobal_API(string eventName, bool value) { Core.SetGlobalEventState(eventName, value); } private bool PlayerHasRecquiredStates_API(ulong playerId, Dictionary states) { var player = Core.GetOrCreatePlayerController(playerId); return player.HasRecquiredStates(states); } #endregion #region Data public class EventStateData { public string Name; public bool State; } public class GlobalEventStatesData { public Dictionary EventStates = new Dictionary(); private bool m_stateHasChanged; public static GlobalEventStatesData Load() { GlobalEventStatesData data = null; var file = Interface.Oxide.DataFileSystem.GetFile($"{Instance.Name}/global_events"); if (file == null) { Instance.Puts("GlobalEventStatesData file not found"); return null; } else { data = file.ReadObject(); } return data; } public bool Save() { if (m_stateHasChanged == false) { return false; } Interface.Oxide.DataFileSystem.WriteObject($"{Instance.Name}/global_events", this); m_stateHasChanged = false; return true; } public void OnChange() { m_stateHasChanged = true; } } public class PlayerData { public ulong PlayerId; public Dictionary EventStates = new Dictionary(); private bool m_stateHasChanged; public static PlayerData Load(ulong userId) { PlayerData playerData = null; var file = Interface.Oxide.DataFileSystem.GetFile($"{Instance.Name}/user_{userId}"); if (file == null) { Instance.Puts("PlayerData file not found for player " + userId.ToString()); return null; } else { playerData = file.ReadObject(); } playerData.PlayerId = userId; playerData.OnChange(); return playerData; } public bool Save() { if (m_stateHasChanged == false) { return false; } Interface.Oxide.DataFileSystem.WriteObject($"{Instance.Name}/user_{PlayerId}", this); m_stateHasChanged = false; return true; } public void OnChange() { m_stateHasChanged = true; } } #endregion } }