using System; using System.Collections.Generic; using System.Reflection.Metadata; using System.Runtime.ConstrainedExecution; using Vintagestory.API.Common; using Vintagestory.API.Server; namespace AriasServerUtils { public enum ModConfigType { Global, World } [Serializable] public class ASUModConfig { private readonly static Dictionary m_defaultCD = new Dictionary{ { CooldownType.Home, "5s" }, { CooldownType.Warp, "10s" }, { CooldownType.Spawn, "5s" }, { CooldownType.RTP, "30s" }, { CooldownType.Back, "5s" } }; private static readonly int CURRENT_VERSION = 7; public int Version { get; set; } = 0; public int MaxHomes { get; set; } = 20; public bool AdminsBypassMaxHomes { get; set; } = true; public bool onlyAdminsCreateWarps { get; set; } = true; public bool AdminsBypassCooldowns { get; set; } = true; public bool AdminsBypassRTPMaxDistance { get; set; } = false; public int MaxBackCache { get; set; } = 10; public int PlayerSleepingPercentage { get; set; } = 50; public int MaxRTPBlockDistance { get; set; } = 50000; public Dictionary Cooldowns { get; set; } = new Dictionary(); public Costs costs { get; set; } = new Costs(); /// /// If true, attempts to downgrade the soil quality when breaking farmland. /// public bool EnableFarmlandDowngrade { get; set; } = false; /// /// If true, farmland will drop as soil when broken. /// public bool EnableFarmlandDrop { get; set; } = true; public Dictionary GetDefaultCooldowns() { return m_defaultCD; } /// /// Performs some checks against known possible invalid values and sets them to sane values. /// public void SanityCheck() { foreach (var cd in GetDefaultCooldowns()) { if (!Cooldowns.ContainsKey(cd.Key)) { Cooldowns.Add(cd.Key, cd.Value); ServerUtilities.MarkDirty(); } } if (Version < CURRENT_VERSION) { Version = CURRENT_VERSION; ServerUtilities.MarkDirty(); // This is here to ensure that the config gets saved when there is a update. Whenever a new field is added to config, the CURRENT_VERSION should get bumped so that this SanityCheck can properly work } // Sanity check costs config bool checkCostDefaults = false; if (costs == null) { costs = new Costs(); // Initialize a brand new costs object checkCostDefaults = true; } else if (costs.costs.Count != Costs.defaults.Count) checkCostDefaults = true; if (checkCostDefaults) { foreach (var def in Costs.defaults) { if (!costs.costs.ContainsKey(def.Key)) { costs.costs.Add(def.Key, def.Value); } } ServerUtilities.MarkDirty(); } } public PlayerPosition Spawn { get; set; } } [Serializable] public enum CooldownType { Home, // Default: 5s Warp, // Default 10s Spawn, // Default 5s RTP, // Default 30s Back // Default 5s } [Serializable] public class Warp { public PlayerPosition Location; public string CreatedBy; public DateTime CreatedAt; public bool CanHaveMount = false; public static Warp Create(IServerPlayer player, bool withMount = false) { Warp warp = new Warp(); warp.Location = PlayerPosition.from(player.Entity); warp.CreatedBy = player.PlayerName; warp.CreatedAt = DateTime.Now; warp.CanHaveMount = withMount; return warp; } } [Serializable] public class Warps { public Dictionary warps = new Dictionary(); } /// /// This contains per command costs, as well as helper functions that can refund a player, or check if the player has the required balance, or payment /// /// [Serializable] public class Costs { public enum CostType { sethome, home, delhome, sethomemount, warp, setwarp, delwarp, spawn } public Dictionary costs = new Dictionary(); public static readonly Dictionary defaults = new Dictionary() { { CostType.sethome, 0 }, { CostType.home, 0 }, { CostType.delhome, 0 }, { CostType.sethomemount, 10 }, { CostType.setwarp, 5 }, { CostType.warp, 1 }, { CostType.delwarp, 5 }, { CostType.spawn, 0 } }; /// /// Checks if the player has the balance required to use the command /// /// The command the player is trying to use /// The player /// True if the player has the required balance public bool PlayerHasBalance(CostType cmd, EntityPlayer player) { int gears = 0; int required = 0; if (costs.ContainsKey(cmd)) { // Get the cost for that command required = costs[cmd]; } // Scan the player inventory, check gears if (gears >= required) return true; return false; } } public class BackCaches { private const int MaxCacheSize = 10; private readonly Dictionary> playerCache = new(); public void AddPosition(string playerName, PlayerPosition position) { if (!playerCache.TryGetValue(playerName, out var positions)) { positions = new LinkedList(); playerCache[playerName] = positions; } if (positions.Count >= MaxCacheSize) { positions.RemoveFirst(); // Remove the oldest position } positions.AddLast(position.Clone()); // Add the new position } public PlayerPosition ReadAndPopNewestPosition(string playerName) { if (playerCache.TryGetValue(playerName, out var positions) && positions.Count > 0) { var newestPosition = positions.Last.Value; positions.RemoveLast(); // Remove the newest position return newestPosition; } return null; // Return null if no positions are available } } }