From cd16334db8c043a9b67ee0153d2c8557d534405e Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Sat, 28 Aug 2021 23:31:50 +0300 Subject: [PATCH] Moved TestWorldDiskIO to a subpackage and introduced some abstractions --- .../ru/windcorp/progressia/server/Server.java | 13 ++++- .../progressia/server/ServerState.java | 13 ++++- .../server/management/load/ChunkManager.java | 10 +++- .../server/world/DefaultWorldLogic.java | 10 +++- .../server/world/io/WorldContainer.java | 37 ++++++++++++ .../server/world/io/WorldContainerFormat.java | 32 ++++++++++ .../test/gen/TestGenerationConfig.java | 45 ++++++++------ .../progressia/test/region/RegionFormat.java | 36 ++++++++++++ .../test/{ => region}/TestWorldDiskIO.java | 58 +++++++++++-------- 9 files changed, 204 insertions(+), 50 deletions(-) create mode 100644 src/main/java/ru/windcorp/progressia/server/world/io/WorldContainer.java create mode 100644 src/main/java/ru/windcorp/progressia/server/world/io/WorldContainerFormat.java create mode 100644 src/main/java/ru/windcorp/progressia/test/region/RegionFormat.java rename src/main/java/ru/windcorp/progressia/test/{ => region}/TestWorldDiskIO.java (92%) diff --git a/src/main/java/ru/windcorp/progressia/server/Server.java b/src/main/java/ru/windcorp/progressia/server/Server.java index ea8504f..1b67392 100644 --- a/src/main/java/ru/windcorp/progressia/server/Server.java +++ b/src/main/java/ru/windcorp/progressia/server/Server.java @@ -46,6 +46,7 @@ import ru.windcorp.progressia.server.world.context.impl.DefaultServerContext; import ru.windcorp.progressia.server.world.context.impl.ReportingServerContext; import ru.windcorp.progressia.server.world.context.impl.RotatingServerContext; import ru.windcorp.progressia.server.world.generation.WorldGenerator; +import ru.windcorp.progressia.server.world.io.WorldContainer; import ru.windcorp.progressia.server.world.tasks.WorldAccessor; import ru.windcorp.progressia.server.world.ticking.Change; import ru.windcorp.progressia.server.world.ticking.Evaluation; @@ -78,11 +79,16 @@ public class Server { private final TickingSettings tickingSettings = new TickingSettings(); - public Server(DefaultWorldData world, Function generatorCreator) { + public Server( + DefaultWorldData world, + Function generatorCreator, + WorldContainer worldContainer + ) { this.world = new DefaultWorldLogic( world, this, generatorCreator.apply(this), + worldContainer, worldAccessor ); this.serverThread = new ServerThread(this); @@ -241,14 +247,14 @@ public class Server { public void scheduleChange(Change change) { serverThread.getTicker().requestChange(change); } - + /** * Delayed */ public void scheduleEvaluation(Evaluation evaluation) { serverThread.getTicker().requestEvaluation(evaluation); } - + /** * Immediate if possible, otherwise delayed */ @@ -349,6 +355,7 @@ public class Server { public void shutdown(String message) { LogManager.getLogger().warn("Server.shutdown() is not yet implemented"); serverThread.stop(); + getWorld().getContainer().close(); } private void scheduleWorldTicks(Server server) { diff --git a/src/main/java/ru/windcorp/progressia/server/ServerState.java b/src/main/java/ru/windcorp/progressia/server/ServerState.java index 00aa901..c38f21b 100644 --- a/src/main/java/ru/windcorp/progressia/server/ServerState.java +++ b/src/main/java/ru/windcorp/progressia/server/ServerState.java @@ -18,8 +18,14 @@ package ru.windcorp.progressia.server; +import java.nio.file.Paths; +import java.util.function.Function; + import ru.windcorp.progressia.common.world.DefaultWorldData; +import ru.windcorp.progressia.server.world.generation.WorldGenerator; +import ru.windcorp.progressia.server.world.io.WorldContainer; import ru.windcorp.progressia.test.gen.TestGenerationConfig; +import ru.windcorp.progressia.test.region.RegionFormat; public class ServerState { @@ -34,9 +40,14 @@ public class ServerState { } public static void startServer() { - Server server = new Server(new DefaultWorldData(), TestGenerationConfig.createGenerator()); + + Function generator = new TestGenerationConfig().getGenerator(); + WorldContainer container = new RegionFormat("Test:Region").create(Paths.get("tmp_world")); + + Server server = new Server(new DefaultWorldData(), generator, container); setInstance(server); server.start(); + } private ServerState() { diff --git a/src/main/java/ru/windcorp/progressia/server/management/load/ChunkManager.java b/src/main/java/ru/windcorp/progressia/server/management/load/ChunkManager.java index 3071530..b58a3b2 100644 --- a/src/main/java/ru/windcorp/progressia/server/management/load/ChunkManager.java +++ b/src/main/java/ru/windcorp/progressia/server/management/load/ChunkManager.java @@ -24,7 +24,7 @@ import ru.windcorp.progressia.common.world.PacketSendChunk; import ru.windcorp.progressia.common.world.DefaultWorldData; import ru.windcorp.progressia.server.Player; import ru.windcorp.progressia.server.Server; -import ru.windcorp.progressia.test.TestWorldDiskIO; +import ru.windcorp.progressia.server.world.io.WorldContainer; /** * Chunk manager provides facilities to load, unload and generate chunks for a @@ -51,6 +51,10 @@ public class ChunkManager { public Server getServer() { return getLoadManager().getServer(); } + + public WorldContainer getContainer() { + return getServer().getWorld().getContainer(); + } /** * Describes the result of an attempt to load a chunk. @@ -115,7 +119,7 @@ public class ChunkManager { DefaultWorldData world = getServer().getWorld().getData(); - DefaultChunkData chunk = TestWorldDiskIO.tryToLoad(chunkPos, world, getServer()); + DefaultChunkData chunk = getServer().getWorld().getContainer().load(chunkPos, world, getServer()); if (chunk != null) { world.addChunk(chunk); return LoadResult.LOADED_FROM_DISK; @@ -141,7 +145,7 @@ public class ChunkManager { } world.removeChunk(chunk); - TestWorldDiskIO.saveChunk(chunk, getServer()); + getContainer().save(chunk, getServer().getWorld().getData(), getServer()); return true; } 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 3e654b6..b573d07 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java @@ -32,6 +32,7 @@ import ru.windcorp.progressia.common.world.WorldDataListener; import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.world.generation.WorldGenerator; +import ru.windcorp.progressia.server.world.io.WorldContainer; import ru.windcorp.progressia.server.world.tasks.TickEntitiesTask; import ru.windcorp.progressia.server.world.tasks.WorldAccessor; import ru.windcorp.progressia.server.world.ticking.Evaluation; @@ -42,17 +43,20 @@ public class DefaultWorldLogic implements WorldLogic { private final Server server; private final WorldGenerator generator; + private final WorldContainer container; private final Map chunks = new HashMap<>(); private final Evaluation tickEntitiesTask = new TickEntitiesTask(); - public DefaultWorldLogic(DefaultWorldData data, Server server, WorldGenerator generator, WorldAccessor accessor) { + public DefaultWorldLogic(DefaultWorldData data, Server server, WorldGenerator generator, WorldContainer container, WorldAccessor accessor) { this.data = data; this.server = server; this.generator = generator; data.setGravityModel(getGenerator().getGravityModel()); + + this.container = container; data.addListener(new WorldDataListener() { @Override @@ -105,6 +109,10 @@ public class DefaultWorldLogic implements WorldLogic { public WorldGenerator getGenerator() { return generator; } + + public WorldContainer getContainer() { + return container; + } public DefaultChunkData generate(Vec3i chunkPos) { DefaultChunkData chunk = getGenerator().generate(chunkPos); diff --git a/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainer.java b/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainer.java new file mode 100644 index 0000000..07aa7b5 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainer.java @@ -0,0 +1,37 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package ru.windcorp.progressia.server.world.io; + +import java.nio.file.Path; + +import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.common.world.DefaultChunkData; +import ru.windcorp.progressia.common.world.DefaultWorldData; +import ru.windcorp.progressia.server.Server; + +public interface WorldContainer { + + Path getPath(); + + DefaultChunkData load(Vec3i position, DefaultWorldData world, Server server); + + void save(DefaultChunkData chunk, DefaultWorldData world, Server server); + + void close(); + +} diff --git a/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainerFormat.java b/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainerFormat.java new file mode 100644 index 0000000..9c8e0c8 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainerFormat.java @@ -0,0 +1,32 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package ru.windcorp.progressia.server.world.io; + +import java.nio.file.Path; + +import ru.windcorp.progressia.common.util.namespaces.Namespaced; + +public abstract class WorldContainerFormat extends Namespaced { + + public WorldContainerFormat(String id) { + super(id); + } + + public abstract WorldContainer create(Path directory); + +} 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 ee0f312..76090d6 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java @@ -49,9 +49,18 @@ public class TestGenerationConfig { private static final float CURVATURE = Units.get("100 m"); private static final float INNER_RADIUS = Units.get("200 m"); - private static final Fields FIELDS = new Fields(SEED); + private final Fields fields = new Fields(SEED); + private final Function generator; + + public TestGenerationConfig() { + this.generator = createGenerator(); + } + + public Function getGenerator() { + return generator; + } - public static Function createGenerator() { + private Function createGenerator() { Planet planet = new Planet( ((int) PLANET_RADIUS) / Coordinates.CHUNK_SIZE, @@ -60,7 +69,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); @@ -72,11 +81,11 @@ public class TestGenerationConfig { } - private static void registerTerrainLayers(FloatRangeMap layers) { + private 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 -> { @@ -88,9 +97,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); @@ -105,28 +114,28 @@ public class TestGenerationConfig { layers.put(4, Float.POSITIVE_INFINITY, rockLayer); } - private static void registerFeatures(List features) { + private 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)) ) ); diff --git a/src/main/java/ru/windcorp/progressia/test/region/RegionFormat.java b/src/main/java/ru/windcorp/progressia/test/region/RegionFormat.java new file mode 100644 index 0000000..85d1bbe --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/region/RegionFormat.java @@ -0,0 +1,36 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package ru.windcorp.progressia.test.region; + +import java.nio.file.Path; + +import ru.windcorp.progressia.server.world.io.WorldContainer; +import ru.windcorp.progressia.server.world.io.WorldContainerFormat; + +public class RegionFormat extends WorldContainerFormat { + + public RegionFormat(String id) { + super(id); + } + + @Override + public WorldContainer create(Path directory) { + return new TestWorldDiskIO(directory); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java similarity index 92% rename from src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java rename to src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java index d15e88f..b391ec3 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package ru.windcorp.progressia.test; +package ru.windcorp.progressia.test.region; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -52,12 +52,13 @@ import ru.windcorp.progressia.common.world.DecodingException; import ru.windcorp.progressia.common.world.DefaultWorldData; import ru.windcorp.progressia.common.world.io.ChunkIO; import ru.windcorp.progressia.server.Server; +import ru.windcorp.progressia.server.world.io.WorldContainer; -public class TestWorldDiskIO { +public class TestWorldDiskIO implements WorldContainer { private static final boolean resetCorrupted = true; - public static class RandomFileMapped { + public class RandomFileMapped { public RandomAccessFile file; public HashMap offsets; public HashMap lengths; @@ -121,11 +122,11 @@ public class TestWorldDiskIO { } } - private static Path SAVE_DIR = Paths.get("tmp_world"); + private Path SAVE_DIR = Paths.get("tmp_world"); private static final String formatFile = "world.format"; private static final Logger LOG = LogManager.getLogger("TestWorldDiskIO"); - private static HashMap inOutMap; + private HashMap inOutMap; private static final boolean ENABLE = false; private static int maxSize = 1048576; @@ -134,11 +135,11 @@ public class TestWorldDiskIO { private static final int bestFormat = 65536; // private Map regions = new HashMap(); - private static Vec3i regionSize; - private static int chunksPerRegion; + private Vec3i regionSize; + private int chunksPerRegion; - private static int currentFormat = -1; - private static String extension = ".null"; + private int currentFormat = -1; + private String extension = ".null"; private static int natFromInt(int loc) { if (loc < 0) @@ -155,7 +156,7 @@ public class TestWorldDiskIO { * } */ - private static Vec3i getRegion(Vec3i chunkLoc) { + private Vec3i getRegion(Vec3i chunkLoc) { int x = chunkLoc.x; if (x<0) { @@ -197,15 +198,11 @@ public class TestWorldDiskIO { return ((a % m) + m) % m; } - private static Vec3i getRegionLoc(Vec3i chunkLoc) { + private Vec3i getRegionLoc(Vec3i chunkLoc) { return new Vec3i(mod(chunkLoc.x, regionSize.x), mod(chunkLoc.y, regionSize.y), mod(chunkLoc.z, regionSize.z)); } - public static void initRegions() { - initRegions(null); - } - - public static void initRegions(Path worldPath) { + public TestWorldDiskIO(Path worldPath) { if (worldPath != null) { SAVE_DIR = worldPath; } @@ -224,7 +221,7 @@ public class TestWorldDiskIO { return sectorsUsed; }*/ - private static void setRegionSize(int format) { + private void setRegionSize(int format) { inOutMap = new HashMap(); switch (format) { case 65536: @@ -243,7 +240,7 @@ public class TestWorldDiskIO { } } - public static boolean confirmHeaderHealth(RandomAccessFile input, HashMap offsets, HashMap length) throws IOException + public boolean confirmHeaderHealth(RandomAccessFile input, HashMap offsets, HashMap length) throws IOException { Set used = new HashSet(); input.seek(0); @@ -282,7 +279,8 @@ public class TestWorldDiskIO { return true; } - public static void saveChunk(DefaultChunkData chunk, Server server) { + @Override + public void save(DefaultChunkData chunk, DefaultWorldData world, Server server) { if (!ENABLE) return; @@ -472,7 +470,7 @@ public class TestWorldDiskIO { } } - private static RandomFileMapped makeNew(Path path, Object hashObj) { + private RandomFileMapped makeNew(Path path, Object hashObj) { try { RandomAccessFile raf = new RandomAccessFile(path.toFile(), "rw"); @@ -490,12 +488,13 @@ public class TestWorldDiskIO { return null; } - private static void writeGenerationHint(DefaultChunkData chunk, DataOutputStream output, Server server) + private void writeGenerationHint(DefaultChunkData chunk, DataOutputStream output, Server server) throws IOException { server.getWorld().getGenerator().writeGenerationHint(output, chunk.getGenerationHint()); } - public static DefaultChunkData tryToLoad(Vec3i chunkPos, DefaultWorldData world, Server server) { + @Override + public DefaultChunkData load(Vec3i chunkPos, DefaultWorldData world, Server server) { if (!ENABLE) return null; @@ -650,7 +649,7 @@ public class TestWorldDiskIO { return null; } - private static DefaultChunkData loadRegion(Path path, Vec3i chunkPos, DefaultWorldData world, Server server) + private DefaultChunkData loadRegion(Path path, Vec3i chunkPos, DefaultWorldData world, Server server) throws IOException, DecodingException { int offset = 0; @@ -724,7 +723,7 @@ public class TestWorldDiskIO { return null; } - private static DefaultChunkData loadRegionX(Path path, Vec3i chunkPos, DefaultWorldData world, Server server) + private DefaultChunkData loadRegionX(Path path, Vec3i chunkPos, DefaultWorldData world, Server server) throws IOException, DecodingException { int offset = 0; @@ -810,4 +809,15 @@ public class TestWorldDiskIO { chunk.setGenerationHint(server.getWorld().getGenerator().readGenerationHint(input)); } + @Override + public Path getPath() { + return SAVE_DIR; + } + + @Override + public void close() { + // TODO Auto-generated method stub + + } + }