Implement the rtp function

#2
This commit is contained in:
zontreck 2025-03-06 16:48:41 -07:00
parent aedef3317c
commit 86ff08b9e7
5 changed files with 113 additions and 0 deletions

View file

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using Vintagestory.API.Client; using Vintagestory.API.Client;
using Vintagestory.API.Common; using Vintagestory.API.Common;
using Vintagestory.API.Common.CommandAbbr;
using Vintagestory.API.Common.Entities; using Vintagestory.API.Common.Entities;
using Vintagestory.API.Config; using Vintagestory.API.Config;
using Vintagestory.API.MathTools; using Vintagestory.API.MathTools;
@ -137,6 +138,14 @@ namespace AriasServerUtils
.WithDescription("Percentage of players required to sleep before sleeping through the night") .WithDescription("Percentage of players required to sleep before sleeping through the night")
.HandleWith(Events.HandleUpdateASUPSP) .HandleWith(Events.HandleUpdateASUPSP)
.EndSubCommand() .EndSubCommand()
.BeginSubCommand("rtp")
.RequiresPrivilege(Privilege.controlserver)
.WithArgs(
parsers.Int("maxDistance")
)
.WithDescription("Update RTP Max block distance. Plus and/or minus this distance from player current position")
.HandleWith(Events.HandleUpdateASURTPMax)
.EndSubCommand()
.EndSubCommand() .EndSubCommand()
.BeginSubCommand("help") .BeginSubCommand("help")
.RequiresPrivilege(Privilege.chat) .RequiresPrivilege(Privilege.chat)

View file

@ -4,6 +4,7 @@ using System.Linq;
using System.Text; using System.Text;
using Vintagestory.API.Common; using Vintagestory.API.Common;
using Vintagestory.API.Config; using Vintagestory.API.Config;
using Vintagestory.API.MathTools;
using Vintagestory.API.Server; using Vintagestory.API.Server;
namespace AriasServerUtils namespace AriasServerUtils
@ -41,6 +42,23 @@ namespace AriasServerUtils
internal static TextCommandResult HandleRTP(TextCommandCallingArgs args) internal static TextCommandResult HandleRTP(TextCommandCallingArgs args)
{ {
if (args.Caller is IServerPlayer isp)
{
ServerUtilities.SendMessageTo(isp, Lang.Get($"{ServerUtilities.MOD_ID}:rtp-search"));
PlayerPosition pPos = RTPFactory.GetRandomPosition(isp);
if (pPos == null)
{
ServerUtilities.SendMessageTo(isp, Lang.Get($"{ServerUtilities.MOD_ID}:rtp-fail"));
}
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);
ServerUtilities.SendMessageTo(isp, Lang.Get($"{ServerUtilities.MOD_ID}:rtp", distance));
}
return TextCommandResult.Success(); return TextCommandResult.Success();
} }
@ -349,5 +367,18 @@ namespace AriasServerUtils
return TextCommandResult.Success(); return TextCommandResult.Success();
} }
internal static TextCommandResult HandleUpdateASURTPMax(TextCommandCallingArgs args)
{
if (args[0] is int maxDist)
{
ServerUtilities.config.MaxRTPBlockDistance = maxDist;
ServerUtilities.MarkDirty();
return TextCommandResult.Success(Lang.Get($"{ServerUtilities.MOD_ID}:updatedconfig"));
}
return TextCommandResult.Success();
}
} }
} }

View file

@ -18,6 +18,7 @@ namespace AriasServerUtils
public bool onlyAdminsCreateWarps { get; set; } = true; public bool onlyAdminsCreateWarps { get; set; } = true;
public int MaxBackCache { get; set; } = 10; public int MaxBackCache { get; set; } = 10;
public int PlayerSleepingPercentage { get; set; } = 50; public int PlayerSleepingPercentage { get; set; } = 50;
public int MaxRTPBlockDistance { get; set; } = 5000;
public PlayerPosition Spawn { get; set; } public PlayerPosition Spawn { get; set; }

View file

@ -0,0 +1,71 @@
using System;
using System.Data;
using System.Numerics;
using AriasServerUtils;
using Vintagestory.API.Common;
using Vintagestory.API.Common.Entities;
using Vintagestory.API.MathTools;
using Vintagestory.API.Server;
using Vintagestory.GameContent;
public class RTPFactory
{
/// <summary>
/// This function searches for a safe position, honoring the max RTP distance in the global configuration
/// </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)
{
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 = 5;
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(-ServerUtilities.config.MaxRTPBlockDistance, ServerUtilities.config.MaxRTPBlockDistance);
bPos.Z = (int)vPos.Z + rng.Next(-ServerUtilities.config.MaxRTPBlockDistance, ServerUtilities.config.MaxRTPBlockDistance);
bPos.Y = 255;
Block lastAboveLast = null;
Block lastBlock = null;
Block curBlock;
// Scan downwards to find a valid landing spot
for (int i = 255; i > 50; i--)
{
bPos.Y = i;
curBlock = iswa.BlockAccessor.GetBlock(bPos);
if (curBlock != null && !curBlock.IsLiquid() && curBlock.MatterState == EnumMatterState.Solid)
{
if (lastBlock != null && lastBlock.MatterState == EnumMatterState.Gas &&
lastAboveLast != null && lastAboveLast.MatterState == EnumMatterState.Gas)
{
// 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
}
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));
}
}

View file

@ -34,6 +34,7 @@
"rtp-search": "Searching for a random position...", "rtp-search": "Searching for a random position...",
"rtp": "You have been teleported [{0}] blocks away!", "rtp": "You have been teleported [{0}] blocks away!",
"rtp-fail": "Giving up on RTP search. No valid position could be found. Try again later",
"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}]"
} }