From c1807140e101507f358a34a1cd0196cf07196339 Mon Sep 17 00:00:00 2001 From: Kaitly Date: Fri, 8 May 2026 16:17:10 -0500 Subject: [PATCH 1/5] Ensure map chunk exists before river generation Added null checks for map chunk to ensure terrain data exists before generating rivers. --- Rivers/src/Boulders/GeneratePartialFeatures.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Rivers/src/Boulders/GeneratePartialFeatures.cs b/Rivers/src/Boulders/GeneratePartialFeatures.cs index eeaa7a6..2ef888c 100644 --- a/Rivers/src/Boulders/GeneratePartialFeatures.cs +++ b/Rivers/src/Boulders/GeneratePartialFeatures.cs @@ -79,12 +79,24 @@ public override void GeneratePartial(IServerChunk[] chunks, int mainChunkX, int { chunkRand.InitPositionSeed(generatingChunkX, generatingChunkZ); + // FIX: Ensure map chunk exists before accessing it IMapChunk mapChunk = blockAccessor.GetMapChunk(generatingChunkX, generatingChunkZ); + if (mapChunk == null) + { + // Try to get or create the map chunk through the world manager + // This ensures terrain data exists for river generation + mapChunk = sapi.WorldManager.GetMapChunk(generatingChunkX, generatingChunkZ); + + // If still null, this chunk column truly isn't ready — skip but don't break + if (mapChunk == null) return; + } + ushort[] heightMap = mapChunk.WorldGenTerrainHeightMap; ushort[] riverDistanceMap = mapChunk.GetModdata("riverDistance"); if (riverDistanceMap == null) return; + if (heightMap == null) return; int startX = generatingChunkX * chunkSize; int startZ = generatingChunkZ * chunkSize; @@ -125,4 +137,4 @@ public override void GeneratePartial(IServerChunk[] chunks, int mainChunkX, int } } } -} \ No newline at end of file +} From aaba95c1c4eb86a7968df4b85bddee4506c00887 Mon Sep 17 00:00:00 2001 From: Kaitly Date: Fri, 8 May 2026 16:22:09 -0500 Subject: [PATCH 2/5] Enhance chunk generation with neighbor chunk loading --- Rivers/src/Boulders/WorldGenPartial.cs | 33 +++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/Rivers/src/Boulders/WorldGenPartial.cs b/Rivers/src/Boulders/WorldGenPartial.cs index 19f4ce4..e3915e9 100644 --- a/Rivers/src/Boulders/WorldGenPartial.cs +++ b/Rivers/src/Boulders/WorldGenPartial.cs @@ -15,19 +15,46 @@ public abstract class WorldGenPartial : WorldGenBase public virtual void ChunkColumnGeneration(IChunkColumnGenerateRequest request) { - IServerChunk[] chunks = request.Chunks; int chunkX = request.ChunkX; int chunkZ = request.ChunkZ; + for (int i = -ChunkRange; i <= ChunkRange; i++) { for (int j = -ChunkRange; j <= ChunkRange; j++) { - GeneratePartial(chunks, chunkX, chunkZ, chunkX + i, chunkZ + j); + int targetChunkX = chunkX + i; + int targetChunkZ = chunkZ + j; + + IServerChunk[] targetChunks; + + if (i == 0 && j == 0) + { + targetChunks = request.Chunks; + } + else + { + // Ensure neighbor chunks are loaded/accessible + // Use GetChunkColumn first (non-blocking, returns null if not loaded) + targetChunks = sapi.WorldManager.GetChunkColumn(targetChunkX, targetChunkZ); + + // If not available, try blocking load during worldgen + if (targetChunks == null) + { + // Only use BlockingLoadChunkColumn during worldgen phases before RunGame + // This forces generation if needed + targetChunks = sapi.WorldManager.BlockingLoadChunkColumn(targetChunkX, targetChunkZ); + } + + if (targetChunks == null) continue; + } + + GeneratePartial(targetChunks, chunkX, chunkZ, targetChunkX, targetChunkZ); } } } + public virtual void GeneratePartial(IServerChunk[] chunks, int mainChunkX, int mainChunkZ, int generatingChunkX, int generatingChunkZ) { } -} \ No newline at end of file +} From fb602abad3788d6ca42e705459de48c3d32a6f09 Mon Sep 17 00:00:00 2001 From: QtKaitly Date: Fri, 8 May 2026 17:56:15 -0500 Subject: [PATCH 3/5] Should be all to fix errors - onto testing --- CakeBuild/CakeBuild.csproj | 2 +- Rivers/Rivers.csproj | 2 +- Rivers/modinfo.json | 6 +++- Rivers/src/Boulders/WorldGenBase.cs | 30 ++++++++++++++----- Rivers/src/Gravel/GravelGen.cs | 4 +++ Rivers/src/Patches/BlockLayersPatches.cs | 15 ++++++++++ .../Patches/ChunkTesselatorManagerPatch.cs | 3 +- Rivers/src/Patches/LiquidTesselatorPatch.cs | 2 +- Rivers/src/Rivers/RiverZone.cs | 3 +- Rivers/src/WorldGenSystems/NewGenTerra.cs | 22 ++++++++++++++ build.sh | 0 11 files changed, 76 insertions(+), 13 deletions(-) mode change 100644 => 100755 build.sh diff --git a/CakeBuild/CakeBuild.csproj b/CakeBuild/CakeBuild.csproj index 0e3b64c..85c90f8 100644 --- a/CakeBuild/CakeBuild.csproj +++ b/CakeBuild/CakeBuild.csproj @@ -20,4 +20,4 @@ $(VINTAGE_STORY)/VintagestoryAPI.dll - \ No newline at end of file + diff --git a/Rivers/Rivers.csproj b/Rivers/Rivers.csproj index 7e06e43..3631e0f 100644 --- a/Rivers/Rivers.csproj +++ b/Rivers/Rivers.csproj @@ -66,4 +66,4 @@ - \ No newline at end of file + diff --git a/Rivers/modinfo.json b/Rivers/modinfo.json index af9eedc..b246569 100644 --- a/Rivers/modinfo.json +++ b/Rivers/modinfo.json @@ -6,8 +6,12 @@ "sneeze" ], "description": "Standalone version of rivers.", +<<<<<<< Updated upstream "version": "5.0.0", +======= + "version": "5.0.1", +>>>>>>> Stashed changes "dependencies": { "game": "" } -} \ No newline at end of file +} diff --git a/Rivers/src/Boulders/WorldGenBase.cs b/Rivers/src/Boulders/WorldGenBase.cs index 48acb8e..c0d4362 100644 --- a/Rivers/src/Boulders/WorldGenBase.cs +++ b/Rivers/src/Boulders/WorldGenBase.cs @@ -48,13 +48,29 @@ public void LoadGlobalConfig(ICoreServerAPI api) globalConfig = api.Assets.Get("game:worldgen/global.json").ToObject(); - globalConfig.defaultRockId = api.World.GetBlock(globalConfig.defaultRockCode).BlockId; - globalConfig.waterBlockId = api.World.GetBlock(globalConfig.waterBlockCode).BlockId; - globalConfig.saltWaterBlockId = api.World.GetBlock(globalConfig.saltWaterBlockCode).BlockId; - globalConfig.lakeIceBlockId = api.World.GetBlock(globalConfig.lakeIceBlockCode).BlockId; - globalConfig.lavaBlockId = api.World.GetBlock(globalConfig.lavaBlockCode).BlockId; - globalConfig.basaltBlockId = api.World.GetBlock(globalConfig.basaltBlockCode).BlockId; - globalConfig.mantleBlockId = api.World.GetBlock(globalConfig.mantleBlockCode).BlockId; + Block? block; + + block = api.World.GetBlock(globalConfig.defaultRockCode); + globalConfig.defaultRockId = block?.BlockId ?? 0; + + block = api.World.GetBlock(globalConfig.waterBlockCode); + globalConfig.waterBlockId = block?.BlockId ?? 0; + + block = api.World.GetBlock(globalConfig.saltWaterBlockCode); + globalConfig.saltWaterBlockId = block?.BlockId ?? 0; + + block = api.World.GetBlock(globalConfig.lakeIceBlockCode); + globalConfig.lakeIceBlockId = block?.BlockId ?? 0; + + block = api.World.GetBlock(globalConfig.lavaBlockCode); + globalConfig.lavaBlockId = block?.BlockId ?? 0; + + block = api.World.GetBlock(globalConfig.basaltBlockCode); + globalConfig.basaltBlockId = block?.BlockId ?? 0; + + block = api.World.GetBlock(globalConfig.mantleBlockCode); + globalConfig.mantleBlockId = block?.BlockId ?? 0; + } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/Rivers/src/Gravel/GravelGen.cs b/Rivers/src/Gravel/GravelGen.cs index 24b8733..70cad6c 100644 --- a/Rivers/src/Gravel/GravelGen.cs +++ b/Rivers/src/Gravel/GravelGen.cs @@ -51,6 +51,10 @@ public void InitWorldGen() foreach (RockStratum stratum in rockStrata.Variants) { int stratumId = sapi.World.GetBlock(stratum.BlockCode)?.BlockId ?? 0; +<<<<<<< Updated upstream +======= + if (stratumId == 0) continue; // Skip if block not found +>>>>>>> Stashed changes if (gravelMappings.ContainsKey(stratumId) || stratumId == 0) continue; diff --git a/Rivers/src/Patches/BlockLayersPatches.cs b/Rivers/src/Patches/BlockLayersPatches.cs index 38edce3..866d5ac 100644 --- a/Rivers/src/Patches/BlockLayersPatches.cs +++ b/Rivers/src/Patches/BlockLayersPatches.cs @@ -36,10 +36,14 @@ public static IEnumerable Transpiler(IEnumerable loopVarLoads = []; for (int k = 2; k < code.Count; k++) { +<<<<<<< Updated upstream if ((code[k].opcode == OpCodes.Blt || code[k].opcode == OpCodes.Blt_S) && ((code[k - 1].opcode == OpCodes.Ldc_I4_S && Convert.ToInt32(code[k - 1].operand) == 32) || (code[k - 1].opcode == OpCodes.Ldc_I4 && (int)code[k - 1].operand == 32)) && code[k - 2].IsLdloc()) +======= + if (code[i].opcode == OpCodes.Newobj && (MethodInfo)code[i].operand == typeof(BlockPos).GetConstructor(Array.Empty()) && code[i + 1].opcode == OpCodes.Stloc_S && code[i + 2].opcode == OpCodes.Ldc_I4_0) +>>>>>>> Stashed changes { loopVarLoads.Add(code[k - 2]); } @@ -66,7 +70,18 @@ public static IEnumerable Transpiler(IEnumerable>>>>>> Stashed changes { if (code[k].opcode == OpCodes.Call && code[k].operand is MethodInfo maxMi && maxMi == mathMaxFloat) diff --git a/Rivers/src/Patches/ChunkTesselatorManagerPatch.cs b/Rivers/src/Patches/ChunkTesselatorManagerPatch.cs index 6ff0752..077c6c6 100644 --- a/Rivers/src/Patches/ChunkTesselatorManagerPatch.cs +++ b/Rivers/src/Patches/ChunkTesselatorManagerPatch.cs @@ -1,5 +1,6 @@ using HarmonyLib; using System.Collections.Generic; +using System.Reflection; using System.Reflection.Emit; using Vintagestory.Client.NoObf; @@ -62,7 +63,7 @@ public static IEnumerable Transpiler(IEnumerable Transpiler(IEnumerable landformMapCache = []; @@ -113,6 +114,7 @@ public void LoadGamePre() public void InitWorldGen() { // Loads global settings into the Worldgen mod system. + LoadGlobalConfig(sapi); landformMapCache.Clear(); @@ -230,11 +232,15 @@ private void Generate(IServerChunk[] chunks, int chunkX, int chunkZ) { IMapChunk mapChunk = chunks[0].MapChunk; +<<<<<<< Updated upstream int rockId = GlobalConfig.GetInstance(sapi).defaultRockId; int waterBlockId = GlobalConfig.GetInstance(sapi).waterBlockId; int saltWaterBlockId = GlobalConfig.GetInstance(sapi).saltWaterBlockId; int mantleBlockId = GlobalConfig.GetInstance(sapi).mantleBlockId; int lakeIceBlockId = GlobalConfig.GetInstance(sapi).lakeIceBlockId; +======= + int rockId = globalConfig.defaultRockId; +>>>>>>> Stashed changes RiverConfig riverConfig = RiverConfig.Loaded; @@ -401,7 +407,11 @@ private void Generate(IServerChunk[] chunks, int chunkX, int chunkZ) float distY = oceanicity + ComputeOceanAndUpheavalDistY(upheavalStrength, worldX, worldZ, distGeo); +<<<<<<< Updated upstream columnResults[chunkIndex2d].waterBlockId = oceanicity > 1f ? saltWaterBlockId : waterBlockId; +======= + columnResults[chunkIndex2d].waterBlockId = oceanicity > 1f ? globalConfig.saltWaterBlockId : globalConfig.waterBlockId; +>>>>>>> Stashed changes // Prepare the noise for the entire column. NewNormalizedSimplexFractalNoise.ColumnNoise columnNoise = terrainNoise.ForColumn(verticalNoiseRelativeFrequency, lerpedAmps, lerpedThresh, worldX + distTerrain.X, worldZ + distTerrain.Y); @@ -477,7 +487,11 @@ private void Generate(IServerChunk[] chunks, int chunkX, int chunkZ) IChunkBlocks chunkBlockData = chunks[0].Data; // First set all the fully solid layers in bulk, as much as possible. +<<<<<<< Updated upstream chunkBlockData.SetBlockBulk(0, chunkSize, chunkSize, mantleBlockId); +======= + chunkBlockData.SetBlockBulk(0, chunkSize, chunkSize, globalConfig.mantleBlockId); +>>>>>>> Stashed changes int yBase = 1; for (; yBase < mapSizeY - 1; yBase++) { @@ -516,12 +530,20 @@ private void Generate(IServerChunk[] chunks, int chunkX, int chunkZ) int waterId = columnResult.waterBlockId; surfaceWaterId = waterId; +<<<<<<< Updated upstream if (yBase < seaLevel && waterId != saltWaterBlockId && !columnResult.columnBlockSolidities[seaLevel - 1]) // Should surface water be lake ice? Relevant only for fresh water and only if this particular XZ column has a non-solid block at sea-level. +======= + if (yBase < seaLevel && waterId != globalConfig.saltWaterBlockId && !columnResult.columnBlockSolidities[seaLevel - 1]) // Should surface water be lake ice? Relevant only for fresh water and only if this particular XZ column has a non-solid block at sea-level. +>>>>>>> Stashed changes { int temp = (GameMath.BiLerpRgbColor(localX * chunkBlockDelta, localZ * chunkBlockDelta, climateMapData.UpperLeft, climateMapData.UpperRight, climateMapData.BottomLeft, climateMapData.BottomRight) >> 16) & 0xFF; float distort = (float)distort2dx.Noise((chunkX * chunkSize) + localX, worldZ) / 20f; float tempF = Climate.GetScaledAdjustedTemperatureFloat(temp, 0) + distort; +<<<<<<< Updated upstream if (tempF < TerraGenConfig.WaterFreezingTempOnGen) surfaceWaterId = lakeIceBlockId; +======= + if (tempF < TerraGenConfig.WaterFreezingTempOnGen) surfaceWaterId = globalConfig.lakeIceBlockId; +>>>>>>> Stashed changes } terrainHeightMap[mapIndex] = (ushort)(yBase - 1); // Initially set the height maps to values reflecting the top of the fully solid layers. diff --git a/build.sh b/build.sh old mode 100644 new mode 100755 From 553a479e9ad6d4d075c1d3322e8549b2b13f9e21 Mon Sep 17 00:00:00 2001 From: QtKaitly Date: Fri, 8 May 2026 18:17:08 -0500 Subject: [PATCH 4/5] I fugged up, okay testing now --- Rivers/modinfo.json | 4 ---- Rivers/src/Boulders/WorldGenPartial.cs | 17 +++++-------- Rivers/src/Gravel/GravelGen.cs | 3 --- Rivers/src/Patches/BlockLayersPatches.cs | 15 ------------ Rivers/src/WorldGenSystems/NewGenTerra.cs | 29 ++++------------------- 5 files changed, 11 insertions(+), 57 deletions(-) diff --git a/Rivers/modinfo.json b/Rivers/modinfo.json index b246569..b5feede 100644 --- a/Rivers/modinfo.json +++ b/Rivers/modinfo.json @@ -6,11 +6,7 @@ "sneeze" ], "description": "Standalone version of rivers.", -<<<<<<< Updated upstream - "version": "5.0.0", -======= "version": "5.0.1", ->>>>>>> Stashed changes "dependencies": { "game": "" } diff --git a/Rivers/src/Boulders/WorldGenPartial.cs b/Rivers/src/Boulders/WorldGenPartial.cs index e3915e9..d0e6e8f 100644 --- a/Rivers/src/Boulders/WorldGenPartial.cs +++ b/Rivers/src/Boulders/WorldGenPartial.cs @@ -33,20 +33,15 @@ public virtual void ChunkColumnGeneration(IChunkColumnGenerateRequest request) } else { - // Ensure neighbor chunks are loaded/accessible - // Use GetChunkColumn first (non-blocking, returns null if not loaded) - targetChunks = sapi.WorldManager.GetChunkColumn(targetChunkX, targetChunkZ); + // Get individual chunk, not full column + // Returns null if not loaded — check before use + IServerChunk? chunk = sapi.WorldManager.GetChunk(targetChunkX, 0, targetChunkZ); + if (chunk == null) continue; - // If not available, try blocking load during worldgen - if (targetChunks == null) - { - // Only use BlockingLoadChunkColumn during worldgen phases before RunGame - // This forces generation if needed - targetChunks = sapi.WorldManager.BlockingLoadChunkColumn(targetChunkX, targetChunkZ); + // Build minimal array for GeneratePartial + targetChunks = new IServerChunk[] { chunk }; } - if (targetChunks == null) continue; - } GeneratePartial(targetChunks, chunkX, chunkZ, targetChunkX, targetChunkZ); } diff --git a/Rivers/src/Gravel/GravelGen.cs b/Rivers/src/Gravel/GravelGen.cs index 70cad6c..b36cee3 100644 --- a/Rivers/src/Gravel/GravelGen.cs +++ b/Rivers/src/Gravel/GravelGen.cs @@ -51,10 +51,7 @@ public void InitWorldGen() foreach (RockStratum stratum in rockStrata.Variants) { int stratumId = sapi.World.GetBlock(stratum.BlockCode)?.BlockId ?? 0; -<<<<<<< Updated upstream -======= if (stratumId == 0) continue; // Skip if block not found ->>>>>>> Stashed changes if (gravelMappings.ContainsKey(stratumId) || stratumId == 0) continue; diff --git a/Rivers/src/Patches/BlockLayersPatches.cs b/Rivers/src/Patches/BlockLayersPatches.cs index 866d5ac..38edce3 100644 --- a/Rivers/src/Patches/BlockLayersPatches.cs +++ b/Rivers/src/Patches/BlockLayersPatches.cs @@ -36,14 +36,10 @@ public static IEnumerable Transpiler(IEnumerable loopVarLoads = []; for (int k = 2; k < code.Count; k++) { -<<<<<<< Updated upstream if ((code[k].opcode == OpCodes.Blt || code[k].opcode == OpCodes.Blt_S) && ((code[k - 1].opcode == OpCodes.Ldc_I4_S && Convert.ToInt32(code[k - 1].operand) == 32) || (code[k - 1].opcode == OpCodes.Ldc_I4 && (int)code[k - 1].operand == 32)) && code[k - 2].IsLdloc()) -======= - if (code[i].opcode == OpCodes.Newobj && (MethodInfo)code[i].operand == typeof(BlockPos).GetConstructor(Array.Empty()) && code[i + 1].opcode == OpCodes.Stloc_S && code[i + 2].opcode == OpCodes.Ldc_I4_0) ->>>>>>> Stashed changes { loopVarLoads.Add(code[k - 2]); } @@ -70,18 +66,7 @@ public static IEnumerable Transpiler(IEnumerable>>>>>> Stashed changes { if (code[k].opcode == OpCodes.Call && code[k].operand is MethodInfo maxMi && maxMi == mathMaxFloat) diff --git a/Rivers/src/WorldGenSystems/NewGenTerra.cs b/Rivers/src/WorldGenSystems/NewGenTerra.cs index 90c22b6..623603e 100644 --- a/Rivers/src/WorldGenSystems/NewGenTerra.cs +++ b/Rivers/src/WorldGenSystems/NewGenTerra.cs @@ -232,15 +232,7 @@ private void Generate(IServerChunk[] chunks, int chunkX, int chunkZ) { IMapChunk mapChunk = chunks[0].MapChunk; -<<<<<<< Updated upstream - int rockId = GlobalConfig.GetInstance(sapi).defaultRockId; - int waterBlockId = GlobalConfig.GetInstance(sapi).waterBlockId; - int saltWaterBlockId = GlobalConfig.GetInstance(sapi).saltWaterBlockId; - int mantleBlockId = GlobalConfig.GetInstance(sapi).mantleBlockId; - int lakeIceBlockId = GlobalConfig.GetInstance(sapi).lakeIceBlockId; -======= int rockId = globalConfig.defaultRockId; ->>>>>>> Stashed changes RiverConfig riverConfig = RiverConfig.Loaded; @@ -407,11 +399,7 @@ private void Generate(IServerChunk[] chunks, int chunkX, int chunkZ) float distY = oceanicity + ComputeOceanAndUpheavalDistY(upheavalStrength, worldX, worldZ, distGeo); -<<<<<<< Updated upstream - columnResults[chunkIndex2d].waterBlockId = oceanicity > 1f ? saltWaterBlockId : waterBlockId; -======= columnResults[chunkIndex2d].waterBlockId = oceanicity > 1f ? globalConfig.saltWaterBlockId : globalConfig.waterBlockId; ->>>>>>> Stashed changes // Prepare the noise for the entire column. NewNormalizedSimplexFractalNoise.ColumnNoise columnNoise = terrainNoise.ForColumn(verticalNoiseRelativeFrequency, lerpedAmps, lerpedThresh, worldX + distTerrain.X, worldZ + distTerrain.Y); @@ -487,11 +475,9 @@ private void Generate(IServerChunk[] chunks, int chunkX, int chunkZ) IChunkBlocks chunkBlockData = chunks[0].Data; // First set all the fully solid layers in bulk, as much as possible. -<<<<<<< Updated upstream - chunkBlockData.SetBlockBulk(0, chunkSize, chunkSize, mantleBlockId); -======= + chunkBlockData.SetBlockBulk(0, chunkSize, chunkSize, globalConfig.mantleBlockId); ->>>>>>> Stashed changes + int yBase = 1; for (; yBase < mapSizeY - 1; yBase++) { @@ -530,20 +516,15 @@ private void Generate(IServerChunk[] chunks, int chunkX, int chunkZ) int waterId = columnResult.waterBlockId; surfaceWaterId = waterId; -<<<<<<< Updated upstream - if (yBase < seaLevel && waterId != saltWaterBlockId && !columnResult.columnBlockSolidities[seaLevel - 1]) // Should surface water be lake ice? Relevant only for fresh water and only if this particular XZ column has a non-solid block at sea-level. -======= if (yBase < seaLevel && waterId != globalConfig.saltWaterBlockId && !columnResult.columnBlockSolidities[seaLevel - 1]) // Should surface water be lake ice? Relevant only for fresh water and only if this particular XZ column has a non-solid block at sea-level. ->>>>>>> Stashed changes + { int temp = (GameMath.BiLerpRgbColor(localX * chunkBlockDelta, localZ * chunkBlockDelta, climateMapData.UpperLeft, climateMapData.UpperRight, climateMapData.BottomLeft, climateMapData.BottomRight) >> 16) & 0xFF; float distort = (float)distort2dx.Noise((chunkX * chunkSize) + localX, worldZ) / 20f; float tempF = Climate.GetScaledAdjustedTemperatureFloat(temp, 0) + distort; -<<<<<<< Updated upstream - if (tempF < TerraGenConfig.WaterFreezingTempOnGen) surfaceWaterId = lakeIceBlockId; -======= + if (tempF < TerraGenConfig.WaterFreezingTempOnGen) surfaceWaterId = globalConfig.lakeIceBlockId; ->>>>>>> Stashed changes + } terrainHeightMap[mapIndex] = (ushort)(yBase - 1); // Initially set the height maps to values reflecting the top of the fully solid layers. From 64c3b9a05afb8e5ce7996265bd42572859a1a0f1 Mon Sep 17 00:00:00 2001 From: QtKaitly Date: Fri, 8 May 2026 19:44:33 -0500 Subject: [PATCH 5/5] This does it up good --- .../src/Boulders/GeneratePartialFeatures.cs | 12 +------ Rivers/src/Boulders/WorldGenPartial.cs | 31 ++----------------- Rivers/src/WorldGenSystems/NewGenTerra.cs | 21 ++++++------- 3 files changed, 12 insertions(+), 52 deletions(-) diff --git a/Rivers/src/Boulders/GeneratePartialFeatures.cs b/Rivers/src/Boulders/GeneratePartialFeatures.cs index 2ef888c..66dc1d5 100644 --- a/Rivers/src/Boulders/GeneratePartialFeatures.cs +++ b/Rivers/src/Boulders/GeneratePartialFeatures.cs @@ -79,22 +79,12 @@ public override void GeneratePartial(IServerChunk[] chunks, int mainChunkX, int { chunkRand.InitPositionSeed(generatingChunkX, generatingChunkZ); - // FIX: Ensure map chunk exists before accessing it IMapChunk mapChunk = blockAccessor.GetMapChunk(generatingChunkX, generatingChunkZ); - if (mapChunk == null) - { - // Try to get or create the map chunk through the world manager - // This ensures terrain data exists for river generation - mapChunk = sapi.WorldManager.GetMapChunk(generatingChunkX, generatingChunkZ); - - // If still null, this chunk column truly isn't ready — skip but don't break - if (mapChunk == null) return; - } + if (mapChunk == null) return; ushort[] heightMap = mapChunk.WorldGenTerrainHeightMap; ushort[] riverDistanceMap = mapChunk.GetModdata("riverDistance"); - if (riverDistanceMap == null) return; if (heightMap == null) return; diff --git a/Rivers/src/Boulders/WorldGenPartial.cs b/Rivers/src/Boulders/WorldGenPartial.cs index d0e6e8f..3be57d9 100644 --- a/Rivers/src/Boulders/WorldGenPartial.cs +++ b/Rivers/src/Boulders/WorldGenPartial.cs @@ -18,37 +18,10 @@ public virtual void ChunkColumnGeneration(IChunkColumnGenerateRequest request) int chunkX = request.ChunkX; int chunkZ = request.ChunkZ; - for (int i = -ChunkRange; i <= ChunkRange; i++) - { - for (int j = -ChunkRange; j <= ChunkRange; j++) - { - int targetChunkX = chunkX + i; - int targetChunkZ = chunkZ + j; - - IServerChunk[] targetChunks; - - if (i == 0 && j == 0) - { - targetChunks = request.Chunks; - } - else - { - // Get individual chunk, not full column - // Returns null if not loaded — check before use - IServerChunk? chunk = sapi.WorldManager.GetChunk(targetChunkX, 0, targetChunkZ); - if (chunk == null) continue; - - // Build minimal array for GeneratePartial - targetChunks = new IServerChunk[] { chunk }; - } - - - GeneratePartial(targetChunks, chunkX, chunkZ, targetChunkX, targetChunkZ); - } - } + // ONLY process current chunk — moddata already contains river info + GeneratePartial(request.Chunks, chunkX, chunkZ, chunkX, chunkZ); } - public virtual void GeneratePartial(IServerChunk[] chunks, int mainChunkX, int mainChunkZ, int generatingChunkX, int generatingChunkZ) { } diff --git a/Rivers/src/WorldGenSystems/NewGenTerra.cs b/Rivers/src/WorldGenSystems/NewGenTerra.cs index 623603e..61c4e6b 100644 --- a/Rivers/src/WorldGenSystems/NewGenTerra.cs +++ b/Rivers/src/WorldGenSystems/NewGenTerra.cs @@ -39,7 +39,6 @@ public struct ThreadLocalTempData public class NewGenTerra : ModStdWorldGen { public ICoreServerAPI sapi = null!; - public GlobalConfig globalConfig = null!; // Cache of landforms, cleared on init (why?) and when /wgen regen command reloads all the generators. public Dictionary landformMapCache = []; @@ -114,7 +113,6 @@ public void LoadGamePre() public void InitWorldGen() { // Loads global settings into the Worldgen mod system. - LoadGlobalConfig(sapi); landformMapCache.Clear(); @@ -232,7 +230,11 @@ private void Generate(IServerChunk[] chunks, int chunkX, int chunkZ) { IMapChunk mapChunk = chunks[0].MapChunk; - int rockId = globalConfig.defaultRockId; + int rockId = GlobalConfig.GetInstance(sapi).defaultRockId; + int waterBlockId = GlobalConfig.GetInstance(sapi).waterBlockId; + int saltWaterBlockId = GlobalConfig.GetInstance(sapi).saltWaterBlockId; + int mantleBlockId = GlobalConfig.GetInstance(sapi).mantleBlockId; + int lakeIceBlockId = GlobalConfig.GetInstance(sapi).lakeIceBlockId; RiverConfig riverConfig = RiverConfig.Loaded; @@ -399,7 +401,7 @@ private void Generate(IServerChunk[] chunks, int chunkX, int chunkZ) float distY = oceanicity + ComputeOceanAndUpheavalDistY(upheavalStrength, worldX, worldZ, distGeo); - columnResults[chunkIndex2d].waterBlockId = oceanicity > 1f ? globalConfig.saltWaterBlockId : globalConfig.waterBlockId; + columnResults[chunkIndex2d].waterBlockId = oceanicity > 1f ? saltWaterBlockId : waterBlockId; // Prepare the noise for the entire column. NewNormalizedSimplexFractalNoise.ColumnNoise columnNoise = terrainNoise.ForColumn(verticalNoiseRelativeFrequency, lerpedAmps, lerpedThresh, worldX + distTerrain.X, worldZ + distTerrain.Y); @@ -475,9 +477,7 @@ private void Generate(IServerChunk[] chunks, int chunkX, int chunkZ) IChunkBlocks chunkBlockData = chunks[0].Data; // First set all the fully solid layers in bulk, as much as possible. - - chunkBlockData.SetBlockBulk(0, chunkSize, chunkSize, globalConfig.mantleBlockId); - + chunkBlockData.SetBlockBulk(0, chunkSize, chunkSize, mantleBlockId); int yBase = 1; for (; yBase < mapSizeY - 1; yBase++) { @@ -516,15 +516,12 @@ private void Generate(IServerChunk[] chunks, int chunkX, int chunkZ) int waterId = columnResult.waterBlockId; surfaceWaterId = waterId; - if (yBase < seaLevel && waterId != globalConfig.saltWaterBlockId && !columnResult.columnBlockSolidities[seaLevel - 1]) // Should surface water be lake ice? Relevant only for fresh water and only if this particular XZ column has a non-solid block at sea-level. - + if (yBase < seaLevel && waterId != saltWaterBlockId && !columnResult.columnBlockSolidities[seaLevel - 1]) // Should surface water be lake ice? Relevant only for fresh water and only if this particular XZ column has a non-solid block at sea-level. { int temp = (GameMath.BiLerpRgbColor(localX * chunkBlockDelta, localZ * chunkBlockDelta, climateMapData.UpperLeft, climateMapData.UpperRight, climateMapData.BottomLeft, climateMapData.BottomRight) >> 16) & 0xFF; float distort = (float)distort2dx.Noise((chunkX * chunkSize) + localX, worldZ) / 20f; float tempF = Climate.GetScaledAdjustedTemperatureFloat(temp, 0) + distort; - - if (tempF < TerraGenConfig.WaterFreezingTempOnGen) surfaceWaterId = globalConfig.lakeIceBlockId; - + if (tempF < TerraGenConfig.WaterFreezingTempOnGen) surfaceWaterId = lakeIceBlockId; } terrainHeightMap[mapIndex] = (ushort)(yBase - 1); // Initially set the height maps to values reflecting the top of the fully solid layers.