Add spawn related commands and data storage system

This commit is contained in:
zontreck 2025-01-18 02:59:24 -07:00
parent f2a23552af
commit 0f318a9efa
7 changed files with 211 additions and 9 deletions

View file

@ -1,13 +1,20 @@
using Vintagestory.API.Client; using System;
using System.IO;
using Vintagestory.API.Client;
using Vintagestory.API.Common; using Vintagestory.API.Common;
using Vintagestory.API.Common.Entities;
using Vintagestory.API.Config; using Vintagestory.API.Config;
using Vintagestory.API.Server; using Vintagestory.API.Server;
using Vintagestory.GameContent;
namespace ServerUtilities namespace AriasServerUtils
{ {
public class ServerUtilities : ModSystem public class ServerUtilities : ModSystem
{ {
public static string MOD_ID = "ariasserverutils"; public static string MOD_ID = "ariasserverutils";
public static ASUModConfig config = new ASUModConfig();
private static ICoreServerAPI API;
private static bool bDirty = false;
/// <summary> /// <summary>
/// Method to register all mod blocks /// Method to register all mod blocks
@ -35,16 +42,90 @@ namespace ServerUtilities
RegisterBlocks(api); RegisterBlocks(api);
RegisterBlockEntities(api); RegisterBlockEntities(api);
} }
public override void StartServerSide(ICoreServerAPI api) public override void StartServerSide(ICoreServerAPI api)
{ {
API = api;
api.Logger.Notification(Lang.Get($"{MOD_ID}:start")); api.Logger.Notification(Lang.Get($"{MOD_ID}:start"));
api.Event.ServerRunPhase(EnumServerRunPhase.GameReady, OnGameReady);
api.Event.ServerRunPhase(EnumServerRunPhase.Shutdown, OnShutdown);
api.Event.Timer(OnCheckModDirty, 20);
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);
}
private void OnCheckModDirty()
{
if (bDirty)
{
//API.Logger.Notification(Lang.Get($"{MOD_ID}:timer"));
bDirty = false;
SaveGlobalConfig();
}
}
private void OnShutdown()
{
// Mod Shutdown //
// Handle any remaining tasks before shutdown
OnCheckModDirty();
}
public void SaveGlobalConfig()
{
API.StoreModConfig<ASUModConfig>(config, GetConfigurationFile("", ModConfigType.Global));
}
private void OnGameReady()
{
// Mod Setup Info //
// -> Step 1. Load Mod Global Config <-
config = API.LoadModConfig<ASUModConfig>(GetConfigurationFile("", ModConfigType.Global));
if (config == null) config = new ASUModConfig();
}
public string GetConfigurationFile(string sName, ModConfigType type)
{
if (type == ModConfigType.Global)
{
return "ariaserverconfig/global.json";
}
else if (type == ModConfigType.World)
{
return $"ariaserverconfig/{GetWorldName()}/{sName}.json";
}
else return $"ariaserverconfig/global.json";
}
/// <summary>
/// This function is used to mark the mod's global config, and all loaded player configs as dirty. They will be flushed to disk, then the dirty flag will be cleared.
/// </summary>
public static void MarkDirty()
{
bDirty = true;
}
public string GetWorldName()
{
string[] lName = API.WorldManager.CurrentWorldName.Split(Path.DirectorySeparatorChar);
string sName = lName[lName.Length - 1];
return sName.Substring(0, sName.Length - 6);
} }
public override void StartClientSide(ICoreClientAPI api) public override void StartClientSide(ICoreClientAPI api)
{ {
api.Logger.Notification(Lang.Get($"{MOD_ID}:start")); api.Logger.Notification(Lang.Get($"{MOD_ID}:start"));
} }
public static void SendMessageTo(IServerPlayer player, string sMsg)
{
player.SendMessage(0, sMsg, EnumChatType.CommandSuccess);
}
} }
} }

View file

@ -0,0 +1,52 @@
using System;
using Vintagestory.API.Common;
using Vintagestory.API.Config;
using Vintagestory.API.Server;
namespace AriasServerUtils
{
public class Events
{
internal static TextCommandResult HandleClearSpawn(TextCommandCallingArgs args)
{
ServerUtilities.config.Spawn = null;
ServerUtilities.MarkDirty();
return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:rmspawn"));
}
internal static TextCommandResult HandleSetSpawn(TextCommandCallingArgs args)
{
PlayerPosition pos = PlayerPosition.from(args.Caller.Entity);
ServerUtilities.config.Spawn = pos;
if (args.Caller.Player is IServerPlayer isp)
ServerUtilities.SendMessageTo(isp, Lang.Get($"{ServerUtilities.MOD_ID}:setspawn"));
ServerUtilities.MarkDirty();
return TextCommandResult.Success();
}
internal static TextCommandResult HandleSpawn(TextCommandCallingArgs args)
{
if (ServerUtilities.config.Spawn == null)
{
if (args.Caller.Player is IServerPlayer isp)
{
ServerUtilities.SendMessageTo(isp, Lang.Get($"{ServerUtilities.MOD_ID}:spawn-not-set"));
}
}
else
{
if (args.Caller.Player is IServerPlayer isp)
{
ServerUtilities.SendMessageTo(isp, Lang.Get($"{ServerUtilities.MOD_ID}:tp-spawn"));
ServerUtilities.config.Spawn.Merge(args.Caller.Player.Entity);
}
}
return TextCommandResult.Success();
}
}
}

View file

@ -0,0 +1,17 @@
using System;
namespace AriasServerUtils
{
public enum ModConfigType
{
Global,
World
}
[Serializable]
public class ASUModConfig
{
public int MaxHomes { get; set; } = 20;
public PlayerPosition Spawn { get; set; }
}
}

View file

@ -0,0 +1,45 @@
using System;
using Vintagestory.API.Common.Entities;
using Vintagestory.API.MathTools;
namespace AriasServerUtils
{
[Serializable]
public class PlayerPosition
{
public int X { get; set; } = 0;
public int Y { get; set; } = 0;
public int Z { get; set; } = 0;
public int Dimension { get; set; } = 0;
public float Yaw { get; set; } = 0.0f;
public void Merge(Entity entity)
{
entity.TeleportTo(new BlockPos(X, Y, Z, Dimension));
entity.Pos.SetYaw(Yaw);
}
/// <summary>
/// Generates a PlayerPosition object using a entity.
/// </summary>
/// <param name="entity">A player entity</param>
/// <returns>PlayerPos snapshot object of the entity</returns>
public static PlayerPosition from(Entity entity)
{
PlayerPosition pos = new PlayerPosition();
BlockPos playerPos = entity.Pos.AsBlockPos;
pos.X = playerPos.X;
pos.Y = playerPos.Y;
pos.Z = playerPos.Z;
pos.Dimension = playerPos.dimension;
pos.Yaw = entity.Pos.Yaw;
return pos;
}
}
}

View file

@ -2,15 +2,15 @@
"profiles": { "profiles": {
"Client": { "Client": {
"commandName": "Executable", "commandName": "Executable",
"executablePath": "$(VINTAGE_STORY)/Vintagestory.exe", "executablePath": "~/.local/share/vintagestory/Vintagestory",
"commandLineArgs": "--tracelog --addModPath \"$(ProjectDir)/bin/$(Configuration)/Mods\"", "commandLineArgs": "--tracelog --addModPath \"$(ProjectDir)/bin/$(Configuration)/Mods\"",
"workingDirectory": "$(VINTAGE_STORY)" "workingDirectory": "~/.local/share/vintagestory"
}, },
"Server": { "Server": {
"commandName": "Executable", "commandName": "Executable",
"executablePath": "$(VINTAGE_STORY)/VintagestoryServer.exe", "executablePath": "~/.local/share/vintagestory/VintagestoryServer",
"commandLineArgs": "--tracelog --addModPath \"$(ProjectDir)/bin/$(Configuration)/Mods\"", "commandLineArgs": "--tracelog --addModPath \"$(ProjectDir)/bin/$(Configuration)/Mods\"",
"workingDirectory": "$(VINTAGE_STORY)" "workingDirectory": "~/.local/share/vintagestory"
} }
} }
} }

View file

@ -1 +1,8 @@
{} {
"setspawn": "Spawn location set successfully.",
"timer": "[DEBUG] timer executed",
"spawn-not-set": "A world spawn location is not currently set",
"tp-spawn": "Teleported to spawn",
"rmspawn": "World Spawn cleared. The /spawn command will now be non-functional until a new spawn is set"
}

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: 01-17-2025 @ 03:12 PM", "description": "A collection of server utilities\n\nBuild Date: 01-18-2025 @ 02:58 AM",
"version": "1.0.0-dev.1", "version": "1.0.0-dev.2",
"dependencies": { "dependencies": {
"game": "" "game": ""
} }