VSMod_AriasServerUtils/AriasServerUtils/ASUModSystem.cs
2025-01-18 15:19:04 -07:00

275 lines
10 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using Vintagestory.API.Client;
using Vintagestory.API.Common;
using Vintagestory.API.Common.Entities;
using Vintagestory.API.Config;
using Vintagestory.API.Server;
using Vintagestory.GameContent;
namespace AriasServerUtils
{
public class ServerUtilities : ModSystem
{
public static string MOD_ID = "ariasserverutils";
public static ASUModConfig config = new ASUModConfig();
private static ICoreServerAPI API;
private static bool bDirty = false;
internal static Dictionary<string, PlayerInventory> backupInventory = new Dictionary<string, PlayerInventory>();
internal static Dictionary<string, PlayerStorage> mPlayerData = new Dictionary<string, PlayerStorage>();
internal static string[] saveInvTypes = new string[] {
GlobalConstants.hotBarInvClassName,
GlobalConstants.backpackInvClassName,
GlobalConstants.craftingInvClassName,
GlobalConstants.mousecursorInvClassName,
GlobalConstants.characterInvClassName
};
/// <summary>
/// Method to register all mod blocks
/// </summary>
/// <param name="api"></param>
private void RegisterBlocks(ICoreAPI api)
{
api.Logger.Notification("Begin registering block classes for Aria's Server Utils...");
api.Logger.Notification("Block Classes have been registered for Aria's Server Utils!");
}
private void RegisterBlockEntities(ICoreAPI api)
{
}
// Called on server and client
public override void Start(ICoreAPI api)
{
api.Logger.Notification(Lang.Get($"{MOD_ID}:start"));
RegisterBlocks(api);
RegisterBlockEntities(api);
}
public override void StartServerSide(ICoreServerAPI api)
{
API = api;
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.Event.PlayerDeath += OnPlayerDeath;
api.Event.PlayerJoin += OnPlayerJoin;
api.Event.PlayerDisconnect += OnPlayerDC;
//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("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.controlserver).HandleWith(Events.HandleListHomes);
api.ChatCommands.Create("asu")
.RequiresPrivilege(Privilege.chat)
.BeginSubCommand("update")
.BeginSubCommand("maxhomes")
.RequiresPrivilege(Privilege.controlserver)
.WithArgs(
parsers.Int("maxHomes")
)
.WithDescription("Updates the maximum number of homes")
.HandleWith(Events.HandleUpdateASUMaxHomes)
.EndSubCommand()
.BeginSubCommand("adminhomes")
.RequiresPrivilege(Privilege.controlserver)
.WithArgs(
parsers.Bool("adminsBypass")
)
.WithDescription("Updates the flag deciding whether admins can bypass max number of homes")
.HandleWith(Events.HandleUpdateASUBypass)
.EndSubCommand()
.WithDescription("Updates the ASU mod configuration")
.EndSubCommand()
.BeginSubCommand("help")
.RequiresPlayer()
.RequiresPrivilege(Privilege.chat)
.HandleWith(Events.HandleASU)
.WithDescription("Lists all Aria's Server Utils commands")
.EndSubCommand();
}
private void OnPlayerDC(IServerPlayer byPlayer)
{
OnCheckModDirty();
mPlayerData.Remove(byPlayer.PlayerName);
}
private void OnPlayerJoin(IServerPlayer byPlayer)
{
API.Logger.Notification($"[ASU] {Lang.Get($"{MOD_ID}:playerjoin")}");
PlayerStorage data = API.LoadModConfig<PlayerStorage>(GetConfigurationFile(byPlayer.PlayerName, ModConfigType.World));
if (data == null) data = new PlayerStorage();
mPlayerData[byPlayer.PlayerName] = data;
}
public static PlayerStorage GetPlayerData(IServerPlayer player)
{
if (mPlayerData.ContainsKey(player.PlayerName))
{
return mPlayerData[player.PlayerName];
}
else
{
return new PlayerStorage();
}
}
private TextCommandResult TestDeath(TextCommandCallingArgs args)
{
if (args.Caller.Player is IServerPlayer isp) OnPlayerDeath(isp, null);
return TextCommandResult.Success();
}
private void OnPlayerDeath(IServerPlayer player, DamageSource damageSource)
{
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());
API.Logger.Notification($"SAVED STORAGE ITEM TYPE: {stack.Itemstack}");
}
}
backupInventory[player.PlayerName] = inv;
}
private void OnCheckModDirty()
{
if (bDirty)
{
//API.Logger.Notification(Lang.Get($"{MOD_ID}:timer"));
bDirty = false;
SaveGlobalConfig();
SavePlayerData();
}
}
private void SavePlayerData()
{
foreach (var data in mPlayerData)
{
API.StoreModConfig<PlayerStorage>(data.Value, GetConfigurationFile(data.Key, ModConfigType.World));
}
}
private void OnShutdown()
{
// Mod Shutdown //
// Handle any remaining tasks before shutdown
API.Logger.Notification(Lang.Get($"{MOD_ID}:halt"));
OnCheckModDirty();
}
public void SaveGlobalConfig()
{
API.StoreModConfig<ASUModConfig>(config, GetConfigurationFile("global", ModConfigType.Global));
}
private void OnGameReady()
{
// Mod Setup Info //
// -> Step 1. Load Mod Global Config <-
config = API.LoadModConfig<ASUModConfig>(GetConfigurationFile("global", ModConfigType.Global));
if (config == null) config = new ASUModConfig();
}
public string GetConfigurationFile(string sName, ModConfigType type)
{
if (type == ModConfigType.Global)
{
return $"ariaserverconfig/{sName}.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)
{
api.Logger.Notification(Lang.Get($"{MOD_ID}:start"));
}
public static void SendMessageTo(IServerPlayer player, string sMsg)
{
player.SendMessage(0, sMsg, EnumChatType.CommandSuccess);
}
}
}