From 41a2909f7c1575774a1bc6b93ecfa9e316e55bd7 Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Sat, 28 Aug 2021 21:31:34 +0300 Subject: [PATCH] Reverted last two commits because no one wants to fix the bugs --- .../common/world/DefaultChunkData.java | 38 ++-- .../ru/windcorp/progressia/server/Server.java | 12 +- .../progressia/server/ServerState.java | 2 +- .../management/load/ChunkRequestDaemon.java | 191 ++++++------------ .../server/world/DefaultChunkLogic.java | 4 +- .../server/world/DefaultWorldLogic.java | 3 +- .../test/gen/TestGenerationConfig.java | 45 ++--- 7 files changed, 104 insertions(+), 191 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/common/world/DefaultChunkData.java b/src/main/java/ru/windcorp/progressia/common/world/DefaultChunkData.java index 730580c..967fe4e 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/DefaultChunkData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/DefaultChunkData.java @@ -25,9 +25,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.Objects; -import java.util.Set; - import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.world.block.BlockData; @@ -50,7 +49,7 @@ public class DefaultChunkData implements ChunkData { public boolean isEmpty = false; public boolean isOpaque = false; - public static Set transparent = Collections.emptySet(); + public static HashSet transparent; private final Vec3i position = new Vec3i(); private final DefaultWorldData world; @@ -205,36 +204,45 @@ public class DefaultChunkData implements ChunkData { public void setGenerationHint(Object generationHint) { this.generationHint = generationHint; } - - public void computeOpaque() { - for (int xyz = 0; xyz < BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK; xyz++) { - if (transparent.contains(blocks[xyz])) { + + public void computeOpaque() + { + for (int xyz=0;xyz buffer = new ArrayList<>(); - + private static class ChunkUnloadRequest { private final Vec3i chunkPos; private final long unloadAt; - + public ChunkUnloadRequest(Vec3i chunkPos, long unloadAt) { this.chunkPos = chunkPos; this.unloadAt = unloadAt; } - + /** * @return the chunk position */ public Vec3i getChunkPos() { return chunkPos; } - + /** * @return the moment when the chunks becomes eligible for unloading */ @@ -72,42 +72,19 @@ public class ChunkRequestDaemon { return unloadAt; } } - + private final ChunkMap unloadSchedule = ChunkMaps.newHashMap(); - private Thread thread = null; - private final AtomicBoolean shouldRun = new AtomicBoolean(false); - public ChunkRequestDaemon(ChunkManager chunkManager) { this.chunkManager = chunkManager; this.loaded = getServer().getWorld().getData().getLoadedChunks(); } - - public synchronized void start() { - if (this.thread != null) { - throw new IllegalStateException("Already running"); - } - - this.thread = new Thread(this::runOffthread, getClass().getSimpleName()); - this.shouldRun.set(true); - this.thread.start(); - } - - public synchronized void stop() { - this.shouldRun.set(false); - - synchronized (this) { - notify(); - } - } - - public synchronized void tick() { + + public void tick() { synchronized (getServer().getWorld().getData()) { synchronized (getServer().getPlayerManager().getMutex()) { loadAndUnloadChunks(); sendAndRevokeChunks(); - - notify(); } } } @@ -139,13 +116,18 @@ public class ChunkRequestDaemon { } private void processLoadQueues() { - toGenerate.forEach(getChunkManager()::loadOrGenerateChunk); - toGenerate.clear(); - - toRequestUnload.forEach(this::scheduleUnload); + toRequestUnload.forEach((pos) -> executor.submit(() -> scheduleUnload(pos))); toRequestUnload.clear(); + + toLoad.forEach((pos) -> executor.submit(() -> getChunkManager().loadOrGenerateChunk(pos))); + toLoad.clear(); + + toGenerate.forEach((pos) -> executor.submit(() -> getChunkManager().loadOrGenerateChunk(pos))); + toGenerate.clear(); + + executor.submit(() -> unloadScheduledChunks()); } - + private void scheduleUnload(Vec3i chunkPos) { if (unloadSchedule.containsKey(chunkPos)) { // Unload already requested, skip @@ -154,9 +136,28 @@ public class ChunkRequestDaemon { long unloadAt = System.currentTimeMillis() + (long) (getUnloadDelay() * 1000); Vec3i chunkPosCopy = new Vec3i(chunkPos); - + unloadSchedule.put(chunkPosCopy, new ChunkUnloadRequest(chunkPosCopy, unloadAt)); } + + private void unloadScheduledChunks() { + long now = System.currentTimeMillis(); + + for (Iterator it = unloadSchedule.values().iterator(); it.hasNext();) { + ChunkUnloadRequest request = it.next(); + + if (request.getUnloadAt() < now) { + + it.remove(); + + if (requested.contains(request.getChunkPos())) { + continue; // do not unload chunks that became requested + } + + getChunkManager().unloadChunk(request.getChunkPos()); + } + } + } private void sendAndRevokeChunks() { getChunkManager().getLoadManager().getVisionManager().forEachVision(vision -> { @@ -171,129 +172,51 @@ public class ChunkRequestDaemon { toGenerate.add(chunk); return; } - + if (vision.isChunkVisible(chunk.getPosition())) { return; } - + buffer.add(chunk.getPosition()); }); - - if (buffer.isEmpty()) - return; + + if (buffer.isEmpty()) return; for (Vec3i chunkPos : buffer) { getChunkManager().sendChunk(vision.getPlayer(), chunkPos); } - + buffer.clear(); } - + private void revokeChunks(PlayerVision vision) { vision.getVisibleChunks().forEach(chunkPos -> { if (getChunkManager().isChunkLoaded(chunkPos) && vision.getRequestedChunks().contains(chunkPos)) return; buffer.add(new Vec3i(chunkPos)); }); - - if (buffer.isEmpty()) - return; + + if (buffer.isEmpty()) return; for (Vec3i chunkPos : buffer) { getChunkManager().revokeChunk(vision.getPlayer(), chunkPos); } - + buffer.clear(); } - /* - * Off-thread activity - */ - - private void runOffthread() { - while (true) { - - processLoadQueue(); - processUnloadQueue(); - - synchronized (this) { - try { - // We're not afraid of spurious wakeups - wait(); - } catch (InterruptedException e) { - // Pretend nothing happened - } - - if (!shouldRun.get()) { - return; - } - } - - } - } - - private void processQueueOffthread(ChunkSet queue, Consumer action) { - while (true) { - synchronized (this) { - Iterator iterator = toLoad.iterator(); - if (!iterator.hasNext()) { - return; - } - Vec3i position = iterator.next(); - iterator.remove(); - - action.accept(position); - } - } - } - - private void processLoadQueue() { - processQueueOffthread(toLoad, getChunkManager()::loadOrGenerateChunk); - } - - private void processUnloadQueue() { - long now = System.currentTimeMillis(); - - Collection toUnload = null; - - synchronized (this) { - for (Iterator it = unloadSchedule.values().iterator(); it.hasNext();) { - ChunkUnloadRequest request = it.next(); - - if (request.getUnloadAt() < now) { - it.remove(); - - if (requested.contains(request.getChunkPos())) { - continue; // do not unload chunks that became requested - } - - if (toUnload == null) { - toUnload = new ArrayList<>(); - } - toUnload.add(request.getChunkPos()); - } - } - } - - if (toUnload == null) { - return; - } - - toUnload.forEach(getChunkManager()::unloadChunk); - } - /** * @return the minimum amount of time a chunk will spend in the unload queue */ public float getUnloadDelay() { return CHUNK_UNLOAD_DELAY; } - + /** * @return the manager */ public ChunkManager getChunkManager() { return chunkManager; } - + public Server getServer() { return getChunkManager().getServer(); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/DefaultChunkLogic.java b/src/main/java/ru/windcorp/progressia/server/world/DefaultChunkLogic.java index 7a05adf..d18ff11 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/DefaultChunkLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/DefaultChunkLogic.java @@ -34,7 +34,7 @@ import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.TileDataStack; import ru.windcorp.progressia.common.world.generic.GenericChunks; import ru.windcorp.progressia.common.world.TileDataReference; -import ru.windcorp.progressia.server.ServerState; +import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.world.block.BlockLogic; import ru.windcorp.progressia.server.world.block.BlockLogicRegistry; import ru.windcorp.progressia.server.world.block.TickableBlock; @@ -226,7 +226,7 @@ public class DefaultChunkLogic implements ChunkLogic { } private void tmp_generateTickLists() { - ServerWorldContextRO context = ServerState.getInstance().createContext(getUp()); + ServerWorldContextRO context = Server.getCurrentServer().createContext(getUp()); GenericChunks.forEachBiC(blockInChunk -> { diff --git a/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java b/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java index 5c4e75d..3e654b6 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java @@ -19,7 +19,6 @@ package ru.windcorp.progressia.server.world; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -44,7 +43,7 @@ public class DefaultWorldLogic implements WorldLogic { private final WorldGenerator generator; - private final Map chunks = Collections.synchronizedMap(new HashMap<>()); + private final Map chunks = new HashMap<>(); private final Evaluation tickEntitiesTask = new TickEntitiesTask(); diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java b/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java index 76090d6..ee0f312 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java @@ -49,18 +49,9 @@ public class TestGenerationConfig { private static final float CURVATURE = Units.get("100 m"); private static final float INNER_RADIUS = Units.get("200 m"); - private final Fields fields = new Fields(SEED); - private final Function generator; - - public TestGenerationConfig() { - this.generator = createGenerator(); - } - - public Function getGenerator() { - return generator; - } + private static final Fields FIELDS = new Fields(SEED); - private Function createGenerator() { + public static Function createGenerator() { Planet planet = new Planet( ((int) PLANET_RADIUS) / Coordinates.CHUNK_SIZE, @@ -69,7 +60,7 @@ public class TestGenerationConfig { INNER_RADIUS ); - TestHeightMap heightMap = new TestHeightMap(planet, planet.getRadius() / 4, fields); + TestHeightMap heightMap = new TestHeightMap(planet, planet.getRadius() / 4, FIELDS); FloatRangeMap layers = new ArrayFloatRangeMap<>(); registerTerrainLayers(layers); @@ -81,11 +72,11 @@ public class TestGenerationConfig { } - private void registerTerrainLayers(FloatRangeMap layers) { + private static void registerTerrainLayers(FloatRangeMap layers) { BlockData dirt = BlockDataRegistry.getInstance().get("Test:Dirt"); BlockData air = BlockDataRegistry.getInstance().get("Test:Air"); - SurfaceFloatField cliffs = fields.get("Test:Cliff"); + SurfaceFloatField cliffs = FIELDS.get("Test:Cliff"); WorleyProceduralNoise.Builder builder = WorleyProceduralNoise.builder(); TestContent.ROCKS.getRocks().forEach(rock -> { @@ -97,9 +88,9 @@ public class TestGenerationConfig { } }, 1); }); - SurfaceFloatField rockDepthOffsets = fields.register( + SurfaceFloatField rockDepthOffsets = FIELDS.register( "Test:RockDepthOffsets", - () -> tweak(fields.primitive(), 40, 5) + () -> tweak(FIELDS.primitive(), 40, 5) ); RockLayer rockLayer = new RockLayer(builder.build(SEED), rockDepthOffsets); @@ -114,28 +105,28 @@ public class TestGenerationConfig { layers.put(4, Float.POSITIVE_INFINITY, rockLayer); } - private void registerFeatures(List features) { + private static void registerFeatures(List features) { - SurfaceFloatField forestiness = fields.register( + SurfaceFloatField forestiness = FIELDS.register( "Test:Forest", - () -> squash(scale(fields.primitive(), 200), 5) + () -> squash(scale(FIELDS.primitive(), 200), 5) ); - SurfaceFloatField grassiness = fields.register( + SurfaceFloatField grassiness = FIELDS.register( "Test:Grass", f -> multiply( - tweak(octaves(fields.primitive(), 2, 2), 40, 0.5, 1.2), - squash(tweak(fields.get("Test:Forest", f), 1, -1, 1), 10), - anti(squash(fields.get("Test:Cliff", f), 10)) + tweak(octaves(FIELDS.primitive(), 2, 2), 40, 0.5, 1.2), + squash(tweak(FIELDS.get("Test:Forest", f), 1, -1, 1), 10), + anti(squash(FIELDS.get("Test:Cliff", f), 10)) ) ); - Function floweriness = flowerName -> fields.register( + Function floweriness = flowerName -> FIELDS.register( "Test:Flower" + flowerName, f -> multiply( - selectPositive(squash(scale(octaves(fields.primitive(), 2, 3), 100), 2), 1, 0.5), - tweak(fields.get("Test:Forest", f), 1, -1, 1.1), - anti(squash(fields.get("Test:Cliff", f), 10)) + selectPositive(squash(scale(octaves(FIELDS.primitive(), 2, 3), 100), 2), 1, 0.5), + tweak(FIELDS.get("Test:Forest", f), 1, -1, 1.1), + anti(squash(FIELDS.get("Test:Cliff", f), 10)) ) );