From 139a5a11d3867981b9b9f9db7684a1302228ba6b Mon Sep 17 00:00:00 2001 From: austin Date: Sun, 18 May 2025 15:12:57 -0400 Subject: [PATCH] player character movement triggers layoutTown --- .../electrosphere/server/macro/MacroData.java | 19 ++++++- .../server/macro/MacroDataUpdater.java | 21 +++++++- .../macro/civilization/Civilization.java | 22 ++++++++ .../civilization/CivilizationGenerator.java | 4 +- .../electrosphere/server/macro/town/Town.java | 50 ++++++++++++++++++- .../server/macro/town/TownLayout.java | 31 +++++++++++- .../terrain/manager/ServerTerrainManager.java | 15 ++++++ 7 files changed, 155 insertions(+), 7 deletions(-) diff --git a/src/main/java/electrosphere/server/macro/MacroData.java b/src/main/java/electrosphere/server/macro/MacroData.java index 2678b0f2..8a649bf5 100644 --- a/src/main/java/electrosphere/server/macro/MacroData.java +++ b/src/main/java/electrosphere/server/macro/MacroData.java @@ -179,6 +179,20 @@ public class MacroData { public List getCivilizations(){ return civilizations; } + + /** + * Gets a civilization by its id + * @param id The id + * @return The civilization if it exists, null otherwise + */ + public Civilization getCivilization(int id){ + for(Civilization civ : this.civilizations){ + if(civ.getId() == id){ + return civ; + } + } + return null; + } /** * Adds a civilization @@ -203,9 +217,10 @@ public class MacroData { * Adds a town * @param center The center point of the town * @param radius The radius of the town + * @param parentCivId The id of the parent civilization */ - public Town addTown(Vector3d center, double radius){ - Town rVal = Town.createTown(center, radius); + public Town addTown(Vector3d center, double radius, int parentCivId){ + Town rVal = Town.createTown(center, radius, parentCivId); rVal.setId(towns.size()); towns.add(rVal); return rVal; diff --git a/src/main/java/electrosphere/server/macro/MacroDataUpdater.java b/src/main/java/electrosphere/server/macro/MacroDataUpdater.java index b6896491..b7ba8a22 100644 --- a/src/main/java/electrosphere/server/macro/MacroDataUpdater.java +++ b/src/main/java/electrosphere/server/macro/MacroDataUpdater.java @@ -2,10 +2,18 @@ package electrosphere.server.macro; import org.joml.Vector3d; +import electrosphere.server.macro.town.Town; +import electrosphere.server.macro.town.TownLayout; + /** * Updates macro data as a player comes into range of it */ public class MacroDataUpdater { + + /** + * Generate all towns within 5 km of a player + */ + private static final int TOWN_GENERATION_DIST = 5 * 1000; /** * Updates the macro data @@ -13,8 +21,17 @@ public class MacroDataUpdater { * @param playerPos The player's position */ public static void update(MacroData macroData, Vector3d playerPos){ - //scan for all objects within update range - //update them + //scan for all towns within update range + for(Town town : macroData.getTowns()){ + //only generate data for towns that aren't already full resolution + if(town.getResolution() == Town.TOWN_RES_MAX){ + continue; + } + Vector3d townPos = town.getPos(); + if(townPos.distance(playerPos) < TOWN_GENERATION_DIST){ + TownLayout.layoutTown(macroData, town); + } + } } } diff --git a/src/main/java/electrosphere/server/macro/civilization/Civilization.java b/src/main/java/electrosphere/server/macro/civilization/Civilization.java index 06037386..ec76b97b 100644 --- a/src/main/java/electrosphere/server/macro/civilization/Civilization.java +++ b/src/main/java/electrosphere/server/macro/civilization/Civilization.java @@ -8,6 +8,7 @@ import electrosphere.engine.Globals; import electrosphere.server.macro.MacroData; import electrosphere.server.macro.town.Town; import electrosphere.server.macro.character.Character; +import electrosphere.server.macro.race.Race; /** * A civilization @@ -34,6 +35,11 @@ public class Civilization { */ private List citizens = new LinkedList(); + /** + * The races that are a part of this civilization + */ + private List races = new LinkedList(); + /** * Gets the id of the civilization * @return The id @@ -98,4 +104,20 @@ public class Civilization { this.citizens.add(chara.getId()); } + /** + * Adds a race to the civilization + * @param race The race + */ + public void addRace(Race race){ + this.races.add(race.getId()); + } + + /** + * Gets the list of race ids of this civilization + * @return The list of race ids + */ + public List getRaceIds(){ + return this.races; + } + } diff --git a/src/main/java/electrosphere/server/macro/civilization/CivilizationGenerator.java b/src/main/java/electrosphere/server/macro/civilization/CivilizationGenerator.java index 120d2c31..fdf01273 100644 --- a/src/main/java/electrosphere/server/macro/civilization/CivilizationGenerator.java +++ b/src/main/java/electrosphere/server/macro/civilization/CivilizationGenerator.java @@ -28,9 +28,11 @@ public class CivilizationGenerator { public static void generate(ServerWorldData serverWorldData, MacroData macroData, Config config){ //TODO: spread out and don't just put at global spawn point Vector3d spawnPoint = new Vector3d(serverWorldData.getWorldSizeDiscrete() * ServerTerrainChunk.CHUNK_PLACEMENT_OFFSET / 2); + spawnPoint.y = serverWorldData.getServerTerrainManager().getElevation(spawnPoint); for(Race race : config.getRaceMap().getRaces()){ Civilization newCiv = macroData.addCivilization(race); - Town startingTown = macroData.addTown(spawnPoint, INITIAL_TOWN_RADIUS); + newCiv.addRace(race); + Town startingTown = macroData.addTown(spawnPoint, INITIAL_TOWN_RADIUS, newCiv.getId()); newCiv.addTown(startingTown); } } diff --git a/src/main/java/electrosphere/server/macro/town/Town.java b/src/main/java/electrosphere/server/macro/town/Town.java index 04623a05..aa308b76 100644 --- a/src/main/java/electrosphere/server/macro/town/Town.java +++ b/src/main/java/electrosphere/server/macro/town/Town.java @@ -3,6 +3,7 @@ package electrosphere.server.macro.town; import electrosphere.engine.Globals; import electrosphere.server.macro.MacroData; import electrosphere.server.macro.character.Character; +import electrosphere.server.macro.civilization.Civilization; import electrosphere.server.macro.spatial.MacroAreaObject; import electrosphere.server.macro.structure.VirtualStructure; @@ -18,6 +19,16 @@ import org.joml.Vector3d; */ public class Town implements MacroAreaObject { + /** + * Minimum data resolution town (ie hasn't generated structures or residents) + */ + public static final int TOWN_RES_MIN = 0; + + /** + * Maximim data resolution town (has fully generated all default structures and residents) + */ + public static final int TOWN_RES_MAX = 1; + /** * The id of the town */ @@ -27,6 +38,11 @@ public class Town implements MacroAreaObject { * Incrementer for IDs */ static int idIncrementer = 0; + + /** + * The resolution of data that has been generated for this town + */ + private int resolution = TOWN_RES_MIN; /** * The position of the town @@ -53,6 +69,11 @@ public class Town implements MacroAreaObject { */ private List jobs = new LinkedList(); + /** + * The id of the parent civilization + */ + private int parentCivId; + /** * Constructor */ @@ -65,12 +86,14 @@ public class Town implements MacroAreaObject { * Creates a town * @param position The position of the town * @param radius The radius of the town + * @param parentCiv The id of the parent civilization * @return The town */ - public static Town createTown(Vector3d position, double radius){ + public static Town createTown(Vector3d position, double radius, int parentCiv){ Town rVal = new Town(); rVal.position = position; rVal.radius = radius; + rVal.parentCivId = parentCiv; return rVal; } @@ -170,5 +193,30 @@ public class Town implements MacroAreaObject { public int getId(){ return this.id; } + + /** + * Gets the resolution of the data that has been generated for this town + * @return The resolution of the data + */ + public int getResolution() { + return resolution; + } + + /** + * Sets the resolution of the data that has been generated for this town + * @param resolution The resolution of the data + */ + public void setResolution(int resolution) { + this.resolution = resolution; + } + + /** + * Gets the parent civilization + * @param macroData The macro data + * @return The parent civilization + */ + public Civilization getParent(MacroData macroData){ + return macroData.getCivilization(this.parentCivId); + } } diff --git a/src/main/java/electrosphere/server/macro/town/TownLayout.java b/src/main/java/electrosphere/server/macro/town/TownLayout.java index 660baf85..3cff71e5 100644 --- a/src/main/java/electrosphere/server/macro/town/TownLayout.java +++ b/src/main/java/electrosphere/server/macro/town/TownLayout.java @@ -1,18 +1,47 @@ package electrosphere.server.macro.town; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +import electrosphere.data.struct.StructureData; +import electrosphere.engine.Globals; +import electrosphere.logger.LoggerInterface; import electrosphere.server.macro.MacroData; +import electrosphere.server.macro.civilization.Civilization; +import electrosphere.server.macro.race.Race; /** * Lays out town objects */ public class TownLayout { - + /** * Lays out structures for a town * @param macroData The macro data * @param town The town */ public static void layoutTown(MacroData macroData, Town town){ + Civilization parentCiv = town.getParent(macroData); + List raceIds = parentCiv.getRaceIds(); + List races = raceIds.stream().map((String raceId) -> Globals.gameConfigCurrent.getRaceMap().getRace(raceId)).filter((Race race) -> race != null).collect(Collectors.toList()); + if(races.size() == 0){ + throw new Error("No races found! " + raceIds); + } + List allowedStructures = new LinkedList(); + for(Race race : races){ + for(String structureId : race.getStructureIds()){ + StructureData structData = Globals.gameConfigCurrent.getStructureData().getType(structureId); + if(!allowedStructures.contains(structData)){ + allowedStructures.add(structData); + } + } + } + if(allowedStructures.size() < 1){ + throw new Error("No structures found! " + raceIds); + } + LoggerInterface.loggerEngine.DEBUG("Allowed structure count: " + allowedStructures.size()); + town.setResolution(Town.TOWN_RES_MAX); } } diff --git a/src/main/java/electrosphere/server/physics/terrain/manager/ServerTerrainManager.java b/src/main/java/electrosphere/server/physics/terrain/manager/ServerTerrainManager.java index 8b117202..986d9b00 100644 --- a/src/main/java/electrosphere/server/physics/terrain/manager/ServerTerrainManager.java +++ b/src/main/java/electrosphere/server/physics/terrain/manager/ServerTerrainManager.java @@ -22,6 +22,7 @@ import java.nio.ShortBuffer; import java.util.concurrent.ExecutorService; import java.util.function.Consumer; +import org.joml.Vector3d; import org.joml.Vector3i; /** @@ -311,6 +312,20 @@ public class ServerTerrainManager { return elevation; } + /** + * Gets the elevation at a real x and z (ignores y component) + * @param realPos The real position + * @return The elevation + */ + public double getElevation(Vector3d realPos){ + Globals.profiler.beginAggregateCpuSample("ServerTerrainManager.getChunk"); + Vector3i chunkPos = ServerWorldData.convertRealToChunkSpace(realPos); + Vector3i voxelPos = ServerWorldData.convertRealToVoxelSpace(realPos); + double elevation = chunkGenerator.getElevation(chunkPos.x, chunkPos.z, voxelPos.x, voxelPos.z); + Globals.profiler.endCpuSample(); + return elevation; + } + /** * Performs logic once a server chunk is available * @param worldX The world x position