mirror of
https://github.com/smartcmd/MinecraftConsoles.git
synced 2026-08-20 09:57:09 +00:00
add: restore the basic anti-cheat implementation and add spawn protection
Added the following anti-cheat measures and add spawn protection to `server.properties`. - instant break - speed - reach
This commit is contained in:
parent
797f73ba91
commit
48f0023d67
|
|
@ -569,6 +569,7 @@ MinecraftServer::MinecraftServer()
|
|||
playerIdleTimeout = 0;
|
||||
m_postUpdateThread = nullptr;
|
||||
forceGameType = false;
|
||||
m_spawnProtectionRadius = 0;
|
||||
|
||||
commandDispatcher = new ServerCommandDispatcher();
|
||||
InitializeCriticalSection(&m_consoleInputCS);
|
||||
|
|
@ -615,6 +616,10 @@ bool MinecraftServer::initServer(int64_t seed, NetworkGameInitData *initData, DW
|
|||
logger.info("Loading properties");
|
||||
#endif
|
||||
settings = new Settings(new File(L"server.properties"));
|
||||
// Dedicated-only: spawn-protection radius in blocks; 0 disables protection.
|
||||
m_spawnProtectionRadius = GetDedicatedServerInt(settings, L"spawn-protection", 0);
|
||||
if (m_spawnProtectionRadius < 0) m_spawnProtectionRadius = 0;
|
||||
if (m_spawnProtectionRadius > 256) m_spawnProtectionRadius = 256;
|
||||
|
||||
app.SetGameHostOption(eGameHostOption_Difficulty, GetDedicatedServerInt(settings, L"difficulty", app.GetGameHostOption(eGameHostOption_Difficulty)));
|
||||
app.SetGameHostOption(eGameHostOption_GameType, GetDedicatedServerInt(settings, L"gamemode", app.GetGameHostOption(eGameHostOption_GameType)));
|
||||
|
|
@ -631,6 +636,7 @@ bool MinecraftServer::initServer(int64_t seed, NetworkGameInitData *initData, DW
|
|||
app.DebugPrintf("ServerSettings: pvp is %s\n",(app.GetGameHostOption(eGameHostOption_PvP)>0)?"on":"off");
|
||||
app.DebugPrintf("ServerSettings: fire spreads is %s\n",(app.GetGameHostOption(eGameHostOption_FireSpreads)>0)?"on":"off");
|
||||
app.DebugPrintf("ServerSettings: tnt explodes is %s\n",(app.GetGameHostOption(eGameHostOption_TNT)>0)?"on":"off");
|
||||
app.DebugPrintf("ServerSettings: spawn protection radius is %d\n", m_spawnProtectionRadius);
|
||||
app.DebugPrintf("\n");
|
||||
|
||||
// TODO 4J Stu - Init a load of settings based on data passed as params
|
||||
|
|
@ -1661,7 +1667,9 @@ Level *MinecraftServer::getCommandSenderWorld()
|
|||
|
||||
int MinecraftServer::getSpawnProtectionRadius()
|
||||
{
|
||||
return 16;
|
||||
// Client-host mode must never apply dedicated-server spawn protection settings.
|
||||
if (!ShouldUseDedicatedServerProperties()) return 0;
|
||||
return m_spawnProtectionRadius;
|
||||
}
|
||||
|
||||
bool MinecraftServer::isUnderSpawnProtection(Level *level, int x, int y, int z, shared_ptr<Player> player)
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ public:
|
|||
int maxBuildHeight;
|
||||
int playerIdleTimeout;
|
||||
bool forceGameType;
|
||||
int m_spawnProtectionRadius;
|
||||
|
||||
private:
|
||||
// 4J Added
|
||||
|
|
|
|||
|
|
@ -38,6 +38,19 @@
|
|||
#include "..\Minecraft.Server\ServerLogManager.h"
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
// Anti-cheat thresholds. Keep server-side checks authoritative even in host mode.
|
||||
// Base max squared displacement allowed per move packet before speed flags trigger.
|
||||
const double kMoveBaseAllowanceSq = 100.0;
|
||||
// Extra squared displacement allowance derived from current server-side velocity.
|
||||
const double kMoveVelocityAllowanceScale = 100.0;
|
||||
// Max squared distance for interact/attack when the target is visible (normal reach).
|
||||
const double kInteractReachSq = 6.0 * 6.0;
|
||||
// Stricter max squared distance used when LOS is blocked to reduce wall-hit abuse.
|
||||
const double kInteractBlockedReachSq = 3.0 * 3.0;
|
||||
}
|
||||
|
||||
Random PlayerConnection::random;
|
||||
|
||||
|
||||
|
|
@ -300,16 +313,19 @@ void PlayerConnection::handleMovePlayer(shared_ptr<MovePlayerPacket> packet)
|
|||
|
||||
double dist = xDist * xDist + yDist * yDist + zDist * zDist;
|
||||
|
||||
// 4J-PB - removing this one for now
|
||||
/*if (dist > 100.0f)
|
||||
// Anti-cheat: reject movement packets that exceed server-authoritative bounds.
|
||||
double velocitySq = player->xd * player->xd + player->yd * player->yd + player->zd * player->zd;
|
||||
double maxAllowedSq = kMoveBaseAllowanceSq + (velocitySq * kMoveVelocityAllowanceScale);
|
||||
if (player->isAllowedToFly() || player->gameMode->isCreative())
|
||||
{
|
||||
// logger.warning(player->name + " moved too quickly!");
|
||||
disconnect(DisconnectPacket::eDisconnect_MovedTooQuickly);
|
||||
// System.out.println("Moved too quickly at " + xt + ", " + yt + ", " + zt);
|
||||
// teleport(player->x, player->y, player->z, player->yRot, player->xRot);
|
||||
return;
|
||||
// Creative / flight-allowed players can move farther legitimately per tick.
|
||||
maxAllowedSq *= 1.5;
|
||||
}
|
||||
if (dist > maxAllowedSq)
|
||||
{
|
||||
disconnect(DisconnectPacket::eDisconnect_MovedTooQuickly);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
float r = 1 / 16.0f;
|
||||
bool oldOk = level->getCubes(player, player->bb->copy()->shrink(r, r, r))->empty();
|
||||
|
|
@ -337,8 +353,8 @@ void PlayerConnection::handleMovePlayer(shared_ptr<MovePlayerPacket> packet)
|
|||
xDist = xt - player->x;
|
||||
yDist = yt - player->y;
|
||||
|
||||
// 4J-PB - line below will always be true!
|
||||
if (yDist > -0.5 || yDist < 0.5)
|
||||
// Clamp tiny Y drift noise to reduce false positives.
|
||||
if (yDist > -0.5 && yDist < 0.5)
|
||||
{
|
||||
yDist = 0;
|
||||
}
|
||||
|
|
@ -459,7 +475,8 @@ void PlayerConnection::handlePlayerAction(shared_ptr<PlayerActionPacket> packet)
|
|||
|
||||
if (packet->action == PlayerActionPacket::START_DESTROY_BLOCK)
|
||||
{
|
||||
if (true) player->gameMode->startDestroyBlock(x, y, z, packet->face); // 4J - condition was !server->isUnderSpawnProtection(level, x, y, z, player) (from Java 1.6.4) but putting back to old behaviour
|
||||
// Anti-cheat: validate spawn protection on the server for mining start.
|
||||
if (!server->isUnderSpawnProtection(level, x, y, z, player)) player->gameMode->startDestroyBlock(x, y, z, packet->face);
|
||||
else player->connection->send(std::make_shared<TileUpdatePacket>(x, y, z, level));
|
||||
|
||||
}
|
||||
|
|
@ -487,8 +504,6 @@ void PlayerConnection::handleUseItem(shared_ptr<UseItemPacket> packet)
|
|||
int face = packet->getFace();
|
||||
player->resetLastActionTime();
|
||||
|
||||
// 4J Stu - We don't have ops, so just use the levels setting
|
||||
bool canEditSpawn = level->canEditSpawn; // = level->dimension->id != 0 || server->players->isOp(player->name);
|
||||
if (packet->getFace() == 255)
|
||||
{
|
||||
if (item == nullptr) return;
|
||||
|
|
@ -498,7 +513,8 @@ void PlayerConnection::handleUseItem(shared_ptr<UseItemPacket> packet)
|
|||
{
|
||||
if (synched && player->distanceToSqr(x + 0.5, y + 0.5, z + 0.5) < 8 * 8)
|
||||
{
|
||||
if (true) // 4J - condition was !server->isUnderSpawnProtection(level, x, y, z, player) (from java 1.6.4) but putting back to old behaviour
|
||||
// Anti-cheat: block placement/use must pass server-side spawn protection.
|
||||
if (!server->isUnderSpawnProtection(level, x, y, z, player))
|
||||
{
|
||||
player->gameMode->useItemOn(player, level, item, x, y, z, face, packet->getClickX(), packet->getClickY(), packet->getClickZ());
|
||||
}
|
||||
|
|
@ -782,17 +798,16 @@ void PlayerConnection::handleInteract(shared_ptr<InteractPacket> packet)
|
|||
// 4J Stu - If the client says that we hit something, then agree with it. The canSee can fail here as it checks
|
||||
// a ray from head->head, but we may actually be looking at a different part of the entity that can be seen
|
||||
// even though the ray is blocked.
|
||||
if (target != nullptr) // && player->canSee(target) && player->distanceToSqr(target) < 6 * 6)
|
||||
if (target != nullptr)
|
||||
{
|
||||
//boole canSee = player->canSee(target);
|
||||
//double maxDist = 6 * 6;
|
||||
//if (!canSee)
|
||||
//{
|
||||
// maxDist = 3 * 3;
|
||||
//}
|
||||
// Anti-cheat: enforce reach and LOS on the server to reject forged hits.
|
||||
bool canSeeTarget = player->canSee(target);
|
||||
double maxDistSq = canSeeTarget ? kInteractReachSq : kInteractBlockedReachSq;
|
||||
if (player->distanceToSqr(target) > maxDistSq)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//if (player->distanceToSqr(target) < maxDist)
|
||||
//{
|
||||
if (packet->action == InteractPacket::INTERACT)
|
||||
{
|
||||
player->interact(target);
|
||||
|
|
@ -807,7 +822,6 @@ void PlayerConnection::handleInteract(shared_ptr<InteractPacket> packet)
|
|||
}
|
||||
player->attack(target);
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -176,31 +176,29 @@ void ServerPlayerGameMode::stopDestroyBlock(int x, int y, int z)
|
|||
{
|
||||
if (x == xDestroyBlock && y == yDestroyBlock && z == zDestroyBlock)
|
||||
{
|
||||
// int ticksSpentDestroying = gameTicks - destroyProgressStart;
|
||||
|
||||
int t = level->getTile(x, y, z);
|
||||
if (t != 0)
|
||||
{
|
||||
Tile *tile = Tile::tiles[t];
|
||||
|
||||
// MGH - removed checking for the destroy progress here, it has already been checked on the client before it sent the packet.
|
||||
// fixes issues with this failing to destroy because of packets bunching up
|
||||
// float destroyProgress = tile->getDestroyProgress(player, player->level, x, y, z) * (ticksSpentDestroying + 1);
|
||||
// if (destroyProgress >= .7f || bIgnoreDestroyProgress)
|
||||
// Anti-cheat: re-check destroy progress on the server for STOP_DESTROY.
|
||||
int ticksSpentDestroying = gameTicks - destroyProgressStart;
|
||||
float destroyProgress = tile->getDestroyProgress(player, player->level, x, y, z) * (ticksSpentDestroying + 1);
|
||||
if (destroyProgress >= 1.0f)
|
||||
{
|
||||
isDestroyingBlock = false;
|
||||
level->destroyTileProgress(player->entityId, x, y, z, -1);
|
||||
destroyBlock(x, y, z);
|
||||
}
|
||||
// else if (!hasDelayedDestroy)
|
||||
// {
|
||||
// isDestroyingBlock = false;
|
||||
// hasDelayedDestroy = true;
|
||||
// delayedDestroyX = x;
|
||||
// delayedDestroyY = y;
|
||||
// delayedDestroyZ = z;
|
||||
// delayedTickStart = destroyProgressStart;
|
||||
// }
|
||||
else if (!hasDelayedDestroy)
|
||||
{
|
||||
// Keep server-authoritative mining while allowing legit latency to finish via delayed tick progression.
|
||||
isDestroyingBlock = false;
|
||||
hasDelayedDestroy = true;
|
||||
delayedDestroyX = x;
|
||||
delayedDestroyY = y;
|
||||
delayedDestroyZ = z;
|
||||
delayedTickStart = destroyProgressStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -393,4 +391,4 @@ void ServerPlayerGameMode::setGameRules(GameRulesInstance *rules)
|
|||
{
|
||||
if(m_gameRules != nullptr) delete m_gameRules;
|
||||
m_gameRules = rules;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ static const ServerPropertyDefault kServerPropertyDefaults[] =
|
|||
{ "level-seed", "" },
|
||||
{ "level-type", "default" },
|
||||
{ "world-size", "classic" },
|
||||
{ "spawn-protection", "0" },
|
||||
{ "log-level", "info" },
|
||||
{ "max-build-height", "256" },
|
||||
{ "max-players", "16" },
|
||||
|
|
@ -834,6 +835,7 @@ ServerPropertiesConfig LoadServerPropertiesConfig()
|
|||
&config.worldHellScale,
|
||||
&shouldWrite);
|
||||
config.levelType = ReadNormalizedLevelTypeProperty(&merged, "level-type", &config.levelTypeFlat, &shouldWrite);
|
||||
config.spawnProtectionRadius = ReadNormalizedIntProperty(&merged, "spawn-protection", 0, 0, 256, &shouldWrite);
|
||||
config.generateStructures = ReadNormalizedBoolProperty(&merged, "generate-structures", true, &shouldWrite);
|
||||
config.bonusChest = ReadNormalizedBoolProperty(&merged, "bonus-chest", false, &shouldWrite);
|
||||
config.pvp = ReadNormalizedBoolProperty(&merged, "pvp", true, &shouldWrite);
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ namespace ServerRuntime
|
|||
/** Nether scale derived from `world-size` */
|
||||
int worldHellScale;
|
||||
bool levelTypeFlat;
|
||||
/** `spawn-protection` radius in blocks (0 disables protection) */
|
||||
int spawnProtectionRadius;
|
||||
bool generateStructures;
|
||||
bool bonusChest;
|
||||
bool pvp;
|
||||
|
|
|
|||
|
|
@ -409,6 +409,7 @@ int main(int argc, char **argv)
|
|||
accessShutdownGuard.Activate();
|
||||
LogInfof("startup", "LAN advertise: %s", serverProperties.lanAdvertise ? "enabled" : "disabled");
|
||||
LogInfof("startup", "Whitelist: %s", serverProperties.whiteListEnabled ? "enabled" : "disabled");
|
||||
LogInfof("startup", "Spawn protection radius: %d", serverProperties.spawnProtectionRadius);
|
||||
#ifdef _LARGE_WORLDS
|
||||
LogInfof(
|
||||
"startup",
|
||||
|
|
|
|||
Loading…
Reference in a new issue