mirror of
https://github.com/neoStudiosLCE/neoLegacy.git
synced 2026-06-16 21:32:54 +00:00
Add seed validation for server world creation and override-seed property
The dedicated server previously picked a completely random seed with no biome diversity checks (the client validates but the server skipped it). On top of that, the client's findSeed() was hardcoded to only check a 54-chunk (Classic) area, so Large worlds had no diversity guarantee beyond the center. New server worlds now use findSeed() scaled to the full target world size. Added override-seed in server.properties to fix existing worlds without deleting them.
This commit is contained in:
parent
5dad6c24f7
commit
08f14e32ae
|
|
@ -206,6 +206,8 @@ CMinecraftApp::CMinecraftApp()
|
|||
m_dwRequiredTexturePackID=0;
|
||||
|
||||
m_bResetNether=false;
|
||||
m_seedOverride = 0;
|
||||
m_hasSeedOverride = false;
|
||||
|
||||
#ifdef _XBOX
|
||||
// m_bTransferSavesToXboxOne=false;
|
||||
|
|
|
|||
|
|
@ -706,6 +706,8 @@ private:
|
|||
bool m_bGameNewWorldSizeUseMoat;
|
||||
unsigned int m_GameNewHellScale;
|
||||
#endif
|
||||
int64_t m_seedOverride;
|
||||
bool m_hasSeedOverride;
|
||||
unsigned int FromBigEndian(unsigned int uiValue);
|
||||
|
||||
public:
|
||||
|
|
@ -723,6 +725,10 @@ public:
|
|||
void SetGameNewHellScale(unsigned int newScale) { m_GameNewHellScale = newScale; }
|
||||
unsigned int GetGameNewHellScale() { return m_GameNewHellScale; }
|
||||
#endif
|
||||
void SetSeedOverride(int64_t seed) { m_seedOverride = seed; m_hasSeedOverride = true; }
|
||||
bool HasSeedOverride() { return m_hasSeedOverride; }
|
||||
int64_t GetSeedOverride() { return m_seedOverride; }
|
||||
|
||||
void SetResetNether(bool bResetNether) {m_bResetNether=bResetNether;}
|
||||
bool GetResetNether() {return m_bResetNether;}
|
||||
bool CanRecordStatsAndAchievements();
|
||||
|
|
|
|||
|
|
@ -735,10 +735,11 @@ bool MinecraftServer::initServer(int64_t seed, NetworkGameInitData *initData, DW
|
|||
|
||||
if( findSeed )
|
||||
{
|
||||
int worldSizeChunks = (initData && initData->xzSize > 0) ? (int)initData->xzSize : 54;
|
||||
#ifdef __PSVITA__
|
||||
seed = BiomeSource::findSeed(pLevelType, &running);
|
||||
seed = BiomeSource::findSeed(pLevelType, &running, worldSizeChunks);
|
||||
#else
|
||||
seed = BiomeSource::findSeed(pLevelType);
|
||||
seed = BiomeSource::findSeed(pLevelType, worldSizeChunks);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -824,6 +824,20 @@ ServerPropertiesConfig LoadServerPropertiesConfig()
|
|||
config.maxPlayers = ReadNormalizedIntProperty(&merged, "max-players", kDefaultMaxPlayers, 1, kMaxDedicatedPlayers, &shouldWrite);
|
||||
config.seed = 0;
|
||||
config.hasSeed = ReadNormalizedOptionalInt64Property(&merged, "level-seed", &config.seed, &shouldWrite);
|
||||
config.overrideSeed = 0;
|
||||
config.hasOverrideSeed = false;
|
||||
{
|
||||
auto it = merged.find("override-seed");
|
||||
if (it != merged.end() && !TrimAscii(it->second).empty())
|
||||
{
|
||||
__int64 parsed = 0;
|
||||
if (TryParseInt64(TrimAscii(it->second), &parsed))
|
||||
{
|
||||
config.overrideSeed = parsed;
|
||||
config.hasOverrideSeed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
config.logLevel = ReadNormalizedLogLevelProperty(&merged, "log-level", eServerLogLevel_Info, &shouldWrite);
|
||||
config.autosaveIntervalSeconds = ReadNormalizedIntProperty(&merged, "autosave-interval", kDefaultAutosaveIntervalSeconds, 5, 3600, &shouldWrite);
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ namespace ServerRuntime
|
|||
bool hasSeed;
|
||||
/** `level-seed` */
|
||||
__int64 seed;
|
||||
/** `override-seed` replaces the seed for biome generation on existing worlds */
|
||||
bool hasOverrideSeed;
|
||||
__int64 overrideSeed;
|
||||
/** `log-level` */
|
||||
EServerLogLevel logLevel;
|
||||
/** `autosave-interval` (seconds) */
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include "../../Minecraft.World/TilePos.h"
|
||||
#include "../../Minecraft.World/compression.h"
|
||||
#include "../../Minecraft.World/OldChunkStorage.h"
|
||||
#include "../../Minecraft.World/BiomeSource.h"
|
||||
#include "../../Minecraft.World/LevelType.h"
|
||||
#include "../../Minecraft.World/net.minecraft.world.level.tile.h"
|
||||
#include "../../Minecraft.World/Random.h"
|
||||
|
||||
|
|
@ -545,6 +547,12 @@ int main(int argc, char **argv)
|
|||
app.SetGameNewHellScale(serverProperties.worldHellScale);
|
||||
#endif
|
||||
|
||||
if (serverProperties.hasOverrideSeed)
|
||||
{
|
||||
LogInfof("startup", "Seed override active: %lld", serverProperties.overrideSeed);
|
||||
app.SetSeedOverride(serverProperties.overrideSeed);
|
||||
}
|
||||
|
||||
StorageManager.SetSaveDisabled(serverProperties.disableSaving);
|
||||
// Read world name and fixed save-id from server.properties
|
||||
// Delegate load-vs-create decision to WorldManager
|
||||
|
|
@ -584,9 +592,17 @@ int main(int argc, char **argv)
|
|||
{
|
||||
param->seed = config.seed;
|
||||
}
|
||||
else if (worldBootstrap.saveData == nullptr)
|
||||
{
|
||||
// Only run seed validation when creating a brand-new world.
|
||||
// Existing worlds already have their seed in level.dat.
|
||||
LogInfof("startup", "Finding seed with biome diversity for %d-chunk world...", config.worldSizeChunks);
|
||||
param->seed = BiomeSource::findSeed(LevelType::lvl_normal, config.worldSizeChunks);
|
||||
LogInfof("startup", "Selected seed: %lld", param->seed);
|
||||
}
|
||||
else
|
||||
{
|
||||
param->seed = (new Random())->nextLong();
|
||||
param->seed = (new Random())->nextLong(); // placeholder; level.dat seed takes priority
|
||||
}
|
||||
#ifdef _LARGE_WORLDS
|
||||
param->xzSize = (unsigned int)config.worldSizeChunks;
|
||||
|
|
|
|||
|
|
@ -411,9 +411,9 @@ void BiomeSource::update()
|
|||
|
||||
// 4J added - find a seed for this biomesource that matches certain criteria
|
||||
#ifdef __PSVITA__
|
||||
int64_t BiomeSource::findSeed(LevelType *generator, bool* pServerRunning) // MGH - added pRunning, so we can early out of this on Vita as it can take up to 60 secs
|
||||
int64_t BiomeSource::findSeed(LevelType *generator, bool* pServerRunning, int worldSizeChunks)
|
||||
#else
|
||||
int64_t BiomeSource::findSeed(LevelType *generator)
|
||||
int64_t BiomeSource::findSeed(LevelType *generator, int worldSizeChunks)
|
||||
#endif
|
||||
{
|
||||
|
||||
|
|
@ -440,8 +440,8 @@ int64_t BiomeSource::findSeed(LevelType *generator)
|
|||
// Raw biome data has one result per 4x4 group of tiles.
|
||||
// Removing a border of 8 from each side since we'll be doing special things at the edge to turn our world into an island, and so don't want to count things
|
||||
// in the edge region in case they later get removed
|
||||
static const int biomeWidth = ( 54 * 4 ) - 16; // Should be even so we can offset evenly
|
||||
static const int biomeOffset = -( biomeWidth / 2 );
|
||||
const int biomeWidth = ( worldSizeChunks * 4 ) - 16; // Should be even so we can offset evenly
|
||||
const int biomeOffset = -( biomeWidth / 2 );
|
||||
|
||||
// Storage for our biome indices
|
||||
intArray indices = intArray( biomeWidth * biomeWidth );
|
||||
|
|
|
|||
|
|
@ -36,9 +36,9 @@ private:
|
|||
static void getFracs(intArray indices, float *fracs); // 4J added
|
||||
public:
|
||||
#ifdef __PSVITA__
|
||||
static int64_t findSeed(LevelType *generator, bool* pServerRunning); // MGH - added pRunning, so we can early out of this on Vita as it can take up to 60 secs // 4J added
|
||||
static int64_t findSeed(LevelType *generator, bool* pServerRunning, int worldSizeChunks = 54);
|
||||
#else
|
||||
static int64_t findSeed(LevelType *generator); // 4J added
|
||||
static int64_t findSeed(LevelType *generator, int worldSizeChunks = 54);
|
||||
#endif
|
||||
~BiomeSource();
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,15 @@ LevelData::LevelData()
|
|||
LevelData::LevelData(CompoundTag *tag)
|
||||
{
|
||||
seed = tag->getLong(L"RandomSeed");
|
||||
|
||||
// Allow server.properties to override the world seed for biome generation
|
||||
// on existing worlds (e.g. to fix monotonous biomes after world expansion).
|
||||
if (app.HasSeedOverride())
|
||||
{
|
||||
app.DebugPrintf("Overriding world seed: %lld -> %lld\n", seed, app.GetSeedOverride());
|
||||
seed = app.GetSeedOverride();
|
||||
}
|
||||
|
||||
m_pGenerator = LevelType::lvl_normal;
|
||||
if (tag->contains(L"generatorName"))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -14,6 +14,12 @@ This project is based on source code of Minecraft Legacy Console Edition v1.6.05
|
|||
|
||||
## Latest:
|
||||
|
||||
Dedicated server biome diversity fix:
|
||||
- The dedicated server previously used a completely random seed with no biome diversity checks — unlike the client which validates seeds to guarantee varied biomes. This could result in server worlds with large regions dominated by only one or two biome types (e.g. all taiga/snowy)
|
||||
- On top of that, the client's seed validation was hardcoded to only check a 54-chunk (Classic) area, so even validated seeds had no diversity guarantee beyond that — making the problem especially noticeable on Large worlds or worlds expanded from Classic to Large
|
||||
- New server worlds now validate seeds for biome diversity, and the validation scales to the full target world size
|
||||
- Added `override-seed` in server.properties to fix existing worlds without deleting them — set it to any seed number and newly generated chunks will use it instead of the original
|
||||
|
||||
Server list and connection improvements:
|
||||
- Server edits and deletions now apply immediately without needing to restart the game
|
||||
- Connecting to an offline/unreachable server no longer freezes the game indefinitely
|
||||
|
|
|
|||
Loading…
Reference in a new issue