Compare commits

..

No commits in common. "master" and "1.0.8" have entirely different histories.

10 changed files with 189 additions and 445 deletions

View file

@ -3,12 +3,10 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Vintagestory.API.Common; using Vintagestory.API.Common;
using Vintagestory.API.Common.Entities;
using Vintagestory.API.Config; using Vintagestory.API.Config;
using Vintagestory.API.MathTools; using Vintagestory.API.MathTools;
using Vintagestory.API.Server; using Vintagestory.API.Server;
using Vintagestory.API.Util; using Vintagestory.API.Util;
using Vintagestory.GameContent;
namespace AriasServerUtils namespace AriasServerUtils
{ {
@ -127,10 +125,8 @@ namespace AriasServerUtils
if (data.Homes.ContainsKey(homeName)) if (data.Homes.ContainsKey(homeName))
{ {
Home home = data.Homes[homeName];
ServerUtilities.NewBackCacheForPlayer(isp); 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")); ServerUtilities.SendMessageTo(isp, Lang.Get($"{ServerUtilities.MOD_ID}:home-tp"));
} }
@ -202,20 +198,14 @@ namespace AriasServerUtils
if (args.Caller.Player is IServerPlayer isp) 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; bool bypass = isOp && ServerUtilities.config.AdminsBypassMaxHomes;
var data = ServerUtilities.GetPlayerData(isp); var data = ServerUtilities.GetPlayerData(isp);
if (bypass || data.Homes.Count < ServerUtilities.config.MaxHomes || data.Homes.ContainsKey(homeName)) if (bypass || data.Homes.Count < ServerUtilities.config.MaxHomes || data.Homes.ContainsKey(homeName))
{ {
data.Homes[homeName] = Home.MakeHome(args.Caller.Player.Entity, homeName, withMount: withMount); data.Homes[homeName] = Home.MakeHome(args.Caller.Player.Entity, homeName);
ServerUtilities.SendMessageTo(isp, Lang.Get($"{ServerUtilities.MOD_ID}:home-set")); ServerUtilities.SendMessageTo(isp, Lang.Get($"{ServerUtilities.MOD_ID}:home-set"));
} }
else else
{ {
@ -284,7 +274,7 @@ namespace AriasServerUtils
{ {
ServerUtilities.config.AdminsBypassMaxHomes = bypass; ServerUtilities.config.AdminsBypassMaxHomes = bypass;
ServerUtilities.MarkDirty(); ServerUtilities.MarkDirty();
return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", bypass)); return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig"));
} }
return TextCommandResult.Success(); return TextCommandResult.Success();
@ -298,7 +288,7 @@ namespace AriasServerUtils
ServerUtilities.config.MaxBackCache = max; ServerUtilities.config.MaxBackCache = max;
ServerUtilities.MarkDirty(); ServerUtilities.MarkDirty();
return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", max)); return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig"));
} }
return TextCommandResult.Success(); return TextCommandResult.Success();
@ -311,7 +301,7 @@ namespace AriasServerUtils
ServerUtilities.config.MaxHomes = maxHomes; ServerUtilities.config.MaxHomes = maxHomes;
ServerUtilities.MarkDirty(); ServerUtilities.MarkDirty();
return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", maxHomes)); return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig"));
} }
return TextCommandResult.Success(); return TextCommandResult.Success();
@ -320,32 +310,19 @@ namespace AriasServerUtils
internal static TextCommandResult HandleUpdateASUMgrWarps(TextCommandCallingArgs args) internal static TextCommandResult HandleUpdateASUMgrWarps(TextCommandCallingArgs args)
{ {
if (args[0] is bool mgr) if (args[0] is bool mgr)
{
ServerUtilities.config.onlyAdminsCreateWarps = mgr; ServerUtilities.config.onlyAdminsCreateWarps = mgr;
ServerUtilities.MarkDirty();
return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", mgr));
}
else ServerUtilities.config.onlyAdminsCreateWarps = true; else ServerUtilities.config.onlyAdminsCreateWarps = true;
ServerUtilities.MarkDirty(); 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) internal static TextCommandResult HandleUpdateASUPSP(TextCommandCallingArgs args)
{ {
if (args[0] is int psp) if (args[0] is int psp) ServerUtilities.config.PlayerSleepingPercentage = psp;
{
ServerUtilities.config.PlayerSleepingPercentage = psp;
ServerUtilities.MarkDirty(); ServerUtilities.MarkDirty();
return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", psp)); return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig"));
}
return TextCommandResult.Success();
} }
internal static TextCommandResult HandleWarp(TextCommandCallingArgs args) internal static TextCommandResult HandleWarp(TextCommandCallingArgs args)
@ -364,11 +341,13 @@ namespace AriasServerUtils
if (ServerUtilities.serverWarps.warps.ContainsKey(name)) if (ServerUtilities.serverWarps.warps.ContainsKey(name))
{ {
Warp warp = ServerUtilities.serverWarps.warps[name];
ServerUtilities.NewBackCacheForPlayer(isp); ServerUtilities.NewBackCacheForPlayer(isp);
warp.Location.Merge(isp.Entity, unmount: !warp.CanHaveMount); ServerUtilities.serverWarps.warps[name].Location.Merge(isp.Entity);
ServerUtilities.SendMessageTo(isp, Lang.Get($"{ServerUtilities.MOD_ID}:warp-set", name));
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()); data.ActiveCooldowns.Add(CooldownType.Warp, TimeUtil.DecodeTimeNotation(ServerUtilities.config.Cooldowns.Get(CooldownType.Warp)) + TimeUtil.GetUnixEpochTimestamp());
@ -451,7 +430,7 @@ namespace AriasServerUtils
ServerUtilities.config.MaxRTPBlockDistance = maxDist; ServerUtilities.config.MaxRTPBlockDistance = maxDist;
ServerUtilities.MarkDirty(); ServerUtilities.MarkDirty();
return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", maxDist)); return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig"));
} }
return TextCommandResult.Success(); return TextCommandResult.Success();
@ -464,7 +443,7 @@ namespace AriasServerUtils
ServerUtilities.config.Cooldowns[CooldownType.Back] = CD; ServerUtilities.config.Cooldowns[CooldownType.Back] = CD;
ServerUtilities.MarkDirty(); ServerUtilities.MarkDirty();
return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", CD)); return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig"));
} }
else else
{ {
@ -482,7 +461,7 @@ namespace AriasServerUtils
ServerUtilities.config.Cooldowns[CooldownType.Warp] = CD; ServerUtilities.config.Cooldowns[CooldownType.Warp] = CD;
ServerUtilities.MarkDirty(); ServerUtilities.MarkDirty();
return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", CD)); return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig"));
} }
else else
{ {
@ -500,7 +479,7 @@ namespace AriasServerUtils
ServerUtilities.config.Cooldowns[CooldownType.Home] = CD; ServerUtilities.config.Cooldowns[CooldownType.Home] = CD;
ServerUtilities.MarkDirty(); ServerUtilities.MarkDirty();
return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", CD)); return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig"));
} }
else else
{ {
@ -518,7 +497,7 @@ namespace AriasServerUtils
ServerUtilities.config.Cooldowns[CooldownType.Spawn] = CD; ServerUtilities.config.Cooldowns[CooldownType.Spawn] = CD;
ServerUtilities.MarkDirty(); ServerUtilities.MarkDirty();
return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", CD)); return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig"));
} }
else else
{ {
@ -536,7 +515,7 @@ namespace AriasServerUtils
ServerUtilities.config.Cooldowns[CooldownType.RTP] = CD; ServerUtilities.config.Cooldowns[CooldownType.RTP] = CD;
ServerUtilities.MarkDirty(); ServerUtilities.MarkDirty();
return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", CD)); return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig"));
} }
else else
{ {
@ -562,7 +541,7 @@ namespace AriasServerUtils
// Update the bypass // Update the bypass
ServerUtilities.config.AdminsBypassCooldowns = bypass; ServerUtilities.config.AdminsBypassCooldowns = bypass;
ServerUtilities.MarkDirty(); ServerUtilities.MarkDirty();
return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", bypass)); return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig"));
} }
else return TextCommandResult.Success(); else return TextCommandResult.Success();
} }
@ -574,43 +553,11 @@ namespace AriasServerUtils
// Update the flag // Update the flag
ServerUtilities.config.AdminsBypassRTPMaxDistance = bypass; ServerUtilities.config.AdminsBypassRTPMaxDistance = bypass;
ServerUtilities.MarkDirty(); ServerUtilities.MarkDirty();
return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", bypass)); return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig"));
} }
else return TextCommandResult.Success(); 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) internal static TextCommandResult HandleListCooldowns(TextCommandCallingArgs args)
{ {
string sReturn = "SERVER COOLDOWN SETTINGS\n"; string sReturn = "SERVER COOLDOWN SETTINGS\n";
@ -630,63 +577,5 @@ namespace AriasServerUtils
} }
return TextCommandResult.Success(sReturn); return TextCommandResult.Success(sReturn);
} }
internal static TextCommandResult HandleSleepyDebug(TextCommandCallingArgs args)
{
EntityBehaviorTiredness sleepy = args.Caller.Entity.GetBehavior<EntityBehaviorTiredness>();
if (sleepy != null)
{
sleepy.Tiredness = 100;
}
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<BlockEntityFarmland>(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));
}
}
} }
} }

View file

@ -1,8 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Runtime.ConstrainedExecution; using System.Runtime.ConstrainedExecution;
using Vintagestory.API.Common;
using Vintagestory.API.Server; using Vintagestory.API.Server;
namespace AriasServerUtils namespace AriasServerUtils
@ -24,7 +22,7 @@ namespace AriasServerUtils
{ CooldownType.RTP, "30s" }, { CooldownType.RTP, "30s" },
{ CooldownType.Back, "5s" } { CooldownType.Back, "5s" }
}; };
private static readonly int CURRENT_VERSION = 7; private static readonly int CURRENT_VERSION = 5;
public int Version { get; set; } = 0; public int Version { get; set; } = 0;
@ -37,27 +35,12 @@ namespace AriasServerUtils
public int PlayerSleepingPercentage { get; set; } = 50; public int PlayerSleepingPercentage { get; set; } = 50;
public int MaxRTPBlockDistance { get; set; } = 50000; public int MaxRTPBlockDistance { get; set; } = 50000;
public Dictionary<CooldownType, string> Cooldowns { get; set; } = new Dictionary<CooldownType, string>(); public Dictionary<CooldownType, string> Cooldowns { get; set; } = new Dictionary<CooldownType, string>();
public Costs costs { get; set; } = new Costs();
/// <summary>
/// If true, attempts to downgrade the soil quality when breaking farmland.
/// </summary>
public bool EnableFarmlandDowngrade { get; set; } = false;
/// <summary>
/// If true, farmland will drop as soil when broken.
/// </summary>
public bool EnableFarmlandDrop { get; set; } = true;
public Dictionary<CooldownType, string> GetDefaultCooldowns() public Dictionary<CooldownType, string> GetDefaultCooldowns()
{ {
return m_defaultCD; return m_defaultCD;
} }
/// <summary>
/// Performs some checks against known possible invalid values and sets them to sane values.
/// </summary>
public void SanityCheck() public void SanityCheck()
{ {
foreach (var cd in GetDefaultCooldowns()) foreach (var cd in GetDefaultCooldowns())
@ -74,29 +57,6 @@ namespace AriasServerUtils
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 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();
}
} }
@ -119,16 +79,14 @@ namespace AriasServerUtils
public PlayerPosition Location; public PlayerPosition Location;
public string CreatedBy; public string CreatedBy;
public DateTime CreatedAt; public DateTime CreatedAt;
public bool CanHaveMount = false;
public static Warp Create(IServerPlayer player, bool withMount = false) public static Warp Create(IServerPlayer player)
{ {
Warp warp = new Warp(); Warp warp = new Warp();
warp.Location = PlayerPosition.from(player.Entity); warp.Location = PlayerPosition.from(player.Entity);
warp.CreatedBy = player.PlayerName; warp.CreatedBy = player.PlayerName;
warp.CreatedAt = DateTime.Now; warp.CreatedAt = DateTime.Now;
warp.CanHaveMount = withMount;
return warp; return warp;
} }
@ -140,63 +98,6 @@ namespace AriasServerUtils
public Dictionary<string, Warp> warps = new Dictionary<string, Warp>(); public Dictionary<string, Warp> warps = new Dictionary<string, Warp>();
} }
/// <summary>
/// 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
///
/// </summary>
[Serializable]
public class Costs
{
public enum CostType
{
sethome,
home,
delhome,
sethomemount,
warp,
setwarp,
delwarp,
spawn
}
public Dictionary<CostType, int> costs = new Dictionary<CostType, int>();
public static readonly Dictionary<CostType, int> defaults = new Dictionary<CostType, int>()
{
{ CostType.sethome, 0 },
{ CostType.home, 0 },
{ CostType.delhome, 0 },
{ CostType.sethomemount, 10 },
{ CostType.setwarp, 5 },
{ CostType.warp, 1 },
{ CostType.delwarp, 5 },
{ CostType.spawn, 0 }
};
/// <summary>
/// Checks if the player has the balance required to use the command
/// </summary>
/// <param name="cmd">The command the player is trying to use</param>
/// <param name="player">The player</param>
/// <returns>True if the player has the required balance</returns>
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 public class BackCaches
{ {

View file

@ -15,5 +15,20 @@ public class ASUModClient : ModSystem
public override void StartClientSide(ICoreClientAPI api) public override void StartClientSide(ICoreClientAPI api)
{ {
CAPI = api; CAPI = api;
api.Network.RegisterChannel("asutimeaccel")
.RegisterMessageType<ASUTimeAcceleration>()
.SetMessageHandler<ASUTimeAcceleration>(onReceiveTimeAccel);
}
private void onReceiveTimeAccel(ASUTimeAcceleration packet)
{
// Time acceleration handler
accel = packet.Sleeping;
if (accel)
{
CAPI.World.Calendar.SetTimeSpeedModifier("asu_psp", 500);
}
else CAPI.World.Calendar.RemoveTimeSpeedModifier("asu_psp");
} }
} }

View file

@ -29,9 +29,16 @@ namespace AriasServerUtils
internal static Warps serverWarps = new Warps(); internal static Warps serverWarps = new Warps();
internal static Random rng = new Random((int)TimeUtil.GetUnixEpochTimestamp()); internal static Random rng = new Random((int)TimeUtil.GetUnixEpochTimestamp());
internal bool isFirstStart = true;
internal static string[] saveInvTypes = new string[] {
GlobalConstants.hotBarInvClassName,
GlobalConstants.backpackInvClassName,
GlobalConstants.craftingInvClassName,
GlobalConstants.mousecursorInvClassName,
GlobalConstants.characterInvClassName
};
List<EntityAgent> SleepingPlayers { get; set; } = new(); List<EntityAgent> SleepingPlayers { get; set; } = new();
float OriginalSpeed { get; set; } = 0.0f; float OriginalSpeed { get; set; } = 0.0f;
public double Hours { get; private set; } = 0.0; public double Hours { get; private set; } = 0.0;
@ -86,25 +93,27 @@ namespace AriasServerUtils
api.Event.PlayerJoin += OnPlayerJoin; api.Event.PlayerJoin += OnPlayerJoin;
api.Event.PlayerDisconnect += OnPlayerDC; api.Event.PlayerDisconnect += OnPlayerDC;
api.Event.ChunkColumnLoaded += RTPFactory.ChunkLoaded; api.Event.ChunkColumnLoaded += RTPFactory.ChunkLoaded;
api.Event.BreakBlock += Events.CheckBreakFarmland;
//api.Event.PlayerLeave += OnPlayerDC; //api.Event.PlayerLeave += OnPlayerDC;
ServerNetworkChannel = api.Network.RegisterChannel("asutimeaccel")
.RegisterMessageType<ASUTimeAcceleration>();
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("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("test_death").RequiresPlayer().RequiresPrivilege(Privilege.controlserver).HandleWith(TestDeath); //api.ChatCommands.Create("test_death").RequiresPlayer().RequiresPrivilege(Privilege.controlserver).HandleWith(TestDeath);
var parsers = api.ChatCommands.Parsers; 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("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).WithAlias("sh"); 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).WithAlias("h"); 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).WithAlias("dh"); 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).WithAlias("lh"); api.ChatCommands.Create("homes").RequiresPlayer().WithDescription("Lists your homes").RequiresPrivilege(Privilege.chat).HandleWith(Events.HandleListHomes);
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") api.ChatCommands.Create("asu")
.RequiresPrivilege(Privilege.chat) .RequiresPrivilege(Privilege.chat)
@ -175,18 +184,6 @@ namespace AriasServerUtils
.WithDescription("Update RTP Max block distance. Plus and/or minus this distance from player current position (Default is 50000)") .WithDescription("Update RTP Max block distance. Plus and/or minus this distance from player current position (Default is 50000)")
.HandleWith(Events.HandleUpdateASURTPMax) .HandleWith(Events.HandleUpdateASURTPMax)
.EndSubCommand() .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") .BeginSubCommand("cooldowns")
.WithDescription("Commands related to all the various cooldowns") .WithDescription("Commands related to all the various cooldowns")
.BeginSubCommand("back") .BeginSubCommand("back")
@ -241,7 +238,7 @@ namespace AriasServerUtils
.HandleWith(Events.HandleASU) .HandleWith(Events.HandleASU)
.WithDescription("Lists all Aria's Server Utils commands") .WithDescription("Lists all Aria's Server Utils commands")
.EndSubCommand() .EndSubCommand()
.BeginSubCommand("test") /*.BeginSubCommand("test")
.RequiresPlayer() .RequiresPlayer()
.RequiresPrivilege(Privilege.controlserver) .RequiresPrivilege(Privilege.controlserver)
.BeginSubCommand("sleep") .BeginSubCommand("sleep")
@ -249,45 +246,46 @@ namespace AriasServerUtils
.RequiresPrivilege(Privilege.controlserver) .RequiresPrivilege(Privilege.controlserver)
.HandleWith(TestSleep) .HandleWith(TestSleep)
.EndSubCommand() .EndSubCommand()
.BeginSubCommand("sleepy") .BeginSubCommand("calendarspeed")
.RequiresPlayer() .RequiresPlayer()
.RequiresPrivilege(Privilege.controlserver) .RequiresPrivilege(Privilege.controlserver)
.HandleWith(Events.HandleSleepyDebug) .HandleWith(TestCalendarSpeed)
.EndSubCommand() .EndSubCommand()
.EndSubCommand(); .EndSubCommand()*/ ;
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("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).WithAlias("w"); 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).WithAlias("dw"); 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).WithAlias("lw"); api.ChatCommands.Create("warps").RequiresPlayer().RequiresPrivilege(Privilege.chat).WithDescription("Lists all server warps").HandleWith(Events.HandleWarpList);
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("back").RequiresPlayer().RequiresPrivilege(Privilege.chat).WithDescription("Returns you to the last location you were at").HandleWith(Events.HandleBack);
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("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).WithAlias("lc"); 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);
} }
private TextCommandResult TestSleep(TextCommandCallingArgs args) private TextCommandResult TestSleep(TextCommandCallingArgs args)
{ {
// Initiate the sleep process // Initiate the sleep process
// Basically run all the same commands as we would on a player in bed // Basically run all the same commands as we would on a player in bed
Events.HandleSleepyDebug(args);
OriginalSpeed = API.World.Calendar.CalendarSpeedMul; OriginalSpeed = API.World.Calendar.CalendarSpeedMul;
if (args.Caller.Player is IServerPlayer isp) if (args.Caller.Player is IServerPlayer isp)
{ {
Hours = API.World.Calendar.TotalHours; Hours = API.World.Calendar.TotalHours;
SleepingPlayers.Add(isp.Entity); SleepingPlayers.Add(isp.Entity);
API.Logger.Notification($"Game Hours: {API.World.Calendar.TotalHours}, Difference: {API.World.Calendar.TotalHours - Hours}");
EntityAgent Agent = isp.Entity; EntityAgent Agent = isp.Entity;
EntityBehaviorTiredness ebt = Agent.GetBehavior("tiredness") as EntityBehaviorTiredness;
EntityBehaviorTiredness ebt = Agent.GetBehavior<EntityBehaviorTiredness>();
ebt.IsSleeping = true; ebt.IsSleeping = true;
ebt.Tiredness = 100; ebt.Tiredness = 100;
Sleeping = true; Sleeping = true;
ServerNetworkChannel.BroadcastPacket(new ASUTimeAcceleration
{
Sleeping = true
});
API.World.Calendar.SetTimeSpeedModifier("asu_psp", 1000); API.World.Calendar.SetTimeSpeedModifier("asu_psp", 1000);
} }
@ -310,6 +308,11 @@ namespace AriasServerUtils
OriginalSpeed = 0.5f; OriginalSpeed = 0.5f;
ebt.IsSleeping = true; ebt.IsSleeping = true;
ServerNetworkChannel.BroadcastPacket(new ASUTimeAcceleration
{
Sleeping = true
});
API.World.Calendar.SetTimeSpeedModifier("asu_psp", 1000); API.World.Calendar.SetTimeSpeedModifier("asu_psp", 1000);
SendMessageTo(isp, "Applied calendar speed multiplier"); SendMessageTo(isp, "Applied calendar speed multiplier");
@ -320,6 +323,11 @@ namespace AriasServerUtils
OriginalSpeed = 0; OriginalSpeed = 0;
ebt.IsSleeping = false; ebt.IsSleeping = false;
ServerNetworkChannel.BroadcastPacket(new ASUTimeAcceleration
{
Sleeping = false
});
API.World.Calendar.RemoveTimeSpeedModifier("asu_psp"); API.World.Calendar.RemoveTimeSpeedModifier("asu_psp");
SendMessageTo(isp, "Restored default calendar speed"); SendMessageTo(isp, "Restored default calendar speed");
@ -332,30 +340,27 @@ namespace AriasServerUtils
private void OnCheckSleepingPlayers() private void OnCheckSleepingPlayers()
{ {
if (API.Side == EnumAppSide.Client) return; // This must only ever be called on the server! if (API.Side == EnumAppSide.Client) return; // This must only ever be called on the server!
if (isFirstStart)
{
API.World.Calendar.RemoveTimeSpeedModifier("asu_psp");
isFirstStart = false;
}
if (Sleeping) if (Sleeping)
{ {
//API.Logger.Notification($"Game Hours: {API.World.Calendar.TotalHours}, Difference: {API.World.Calendar.TotalHours - Hours}"); if (API.World.Calendar.TotalHours - Hours >= 7)
if (API.World.Calendar.TotalHours - Hours >= 6)
{ {
Sleeping = false; Sleeping = false;
foreach (var player in SleepingPlayers) foreach (var player in SleepingPlayers)
{ {
EntityBehaviorTiredness ebt = player.GetBehavior<EntityBehaviorTiredness>(); EntityBehaviorTiredness ebt = player.GetBehavior("tiredness") as EntityBehaviorTiredness;
ebt.IsSleeping = false; ebt.IsSleeping = false;
ebt.Tiredness = 0; ebt.Tiredness = 0;
} }
SleepingPlayers.Clear(); SleepingPlayers.Clear();
API.World.Calendar.RemoveTimeSpeedModifier("asu_psp");
//API.Logger.Notification("Stopping PSP Time Acceleration"); ServerNetworkChannel.BroadcastPacket(new ASUTimeAcceleration
{
Sleeping = false
});
API.World.Calendar.RemoveTimeSpeedModifier("asu_psp");
} }
return; return;
} }
@ -366,6 +371,8 @@ namespace AriasServerUtils
if (TotalOnline == 0) return; // No one on, just abort the checks. if (TotalOnline == 0) return; // No one on, just abort the checks.
int TotalInBed = 0; int TotalInBed = 0;
bool isAlreadySleeping = false;
List<BlockEntityBed> BEBs = new(); List<BlockEntityBed> BEBs = new();
foreach (var player in API.World.AllOnlinePlayers) foreach (var player in API.World.AllOnlinePlayers)
@ -375,32 +382,35 @@ namespace AriasServerUtils
{ {
BEBs.Add(beb); BEBs.Add(beb);
TotalInBed++; TotalInBed++;
//API.Logger.Notification($"Bed found for player {player.PlayerName}");
} }
if (ePlay.MountedOn == null) if (ePlay.MountedOn == null)
{ {
//API.Logger.Notification($"No bed found for player {player.PlayerName}");
if (SleepingPlayers.Contains(ePlay)) if (SleepingPlayers.Contains(ePlay))
{ {
EntityBehaviorTiredness ebt = ePlay.GetBehavior<EntityBehaviorTiredness>(); EntityBehaviorTiredness ebt = ePlay.GetBehavior("tiredness") as EntityBehaviorTiredness;
if (ebt != null) if (ebt != null)
ebt.IsSleeping = false; ebt.IsSleeping = false;
} }
} }
EntityBehaviorTiredness EBT = ePlay.GetBehavior("tiredness") as EntityBehaviorTiredness;
if (EBT == null) continue;
if (EBT.IsSleeping) isAlreadySleeping = true;
} }
if (Sleeping) return; // Abort if (isAlreadySleeping) return; // Abort
SleepingPlayers.Clear(); SleepingPlayers.Clear();
int Percentage = TotalInBed * 100 / TotalOnline; int Percentage = TotalInBed * 100 / TotalOnline;
//API.Logger.Notification($"Percentage of players in bed: {Percentage}, Required percentage: {config.PlayerSleepingPercentage}");
if (Percentage >= config.PlayerSleepingPercentage) if (Percentage >= config.PlayerSleepingPercentage)
{ {
ServerNetworkChannel.BroadcastPacket(new ASUTimeAcceleration
{
Sleeping = true
});
API.World.Calendar.SetTimeSpeedModifier("asu_psp", 1000); API.World.Calendar.SetTimeSpeedModifier("asu_psp", 1000);
// Call the API to make sleep happen // Call the API to make sleep happen
@ -409,12 +419,9 @@ namespace AriasServerUtils
if (bed.MountedBy != null) SleepingPlayers.Add(bed.MountedBy); if (bed.MountedBy != null) SleepingPlayers.Add(bed.MountedBy);
// Start sleep // Start sleep
EntityBehaviorTiredness EBT = bed.MountedBy.GetBehavior<EntityBehaviorTiredness>(); EntityBehaviorTiredness EBT = bed.MountedBy.GetBehavior("tiredness") as EntityBehaviorTiredness;
EBT.IsSleeping = true; EBT.IsSleeping = true;
//API.Logger.Notification("Starting PSP Time Acceleration");
bed.MountedBy.TryUnmount(); // Stand up. We cant trigger the real sleep phase, but all code for starting time accel has been executed. bed.MountedBy.TryUnmount(); // Stand up. We cant trigger the real sleep phase, but all code for starting time accel has been executed.
} }
@ -495,10 +502,42 @@ namespace AriasServerUtils
private void OnPlayerDeath(IServerPlayer player, DamageSource damageSource) private void OnPlayerDeath(IServerPlayer player, DamageSource damageSource)
{ {
PlayerInventory inv = RustyGearUtils.GetAllItems(player); PlayerInventory inv = new PlayerInventory();
var invMgr = player.InventoryManager;
NewBackCacheForPlayer(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; backupInventory[player.PlayerName] = inv;
} }

View file

@ -31,15 +31,8 @@ namespace AriasServerUtils
} }
public void Merge(Entity entity, bool unmount = true) public void Merge(Entity entity)
{ {
if (entity is EntityPlayer player)
{
if (unmount && player.MountedOn.Entity != null)
{
player.TryUnmount();
}
}
entity.TeleportTo(new BlockPos(X, Y, Z, Dimension)); entity.TeleportTo(new BlockPos(X, Y, Z, Dimension));
entity.Pos.SetYaw(Yaw); entity.Pos.SetYaw(Yaw);
entity.Pos.Pitch = Pitch; entity.Pos.Pitch = Pitch;
@ -95,13 +88,11 @@ namespace AriasServerUtils
public class Home public class Home
{ {
public PlayerPosition Location { get; set; } public PlayerPosition Location { get; set; }
public bool CanHaveMount = false;
public static Home MakeHome(Entity player, string homeName, bool withMount = false) public static Home MakeHome(Entity player, string homeName)
{ {
Home home = new Home(); Home home = new Home();
home.Location = PlayerPosition.from(player); home.Location = PlayerPosition.from(player);
home.CanHaveMount = withMount;
return home; return home;

View file

@ -59,6 +59,42 @@ public class RTPFactory
check.Y = height + 1; check.Y = height + 1;
PPos.Y = height + 1; PPos.Y = height + 1;
return PPos; return PPos;
int Y = 255;
bool lastBlockAir = true;
bool lastLastBlockAir = true;
bool curBlockAir = true;
bool safe = false;
for (Y = 255; Y > 1; Y--)
{
// Manually scan downwards
check.Y = Y;
var current = BA.GetBlock(check);
if (current.BlockMaterial != EnumBlockMaterial.Air)
{
curBlockAir = false;
}
lastLastBlockAir = lastBlockAir;
lastBlockAir = curBlockAir;
if (!curBlockAir && lastBlockAir && lastLastBlockAir)
{
// We found a safe spot to land
check.Y++;
safe = true;
break;
}
}
if (!safe) return null;
PPos.Y = check.Y;
return PPos;
} }
/// <summary> /// <summary>

View file

@ -1,131 +0,0 @@
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";
/// <summary>
/// Counts the total number of rusty gears in the player's inventory.
/// </summary>
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;
}
/// <summary>
/// Attempts to subtract a specific number of rusty gears from the player's inventory.
/// </summary>
/// <param name="player">The player.</param>
/// <param name="amount">How many gears to remove.</param>
/// <returns>True if the full amount was successfully removed, false if not enough gears.</returns>
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;
}
}

View file

@ -20,12 +20,9 @@
"help": "All Aria's Server Utilities Commands: \n\nMax Homes: {0}; \nAdmins can bypass max homes: {1}\nMax back positions: {2}\n\n{3}", "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 with the new value: {0}", "updatedconfig": "[ASU] server config updated",
"config-value-reset": "[ASU] server config value reset to default", "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-tp": "Teleported to warp [{0}]",
"warp-set": "Warp [{0}] created!", "warp-set": "Warp [{0}] created!",
"warp-no": "You lack permissions to manage a warp", "warp-no": "You lack permissions to manage a warp",

View file

@ -3,8 +3,8 @@
"modid": "ariasserverutils", "modid": "ariasserverutils",
"name": "Aria's Server Utilities", "name": "Aria's Server Utilities",
"authors": ["zontreck"], "authors": ["zontreck"],
"description": "A collection of server utilities\n\nBuild Date: 06-07-2025 @ 1:18 AM MST", "description": "A collection of server utilities\n\nBuild Date: 03-11-2025 @ 1:05 AM MST",
"version": "1.1.0-dev.4", "version": "1.0.8",
"dependencies": { "dependencies": {
"game": "" "game": ""
} }

View file

@ -0,0 +1,7 @@
using System;
[Serializable]
public class ASUTimeAcceleration
{
public bool Sleeping = false;
}