Implement persistent hardcore death bans (XUID + IP) for dedicated server

On the dedicated server, hardcore death now persists XUID and IP bans to
banned-players.json and banned-ips.json via the Access system, and
disconnects the player. Bans survive server restarts. Client-hosted games
retain the existing in-memory XUID ban with force-save behavior.

- Add hardcore property to server.properties (forces Hard difficulty)
- Add LevelData::setHardcore() so loaded worlds respect the server config
- Add PlayerList::banPlayerForHardcoreDeath() with persistent XUID + IP bans
- Reject respawn requests server-side in hardcore mode
- Ensure server-side player ticks run without move packets (fixes
  environmental damage not applying for some clients)
- Restore 0x8 hardcore bit on LoginPacket/RespawnPacket wire format so
  the client-side death screen detects hardcore mode correctly
This commit is contained in:
Revela
2026-03-16 02:52:16 -05:00
parent c92a5ab31a
commit 8a6934c83c
14 changed files with 115 additions and 22 deletions

View File

@@ -369,6 +369,13 @@ int main(int argc, char **argv)
ServerPropertiesConfig serverProperties = LoadServerPropertiesConfig();
ApplyServerPropertiesToDedicatedConfig(serverProperties, &config);
// Hardcore mode forces Hard difficulty (matches vanilla Java behavior)
if (serverProperties.hardcore && serverProperties.difficulty != 3)
{
LogInfof("startup", "Hardcore mode enabled: forcing difficulty from %d to 3 (Hard).", serverProperties.difficulty);
serverProperties.difficulty = 3;
}
if (!ParseCommandLine(argc, argv, &config))
{
PrintUsage();
@@ -529,6 +536,7 @@ int main(int argc, char **argv)
app.SetGameHostOption(eGameHostOption_DoTileDrops, serverProperties.doTileDrops ? 1 : 0);
app.SetGameHostOption(eGameHostOption_NaturalRegeneration, serverProperties.naturalRegeneration ? 1 : 0);
app.SetGameHostOption(eGameHostOption_DoDaylightCycle, serverProperties.doDaylightCycle ? 1 : 0);
app.SetGameHostOption(eGameHostOption_Hardcore, serverProperties.hardcore ? 1 : 0);
#ifdef _LARGE_WORLDS
app.SetGameHostOption(eGameHostOption_WorldSize, serverProperties.worldSize);
// Apply desired target size for loading existing worlds.