generated from AriasCreations/vsmodtemplate
Compare commits
36 commits
Author | SHA1 | Date | |
---|---|---|---|
45b024654a | |||
419c05dbac | |||
9715975a48 | |||
7fb2d38c3d | |||
b00e56fdf7 | |||
12d10a9a3c | |||
e56a123cb8 | |||
4c585f647e | |||
7ca713e42a | |||
268834b434 | |||
11f52de3f7 | |||
37a1c8d361 | |||
3ab3dc099f | |||
d2b92f95c5 | |||
720dafea87 | |||
9a8b9d1545 | |||
c609dde0ee | |||
caf12dfade | |||
bda8e49ee1 | |||
cf7084c164 | |||
c69e1de64b | |||
5f99672a9b | |||
3712399a03 | |||
6598eb44da | |||
74d85c57e1 | |||
aad44f4c45 | |||
40f8eb4048 | |||
6e0dbb361a | |||
89e4835216 | |||
70fe822b0a | |||
2f1ac319de | |||
1b6586c9e8 | |||
29cf4e21b7 | |||
c5c605d057 | |||
700de94ffe | |||
cd00e620c3 |
7 changed files with 711 additions and 100 deletions
|
@ -7,6 +7,7 @@ using Vintagestory.API.Config;
|
|||
using Vintagestory.API.MathTools;
|
||||
using Vintagestory.API.Server;
|
||||
using Vintagestory.API.Util;
|
||||
using Vintagestory.GameContent;
|
||||
|
||||
namespace AriasServerUtils
|
||||
{
|
||||
|
@ -14,7 +15,7 @@ namespace AriasServerUtils
|
|||
{
|
||||
internal static TextCommandResult HandleASU(TextCommandCallingArgs args)
|
||||
{
|
||||
return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:help", ServerUtilities.config.MaxHomes, ServerUtilities.config.AdminsBypassMaxHomes, ServerUtilities.config.MaxBackCache, string.Join(", ", new string[] { "setspawn", "spawn", "delspawn", "sethome", "home", "delhome", "homes", "restoreinv", "asu", "warp", "setwarp", "delwarp", "warps", "back", "rtp" })));
|
||||
return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:help", ServerUtilities.config.MaxHomes, ServerUtilities.config.AdminsBypassMaxHomes, ServerUtilities.config.MaxBackCache, string.Join(", ", new string[] { "setspawn", "spawn", "delspawn", "sethome", "home", "delhome", "homes", "restoreinv", "asu", "warp", "setwarp", "delwarp", "warps", "back", "rtp", "listcooldowns" })));
|
||||
}
|
||||
|
||||
internal static TextCommandResult HandleBack(TextCommandCallingArgs args)
|
||||
|
@ -58,7 +59,7 @@ namespace AriasServerUtils
|
|||
if (args[0] is int ix)
|
||||
{
|
||||
if (ix == -1) ix = maxDistance;
|
||||
if (ix > maxDistance)
|
||||
if (ix > maxDistance && !(ServerUtilities.config.AdminsBypassRTPMaxDistance && isp.HasPrivilege(Privilege.controlserver)))
|
||||
{
|
||||
ServerUtilities.SendMessageTo(isp, Lang.Get($"{ServerUtilities.MOD_ID}:rtp-capped", ix, maxDistance));
|
||||
}
|
||||
|
@ -74,29 +75,7 @@ namespace AriasServerUtils
|
|||
|
||||
ServerUtilities.SendMessageTo(isp, Lang.Get($"{ServerUtilities.MOD_ID}:rtp-search"));
|
||||
|
||||
|
||||
PlayerPosition pPos = RTPFactory.GetRandomPosition(isp, maxDistance: maxDistance);
|
||||
if (pPos == null)
|
||||
{
|
||||
ps.ActiveCooldowns.Add(CooldownType.RTP, (TimeUtil.DecodeTimeNotation(ServerUtilities.config.Cooldowns.Get(CooldownType.RTP)) / 2) + TimeUtil.GetUnixEpochTimestamp());
|
||||
ServerUtilities.MarkDirty();
|
||||
|
||||
ServerUtilities.SendMessageTo(isp, Lang.Get($"{ServerUtilities.MOD_ID}:rtp-fail"));
|
||||
return TextCommandResult.Success();
|
||||
}
|
||||
Vec2i origin = new((int)isp.Entity.Pos.X, (int)isp.Entity.Pos.Z);
|
||||
Vec2i npos = new(pPos.X, pPos.Z);
|
||||
|
||||
float distance = RTPFactory.GetDistance(origin, npos);
|
||||
|
||||
pPos.Merge(isp.Entity);
|
||||
|
||||
|
||||
ps.ActiveCooldowns.Add(CooldownType.RTP, TimeUtil.DecodeTimeNotation(ServerUtilities.config.Cooldowns.Get(CooldownType.RTP)) + TimeUtil.GetUnixEpochTimestamp());
|
||||
ServerUtilities.MarkDirty();
|
||||
|
||||
ServerUtilities.SendMessageTo(isp, Lang.Get($"{ServerUtilities.MOD_ID}:rtp", distance));
|
||||
|
||||
RTPFactory.TryRTP(isp, maxDistance: maxDistance);
|
||||
}
|
||||
return TextCommandResult.Success();
|
||||
}
|
||||
|
@ -296,7 +275,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();
|
||||
|
@ -310,7 +289,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();
|
||||
|
@ -323,7 +302,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();
|
||||
|
@ -332,19 +311,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)
|
||||
|
@ -366,7 +358,7 @@ namespace AriasServerUtils
|
|||
ServerUtilities.NewBackCacheForPlayer(isp);
|
||||
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));
|
||||
|
||||
|
||||
|
||||
|
@ -452,7 +444,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();
|
||||
|
@ -465,7 +457,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
|
||||
{
|
||||
|
@ -483,7 +475,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
|
||||
{
|
||||
|
@ -501,7 +493,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
|
||||
{
|
||||
|
@ -519,7 +511,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
|
||||
{
|
||||
|
@ -537,7 +529,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
|
||||
{
|
||||
|
@ -555,5 +547,139 @@ namespace AriasServerUtils
|
|||
|
||||
return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:config-value-reset"));
|
||||
}
|
||||
|
||||
internal static TextCommandResult HandleUpdateASUBypassCD(TextCommandCallingArgs args)
|
||||
{
|
||||
if (args[0] is bool bypass)
|
||||
{
|
||||
// Update the bypass
|
||||
ServerUtilities.config.AdminsBypassCooldowns = bypass;
|
||||
ServerUtilities.MarkDirty();
|
||||
return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig", bypass));
|
||||
}
|
||||
else return TextCommandResult.Success();
|
||||
}
|
||||
|
||||
internal static TextCommandResult HandleUpdateASUBypassRTPMaxDist(TextCommandCallingArgs args)
|
||||
{
|
||||
if (args[0] is bool bypass)
|
||||
{
|
||||
// Update the flag
|
||||
ServerUtilities.config.AdminsBypassRTPMaxDistance = bypass;
|
||||
ServerUtilities.MarkDirty();
|
||||
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";
|
||||
foreach (var cd in ServerUtilities.config.Cooldowns)
|
||||
{
|
||||
sReturn += $"{cd.Key}: {cd.Value}\n";
|
||||
}
|
||||
if (args.Caller.Player is IServerPlayer isp)
|
||||
{
|
||||
sReturn += "\nYour active cooldowns:";
|
||||
foreach (var cd in ServerUtilities.GetPlayerData(isp).ActiveCooldowns)
|
||||
{
|
||||
long remain = cd.Value - TimeUtil.GetUnixEpochTimestamp();
|
||||
string sCDVal = TimeUtil.EncodeTimeNotation(remain);
|
||||
sReturn += $"{cd.Key}: {sCDVal}\n";
|
||||
}
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,23 +22,39 @@ namespace AriasServerUtils
|
|||
{ CooldownType.RTP, "30s" },
|
||||
{ CooldownType.Back, "5s" }
|
||||
};
|
||||
private static readonly int CURRENT_VERSION = 3;
|
||||
private static readonly int CURRENT_VERSION = 6;
|
||||
|
||||
|
||||
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; } = 5000;
|
||||
public int MaxRTPBlockDistance { get; set; } = 50000;
|
||||
public Dictionary<CooldownType, string> Cooldowns { get; set; } = new Dictionary<CooldownType, string>();
|
||||
|
||||
|
||||
/// <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()
|
||||
{
|
||||
return m_defaultCD;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs some checks against known possible invalid values and sets them to sane values.
|
||||
/// </summary>
|
||||
public void SanityCheck()
|
||||
{
|
||||
foreach (var cd in GetDefaultCooldowns())
|
||||
|
|
19
AriasServerUtils/ModSystems/ASUClient.cs
Normal file
19
AriasServerUtils/ModSystems/ASUClient.cs
Normal file
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
using Vintagestory.API.Client;
|
||||
using Vintagestory.API.Common;
|
||||
|
||||
public class ASUModClient : ModSystem
|
||||
{
|
||||
public static ICoreClientAPI CAPI;
|
||||
bool accel = false;
|
||||
|
||||
public override bool ShouldLoad(EnumAppSide forSide)
|
||||
{
|
||||
return forSide == EnumAppSide.Client;
|
||||
}
|
||||
|
||||
public override void StartClientSide(ICoreClientAPI api)
|
||||
{
|
||||
CAPI = api;
|
||||
}
|
||||
}
|
|
@ -1,11 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Vintagestory.API.Client;
|
||||
using Vintagestory.API.Common;
|
||||
using Vintagestory.API.Common.CommandAbbr;
|
||||
using Vintagestory.API.Common.Entities;
|
||||
using Vintagestory.API.Config;
|
||||
using Vintagestory.API.Datastructures;
|
||||
using Vintagestory.API.MathTools;
|
||||
using Vintagestory.API.Server;
|
||||
using Vintagestory.API.Util;
|
||||
|
@ -17,7 +19,7 @@ namespace AriasServerUtils
|
|||
{
|
||||
public static string MOD_ID = "ariasserverutils";
|
||||
public static ASUModConfig config = new ASUModConfig();
|
||||
private static ICoreServerAPI API;
|
||||
internal static ICoreServerAPI API;
|
||||
private static bool bDirty = false;
|
||||
internal static Dictionary<string, PlayerInventory> backupInventory = new Dictionary<string, PlayerInventory>();
|
||||
|
||||
|
@ -26,6 +28,8 @@ namespace AriasServerUtils
|
|||
internal static BackCaches backCaches = new BackCaches();
|
||||
|
||||
internal static Warps serverWarps = new Warps();
|
||||
internal static Random rng = new Random((int)TimeUtil.GetUnixEpochTimestamp());
|
||||
internal bool isFirstStart = true;
|
||||
|
||||
|
||||
internal static string[] saveInvTypes = new string[] {
|
||||
|
@ -36,6 +40,12 @@ namespace AriasServerUtils
|
|||
GlobalConstants.characterInvClassName
|
||||
};
|
||||
|
||||
List<EntityAgent> SleepingPlayers { get; set; } = new();
|
||||
float OriginalSpeed { get; set; } = 0.0f;
|
||||
public double Hours { get; private set; } = 0.0;
|
||||
bool Sleeping { get; set; } = false;
|
||||
public IServerNetworkChannel ServerNetworkChannel { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Method to register all mod blocks
|
||||
/// </summary>
|
||||
|
@ -54,6 +64,14 @@ namespace AriasServerUtils
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
public override bool ShouldLoad(EnumAppSide side)
|
||||
{
|
||||
return side == EnumAppSide.Server;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Called on server and client
|
||||
public override void Start(ICoreAPI api)
|
||||
{
|
||||
|
@ -72,11 +90,11 @@ namespace AriasServerUtils
|
|||
|
||||
api.Event.ServerRunPhase(EnumServerRunPhase.GameReady, OnGameReady);
|
||||
api.Event.ServerRunPhase(EnumServerRunPhase.Shutdown, OnShutdown);
|
||||
api.Event.Timer(OnCheckModDirty, 20);
|
||||
api.Event.Timer(OnCheckPlayerCooldowns, 1);
|
||||
api.Event.PlayerDeath += OnPlayerDeath;
|
||||
api.Event.PlayerJoin += OnPlayerJoin;
|
||||
api.Event.PlayerDisconnect += OnPlayerDC;
|
||||
api.Event.ChunkColumnLoaded += RTPFactory.ChunkLoaded;
|
||||
api.Event.BreakBlock += Events.CheckBreakFarmland;
|
||||
//api.Event.PlayerLeave += OnPlayerDC;
|
||||
|
||||
|
||||
|
@ -124,6 +142,22 @@ namespace AriasServerUtils
|
|||
.WithDescription("DANGER: This updates the flag allowing anybody to create warps, even non-admins. It is recommended to leave this alone. The default is true/on/yes")
|
||||
.HandleWith(Events.HandleUpdateASUMgrWarps)
|
||||
.EndSubCommand()
|
||||
.BeginSubCommand("adminBypassCooldown")
|
||||
.RequiresPrivilege(Privilege.controlserver)
|
||||
.WithArgs(
|
||||
parsers.Bool("bypass")
|
||||
)
|
||||
.WithDescription("This flag controls whether admins can or can not bypass the cooldown system (Default: true)")
|
||||
.HandleWith(Events.HandleUpdateASUBypassCD)
|
||||
.EndSubCommand()
|
||||
.BeginSubCommand("adminsBypassRTPMaxDist")
|
||||
.RequiresPrivilege(Privilege.controlserver)
|
||||
.WithArgs(
|
||||
parsers.Bool("bypass")
|
||||
)
|
||||
.WithDescription("This flag would allow admins to go further than the max server RTP distance when manually specifying a distance to RTP (Default: false)")
|
||||
.HandleWith(Events.HandleUpdateASUBypassRTPMaxDist)
|
||||
.EndSubCommand()
|
||||
.BeginSubCommand("maxback")
|
||||
.RequiresPrivilege(Privilege.controlserver)
|
||||
.WithArgs(
|
||||
|
@ -145,9 +179,21 @@ namespace AriasServerUtils
|
|||
.WithArgs(
|
||||
parsers.Int("maxDistance")
|
||||
)
|
||||
.WithDescription("Update RTP Max block distance. Plus and/or minus this distance from player current position")
|
||||
.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")
|
||||
|
@ -201,6 +247,20 @@ namespace AriasServerUtils
|
|||
.RequiresPrivilege(Privilege.chat)
|
||||
.HandleWith(Events.HandleASU)
|
||||
.WithDescription("Lists all Aria's Server Utils commands")
|
||||
.EndSubCommand()
|
||||
.BeginSubCommand("test")
|
||||
.RequiresPlayer()
|
||||
.RequiresPrivilege(Privilege.controlserver)
|
||||
.BeginSubCommand("sleep")
|
||||
.RequiresPlayer()
|
||||
.RequiresPrivilege(Privilege.controlserver)
|
||||
.HandleWith(TestSleep)
|
||||
.EndSubCommand()
|
||||
.BeginSubCommand("sleepy")
|
||||
.RequiresPlayer()
|
||||
.RequiresPrivilege(Privilege.controlserver)
|
||||
.HandleWith(Events.HandleSleepyDebug)
|
||||
.EndSubCommand()
|
||||
.EndSubCommand();
|
||||
|
||||
api.ChatCommands.Create("setwarp").RequiresPlayer().RequiresPrivilege(Privilege.chat).WithDescription("Creates a new server warp").WithArgs(parsers.OptionalWord("name")).HandleWith(Events.HandleWarpUpdate);
|
||||
|
@ -211,12 +271,176 @@ namespace AriasServerUtils
|
|||
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("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)
|
||||
{
|
||||
// Initiate the sleep process
|
||||
// Basically run all the same commands as we would on a player in bed
|
||||
Events.HandleSleepyDebug(args);
|
||||
|
||||
OriginalSpeed = API.World.Calendar.CalendarSpeedMul;
|
||||
if (args.Caller.Player is IServerPlayer isp)
|
||||
{
|
||||
Hours = API.World.Calendar.TotalHours;
|
||||
SleepingPlayers.Add(isp.Entity);
|
||||
API.Logger.Notification($"Game Hours: {API.World.Calendar.TotalHours}, Difference: {API.World.Calendar.TotalHours - Hours}");
|
||||
EntityAgent Agent = isp.Entity;
|
||||
|
||||
EntityBehaviorTiredness ebt = Agent.GetBehavior<EntityBehaviorTiredness>();
|
||||
|
||||
ebt.IsSleeping = true;
|
||||
ebt.Tiredness = 100;
|
||||
Sleeping = true;
|
||||
|
||||
API.World.Calendar.SetTimeSpeedModifier("asu_psp", 1000);
|
||||
}
|
||||
|
||||
return TextCommandResult.Success($"Test initiated, original calendar multiplier: '{OriginalSpeed}'");
|
||||
}
|
||||
|
||||
private TextCommandResult TestCalendarSpeed(TextCommandCallingArgs args)
|
||||
{
|
||||
if (args.Caller.Player is IServerPlayer isp)
|
||||
{
|
||||
EntityAgent agent = isp.Entity;
|
||||
EntityBehaviorTiredness ebt = agent.GetBehavior("tiredness") as EntityBehaviorTiredness;
|
||||
|
||||
SendMessageTo(isp, $"- Current calendar speed: {API.World.Calendar.CalendarSpeedMul}");
|
||||
SendMessageTo(isp, $"- Total Hours: {API.World.Calendar.TotalHours}");
|
||||
SendMessageTo(isp, $"- Tiredness: {ebt.Tiredness}");
|
||||
if (OriginalSpeed == 0)
|
||||
{
|
||||
// Apply multiplier
|
||||
OriginalSpeed = 0.5f;
|
||||
ebt.IsSleeping = true;
|
||||
|
||||
API.World.Calendar.SetTimeSpeedModifier("asu_psp", 1000);
|
||||
|
||||
SendMessageTo(isp, "Applied calendar speed multiplier");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unapply multiplier
|
||||
OriginalSpeed = 0;
|
||||
ebt.IsSleeping = false;
|
||||
|
||||
API.World.Calendar.RemoveTimeSpeedModifier("asu_psp");
|
||||
|
||||
SendMessageTo(isp, "Restored default calendar speed");
|
||||
}
|
||||
}
|
||||
|
||||
return TextCommandResult.Success();
|
||||
}
|
||||
|
||||
private void OnCheckSleepingPlayers()
|
||||
{
|
||||
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)
|
||||
{
|
||||
//API.Logger.Notification($"Game Hours: {API.World.Calendar.TotalHours}, Difference: {API.World.Calendar.TotalHours - Hours}");
|
||||
if (API.World.Calendar.TotalHours - Hours >= 6)
|
||||
{
|
||||
Sleeping = false;
|
||||
foreach (var player in SleepingPlayers)
|
||||
{
|
||||
EntityBehaviorTiredness ebt = player.GetBehavior<EntityBehaviorTiredness>();
|
||||
ebt.IsSleeping = false;
|
||||
ebt.Tiredness = 0;
|
||||
}
|
||||
|
||||
SleepingPlayers.Clear();
|
||||
|
||||
API.World.Calendar.RemoveTimeSpeedModifier("asu_psp");
|
||||
|
||||
//API.Logger.Notification("Stopping PSP Time Acceleration");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (config.PlayerSleepingPercentage == 100) return; // Normal behavior
|
||||
// Iterate over all players, get their entity, check if mounted on a bed.
|
||||
// If mounted on a bed, check tiredness
|
||||
int TotalOnline = API.World.AllOnlinePlayers.Length;
|
||||
if (TotalOnline == 0) return; // No one on, just abort the checks.
|
||||
int TotalInBed = 0;
|
||||
|
||||
List<BlockEntityBed> BEBs = new();
|
||||
|
||||
foreach (var player in API.World.AllOnlinePlayers)
|
||||
{
|
||||
EntityAgent ePlay = player.Entity;
|
||||
if (ePlay.MountedOn is BlockEntityBed beb)
|
||||
{
|
||||
BEBs.Add(beb);
|
||||
TotalInBed++;
|
||||
//API.Logger.Notification($"Bed found for player {player.PlayerName}");
|
||||
}
|
||||
if (ePlay.MountedOn == null)
|
||||
{
|
||||
//API.Logger.Notification($"No bed found for player {player.PlayerName}");
|
||||
|
||||
if (SleepingPlayers.Contains(ePlay))
|
||||
{
|
||||
EntityBehaviorTiredness ebt = ePlay.GetBehavior<EntityBehaviorTiredness>();
|
||||
if (ebt != null)
|
||||
ebt.IsSleeping = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Sleeping) return; // Abort
|
||||
|
||||
SleepingPlayers.Clear();
|
||||
|
||||
int Percentage = TotalInBed * 100 / TotalOnline;
|
||||
|
||||
//API.Logger.Notification($"Percentage of players in bed: {Percentage}, Required percentage: {config.PlayerSleepingPercentage}");
|
||||
|
||||
if (Percentage >= config.PlayerSleepingPercentage)
|
||||
{
|
||||
|
||||
API.World.Calendar.SetTimeSpeedModifier("asu_psp", 1000);
|
||||
|
||||
// Call the API to make sleep happen
|
||||
foreach (var bed in BEBs)
|
||||
{
|
||||
if (bed.MountedBy != null) SleepingPlayers.Add(bed.MountedBy);
|
||||
|
||||
// Start sleep
|
||||
EntityBehaviorTiredness EBT = bed.MountedBy.GetBehavior<EntityBehaviorTiredness>();
|
||||
|
||||
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.
|
||||
}
|
||||
|
||||
// Get current calendar speed
|
||||
Hours = API.World.Calendar.TotalHours;
|
||||
Sleeping = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCheckPlayerCooldowns()
|
||||
{
|
||||
foreach (var cdEntry in ServerUtilities.mPlayerData)
|
||||
{
|
||||
// Obtain the IServerPlayer instance for this player.
|
||||
IServerPlayer player = API.Server.Players.First(x => x.PlayerName == cdEntry.Key);
|
||||
if (player.HasPrivilege(Privilege.controlserver) && ServerUtilities.config.AdminsBypassCooldowns)
|
||||
{
|
||||
cdEntry.Value.ActiveCooldowns.Clear(); // Problem solved.
|
||||
}
|
||||
List<CooldownType> toRemove = new();
|
||||
foreach (var cd in cdEntry.Value.ActiveCooldowns)
|
||||
{
|
||||
|
@ -367,6 +591,13 @@ namespace AriasServerUtils
|
|||
// -> Step 3. Load Mod Warps <-
|
||||
serverWarps = API.LoadModConfig<Warps>(GetConfigurationFile("warps", ModConfigType.Global));
|
||||
if (serverWarps == null) serverWarps = new Warps();
|
||||
|
||||
|
||||
|
||||
API.Event.Timer(OnCheckModDirty, 20);
|
||||
API.Event.Timer(OnCheckPlayerCooldowns, 1);
|
||||
API.Event.Timer(OnCheckSleepingPlayers, 5);
|
||||
API.Event.Timer(RTPFactory.HandleRTPChecking, 1);
|
||||
}
|
||||
|
||||
public string GetConfigurationFile(string sName, ModConfigType type)
|
|
@ -1,9 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using AriasServerUtils;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using Vintagestory.API.Common;
|
||||
using Vintagestory.API.Common.Entities;
|
||||
using Vintagestory.API.Config;
|
||||
using Vintagestory.API.MathTools;
|
||||
using Vintagestory.API.Server;
|
||||
using Vintagestory.GameContent;
|
||||
|
@ -11,65 +15,272 @@ using Vintagestory.GameContent;
|
|||
namespace AriasServerUtils;
|
||||
public class RTPFactory
|
||||
{
|
||||
|
||||
private static List<RTPData> RTPCache = new();
|
||||
private static List<RTPChunk> ChunkChecks = new();
|
||||
|
||||
/*
|
||||
if (pPos == null)
|
||||
{
|
||||
ps.ActiveCooldowns.Add(CooldownType.RTP, (TimeUtil.DecodeTimeNotation(ServerUtilities.config.Cooldowns.Get(CooldownType.RTP)) / 2) + TimeUtil.GetUnixEpochTimestamp());
|
||||
ServerUtilities.MarkDirty();
|
||||
|
||||
ServerUtilities.SendMessageTo(isp, Lang.Get($"{ServerUtilities.MOD_ID}:rtp-fail"));
|
||||
return TextCommandResult.Success();
|
||||
}
|
||||
Vec2i origin = new((int)isp.Entity.Pos.X, (int)isp.Entity.Pos.Z);
|
||||
Vec2i npos = new(pPos.X, pPos.Z);
|
||||
|
||||
float distance = RTPFactory.GetDistance(origin, npos);
|
||||
|
||||
pPos.Merge(isp.Entity);
|
||||
|
||||
|
||||
ps.ActiveCooldowns.Add(CooldownType.RTP, TimeUtil.DecodeTimeNotation(ServerUtilities.config.Cooldowns.Get(CooldownType.RTP)) + TimeUtil.GetUnixEpochTimestamp());
|
||||
ServerUtilities.MarkDirty();
|
||||
|
||||
ServerUtilities.SendMessageTo(isp, Lang.Get($"{ServerUtilities.MOD_ID}:rtp", distance));
|
||||
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// This function searches for a safe position, honoring the max RTP distance in the global configuration
|
||||
/// This function searches for a safe position
|
||||
/// </summary>
|
||||
/// <param name="isp">The player to be teleported</param>
|
||||
/// <returns>A random position +/- max distance from current position.</returns>
|
||||
public static PlayerPosition GetRandomPosition(IServerPlayer isp, int maxDistance)
|
||||
/// <returns>A safe position if able to be found</returns>
|
||||
public static PlayerPosition GetSafePosition(RTPData data, RTPPosition position)
|
||||
{
|
||||
Random rng = new Random();
|
||||
EntityPos vPos = isp.Entity.Pos;
|
||||
BlockPos bPos = new BlockPos(isp.Entity.Pos.Dimension);
|
||||
IServerWorldAccessor iswa = isp.Entity.World as IServerWorldAccessor;
|
||||
|
||||
int tries = 1000;
|
||||
PlayerPosition PPos = PlayerPosition.from(isp.Entity);
|
||||
|
||||
while (tries-- > 0)
|
||||
{
|
||||
// Generate random X and Z within max RTP distance
|
||||
bPos.X = (int)vPos.X + rng.Next(0, maxDistance);
|
||||
bPos.Z = (int)vPos.Z + rng.Next(0, maxDistance);
|
||||
bPos.Y = 255;
|
||||
|
||||
if (rng.Next(0, 1) == 1) bPos.X = -bPos.X;
|
||||
if (rng.Next(0, 1) == 1) bPos.Z = -bPos.Z;
|
||||
|
||||
Block lastAboveLast = null;
|
||||
Block lastBlock = null;
|
||||
Block curBlock;
|
||||
|
||||
// Scan downwards to find a valid landing spot
|
||||
for (int i = 255; i > 0; i--)
|
||||
{
|
||||
bPos.Y = i;
|
||||
curBlock = iswa.BlockAccessor.GetBlock(bPos);
|
||||
|
||||
if (curBlock.MatterState == EnumMatterState.Solid)
|
||||
{
|
||||
if (lastBlock != null && lastBlock.BlockMaterial == EnumBlockMaterial.Air &&
|
||||
lastAboveLast != null && lastAboveLast.BlockMaterial == EnumBlockMaterial.Air)
|
||||
{
|
||||
// Found a valid spot: curBlock is solid, lastBlock & lastAboveLast are gas (air)
|
||||
PPos.X = bPos.X;
|
||||
PPos.Y = bPos.Y + 1;
|
||||
PPos.Z = bPos.Z;
|
||||
|
||||
return PPos;
|
||||
}
|
||||
}
|
||||
|
||||
lastAboveLast = lastBlock;
|
||||
lastBlock = curBlock;
|
||||
}
|
||||
}
|
||||
|
||||
return null; // Return null if no valid position is found after retries
|
||||
PlayerPosition PPos = data.LastPosition.GetPlayerPosition();
|
||||
BlockPos check = data.LastPosition.GetBlockPos();
|
||||
var BA = ServerUtilities.API.World.BlockAccessor;
|
||||
check.Y = 1;
|
||||
int height = BA.GetTerrainMapheightAt(check);
|
||||
if (height >= 0 && height <= 20) return null;
|
||||
check.Y = height + 1;
|
||||
PPos.Y = height + 1;
|
||||
return PPos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function will schedule a task to perform an RTP.
|
||||
/// </summary>
|
||||
/// <param name="isp">Player to be teleported</param>
|
||||
/// <param name="maxDistance">Max distance +/- the current position.</param>
|
||||
public static void TryRTP(IServerPlayer isp, int maxDistance)
|
||||
{
|
||||
var data = new RTPData(isp, maxDistance, 10, PlayerPosition.from(isp.Entity));
|
||||
RTPCache.Add(data);
|
||||
}
|
||||
|
||||
public static float GetDistance(Vec2i pos1, Vec2i pos2)
|
||||
{
|
||||
return MathF.Sqrt(MathF.Pow(pos2.X - pos1.X, 2) + MathF.Pow(pos2.Y - pos1.Y, 2));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fired automatically by the internal game timer. This function will handle checking for a RTP Location
|
||||
///
|
||||
/// NOTE: This function will only cause the chunks in question to be force loaded long enough to check their blocks and make sure it is safe to land there.
|
||||
/// </summary>
|
||||
internal static void HandleRTPChecking()
|
||||
{
|
||||
foreach (var chunk in ChunkChecks)
|
||||
{
|
||||
chunk.Wait--;
|
||||
if (chunk.Wait <= 0)
|
||||
{
|
||||
ChunkChecks.Remove(chunk);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// We want to now loop over the entire cache list.
|
||||
// We'll then generate a position to check
|
||||
// We'll also then check the loaded status of the chunk
|
||||
foreach (var rtp in RTPCache)
|
||||
{
|
||||
// Check for any chunks still being checked.
|
||||
int num = ChunkChecks.Select(x => x.rtp.player.PlayerUID == rtp.player.PlayerUID).Count();
|
||||
if (num > 0) continue;
|
||||
|
||||
|
||||
if (rtp.NumTriesRemaining <= 0)
|
||||
{
|
||||
// Send failure message to the player
|
||||
ServerUtilities.SendMessageTo(rtp.player, Lang.Get($"{ServerUtilities.MOD_ID}:rtp-fail"));
|
||||
// This check needs to be removed from the queue
|
||||
RTPCache.Remove(rtp);
|
||||
HandleRTPChecking();
|
||||
return; // We modified the list, so abort the loop.
|
||||
}
|
||||
|
||||
// Get the world handle, then get chunk size
|
||||
var worldManager = ServerUtilities.API.WorldManager;
|
||||
var chunkSize = worldManager.ChunkSize;
|
||||
var worldSize = new Vec3i(worldManager.MapSizeX, worldManager.MapSizeY, worldManager.MapSizeZ);
|
||||
|
||||
// Generate a new position
|
||||
var position = rtp.MakeNewPosition(worldSize);
|
||||
ServerUtilities.SendMessageTo(rtp.player, Lang.Get($"{ServerUtilities.MOD_ID}:rtp-progress", rtp.NumTriesRemaining));
|
||||
|
||||
// Generate a chunk load check object.
|
||||
RTPChunk chunk = new RTPChunk();
|
||||
chunk.ChunkX = position.x / chunkSize;
|
||||
chunk.ChunkZ = position.z / chunkSize;
|
||||
chunk.dim = position.dimension;
|
||||
chunk.rtp = rtp;
|
||||
|
||||
// Log the request
|
||||
ChunkChecks.Add(chunk);
|
||||
|
||||
// Check if the chunk's coordinates are loaded
|
||||
var cxCheck = ServerUtilities.API.World.IsFullyLoadedChunk(position.GetBlockPos());
|
||||
if (cxCheck)
|
||||
{
|
||||
// Process the check here, no need to load
|
||||
var posX = GetSafePosition(rtp, position);
|
||||
if (posX == null)
|
||||
{
|
||||
// Let this get checked again
|
||||
//ServerUtilities.API.Logger.Notification("position null: resume search");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Found! Perform teleport and remove the RTP Check
|
||||
RTPCache.Remove(rtp);
|
||||
posX.Merge(rtp.player.Entity);
|
||||
|
||||
ServerUtilities.SendMessageTo(rtp.player, Lang.Get($"{ServerUtilities.MOD_ID}:rtp", GetDistance(new Vec2i(rtp.StartPosition.X, rtp.StartPosition.Z), new Vec2i(posX.X, posX.Z))));
|
||||
|
||||
//ServerUtilities.API.Logger.Notification("position found");
|
||||
}
|
||||
|
||||
ChunkChecks.Remove(chunk);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load the chunk
|
||||
worldManager.LoadChunkColumnPriority(chunk.ChunkX, chunk.ChunkZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static void ChunkLoaded(Vec2i chunkCoord, IWorldChunk[] chunks)
|
||||
{
|
||||
// Check if this is even a valid check
|
||||
var num = ChunkChecks.Where(x => x.ChunkX == chunkCoord.X && x.ChunkZ == chunkCoord.Y).Count();
|
||||
if (num == 0) return;
|
||||
|
||||
|
||||
// Get the chunk from the stack
|
||||
var chunk = ChunkChecks.Where(x => x.ChunkX == chunkCoord.X && x.ChunkZ == chunkCoord.Y).First();
|
||||
|
||||
// Attempt to find a landing point.
|
||||
var data = chunk.rtp;
|
||||
var pos = GetSafePosition(data, data.LastPosition);
|
||||
|
||||
if (pos == null)
|
||||
{
|
||||
// Let this get checked again
|
||||
//ServerUtilities.API.Logger.Notification("position null: resume search");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Found! Perform teleport and remove the RTP Check
|
||||
RTPCache.Remove(data);
|
||||
pos.Merge(data.player.Entity);
|
||||
|
||||
ServerUtilities.SendMessageTo(data.player, Lang.Get($"{ServerUtilities.MOD_ID}:rtp", GetDistance(new Vec2i(data.StartPosition.X, data.StartPosition.Z), new Vec2i(pos.X, pos.Z))));
|
||||
|
||||
//ServerUtilities.API.Logger.Notification("position found");
|
||||
}
|
||||
|
||||
// Remove this check
|
||||
ChunkChecks.Remove(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
public class RTPChunk
|
||||
{
|
||||
public int ChunkX;
|
||||
public int ChunkZ;
|
||||
public int dim;
|
||||
public RTPData rtp;
|
||||
public int Wait = 5;
|
||||
}
|
||||
|
||||
public class RTPData
|
||||
{
|
||||
public IServerPlayer player;
|
||||
public int NumTriesRemaining;
|
||||
public int MaxDistance;
|
||||
public PlayerPosition StartPosition;
|
||||
public RTPPosition LastPosition;
|
||||
|
||||
public RTPData(IServerPlayer isp, int maxDistance, int tries, PlayerPosition playerPosition)
|
||||
{
|
||||
MaxDistance = maxDistance;
|
||||
player = isp;
|
||||
NumTriesRemaining = tries;
|
||||
StartPosition = playerPosition;
|
||||
}
|
||||
|
||||
public RTPPosition MakeNewPosition(Vec3i mapSize)
|
||||
{
|
||||
NumTriesRemaining--;
|
||||
LastPosition = new RTPPosition((int)player.Entity.Pos.X, (int)player.Entity.Pos.Z, MaxDistance, player.Entity.Pos.Dimension, mapSize, player);
|
||||
|
||||
return LastPosition;
|
||||
}
|
||||
}
|
||||
|
||||
public class RTPPosition
|
||||
{
|
||||
public int x;
|
||||
public int y;
|
||||
public int z;
|
||||
|
||||
public int dimension;
|
||||
|
||||
public RTPPosition(int x, int z, int maxDist, int dim, Vec3i mapSize, IServerPlayer player)
|
||||
{
|
||||
|
||||
int worldx = mapSize.X / 2;
|
||||
int worldz = mapSize.Z / 2;
|
||||
|
||||
if (maxDist > worldx)
|
||||
{
|
||||
ServerUtilities.SendMessageTo(player, Lang.Get($"{ServerUtilities.MOD_ID}:rtp-capped", maxDist, (worldx)));
|
||||
maxDist = worldx / 2;
|
||||
}
|
||||
|
||||
int minX = x - maxDist;
|
||||
int maxX = x + maxDist;
|
||||
int minZ = z - maxDist;
|
||||
int maxZ = z + maxDist;
|
||||
|
||||
this.x = ServerUtilities.rng.Next(minX, maxX);
|
||||
this.y = 1;
|
||||
this.z = ServerUtilities.rng.Next(minZ, maxZ);
|
||||
|
||||
|
||||
|
||||
this.dimension = dim;
|
||||
}
|
||||
|
||||
public PlayerPosition GetPlayerPosition()
|
||||
{
|
||||
return new PlayerPosition
|
||||
{
|
||||
X = x,
|
||||
Y = y,
|
||||
Dimension = dimension,
|
||||
Z = z
|
||||
};
|
||||
}
|
||||
|
||||
public BlockPos GetBlockPos()
|
||||
{
|
||||
return new BlockPos(new Vec3i(x, y, z), dimension);
|
||||
}
|
||||
}
|
|
@ -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",
|
||||
|
@ -34,9 +37,14 @@
|
|||
"back": "You've been taken back to your last position",
|
||||
|
||||
"rtp-search": "Searching for a random position...",
|
||||
"rtp-progress": "Still searching for a random position... [{0}] tries remaining...",
|
||||
"rtp": "You have been teleported [{0}] blocks away!",
|
||||
"rtp-found": "Found a valid landing position after {0} tries.",
|
||||
"rtp-fail": "Giving up on RTP search. No valid position could be found. Try again later",
|
||||
"rtp-capped": "The distance you tried to go [{0}] is greater than the maximum allowable by the server [{1}]",
|
||||
|
||||
"cmd-cooldown": "[{0}] is currently on cooldown. You can use this command again in [{1}]"
|
||||
"cmd-cooldown": "[{0}] is currently on cooldown. You can use this command again in [{1}]",
|
||||
|
||||
"psp": "[ASU] PSP Starting... you do not need to stay in bed",
|
||||
"psp-ending": "[ASU] PSP Complete"
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
"modid": "ariasserverutils",
|
||||
"name": "Aria's Server Utilities",
|
||||
"authors": ["zontreck"],
|
||||
"description": "A collection of server utilities\n\nBuild Date: 03-07-2025 @ 1:28 AM MST",
|
||||
"version": "1.0.5",
|
||||
"description": "A collection of server utilities\n\nBuild Date: 05-7-2025 @ 12:21 PM MST",
|
||||
"version": "1.0.11",
|
||||
"dependencies": {
|
||||
"game": ""
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue