diff --git a/AriasServerUtils/EventHandler.cs b/AriasServerUtils/EventHandler.cs index b4af602..667c1f1 100644 --- a/AriasServerUtils/EventHandler.cs +++ b/AriasServerUtils/EventHandler.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using Vintagestory.API.Common; +using Vintagestory.API.Common.Entities; using Vintagestory.API.Config; using Vintagestory.API.MathTools; using Vintagestory.API.Server; @@ -126,8 +127,10 @@ namespace AriasServerUtils if (data.Homes.ContainsKey(homeName)) { + Home home = data.Homes[homeName]; ServerUtilities.NewBackCacheForPlayer(isp); - data.Homes[homeName].Location.Merge(isp.Entity); + + home.Location.Merge(isp.Entity, unmount: !home.CanHaveMount); ServerUtilities.SendMessageTo(isp, Lang.Get($"{ServerUtilities.MOD_ID}:home-tp")); } @@ -199,14 +202,20 @@ namespace AriasServerUtils if (args.Caller.Player is IServerPlayer isp) { + bool withMount = false; + if (args.Command.Name == "sethomemount") + { + // Check for the gears and pay here, or show error. + withMount = true; + } + bool bypass = isOp && ServerUtilities.config.AdminsBypassMaxHomes; var data = ServerUtilities.GetPlayerData(isp); if (bypass || data.Homes.Count < ServerUtilities.config.MaxHomes || data.Homes.ContainsKey(homeName)) { - data.Homes[homeName] = Home.MakeHome(args.Caller.Player.Entity, homeName); + data.Homes[homeName] = Home.MakeHome(args.Caller.Player.Entity, homeName, withMount: withMount); ServerUtilities.SendMessageTo(isp, Lang.Get($"{ServerUtilities.MOD_ID}:home-set")); - } else { @@ -275,7 +284,7 @@ namespace AriasServerUtils { ServerUtilities.config.AdminsBypassMaxHomes = bypass; ServerUtilities.MarkDirty(); - return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig")); + return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", bypass)); } return TextCommandResult.Success(); @@ -289,7 +298,7 @@ namespace AriasServerUtils ServerUtilities.config.MaxBackCache = max; ServerUtilities.MarkDirty(); - return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig")); + return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", max)); } return TextCommandResult.Success(); @@ -302,7 +311,7 @@ namespace AriasServerUtils ServerUtilities.config.MaxHomes = maxHomes; ServerUtilities.MarkDirty(); - return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig")); + return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", maxHomes)); } return TextCommandResult.Success(); @@ -311,19 +320,32 @@ namespace AriasServerUtils internal static TextCommandResult HandleUpdateASUMgrWarps(TextCommandCallingArgs args) { if (args[0] is bool mgr) + { ServerUtilities.config.onlyAdminsCreateWarps = mgr; + + ServerUtilities.MarkDirty(); + + return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", mgr)); + } else ServerUtilities.config.onlyAdminsCreateWarps = true; ServerUtilities.MarkDirty(); - return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig")); + + + return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", true)); } internal static TextCommandResult HandleUpdateASUPSP(TextCommandCallingArgs args) { - if (args[0] is int psp) ServerUtilities.config.PlayerSleepingPercentage = psp; - ServerUtilities.MarkDirty(); + if (args[0] is int psp) + { + ServerUtilities.config.PlayerSleepingPercentage = psp; + ServerUtilities.MarkDirty(); - return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig")); + return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", psp)); + } + + return TextCommandResult.Success(); } internal static TextCommandResult HandleWarp(TextCommandCallingArgs args) @@ -342,15 +364,13 @@ namespace AriasServerUtils if (ServerUtilities.serverWarps.warps.ContainsKey(name)) { + Warp warp = ServerUtilities.serverWarps.warps[name]; ServerUtilities.NewBackCacheForPlayer(isp); - ServerUtilities.serverWarps.warps[name].Location.Merge(isp.Entity); + warp.Location.Merge(isp.Entity, unmount: !warp.CanHaveMount); ServerUtilities.SendMessageTo(isp, Lang.Get($"{ServerUtilities.MOD_ID}:warp-tp", name)); - - - data.ActiveCooldowns.Add(CooldownType.Warp, TimeUtil.DecodeTimeNotation(ServerUtilities.config.Cooldowns.Get(CooldownType.Warp)) + TimeUtil.GetUnixEpochTimestamp()); ServerUtilities.MarkDirty(); } @@ -431,7 +451,7 @@ namespace AriasServerUtils ServerUtilities.config.MaxRTPBlockDistance = maxDist; ServerUtilities.MarkDirty(); - return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig")); + return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", maxDist)); } return TextCommandResult.Success(); @@ -444,7 +464,7 @@ namespace AriasServerUtils ServerUtilities.config.Cooldowns[CooldownType.Back] = CD; ServerUtilities.MarkDirty(); - return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig")); + return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", CD)); } else { @@ -462,7 +482,7 @@ namespace AriasServerUtils ServerUtilities.config.Cooldowns[CooldownType.Warp] = CD; ServerUtilities.MarkDirty(); - return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig")); + return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", CD)); } else { @@ -480,7 +500,7 @@ namespace AriasServerUtils ServerUtilities.config.Cooldowns[CooldownType.Home] = CD; ServerUtilities.MarkDirty(); - return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig")); + return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", CD)); } else { @@ -498,7 +518,7 @@ namespace AriasServerUtils ServerUtilities.config.Cooldowns[CooldownType.Spawn] = CD; ServerUtilities.MarkDirty(); - return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig")); + return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", CD)); } else { @@ -516,7 +536,7 @@ namespace AriasServerUtils ServerUtilities.config.Cooldowns[CooldownType.RTP] = CD; ServerUtilities.MarkDirty(); - return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig")); + return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", CD)); } else { @@ -542,7 +562,7 @@ namespace AriasServerUtils // Update the bypass ServerUtilities.config.AdminsBypassCooldowns = bypass; ServerUtilities.MarkDirty(); - return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig")); + return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", bypass)); } else return TextCommandResult.Success(); } @@ -554,11 +574,43 @@ namespace AriasServerUtils // Update the flag ServerUtilities.config.AdminsBypassRTPMaxDistance = bypass; ServerUtilities.MarkDirty(); - return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig")); + return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", bypass)); } else return TextCommandResult.Success(); } + + internal static TextCommandResult HandleUpdateASUFarmlandDowngrade(TextCommandCallingArgs args) + { + if (args[0] is bool downgrade) + { + // Update the flag + ServerUtilities.config.EnableFarmlandDowngrade = downgrade; + ServerUtilities.MarkDirty(); + return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", downgrade)); + } + else + { + return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:farmland-downgrade", ServerUtilities.config.EnableFarmlandDowngrade)); + } + } + + + internal static TextCommandResult HandleUpdateASUFarmlandDrop(TextCommandCallingArgs args) + { + if (args[0] is bool drop) + { + // Update the flag + ServerUtilities.config.EnableFarmlandDrop = drop; + ServerUtilities.MarkDirty(); + return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", drop)); + } + else + { + return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:farmland-drop", ServerUtilities.config.EnableFarmlandDrop)); + } + } + internal static TextCommandResult HandleListCooldowns(TextCommandCallingArgs args) { string sReturn = "SERVER COOLDOWN SETTINGS\n"; @@ -588,5 +640,53 @@ namespace AriasServerUtils } return TextCommandResult.Success(); } + + internal static void CheckBreakFarmland(IServerPlayer byPlayer, BlockSelection blockSel, ref float dropQuantityMultiplier, ref EnumHandling handling) + { + if (!ServerUtilities.config.EnableFarmlandDrop) + { + return; // Default behavior + } + + if (blockSel.Block is BlockFarmland farmland) + { + BlockEntityFarmland beFarmland = farmland.GetBlockEntity(blockSel.Position); + string farmlandType = blockSel.Block.LastCodePart(); + + if (ServerUtilities.config.EnableFarmlandDowngrade) + { + + switch (farmlandType) + { + case "verylow": + { // barren + break; // Can't downgrade further + } + case "low": + { + farmlandType = "verylow"; + break; + } + case "medium": + { + farmlandType = "low"; + break; + } + case "compost": + { // high + farmlandType = "medium"; + break; + } + case "high": + { // Terra preta + farmlandType = "compost"; + break; + } + } + } + + byPlayer.Entity.World.SpawnItemEntity(new ItemStack(byPlayer.Entity.World.GetBlock(new AssetLocation($"soil-{farmlandType}-none"))), blockSel.Position.ToVec3d().Add(0.5, 0.5, 0.5)); + } + } } } \ No newline at end of file diff --git a/AriasServerUtils/Globals.cs b/AriasServerUtils/Globals.cs index a98b5cc..b0ed577 100644 --- a/AriasServerUtils/Globals.cs +++ b/AriasServerUtils/Globals.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.Reflection.Metadata; using System.Runtime.ConstrainedExecution; +using Vintagestory.API.Common; using Vintagestory.API.Server; namespace AriasServerUtils @@ -22,7 +24,7 @@ namespace AriasServerUtils { CooldownType.RTP, "30s" }, { CooldownType.Back, "5s" } }; - private static readonly int CURRENT_VERSION = 5; + private static readonly int CURRENT_VERSION = 7; public int Version { get; set; } = 0; @@ -35,12 +37,27 @@ namespace AriasServerUtils 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()) @@ -57,6 +74,29 @@ namespace AriasServerUtils 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(); + } } @@ -79,14 +119,16 @@ namespace AriasServerUtils public PlayerPosition Location; public string CreatedBy; public DateTime CreatedAt; + public bool CanHaveMount = false; - public static Warp Create(IServerPlayer player) + 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; } @@ -98,6 +140,63 @@ namespace AriasServerUtils 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 { diff --git a/AriasServerUtils/ModSystems/ASUServer.cs b/AriasServerUtils/ModSystems/ASUServer.cs index 680db83..1eed677 100644 --- a/AriasServerUtils/ModSystems/ASUServer.cs +++ b/AriasServerUtils/ModSystems/ASUServer.cs @@ -32,14 +32,6 @@ namespace AriasServerUtils internal bool isFirstStart = true; - internal static string[] saveInvTypes = new string[] { - GlobalConstants.hotBarInvClassName, - GlobalConstants.backpackInvClassName, - GlobalConstants.craftingInvClassName, - GlobalConstants.mousecursorInvClassName, - GlobalConstants.characterInvClassName - }; - List SleepingPlayers { get; set; } = new(); float OriginalSpeed { get; set; } = 0.0f; public double Hours { get; private set; } = 0.0; @@ -94,23 +86,25 @@ namespace AriasServerUtils api.Event.PlayerJoin += OnPlayerJoin; api.Event.PlayerDisconnect += OnPlayerDC; api.Event.ChunkColumnLoaded += RTPFactory.ChunkLoaded; + api.Event.BreakBlock += Events.CheckBreakFarmland; //api.Event.PlayerLeave += OnPlayerDC; - api.ChatCommands.Create("setspawn").RequiresPrivilege(Privilege.controlserver).HandleWith(Events.HandleSetSpawn); - api.ChatCommands.Create("spawn").RequiresPrivilege(Privilege.chat).HandleWith(Events.HandleSpawn); - api.ChatCommands.Create("delspawn").RequiresPrivilege(Privilege.controlserver).HandleWith(Events.HandleClearSpawn); + api.ChatCommands.Create("setspawn").RequiresPrivilege(Privilege.controlserver).HandleWith(Events.HandleSetSpawn).WithAlias("ss"); + api.ChatCommands.Create("spawn").RequiresPrivilege(Privilege.chat).HandleWith(Events.HandleSpawn).WithAlias("s"); + api.ChatCommands.Create("delspawn").RequiresPrivilege(Privilege.controlserver).HandleWith(Events.HandleClearSpawn).WithAlias("ds"); //api.ChatCommands.Create("test_death").RequiresPlayer().RequiresPrivilege(Privilege.controlserver).HandleWith(TestDeath); var parsers = api.ChatCommands.Parsers; api.ChatCommands.Create("restoreinv").RequiresPlayer().WithArgs(parsers.OnlinePlayer("player")).HandleWith(Events.HandleReturnItems).WithDescription("Returns items to a player in the event of a problem").RequiresPrivilege(Privilege.controlserver); - api.ChatCommands.Create("sethome").RequiresPlayer().WithArgs(parsers.OptionalWord("name")).WithDescription("Creates a home").RequiresPrivilege(Privilege.chat).HandleWith(Events.HandleSetHome); - api.ChatCommands.Create("home").RequiresPlayer().WithArgs(parsers.OptionalWord("name")).WithDescription("Teleports you to home").RequiresPrivilege(Privilege.chat).HandleWith(Events.HandleGoHome); - api.ChatCommands.Create("delhome").RequiresPlayer().WithArgs(parsers.OptionalWord("name")).WithDescription("Deletes a home entry").RequiresPrivilege(Privilege.chat).HandleWith(Events.HandleDelHome); - api.ChatCommands.Create("homes").RequiresPlayer().WithDescription("Lists your homes").RequiresPrivilege(Privilege.chat).HandleWith(Events.HandleListHomes); + api.ChatCommands.Create("sethome").RequiresPlayer().WithArgs(parsers.OptionalWord("name")).WithDescription("Creates a home").RequiresPrivilege(Privilege.chat).HandleWith(Events.HandleSetHome).WithAlias("sh"); + api.ChatCommands.Create("home").RequiresPlayer().WithArgs(parsers.OptionalWord("name")).WithDescription("Teleports you to home").RequiresPrivilege(Privilege.chat).HandleWith(Events.HandleGoHome).WithAlias("h"); + api.ChatCommands.Create("delhome").RequiresPlayer().WithArgs(parsers.OptionalWord("name")).WithDescription("Deletes a home entry").RequiresPrivilege(Privilege.chat).HandleWith(Events.HandleDelHome).WithAlias("dh"); + api.ChatCommands.Create("homes").RequiresPlayer().WithDescription("Lists your homes").RequiresPrivilege(Privilege.chat).HandleWith(Events.HandleListHomes).WithAlias("lh"); + api.ChatCommands.Create("sethomemount").RequiresPlayer().WithArgs(parsers.OptionalWord("name")).WithDescription("Create a home with the ability to take a mount with you. Costs [undefined] gears.").RequiresPrivilege(Privilege.chat).HandleWith(Events.HandleSetHome).WithAlias("shm", "shb"); api.ChatCommands.Create("asu") .RequiresPrivilege(Privilege.chat) @@ -181,6 +175,18 @@ namespace AriasServerUtils .WithDescription("Update RTP Max block distance. Plus and/or minus this distance from player current position (Default is 50000)") .HandleWith(Events.HandleUpdateASURTPMax) .EndSubCommand() + .BeginSubCommand("farmlandDowngrade") + .RequiresPrivilege(Privilege.controlserver) + .WithArgs(parsers.OptionalBool("downgrade")) + .WithDescription("Enables or disables farmland downgrade when breaking farmland") + .HandleWith(Events.HandleUpdateASUFarmlandDowngrade) + .EndSubCommand() + .BeginSubCommand("farmlandDrop") + .RequiresPrivilege(Privilege.controlserver) + .WithArgs(parsers.OptionalBool("drop")) + .WithDescription("Enables or disables dropping soil when breaking farmland") + .HandleWith(Events.HandleUpdateASUFarmlandDrop) + .EndSubCommand() .BeginSubCommand("cooldowns") .WithDescription("Commands related to all the various cooldowns") .BeginSubCommand("back") @@ -250,16 +256,16 @@ namespace AriasServerUtils .EndSubCommand() .EndSubCommand(); - api.ChatCommands.Create("setwarp").RequiresPlayer().RequiresPrivilege(Privilege.chat).WithDescription("Creates a new server warp").WithArgs(parsers.OptionalWord("name")).HandleWith(Events.HandleWarpUpdate); - api.ChatCommands.Create("warp").RequiresPlayer().RequiresPrivilege(Privilege.chat).WithDescription("Warp to the specified server warp").WithArgs(parsers.OptionalWord("name")).HandleWith(Events.HandleWarp); - api.ChatCommands.Create("delwarp").RequiresPlayer().RequiresPrivilege(Privilege.chat).WithDescription("Deletes the specified warp").WithArgs(parsers.OptionalWord("name")).HandleWith(Events.HandleWarpDelete); - api.ChatCommands.Create("warps").RequiresPlayer().RequiresPrivilege(Privilege.chat).WithDescription("Lists all server warps").HandleWith(Events.HandleWarpList); + api.ChatCommands.Create("setwarp").RequiresPlayer().RequiresPrivilege(Privilege.chat).WithDescription("Creates a new server warp").WithArgs(parsers.OptionalWord("name")).HandleWith(Events.HandleWarpUpdate).WithAlias("sw"); + api.ChatCommands.Create("warp").RequiresPlayer().RequiresPrivilege(Privilege.chat).WithDescription("Warp to the specified server warp").WithArgs(parsers.OptionalWord("name")).HandleWith(Events.HandleWarp).WithAlias("w"); + api.ChatCommands.Create("delwarp").RequiresPlayer().RequiresPrivilege(Privilege.chat).WithDescription("Deletes the specified warp").WithArgs(parsers.OptionalWord("name")).HandleWith(Events.HandleWarpDelete).WithAlias("dw"); + api.ChatCommands.Create("warps").RequiresPlayer().RequiresPrivilege(Privilege.chat).WithDescription("Lists all server warps").HandleWith(Events.HandleWarpList).WithAlias("lw"); - api.ChatCommands.Create("back").RequiresPlayer().RequiresPrivilege(Privilege.chat).WithDescription("Returns you to the last location you were at").HandleWith(Events.HandleBack); + api.ChatCommands.Create("back").RequiresPlayer().RequiresPrivilege(Privilege.chat).WithDescription("Returns you to the last location you were at").HandleWith(Events.HandleBack).WithAlias("b"); api.ChatCommands.Create("rtp").RequiresPlayer().RequiresPrivilege(Privilege.chat).WithArgs(parsers.OptionalInt("maxDist", defaultValue: -1)).WithDescription("Seeks a position possibly thousands of blocks away to teleport to.").HandleWith(Events.HandleRTP); - api.ChatCommands.Create("listcooldowns").RequiresPrivilege(Privilege.chat).WithDescription("Lists the cooldown settings on the server, as well as your own active cooldowns if applicable.").HandleWith(Events.HandleListCooldowns); + api.ChatCommands.Create("listcooldowns").RequiresPrivilege(Privilege.chat).WithDescription("Lists the cooldown settings on the server, as well as your own active cooldowns if applicable.").HandleWith(Events.HandleListCooldowns).WithAlias("lc"); } private TextCommandResult TestSleep(TextCommandCallingArgs args) @@ -489,42 +495,10 @@ namespace AriasServerUtils private void OnPlayerDeath(IServerPlayer player, DamageSource damageSource) { - PlayerInventory inv = new PlayerInventory(); - var invMgr = player.InventoryManager; - + PlayerInventory inv = RustyGearUtils.GetAllItems(player); NewBackCacheForPlayer(player); - var iBackpackSlotNum = 0; - foreach (var type in saveInvTypes) - { - foreach (var stack in invMgr.GetOwnInventory(type)) - { - - if (iBackpackSlotNum >= 4) - { - continue; - } - if (type == GlobalConstants.backpackInvClassName) - { - iBackpackSlotNum++; - } - if (stack.Empty) continue; - if (stack.Inventory.ClassName == GlobalConstants.characterInvClassName) - { - if (stack.Itemstack.ItemAttributes?["protectionModifiers"].Exists ?? false) - { - inv.Items.Add(stack.Itemstack.Clone()); - } - } - else - inv.Items.Add(stack.Itemstack.Clone()); - - API.Logger.Notification($"SAVED STORAGE ITEM TYPE: {stack.Itemstack}"); - - } - } - backupInventory[player.PlayerName] = inv; } diff --git a/AriasServerUtils/PlayerData.cs b/AriasServerUtils/PlayerData.cs index baec1b3..6be84eb 100644 --- a/AriasServerUtils/PlayerData.cs +++ b/AriasServerUtils/PlayerData.cs @@ -31,8 +31,15 @@ namespace AriasServerUtils } - public void Merge(Entity entity) + public void Merge(Entity entity, bool unmount = true) { + if (entity is EntityPlayer player) + { + if (unmount && player.MountedOn.Entity != null) + { + player.TryUnmount(); + } + } entity.TeleportTo(new BlockPos(X, Y, Z, Dimension)); entity.Pos.SetYaw(Yaw); entity.Pos.Pitch = Pitch; @@ -88,11 +95,13 @@ namespace AriasServerUtils public class Home { public PlayerPosition Location { get; set; } + public bool CanHaveMount = false; - public static Home MakeHome(Entity player, string homeName) + public static Home MakeHome(Entity player, string homeName, bool withMount = false) { Home home = new Home(); home.Location = PlayerPosition.from(player); + home.CanHaveMount = withMount; return home; diff --git a/AriasServerUtils/RustyGearUtils.cs b/AriasServerUtils/RustyGearUtils.cs new file mode 100644 index 0000000..229a7be --- /dev/null +++ b/AriasServerUtils/RustyGearUtils.cs @@ -0,0 +1,131 @@ +using System; +using AriasServerUtils; +using Vintagestory.API.Common; +using Vintagestory.API.Config; +using Vintagestory.API.Datastructures; +using Vintagestory.API.Server; +using Vintagestory.API.Util; + +public static class RustyGearUtils +{ + + + internal static string[] saveInvTypes = new string[] { + GlobalConstants.hotBarInvClassName, + GlobalConstants.backpackInvClassName, + GlobalConstants.craftingInvClassName, + GlobalConstants.mousecursorInvClassName, + GlobalConstants.characterInvClassName + }; + + // Replace with the correct code if it's different + private const string RustyGearCode = "currency-rustygear"; + + /// + /// Counts the total number of rusty gears in the player's inventory. + /// + public static int CountRustyGears(IServerPlayer player) + { + int total = 0; + + player.Entity.WalkInventory((slot) => + { + if (slot is ItemSlotCreative || !(slot.Inventory is InventoryBasePlayer)) return true; + + total += CurrencyValuePerItem(slot) * slot.StackSize; + + return true; + }); + + return total; + } + + private static int CurrencyValuePerItem(ItemSlot slot) + { + JsonObject obj = slot.Itemstack?.Collectible?.Attributes?["currency"]; + if (obj != null && obj.Exists) + { + JsonObject v = obj["value"]; + return v.Exists ? v.AsInt(0) : 0; + } + return 0; + } + /// + /// Attempts to subtract a specific number of rusty gears from the player's inventory. + /// + /// The player. + /// How many gears to remove. + /// True if the full amount was successfully removed, false if not enough gears. + public static bool SubtractRustyGears(IServerPlayer player, int amount) + { + // Check if the player has enough rusty gears + int currentAmount = CountRustyGears(player); + if (currentAmount < amount) return false; + + // Subtract the specified amount of rusty gears from the player's inventory + player.Entity.WalkInventory((slot) => + { + if (slot is ItemSlotCreative || !(slot.Inventory is InventoryBasePlayer)) return true; + + int value = CurrencyValuePerItem(slot) * slot.StackSize; + if (value > 0 && slot.StackSize > 0) + { + // Calculate the amount of rusty gears to remove from this slot + int amountToRemove = Math.Min(value, amount); + + // If the slot size is less than or equal to the amount to remove, set the slot's itemstack to null + if (slot.StackSize <= amountToRemove) slot.Itemstack = null; + else + { + // Otherwise, subtract the amount to remove from the slot size and decrement the total amount + slot.Itemstack.StackSize -= amountToRemove; + amount -= amountToRemove; + } + } + + // If the total amount has been removed, return true + if (amount <= 0) return true; // we're done + return true; + }); + + // If the player's inventory still contains rusty gears, they don't have enough to remove + return false; + } + + public static PlayerInventory GetAllItems(IServerPlayer player) + { + PlayerInventory inv = new PlayerInventory(); + + var invMgr = player.InventoryManager; + + var iBackpackSlotNum = 0; + foreach (var type in saveInvTypes) + { + foreach (var stack in invMgr.GetOwnInventory(type)) + { + + if (iBackpackSlotNum >= 4) + { + continue; + } + if (type == GlobalConstants.backpackInvClassName) + { + iBackpackSlotNum++; + } + if (stack.Empty) continue; + if (stack.Inventory.ClassName == GlobalConstants.characterInvClassName) + { + if (stack.Itemstack.ItemAttributes?["protectionModifiers"].Exists ?? false) + { + inv.Items.Add(stack.Itemstack.Clone()); + } + } + else + inv.Items.Add(stack.Itemstack.Clone()); + + } + } + + return inv; + } +} diff --git a/AriasServerUtils/assets/ariasserverutils/lang/en.json b/AriasServerUtils/assets/ariasserverutils/lang/en.json index 162d5a9..7f983a4 100644 --- a/AriasServerUtils/assets/ariasserverutils/lang/en.json +++ b/AriasServerUtils/assets/ariasserverutils/lang/en.json @@ -20,9 +20,12 @@ "help": "All Aria's Server Utilities Commands: \n\nMax Homes: {0}; \nAdmins can bypass max homes: {1}\nMax back positions: {2}\n\n{3}", - "updatedconfig": "[ASU] server config updated", + "updatedconfig": "[ASU] server config updated with the new value: {0}", "config-value-reset": "[ASU] server config value reset to default", + "farmland-downgrade": "The current farmland downgrade setting is {0}", + "farmland-drop": "The current farmland drop setting is {0}", + "warp-tp": "Teleported to warp [{0}]", "warp-set": "Warp [{0}] created!", "warp-no": "You lack permissions to manage a warp", diff --git a/AriasServerUtils/modinfo.json b/AriasServerUtils/modinfo.json index 594c49e..69e7daf 100644 --- a/AriasServerUtils/modinfo.json +++ b/AriasServerUtils/modinfo.json @@ -3,8 +3,8 @@ "modid": "ariasserverutils", "name": "Aria's Server Utilities", "authors": ["zontreck"], - "description": "A collection of server utilities\n\nBuild Date: 05-3-2025 @ 2:23 PM MST", - "version": "1.0.10", + "description": "A collection of server utilities\n\nBuild Date: 06-07-2025 @ 1:18 AM MST", + "version": "1.1.0-dev.4", "dependencies": { "game": "" }