From 9e7378be63a578d559271e377592641dc0b3dfb3 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 20 Sep 2025 16:16:36 -0500 Subject: [PATCH] Merge branch 'merge-bedrock' --- .../methods/data/DhApiTerrainDataRepo.java | 2 +- .../core/api/internal/ServerApi.java | 4 +- .../core/api/internal/SharedApi.java | 92 +++++++++++++++---- .../internal/chunkUpdating/ChunkPosQueue.java | 3 - .../chunkUpdating/ChunkUpdateData.java | 4 +- 5 files changed, 80 insertions(+), 25 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java index bbda3c133..2a807aefd 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java @@ -503,7 +503,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo // this will throw a cast exception if the chunk object array isn't correct IChunkWrapper chunk = SingletonInjector.INSTANCE.get(IWrapperFactory.class).createChunkWrapper(chunkObjectArray); - SharedApi.INSTANCE.applyChunkUpdate(chunk, dhLevel.getLevelWrapper(), true); + SharedApi.INSTANCE.applyChunkUpdate(chunk, dhLevel.getLevelWrapper(), true, true); return DhApiResult.createSuccess(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ServerApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ServerApi.java index 26fa490de..13c6853bf 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ServerApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ServerApi.java @@ -136,8 +136,8 @@ public class ServerApi // chunk modified events // //=======================// - public void serverChunkLoadEvent(IChunkWrapper chunkWrapper, ILevelWrapper level) { SharedApi.INSTANCE.applyChunkUpdate(chunkWrapper, level, false); } - public void serverChunkSaveEvent(IChunkWrapper chunkWrapper, ILevelWrapper level) { SharedApi.INSTANCE.applyChunkUpdate(chunkWrapper, level, true); } + public void serverChunkLoadEvent(IChunkWrapper chunkWrapper, ILevelWrapper level) { SharedApi.INSTANCE.applyChunkUpdate(chunkWrapper, level, false, false); } + public void serverChunkSaveEvent(IChunkWrapper chunkWrapper, ILevelWrapper level) { SharedApi.INSTANCE.applyChunkUpdate(chunkWrapper, level, true, false); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java index 079ddb7b4..4a2af5b52 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java @@ -187,10 +187,11 @@ public class SharedApi /** handles both block place and break events */ - public void chunkBlockChangedEvent(IChunkWrapper chunk, ILevelWrapper level) { this.applyChunkUpdate(chunk, level, true); } - public void chunkLoadEvent(IChunkWrapper chunk, ILevelWrapper level) { this.applyChunkUpdate(chunk, level, false); } + public void chunkBlockChangedEvent(IChunkWrapper chunk, ILevelWrapper level) { this.applyChunkUpdate(chunk, level, true, false); } + public void chunkLoadEvent(IChunkWrapper chunk, ILevelWrapper level) { this.applyChunkUpdate(chunk, level, true, true); } - public void applyChunkUpdate(IChunkWrapper chunkWrapper, ILevelWrapper level, boolean canGetNeighborChunks) + //public void applyChunkUpdate(IChunkWrapper chunkWrapper, ILevelWrapper level, boolean canGetNeighboringChunks) { this.applyChunkUpdate(chunkWrapper, level, canGetNeighboringChunks, false); } + public void applyChunkUpdate(IChunkWrapper chunkWrapper, ILevelWrapper level, boolean canGetNeighboringChunks, boolean newlyLoaded) { //========================// // world and level checks // @@ -252,7 +253,54 @@ public class SharedApi return; } - queueChunkUpdate(chunkWrapper, dhLevel, canGetNeighborChunks); + + + //===============================// + // update the necessary chunk(s) // + //===============================// + + if (!canGetNeighboringChunks) + { + // only update the center chunk + queueChunkUpdate(chunkWrapper, null, dhLevel, false); + return; + } + + + ArrayList neighboringChunkList = getNeighborChunkListForChunk(chunkWrapper, dhLevel); + + if (newlyLoaded) + { + // this means this chunkWrapper is a newly loaded chunk + // which may be missing some neighboring chunk data + // because it is bordering the render distance + // thus, only the chunks neighboring this chunkWrapper will get updated + // because those are more likely to have their full neighboring chunk data + //TODO this does not prevent those neighboring chunks from updating + // this newly loaded chunk that were just skipped + // leading to occasional lighting issues + for (IChunkWrapper neighboringChunk : neighboringChunkList) + { + if (neighboringChunk == chunkWrapper) + { + continue; + } + + this.applyChunkUpdate(neighboringChunk, level, true, false); + } + } + else + { + // if not all neighboring chunk data is available, do not try to update + if (neighboringChunkList.size() < 9) + { + return; + } + + // update the center with any existing neighbour chunks. + // this is done so lighting changes are propagated correctly + queueChunkUpdate(chunkWrapper, neighboringChunkList, dhLevel, true); + } } private static ArrayList getNeighborChunkListForChunk(IChunkWrapper chunkWrapper, IDhLevel dhLevel) { @@ -282,16 +330,18 @@ public class SharedApi return neighborChunkList; } - private static void queueChunkUpdate(IChunkWrapper chunkWrapper, IDhLevel dhLevel,boolean canGetNeighborChunks) + private static void queueChunkUpdate(IChunkWrapper chunkWrapper, @Nullable ArrayList neighborChunkList, IDhLevel dhLevel, boolean canGetNeighboringChunks) { + // return if the chunk is already queued if (CHUNK_UPDATE_QUEUE_MANAGER.contains(chunkWrapper.getChunkPos())) { return; } + // add chunk update data to preUpdate queue - ChunkUpdateData updateData = new ChunkUpdateData(chunkWrapper,null,dhLevel,canGetNeighborChunks); + ChunkUpdateData updateData = new ChunkUpdateData(chunkWrapper, neighborChunkList, dhLevel, canGetNeighboringChunks); CHUNK_UPDATE_QUEUE_MANAGER.addItemToPreUpdateQueue(chunkWrapper.getChunkPos(), updateData); @@ -328,6 +378,7 @@ public class SharedApi // Also includes spawn chunks since they're likely to be intentionally utilized with updates maxUpdateSizeMultiplier = 1 + MC_SHARED.getPlayerCount(); } + CHUNK_UPDATE_QUEUE_MANAGER.maxSize = MAX_UPDATING_CHUNK_COUNT_PER_THREAD_AND_PLAYER * Config.Common.MultiThreading.numberOfThreads.get() * maxUpdateSizeMultiplier; @@ -370,14 +421,11 @@ public class SharedApi IDhLevel dhLevel = preUpdateData.dhLevel; IChunkWrapper chunkWrapper = preUpdateData.chunkWrapper; - boolean canGetNeighborChunks = preUpdateData.canGetNeighborChunks; + boolean canGetNeighboringChunks = preUpdateData.canGetNeighboringChunks; + ArrayList neighborChunkList = preUpdateData.neighborChunkList; try { - // get neighbor chunks if possible - ArrayList neighborChunkList = (canGetNeighborChunks) ? getNeighborChunkListForChunk(chunkWrapper, dhLevel) : null; - preUpdateData.neighborChunkList = neighborChunkList; - // check if this chunk has been converted into an LOD already boolean checkChunkHash = !Config.Common.LodBuilding.disableUnchangedChunkCheck.get(); if (checkChunkHash) @@ -392,19 +440,29 @@ public class SharedApi return; } - if (canGetNeighborChunks) + // if this chunk will update and can get neighbors + // then queue neighboring chunks to update as well + // neighboring chunk will get added directly to the update queue + // so they won't queue further chunk updates + if (neighborChunkList != null + && !neighborChunkList.isEmpty()) { - // if this chunk will update and can get neighbors - // then queue neighboring chunks to update as well - // neighboring chunks will get added directly to the update queue - // so they won't queue further chunk updates for (IChunkWrapper adjacentChunk : neighborChunkList) { // pulling a new chunkWrapper is necessary to prevent concurrent modification on the existing chunkWrappers IChunkWrapper newCenterChunk = dhLevel.getLevelWrapper().tryGetChunk(adjacentChunk.getChunkPos()); if (newCenterChunk != null) { - ChunkUpdateData newUpdateData = new ChunkUpdateData(newCenterChunk, getNeighborChunkListForChunk(newCenterChunk, dhLevel), dhLevel, true); + ChunkUpdateData newUpdateData; + if (canGetNeighboringChunks) + { + newUpdateData = new ChunkUpdateData(newCenterChunk, getNeighborChunkListForChunk(newCenterChunk, dhLevel), dhLevel, true); + } + else + { + newUpdateData = new ChunkUpdateData(newCenterChunk, null, dhLevel, false); + } + CHUNK_UPDATE_QUEUE_MANAGER.addItemToUpdateQueue(newCenterChunk.getChunkPos(), newUpdateData); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/chunkUpdating/ChunkPosQueue.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/chunkUpdating/ChunkPosQueue.java index bc99313ac..34df639a0 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/chunkUpdating/ChunkPosQueue.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/chunkUpdating/ChunkPosQueue.java @@ -121,8 +121,5 @@ public class ChunkPosQueue this.closestQueue.remove(furthest); return this.updateDataByChunkPos.remove(furthest); } - - - } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/chunkUpdating/ChunkUpdateData.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/chunkUpdating/ChunkUpdateData.java index 00e9e0cc1..731fa1832 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/chunkUpdating/ChunkUpdateData.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/chunkUpdating/ChunkUpdateData.java @@ -12,7 +12,7 @@ public class ChunkUpdateData @Nullable public ArrayList neighborChunkList; public IDhLevel dhLevel; - public boolean canGetNeighborChunks; + public boolean canGetNeighboringChunks; @@ -21,6 +21,6 @@ public class ChunkUpdateData this.chunkWrapper = chunkWrapper; this.neighborChunkList = neighborChunkList; this.dhLevel = dhLevel; - this.canGetNeighborChunks = canGetNeighborChunks; + this.canGetNeighboringChunks = canGetNeighborChunks; } }