From dd5ee5d0c8d6274d4024bf92d833051eb08811e9 Mon Sep 17 00:00:00 2001 From: zyxkad Date: Sat, 6 Apr 2024 13:29:18 -0600 Subject: [PATCH] start to fix chunky peripheral --- .../peripheral/ChunkyPeripheral.java | 10 +- .../common/util/ChunkManager.java | 174 ++++++++++-------- 2 files changed, 103 insertions(+), 81 deletions(-) diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/ChunkyPeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/ChunkyPeripheral.java index b244e3eb1..5eff10742 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/ChunkyPeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/ChunkyPeripheral.java @@ -20,7 +20,7 @@ public class ChunkyPeripheral extends BasePeripheral { public static final String PERIPHERAL_TYPE = "chunky"; private static final String UUID_TAG = "uuid"; - private @Nullable ChunkPos loadedCentralChunk; + private @Nullable ChunkPos loadedCentralChunk = null; public ChunkyPeripheral(ITurtleAccess turtle, TurtleSide side) { super(PERIPHERAL_TYPE, new TurtlePeripheralOwner(turtle, side)); @@ -58,15 +58,15 @@ public void updateChunkState() { protected void setLoadedChunk(@Nullable ChunkPos newChunk, ChunkManager manager, ServerLevel level) { if (loadedCentralChunk != null) { manager.removeForceChunk(level, getUUID(), loadedCentralChunk); - //Should not be used - //level.setChunkForced(loadedChunk.x, loadedChunk.z, false); + // Should not be used + // level.setChunkForced(loadedChunk.x, loadedChunk.z, false); loadedCentralChunk = null; } if (newChunk != null) { loadedCentralChunk = newChunk; manager.addForceChunk(level, getUUID(), loadedCentralChunk); - //Should not be used - //level.setChunkForced(newChunk.x, newChunk.z, true); + // Should not be used + // level.setChunkForced(newChunk.x, newChunk.z, true); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/ChunkManager.java b/src/main/java/de/srendi/advancedperipherals/common/util/ChunkManager.java index dbd324dc8..f569ebab5 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/ChunkManager.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/ChunkManager.java @@ -9,7 +9,6 @@ import net.minecraftforge.common.world.ForgeChunkManager; import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.server.ServerStartedEvent; -import net.minecraftforge.event.server.ServerStoppingEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.server.ServerLifecycleHooks; @@ -46,11 +45,6 @@ public static ChunkManager load(@NotNull CompoundTag data) { return manager; } - @SubscribeEvent - public static void beforeServerStopped(ServerStoppingEvent event) { - ChunkManager.get(event.getServer().overworld()).stop(); - } - @SubscribeEvent public static void afterServerStarted(ServerStartedEvent event) { ChunkManager.get(event.getServer().overworld()).init(); @@ -59,8 +53,9 @@ public static void afterServerStarted(ServerStartedEvent event) { @SubscribeEvent public static void serverTick(TickEvent.ServerTickEvent event) { if (event.phase == TickEvent.Phase.END) { - tickCounter++; - if (tickCounter % (APConfig.PERIPHERALS_CONFIG.chunkLoadValidTime.get() / 2) == 0) { + tickCounter += 2; + if (tickCounter >= APConfig.PERIPHERALS_CONFIG.chunkLoadValidTime.get()) { + tickCounter = 0; ChunkManager.get(ServerLifecycleHooks.getCurrentServer().overworld()).cleanup(); } } @@ -68,16 +63,14 @@ public static void serverTick(TickEvent.ServerTickEvent event) { public synchronized boolean addForceChunk(ServerLevel level, UUID owner, ChunkPos pos) { AdvancedPeripherals.debug("Trying to load forced chunk cluster" + pos, Level.WARN); - if (forcedChunks.containsKey(owner)) return true; - forcedChunks.put(owner, new LoadChunkRecord(level.dimension().location().toString(), pos)); + if (forcedChunks.containsKey(owner)) + return true; + final int chunkRadius = APConfig.PERIPHERALS_CONFIG.chunkyTurtleRadius.get(); + forcedChunks.put(owner, new LoadChunkRecord(level.dimension().location().toString(), pos, chunkRadius)); setDirty(); - int chunkRadius = APConfig.PERIPHERALS_CONFIG.chunkyTurtleRadius.get(); - if (chunkRadius == 0) { - return ForgeChunkManager.forceChunk(level, AdvancedPeripherals.MOD_ID, owner, pos.x, pos.z, true, true); - } boolean result = true; - for (int x = chunkRadius * -1; x < chunkRadius; x++) { - for (int z = chunkRadius * -1; z < chunkRadius; z++) { + for (int x = -chunkRadius; x <= chunkRadius; x++) { + for (int z = -chunkRadius; z <= chunkRadius; z++) { result &= ForgeChunkManager.forceChunk(level, AdvancedPeripherals.MOD_ID, owner, pos.x + x, pos.z + z, true, true); } } @@ -85,27 +78,34 @@ public synchronized boolean addForceChunk(ServerLevel level, UUID owner, ChunkPo } public synchronized void touch(UUID owner) { - if (forcedChunks.containsKey(owner)) - forcedChunks.get(owner).touch(); + LoadChunkRecord forcedChunk = forcedChunks.get(owner); + if (forcedChunk) { + forcedChunk.touch(); + } } + // This method is kept for backward compatibility + // TODO: remove in next major version public synchronized boolean removeForceChunk(ServerLevel level, UUID owner, ChunkPos pos) { + return removeForceChunk(level, owner); + } + + public synchronized boolean removeForceChunk(ServerLevel level, UUID owner) { AdvancedPeripherals.debug("Trying to unload forced chunk cluster" + pos, Level.WARN); - if (!forcedChunks.containsKey(owner)) - return true; LoadChunkRecord chunkRecord = forcedChunks.get(owner); + if (chunkRecord == null) + return true; String dimensionName = level.dimension().location().toString(); - if (!chunkRecord.getDimensionName().equals(dimensionName)) + if (!chunkRecord.getDimensionName().equals(dimensionName)) throw new IllegalArgumentException(String.format("Incorrect dimension! Should be %s instead of %s", chunkRecord.getDimensionName(), dimensionName)); boolean result = true; - int chunkRadius = APConfig.PERIPHERALS_CONFIG.chunkyTurtleRadius.get(); - if (chunkRadius == 0) { - result = ForgeChunkManager.forceChunk(level, AdvancedPeripherals.MOD_ID, owner, pos.x, pos.z, false, true); - } else { - for (int x = chunkRadius * -1; x < chunkRadius; x++) { - for (int z = chunkRadius * -1; z < chunkRadius; z++) { - result &= ForgeChunkManager.forceChunk(level, AdvancedPeripherals.MOD_ID, owner, pos.x + x, pos.z + z, true, true); - } + final ChunkPos pos = chunkRecord.getPos(); + final int chunkRadius = chunkRecord.getRadius(); + for (int x = -chunkRadius; x <= chunkRadius; x++) { + for (int z = -chunkRadius; z <= chunkRadius; z++) { + // TODO: Must save chunk mark in a map or sth else. + // Because technically the chunk will be unforced anyway when two chunky turtle in the same chunk, and one left the other stay. + result &= ForgeChunkManager.forceChunk(level, AdvancedPeripherals.MOD_ID, owner, pos.x + x, pos.z + z, false, true); } } if (result) { @@ -116,57 +116,56 @@ public synchronized boolean removeForceChunk(ServerLevel level, UUID owner, Chun } public synchronized void init() { - if (!initialized) { - AdvancedPeripherals.debug("Schedule chunk manager init", Level.WARN); - int chunkRadius = APConfig.PERIPHERALS_CONFIG.chunkyTurtleRadius.get(); - ServerLifecycleHooks.getCurrentServer().getAllLevels().forEach(level -> { - String dimensionName = level.dimension().location().toString(); - forcedChunks.entrySet().stream().filter(entry -> entry.getValue().getDimensionName().equals(dimensionName)).forEach(entry -> { - if (chunkRadius == 0) { - ForgeChunkManager.forceChunk(level, AdvancedPeripherals.MOD_ID, entry.getKey(), entry.getValue().getPos().x, entry.getValue().getPos().z, true, true); - } - for (int x = chunkRadius * -1; x < chunkRadius; x++) { - for (int z = chunkRadius * -1; z < chunkRadius; z++) { - ForgeChunkManager.forceChunk(level, AdvancedPeripherals.MOD_ID, entry.getKey(), entry.getValue().getPos().x + x, entry.getValue().getPos().z + z, true, true); - } - } - }); - }); - initialized = true; - } - } - - public synchronized void stop() { if (initialized) { - AdvancedPeripherals.debug("Schedule chunk manager stop", Level.WARN); - int chunkRadius = APConfig.PERIPHERALS_CONFIG.chunkyTurtleRadius.get(); - ServerLifecycleHooks.getCurrentServer().getAllLevels().forEach(level -> { - String dimensionName = level.dimension().location().toString(); - forcedChunks.entrySet().stream().filter(entry -> entry.getValue().getDimensionName().equals(dimensionName)).forEach(entry -> { - if (chunkRadius == 0) { - ForgeChunkManager.forceChunk(level, AdvancedPeripherals.MOD_ID, entry.getKey(), entry.getValue().getPos().x, entry.getValue().getPos().z, false, true); - } - for (int x = chunkRadius * -1; x < chunkRadius; x++) { - for (int z = chunkRadius * -1; z < chunkRadius; z++) { - ForgeChunkManager.forceChunk(level, AdvancedPeripherals.MOD_ID, entry.getKey(), entry.getValue().getPos().x + x, entry.getValue().getPos().z + z, false, true); - } - } - }); - }); - initialized = false; + return; } + initialized = true; + + AdvancedPeripherals.debug("Schedule chunk manager init", Level.WARN); + final int chunkRadius = APConfig.PERIPHERALS_CONFIG.chunkyTurtleRadius.get(); + final Map levels = getServerLevels(); + forcedChunks.forEach((uuid, value) -> { + String dimensionName = value.getDimensionName(); + ServerLevel level = levels.get(dimensionName); + if (level == null) { + return; + } + final ChunkPos pos = chunkRecord.getPos(); + final int loadedRadius = value.getRadius(); + if (loadedRadius > chunkRadius) { + // clean overflowed load radius + for (int x = chunkRadius + 1; x <= loadedRadius; x++) { + for (int z = chunkRadius + 1; z <= loadedRadius; z++) { + ForgeChunkManager.forceChunk(level, AdvancedPeripherals.MOD_ID, uuid, pos.x + x, pos.z + z, false, true); + ForgeChunkManager.forceChunk(level, AdvancedPeripherals.MOD_ID, uuid, pos.x + x, pos.z - z, false, true); + ForgeChunkManager.forceChunk(level, AdvancedPeripherals.MOD_ID, uuid, pos.x - x, pos.z + z, false, true); + ForgeChunkManager.forceChunk(level, AdvancedPeripherals.MOD_ID, uuid, pos.x - x, pos.z - z, false, true); + } + } + value.setRadius(chunkRadius); + } + for (int x = -chunkRadius; x <= chunkRadius; x++) { + for (int z = -chunkRadius; z <= chunkRadius; z++) { + ForgeChunkManager.forceChunk(level, AdvancedPeripherals.MOD_ID, uuid, pos.x + x, pos.z + z, true, true); + } + } + }); } public synchronized void cleanup() { AdvancedPeripherals.debug("Schedule chunk manager cleanup", Level.WARN); - ServerLifecycleHooks.getCurrentServer().getAllLevels().forEach(level -> { - String dimensionName = level.dimension().location().toString(); - List purgeList = new ArrayList<>(); - forcedChunks.entrySet().stream().filter(entry -> entry.getValue().getDimensionName().equals(dimensionName) && !entry.getValue().isValid()).forEach(entry -> purgeList.add(entry.getKey())); - purgeList.forEach(uuid -> { - AdvancedPeripherals.debug(String.format("Purge forced chunk for %s", uuid), Level.WARN); - removeForceChunk(level, uuid, forcedChunks.get(uuid).getPos()); - }); + final Map levels = getServerLevels(); + forcedChunks.forEach((uuid, value) -> { + String dimensionName = value.getDimensionName(); + ServerLevel level = levels.get(dimensionName); + if (level == null) { + return; + } + if (value.isValid()) { + return; + } + AdvancedPeripherals.debug(String.format("Purge forced chunk for %s", uuid), Level.WARN); + removeForceChunk(level, uuid); }); } @@ -177,23 +176,37 @@ public synchronized void cleanup() { return data; } + private static final Map getServerLevels() { + Map levels = new HashMap<>(); + ServerLifecycleHooks.getCurrentServer().getAllLevels().forEach(level -> { + String dimensionName = level.dimension().location().toString(); + levels.put(dimensionName, level); + }); + return levels; + } + private static class LoadChunkRecord { private static final String POS_TAG = "pos"; private static final String DIMENSION_NAME_TAG = "dimensionName"; + private static final String RADIUS_TAG = "radius"; private final @NotNull String dimensionName; private final @NotNull ChunkPos pos; + private int radius; private long lastTouch; - LoadChunkRecord(@NotNull String dimensionName, @NotNull ChunkPos pos) { + LoadChunkRecord(@NotNull String dimensionName, @NotNull ChunkPos pos, int radius) { this.dimensionName = dimensionName; this.pos = pos; + this.radius = radius; this.lastTouch = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC); } public static LoadChunkRecord deserialize(@NotNull CompoundTag tag) { - return new LoadChunkRecord(tag.getString(DIMENSION_NAME_TAG), NBTUtil.chunkPosFromNBT(tag.getCompound(POS_TAG))); + Set keys = tag.getAllKeys(); + int radius = keys.contains(RADIUS_TAG) ? tag.getInt(RADIUS_TAG) : APConfig.PERIPHERALS_CONFIG.chunkyTurtleRadius.get(); + return new LoadChunkRecord(tag.getString(DIMENSION_NAME_TAG), NBTUtil.chunkPosFromNBT(tag.getCompound(POS_TAG)), radius); } public @NotNull ChunkPos getPos() { @@ -204,6 +217,14 @@ public static LoadChunkRecord deserialize(@NotNull CompoundTag tag) { return dimensionName; } + public int getRadius() { + return radius; + } + + public void setRadius(int radius) { + this.radius = radius + } + public void touch() { lastTouch = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC); } @@ -217,6 +238,7 @@ public boolean isValid() { CompoundTag tag = new CompoundTag(); tag.putString(DIMENSION_NAME_TAG, dimensionName); tag.put(POS_TAG, NBTUtil.toNBT(pos)); + tag.putInt(RADIUS_TAG, radius); return tag; } }