Fixed a generation issue and refactored some code around WorldGenerators
- ChunkRequestDaemon now attempts to generate requested loaded non-ready chunks upon discovery - The server is now only specified once for WorldGenerator - WorldLogic now actively checks the generation contract
This commit is contained in:
parent
2d3d250f92
commit
3c3f3816df
@ -72,7 +72,7 @@ public class Server {
|
||||
this.world = new WorldLogic(
|
||||
world,
|
||||
this,
|
||||
w -> new TestPlanetGenerator("Test:PlanetGenerator", new Planet(4, 9.8f, 16f, 16f), w)
|
||||
new TestPlanetGenerator("Test:PlanetGenerator", this, new Planet(4, 9.8f, 16f, 16f))
|
||||
);
|
||||
this.serverThread = new ServerThread(this);
|
||||
|
||||
|
@ -41,6 +41,7 @@ public class ChunkRequestDaemon {
|
||||
private final ChunkSet loaded;
|
||||
private final ChunkSet requested = ChunkSets.newHashSet();
|
||||
private final ChunkSet toLoad = ChunkSets.newHashSet();
|
||||
private final ChunkSet toGenerate = ChunkSets.newHashSet();
|
||||
private final ChunkSet toRequestUnload = ChunkSets.newHashSet();
|
||||
|
||||
private final Collection<Vec3i> buffer = new ArrayList<>();
|
||||
@ -118,6 +119,9 @@ public class ChunkRequestDaemon {
|
||||
toLoad.forEach(getChunkManager()::loadOrGenerateChunk);
|
||||
toLoad.clear();
|
||||
|
||||
toGenerate.forEach(getChunkManager()::loadOrGenerateChunk);
|
||||
toGenerate.clear();
|
||||
|
||||
unloadScheduledChunks();
|
||||
}
|
||||
|
||||
@ -161,10 +165,15 @@ public class ChunkRequestDaemon {
|
||||
|
||||
private void sendChunks(PlayerVision vision) {
|
||||
vision.getRequestedChunks().forEachIn(getServer().getWorld(), chunk -> {
|
||||
if (!chunk.isReady())
|
||||
if (!chunk.isReady()) {
|
||||
toGenerate.add(chunk);
|
||||
return;
|
||||
if (vision.isChunkVisible(chunk.getPosition()))
|
||||
}
|
||||
|
||||
if (vision.isChunkVisible(chunk.getPosition())) {
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.add(chunk.getPosition());
|
||||
});
|
||||
|
||||
|
@ -21,9 +21,10 @@ package ru.windcorp.progressia.server.world;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import glm.Glm;
|
||||
import glm.vec._3.i.Vec3i;
|
||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||
import ru.windcorp.progressia.common.world.ChunkData;
|
||||
import ru.windcorp.progressia.common.world.ChunkDataListeners;
|
||||
import ru.windcorp.progressia.common.world.WorldData;
|
||||
@ -52,11 +53,11 @@ public class WorldLogic
|
||||
|
||||
private final Evaluation tickEntitiesTask = new TickEntitiesTask();
|
||||
|
||||
public WorldLogic(WorldData data, Server server, Function<WorldLogic, WorldGenerator> worldGeneratorConstructor) {
|
||||
public WorldLogic(WorldData data, Server server, WorldGenerator generator) {
|
||||
this.data = data;
|
||||
this.server = server;
|
||||
|
||||
this.generator = worldGeneratorConstructor.apply(this);
|
||||
this.generator = generator;
|
||||
data.setGravityModel(getGenerator().getGravityModel());
|
||||
|
||||
data.addListener(new WorldDataListener() {
|
||||
@ -106,7 +107,38 @@ public class WorldLogic
|
||||
}
|
||||
|
||||
public ChunkData generate(Vec3i chunkPos) {
|
||||
return getGenerator().generate(chunkPos, getData());
|
||||
ChunkData chunk = getGenerator().generate(chunkPos);
|
||||
|
||||
if (!Glm.equals(chunkPos, chunk.getPosition())) {
|
||||
throw CrashReports.report(null, "Generator %s has generated a chunk at (%d; %d; %d) when requested to generate a chunk at (%d; %d; %d)",
|
||||
getGenerator(),
|
||||
chunk.getX(), chunk.getY(), chunk.getZ(),
|
||||
chunkPos.x, chunkPos.y, chunkPos.z
|
||||
);
|
||||
}
|
||||
|
||||
if (getData().getChunk(chunk.getPosition()) != chunk) {
|
||||
if (isChunkLoaded(chunkPos)) {
|
||||
throw CrashReports.report(null, "Generator %s has returned a chunk different to the chunk that is located at (%d; %d; %d)",
|
||||
getGenerator(),
|
||||
chunkPos.x, chunkPos.y, chunkPos.z
|
||||
);
|
||||
} else {
|
||||
throw CrashReports.report(null, "Generator %s has returned a chunk that is not loaded when requested to generate a chunk at (%d; %d; %d)",
|
||||
getGenerator(),
|
||||
chunkPos.x, chunkPos.y, chunkPos.z
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!getChunk(chunk).isReady()) {
|
||||
throw CrashReports.report(null, "Generator %s has returned a chunk that is not ready when requested to generate a chunk at (%d; %d; %d)",
|
||||
getGenerator(),
|
||||
chunkPos.x, chunkPos.y, chunkPos.z
|
||||
);
|
||||
}
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
public ChunkLogic getChunk(ChunkData chunkData) {
|
||||
|
@ -27,6 +27,9 @@ import ru.windcorp.progressia.common.world.ChunkData;
|
||||
import ru.windcorp.progressia.common.world.DecodingException;
|
||||
import ru.windcorp.progressia.common.world.GravityModel;
|
||||
import ru.windcorp.progressia.common.world.GravityModelRegistry;
|
||||
import ru.windcorp.progressia.common.world.WorldData;
|
||||
import ru.windcorp.progressia.server.Server;
|
||||
import ru.windcorp.progressia.server.world.WorldLogic;
|
||||
|
||||
public abstract class AbstractWorldGenerator<H> extends WorldGenerator {
|
||||
|
||||
@ -34,10 +37,13 @@ public abstract class AbstractWorldGenerator<H> extends WorldGenerator {
|
||||
|
||||
private final GravityModel gravityModel;
|
||||
|
||||
public AbstractWorldGenerator(String id, Class<H> hintClass, String gravityModelId) {
|
||||
private final Server server;
|
||||
|
||||
public AbstractWorldGenerator(String id, Server server, Class<H> hintClass, String gravityModelId) {
|
||||
super(id);
|
||||
this.hintClass = Objects.requireNonNull(hintClass, "hintClass");
|
||||
this.gravityModel = GravityModelRegistry.getInstance().create(Objects.requireNonNull(gravityModelId, "gravityModelId"));
|
||||
this.server = server;
|
||||
|
||||
if (this.gravityModel == null) {
|
||||
throw new IllegalArgumentException("Gravity model with ID \"" + gravityModelId + "\" not found");
|
||||
@ -78,4 +84,19 @@ public abstract class AbstractWorldGenerator<H> extends WorldGenerator {
|
||||
return gravityModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Server getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldLogic getWorldLogic() {
|
||||
return server.getWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldData getWorldData() {
|
||||
return server.getWorld().getData();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -29,6 +29,8 @@ import ru.windcorp.progressia.common.world.ChunkData;
|
||||
import ru.windcorp.progressia.common.world.DecodingException;
|
||||
import ru.windcorp.progressia.common.world.GravityModel;
|
||||
import ru.windcorp.progressia.common.world.WorldData;
|
||||
import ru.windcorp.progressia.server.Server;
|
||||
import ru.windcorp.progressia.server.world.WorldLogic;
|
||||
|
||||
public abstract class WorldGenerator extends Namespaced {
|
||||
|
||||
@ -37,7 +39,7 @@ public abstract class WorldGenerator extends Namespaced {
|
||||
// package-private constructor; extend AbstractWorldGeneration
|
||||
}
|
||||
|
||||
public abstract ChunkData generate(Vec3i chunkPos, WorldData world);
|
||||
public abstract ChunkData generate(Vec3i chunkPos);
|
||||
|
||||
public abstract Object readGenerationHint(DataInputStream input) throws IOException, DecodingException;
|
||||
|
||||
@ -49,4 +51,8 @@ public abstract class WorldGenerator extends Namespaced {
|
||||
|
||||
public abstract Vec3 suggestSpawnLocation();
|
||||
|
||||
public abstract Server getServer();
|
||||
public abstract WorldLogic getWorldLogic();
|
||||
public abstract WorldData getWorldData();
|
||||
|
||||
}
|
||||
|
@ -37,18 +37,18 @@ import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.tile.TileData;
|
||||
import ru.windcorp.progressia.common.world.tile.TileDataRegistry;
|
||||
import ru.windcorp.progressia.server.world.WorldLogic;
|
||||
import ru.windcorp.progressia.server.Server;
|
||||
import ru.windcorp.progressia.server.world.generation.AbstractWorldGenerator;
|
||||
|
||||
public class TestWorldGenerator extends AbstractWorldGenerator<Boolean> {
|
||||
|
||||
private final TestTerrainGenerator terrainGen;
|
||||
|
||||
public TestWorldGenerator(WorldLogic world) {
|
||||
super("Test:WorldGenerator", Boolean.class, "Test:TheGravityModel");
|
||||
this.terrainGen = new TestTerrainGenerator(this, world);
|
||||
public TestWorldGenerator(Server server) {
|
||||
super("Test:WorldGenerator", server, Boolean.class, "Test:TheGravityModel");
|
||||
this.terrainGen = new TestTerrainGenerator(this, server.getWorld());
|
||||
|
||||
world.getData().addListener(new WorldDataListener() {
|
||||
getWorldData().addListener(new WorldDataListener() {
|
||||
@Override
|
||||
public void onChunkLoaded(WorldData world, ChunkData chunk) {
|
||||
findAndPopulate(chunk.getPosition(), world);
|
||||
@ -77,9 +77,9 @@ public class TestWorldGenerator extends AbstractWorldGenerator<Boolean> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkData generate(Vec3i chunkPos, WorldData world) {
|
||||
ChunkData chunk = generateUnpopulated(chunkPos, world);
|
||||
world.addChunk(chunk);
|
||||
public ChunkData generate(Vec3i chunkPos) {
|
||||
ChunkData chunk = generateUnpopulated(chunkPos, getWorldData());
|
||||
getWorldData().addChunk(chunk);
|
||||
return chunk;
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,6 @@ import ru.windcorp.progressia.common.util.FloatRangeMap;
|
||||
import ru.windcorp.progressia.common.util.VectorUtil;
|
||||
import ru.windcorp.progressia.common.world.ChunkData;
|
||||
import ru.windcorp.progressia.common.world.Coordinates;
|
||||
import ru.windcorp.progressia.common.world.WorldData;
|
||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
|
||||
import ru.windcorp.progressia.test.gen.TerrainLayer;
|
||||
@ -61,8 +60,8 @@ class PlanetTerrainGenerator {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public ChunkData generateTerrain(Vec3i chunkPos, WorldData world) {
|
||||
ChunkData chunk = new ChunkData(chunkPos, world);
|
||||
public ChunkData generateTerrain(Vec3i chunkPos) {
|
||||
ChunkData chunk = new ChunkData(chunkPos, getGenerator().getWorldData());
|
||||
|
||||
if (isOrdinaryChunk(chunkPos)) {
|
||||
generateOrdinaryTerrain(chunk);
|
||||
|
@ -26,24 +26,19 @@ import glm.vec._3.i.Vec3i;
|
||||
import ru.windcorp.progressia.common.util.VectorUtil;
|
||||
import ru.windcorp.progressia.common.world.ChunkData;
|
||||
import ru.windcorp.progressia.common.world.DecodingException;
|
||||
import ru.windcorp.progressia.common.world.WorldData;
|
||||
import ru.windcorp.progressia.server.Server;
|
||||
import ru.windcorp.progressia.server.world.WorldLogic;
|
||||
import ru.windcorp.progressia.server.world.generation.AbstractWorldGenerator;
|
||||
|
||||
public class TestPlanetGenerator extends AbstractWorldGenerator<Boolean> {
|
||||
|
||||
private final Server server;
|
||||
|
||||
private final Planet planet;
|
||||
|
||||
private final PlanetTerrainGenerator terrainGenerator;
|
||||
private final PlanetFeatureGenerator featureGenerator;
|
||||
|
||||
public TestPlanetGenerator(String id, Planet planet, WorldLogic world) {
|
||||
super(id, Boolean.class, "Test:PlanetGravityModel");
|
||||
public TestPlanetGenerator(String id, Server server, Planet planet) {
|
||||
super(id, server, Boolean.class, "Test:PlanetGravityModel");
|
||||
|
||||
this.server = world.getServer();
|
||||
this.planet = planet;
|
||||
|
||||
TestPlanetGravityModel model = (TestPlanetGravityModel) this.getGravityModel();
|
||||
@ -81,9 +76,9 @@ public class TestPlanetGenerator extends AbstractWorldGenerator<Boolean> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkData generate(Vec3i chunkPos, WorldData world) {
|
||||
VectorUtil.iterateCuboidAround(chunkPos, 3, r -> conjureTerrain(r, world));
|
||||
ChunkData chunk = world.getChunk(chunkPos);
|
||||
public ChunkData generate(Vec3i chunkPos) {
|
||||
VectorUtil.iterateCuboidAround(chunkPos, 3, r -> conjureTerrain(r));
|
||||
ChunkData chunk = getWorldData().getChunk(chunkPos);
|
||||
|
||||
if (!isChunkReady(chunk.getGenerationHint())) {
|
||||
featureGenerator.generateFeatures(chunk);
|
||||
@ -92,17 +87,17 @@ public class TestPlanetGenerator extends AbstractWorldGenerator<Boolean> {
|
||||
return chunk;
|
||||
}
|
||||
|
||||
private void conjureTerrain(Vec3i chunkPos, WorldData world) {
|
||||
ChunkData chunk = world.getChunk(chunkPos);
|
||||
private void conjureTerrain(Vec3i chunkPos) {
|
||||
ChunkData chunk = getWorldData().getChunk(chunkPos);
|
||||
|
||||
if (chunk == null) {
|
||||
server.getLoadManager().getChunkManager().loadChunk(chunkPos);
|
||||
chunk = world.getChunk(chunkPos);
|
||||
getServer().getLoadManager().getChunkManager().loadChunk(chunkPos);
|
||||
chunk = getWorldData().getChunk(chunkPos);
|
||||
}
|
||||
|
||||
if (chunk == null) {
|
||||
chunk = terrainGenerator.generateTerrain(chunkPos, world);
|
||||
world.addChunk(chunk);
|
||||
chunk = terrainGenerator.generateTerrain(chunkPos);
|
||||
getWorldData().addChunk(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user