diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index ef80a9dc..15d33d89 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -2042,6 +2042,7 @@ Y-aligned prism meshgen Rendering prism regions Utilities for turning mesh gen algos into renderable entities Back off farm plots from roads by road radius +Farm plots properly save/load to/from disk diff --git a/src/main/java/electrosphere/renderer/pipelines/debug/DebugContentPipeline.java b/src/main/java/electrosphere/renderer/pipelines/debug/DebugContentPipeline.java index 5bf0e529..e4ad8df9 100644 --- a/src/main/java/electrosphere/renderer/pipelines/debug/DebugContentPipeline.java +++ b/src/main/java/electrosphere/renderer/pipelines/debug/DebugContentPipeline.java @@ -48,10 +48,11 @@ import electrosphere.renderer.pipelines.RenderPipeline; import electrosphere.renderer.texture.Texture; import electrosphere.server.datacell.Realm; import electrosphere.server.datacell.utils.EntityLookupUtils; +import electrosphere.server.macro.MacroData; import electrosphere.server.macro.civilization.road.Road; +import electrosphere.server.macro.region.MacroRegion; import electrosphere.server.macro.structure.VirtualStructure; import electrosphere.util.math.SpatialMathUtils; -import electrosphere.util.math.region.Region; import electrosphere.util.math.region.RegionPrism; /** @@ -222,9 +223,11 @@ public class DebugContentPipeline implements RenderPipeline { DebugContentPipeline.renderTube(openGLState, renderPipelineState, modelTransformMatrix, road.getPoint1(), road.getPoint2(), road.getRadius(), AssetDataStrings.TEXTURE_BLUE_TRANSPARENT); } if(this.farmPlotEntities.isEmpty()){ - if(Globals.serverState.realmManager.first().getMacroData().getTown(0).getFarmPlots().size() > 0){ - for(Region region : Globals.serverState.realmManager.first().getMacroData().getTown(0).getFarmPlots()){ - if(region instanceof RegionPrism prism){ + MacroData macroData = Globals.serverState.realmManager.first().getMacroData(); + List farmPlots = macroData.getTown(0).getFarmPlots(macroData); + if(farmPlots.size() > 0){ + for(MacroRegion region : farmPlots){ + if(region.getRegion() instanceof RegionPrism prism){ Entity plotDebugEnt = EntityCreationUtils.createClientSpatialEntity(); DrawableUtils.makeEntityDrawable(plotDebugEnt, () -> { Vector3d[] finalPoints = new Vector3d[prism.getPoints().length]; diff --git a/src/main/java/electrosphere/server/macro/MacroData.java b/src/main/java/electrosphere/server/macro/MacroData.java index 35779ff2..76284017 100644 --- a/src/main/java/electrosphere/server/macro/MacroData.java +++ b/src/main/java/electrosphere/server/macro/MacroData.java @@ -15,6 +15,7 @@ import electrosphere.server.macro.civilization.CivilizationGenerator; import electrosphere.server.macro.civilization.road.Road; import electrosphere.server.macro.race.Race; import electrosphere.server.macro.race.RaceMap; +import electrosphere.server.macro.region.MacroRegion; import electrosphere.server.macro.spatial.MacroAreaObject; import electrosphere.server.macro.spatial.MacroObject; import electrosphere.server.macro.structure.VirtualStructure; @@ -58,12 +59,23 @@ public class MacroData { */ List structures = new LinkedList(); + /** + * The list of all regions + */ + List regions = new LinkedList(); + /** * Maps structure id -> structure */ @Exclude private Map idStructMap = new HashMap(); + /** + * Maps region id -> region + */ + @Exclude + private Map idRegionMap = new HashMap(); + /** * List of roads */ @@ -173,6 +185,9 @@ public class MacroData { for(VirtualStructure struct : this.structures){ this.idStructMap.put(struct.getId(),struct); } + for(MacroRegion region : this.regions){ + this.idRegionMap.put(region.getId(),region); + } } /** @@ -280,6 +295,25 @@ public class MacroData { return this.roads; } + /** + * Registers a macro region + * @param region The macro region + */ + public void registerRegion(MacroRegion region){ + region.setId(regions.size()); + regions.add(region); + idRegionMap.put(region.getId(),region); + } + + /** + * Gets a macro region by its id + * @param id The id + * @return The macro region if it exists, null otherwise + */ + public MacroRegion getRegion(long id){ + return idRegionMap.get(id); + } + /** * Gets the list of structures * @return The list of structures diff --git a/src/main/java/electrosphere/server/macro/region/MacroRegion.java b/src/main/java/electrosphere/server/macro/region/MacroRegion.java new file mode 100644 index 00000000..1505d43d --- /dev/null +++ b/src/main/java/electrosphere/server/macro/region/MacroRegion.java @@ -0,0 +1,69 @@ +package electrosphere.server.macro.region; + +import electrosphere.server.macro.MacroData; +import electrosphere.util.math.region.Region; + +/** + * A macro data spatial region + */ +public class MacroRegion { + + + /** + * The id of the region + */ + private long id; + + /** + * The region + */ + private Region region; + + /** + * Creates a macro region + * @param macroData The macro data + * @param region The region + * @return The macro region + */ + public static MacroRegion create(MacroData macroData, Region region){ + MacroRegion rVal = new MacroRegion(); + rVal.region = region; + macroData.registerRegion(rVal); + return rVal; + } + + /** + * Gets the id of the region + * @return The id of the region + */ + public long getId() { + return id; + } + + /** + * Sets the id of the region + * @param id The id of the region + */ + public void setId(long id) { + this.id = id; + } + + /** + * Gets the spatial data of the region + * @return The spatial data + */ + public Region getRegion() { + return region; + } + + /** + * Sets the spatial data of the region + * @param region The spatial data of the region + */ + public void setRegion(Region region) { + this.region = region; + } + + + +} diff --git a/src/main/java/electrosphere/server/macro/settlement/Settlement.java b/src/main/java/electrosphere/server/macro/settlement/Settlement.java deleted file mode 100644 index e956616e..00000000 --- a/src/main/java/electrosphere/server/macro/settlement/Settlement.java +++ /dev/null @@ -1,5 +0,0 @@ -package electrosphere.server.macro.settlement; - -public class Settlement { - -} diff --git a/src/main/java/electrosphere/server/macro/town/Town.java b/src/main/java/electrosphere/server/macro/town/Town.java index 13fc4213..faf7e742 100644 --- a/src/main/java/electrosphere/server/macro/town/Town.java +++ b/src/main/java/electrosphere/server/macro/town/Town.java @@ -4,10 +4,10 @@ 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.region.MacroRegion; import electrosphere.server.macro.spatial.MacroAreaObject; import electrosphere.server.macro.spatial.MacroLODObject; import electrosphere.server.macro.structure.VirtualStructure; -import electrosphere.util.math.region.Region; import java.util.LinkedList; import java.util.List; @@ -72,9 +72,9 @@ public class Town implements MacroAreaObject, MacroLODObject { private List jobs = new LinkedList(); /** - * The list of farm plot regions + * The list of farm plot region idss */ - private List farmPlots = new LinkedList(); + private List farmPlotRegions = new LinkedList(); /** * The id of the parent civilization @@ -139,18 +139,20 @@ public class Town implements MacroAreaObject, MacroLODObject { /** * Gets the farm plots in the town + * @param macroData The macro data * @return The list of farm plots */ - public List getFarmPlots(){ - return farmPlots; + public List getFarmPlots(MacroData macroData){ + List regions = this.farmPlotRegions.stream().map((Long id) -> macroData.getRegion(id)).collect(Collectors.toList()); + return regions; } /** * Adds a farm plot region * @param farmPlotRegion The region for the farm plot */ - public void addFarmPlot(Region farmPlotRegion){ - this.farmPlots.add(farmPlotRegion); + public void addFarmPlot(MacroRegion farmPlotRegion){ + this.farmPlotRegions.add(farmPlotRegion.getId()); } /** diff --git a/src/main/java/electrosphere/server/macro/town/TownLayout.java b/src/main/java/electrosphere/server/macro/town/TownLayout.java index a300edb6..7a3418b7 100644 --- a/src/main/java/electrosphere/server/macro/town/TownLayout.java +++ b/src/main/java/electrosphere/server/macro/town/TownLayout.java @@ -18,6 +18,7 @@ import electrosphere.server.macro.MacroData; import electrosphere.server.macro.civilization.Civilization; import electrosphere.server.macro.civilization.road.Road; import electrosphere.server.macro.race.Race; +import electrosphere.server.macro.region.MacroRegion; import electrosphere.server.macro.structure.VirtualStructure; import electrosphere.util.math.HashUtils; import electrosphere.util.math.VoronoiUtils; @@ -288,7 +289,7 @@ public class TownLayout { plotPoint3.y = plotPoint1.y; plotPoint4.y = plotPoint1.y; //define a farm plot with these points - TownLayout.generateFarmPlot(realm,town,plotPoint1,plotPoint2,plotPoint3,plotPoint4); + TownLayout.generateFarmPlot(realm,macroData,town,plotPoint1,plotPoint2,plotPoint3,plotPoint4); } closedSet.add(openHash); @@ -408,20 +409,22 @@ public class TownLayout { /** * Creates a farm plot in the town at a given set of points * @param realm The realm the town is in + * @param macroData The macro data * @param town The town * @param point1 The first point * @param point2 The second point * @param point3 The third point * @param point4 The fourth point */ - private static void generateFarmPlot(Realm realm, Town town, Vector3d point1, Vector3d point2, Vector3d point3, Vector3d point4){ + private static void generateFarmPlot(Realm realm, MacroData macroData, Town town, Vector3d point1, Vector3d point2, Vector3d point3, Vector3d point4){ RegionPrism region = RegionPrism.create(new Vector3d[]{ new Vector3d(point1).sub(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0), new Vector3d(point2).sub(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0), new Vector3d(point3).sub(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0), new Vector3d(point4).sub(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0), }, FARM_PLOT_DEFAULT_HEIGHT); - town.addFarmPlot(region); + MacroRegion macroRegion = MacroRegion.create(macroData, region); + town.addFarmPlot(macroRegion); } /** diff --git a/src/main/java/electrosphere/util/FileUtils.java b/src/main/java/electrosphere/util/FileUtils.java index 8c5543a1..ab5e0ab8 100644 --- a/src/main/java/electrosphere/util/FileUtils.java +++ b/src/main/java/electrosphere/util/FileUtils.java @@ -13,6 +13,8 @@ import electrosphere.server.macro.character.data.CharacterDataSerializer; import electrosphere.server.physics.terrain.generation.noise.NoiseModuleSerializer; import electrosphere.server.physics.terrain.generation.noise.NoiseSampler; import electrosphere.util.annotation.AnnotationExclusionStrategy; +import electrosphere.util.math.region.Region; +import electrosphere.util.math.region.RegionSerializer; import java.awt.image.BufferedImage; import java.io.BufferedReader; @@ -56,6 +58,7 @@ public class FileUtils { gsonBuilder.registerTypeAdapter(AITreeData.class, new AITreeDataSerializer()); gsonBuilder.registerTypeAdapter(NoiseSampler.class, new NoiseModuleSerializer()); gsonBuilder.registerTypeAdapter(CharacterData.class, new CharacterDataSerializer()); + gsonBuilder.registerTypeAdapter(Region.class, new RegionSerializer()); gsonBuilder.addDeserializationExclusionStrategy(new AnnotationExclusionStrategy()); gsonBuilder.addSerializationExclusionStrategy(new AnnotationExclusionStrategy()); gson = gsonBuilder.create(); diff --git a/src/main/java/electrosphere/util/math/region/Region.java b/src/main/java/electrosphere/util/math/region/Region.java index 04fbcba9..2adf1f23 100644 --- a/src/main/java/electrosphere/util/math/region/Region.java +++ b/src/main/java/electrosphere/util/math/region/Region.java @@ -8,26 +8,12 @@ import org.joml.Vector3d; * A region of 3d space */ public interface Region { - - /** - * The type of selection - */ - public static enum RegionType { - /** - * A rectangle - */ - RECTANGULAR, - /** - * A y-aligned prism - */ - Y_ALIGNED_PRISM, - } /** * Gets the type of region * @return The type of region */ - public RegionType getType(); + public String getType(); /** * Checks if the region contains a point diff --git a/src/main/java/electrosphere/util/math/region/RegionPrism.java b/src/main/java/electrosphere/util/math/region/RegionPrism.java index 3321a128..24e01069 100644 --- a/src/main/java/electrosphere/util/math/region/RegionPrism.java +++ b/src/main/java/electrosphere/util/math/region/RegionPrism.java @@ -11,6 +11,16 @@ import electrosphere.util.math.GeomUtils; */ public class RegionPrism implements Region { + /** + * The prism region type + */ + public static final String TYPE_STRING = "Y_ALIGNED_PRISM"; + + /** + * The type of region + */ + private final String type = TYPE_STRING; + /** * The height of the prism @@ -80,8 +90,8 @@ public class RegionPrism implements Region { } @Override - public RegionType getType() { - return RegionType.Y_ALIGNED_PRISM; + public String getType() { + return type; } @Override diff --git a/src/main/java/electrosphere/util/math/region/RegionRectangular.java b/src/main/java/electrosphere/util/math/region/RegionRectangular.java index 4aaf5582..f2c85467 100644 --- a/src/main/java/electrosphere/util/math/region/RegionRectangular.java +++ b/src/main/java/electrosphere/util/math/region/RegionRectangular.java @@ -9,6 +9,16 @@ import org.joml.Vector3d; */ public class RegionRectangular implements Region { + /** + * The prism region type + */ + public static final String TYPE_STRING = "RECTANGULAR"; + + /** + * The type of region + */ + private final String type = RegionRectangular.TYPE_STRING; + /** * The AABB of the area selection */ @@ -41,8 +51,8 @@ public class RegionRectangular implements Region { } @Override - public RegionType getType() { - return RegionType.RECTANGULAR; + public String getType() { + return type; } @Override @@ -52,7 +62,7 @@ public class RegionRectangular implements Region { @Override public boolean intersects(Region other) { - if(other.getType() != RegionType.RECTANGULAR){ + if(other.getType() != RegionRectangular.TYPE_STRING){ throw new Error("One of the areas to test is not rectangular! " + other.getType()); } return aabb.testAABB(other.getAABB()); diff --git a/src/main/java/electrosphere/util/math/region/RegionSerializer.java b/src/main/java/electrosphere/util/math/region/RegionSerializer.java new file mode 100644 index 00000000..44de32ed --- /dev/null +++ b/src/main/java/electrosphere/util/math/region/RegionSerializer.java @@ -0,0 +1,50 @@ +package electrosphere.util.math.region; + +import java.lang.reflect.Type; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +public class RegionSerializer implements JsonSerializer, JsonDeserializer { + + @Override + public Region deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + switch(json.getAsJsonObject().get("type").getAsString()){ + case RegionRectangular.TYPE_STRING: { + return context.deserialize(json, RegionRectangular.class); + } + case RegionPrism.TYPE_STRING: { + return context.deserialize(json, RegionPrism.class); + } + default: { + throw new Error("Failed to serialize datatype: " + json.getAsJsonObject().get("type").getAsString()); + } + } + } + + @Override + public JsonElement serialize(Region src, Type typeOfSrc, JsonSerializationContext context) { + switch(src.getType()){ + + //race + case RegionPrism.TYPE_STRING: { + return context.serialize((RegionPrism)src); + } + + //diety data + case RegionRectangular.TYPE_STRING: { + return context.serialize((RegionRectangular)src); + } + + default: { + throw new Error("Failed to serialize datatype: " + src.getType()); + } + } + } + +}