farm plots properly save/load to/from disk
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This commit is contained in:
austin 2025-05-28 21:50:51 -04:00
parent 8bffe711ae
commit 81f79232e1
12 changed files with 205 additions and 39 deletions

View File

@ -2042,6 +2042,7 @@ Y-aligned prism meshgen
Rendering prism regions Rendering prism regions
Utilities for turning mesh gen algos into renderable entities Utilities for turning mesh gen algos into renderable entities
Back off farm plots from roads by road radius Back off farm plots from roads by road radius
Farm plots properly save/load to/from disk

View File

@ -48,10 +48,11 @@ import electrosphere.renderer.pipelines.RenderPipeline;
import electrosphere.renderer.texture.Texture; import electrosphere.renderer.texture.Texture;
import electrosphere.server.datacell.Realm; import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.utils.EntityLookupUtils; import electrosphere.server.datacell.utils.EntityLookupUtils;
import electrosphere.server.macro.MacroData;
import electrosphere.server.macro.civilization.road.Road; import electrosphere.server.macro.civilization.road.Road;
import electrosphere.server.macro.region.MacroRegion;
import electrosphere.server.macro.structure.VirtualStructure; import electrosphere.server.macro.structure.VirtualStructure;
import electrosphere.util.math.SpatialMathUtils; import electrosphere.util.math.SpatialMathUtils;
import electrosphere.util.math.region.Region;
import electrosphere.util.math.region.RegionPrism; 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); DebugContentPipeline.renderTube(openGLState, renderPipelineState, modelTransformMatrix, road.getPoint1(), road.getPoint2(), road.getRadius(), AssetDataStrings.TEXTURE_BLUE_TRANSPARENT);
} }
if(this.farmPlotEntities.isEmpty()){ if(this.farmPlotEntities.isEmpty()){
if(Globals.serverState.realmManager.first().getMacroData().getTown(0).getFarmPlots().size() > 0){ MacroData macroData = Globals.serverState.realmManager.first().getMacroData();
for(Region region : Globals.serverState.realmManager.first().getMacroData().getTown(0).getFarmPlots()){ List<MacroRegion> farmPlots = macroData.getTown(0).getFarmPlots(macroData);
if(region instanceof RegionPrism prism){ if(farmPlots.size() > 0){
for(MacroRegion region : farmPlots){
if(region.getRegion() instanceof RegionPrism prism){
Entity plotDebugEnt = EntityCreationUtils.createClientSpatialEntity(); Entity plotDebugEnt = EntityCreationUtils.createClientSpatialEntity();
DrawableUtils.makeEntityDrawable(plotDebugEnt, () -> { DrawableUtils.makeEntityDrawable(plotDebugEnt, () -> {
Vector3d[] finalPoints = new Vector3d[prism.getPoints().length]; Vector3d[] finalPoints = new Vector3d[prism.getPoints().length];

View File

@ -15,6 +15,7 @@ import electrosphere.server.macro.civilization.CivilizationGenerator;
import electrosphere.server.macro.civilization.road.Road; import electrosphere.server.macro.civilization.road.Road;
import electrosphere.server.macro.race.Race; import electrosphere.server.macro.race.Race;
import electrosphere.server.macro.race.RaceMap; import electrosphere.server.macro.race.RaceMap;
import electrosphere.server.macro.region.MacroRegion;
import electrosphere.server.macro.spatial.MacroAreaObject; import electrosphere.server.macro.spatial.MacroAreaObject;
import electrosphere.server.macro.spatial.MacroObject; import electrosphere.server.macro.spatial.MacroObject;
import electrosphere.server.macro.structure.VirtualStructure; import electrosphere.server.macro.structure.VirtualStructure;
@ -58,12 +59,23 @@ public class MacroData {
*/ */
List<VirtualStructure> structures = new LinkedList<VirtualStructure>(); List<VirtualStructure> structures = new LinkedList<VirtualStructure>();
/**
* The list of all regions
*/
List<MacroRegion> regions = new LinkedList<MacroRegion>();
/** /**
* Maps structure id -> structure * Maps structure id -> structure
*/ */
@Exclude @Exclude
private Map<Integer,VirtualStructure> idStructMap = new HashMap<Integer,VirtualStructure>(); private Map<Integer,VirtualStructure> idStructMap = new HashMap<Integer,VirtualStructure>();
/**
* Maps region id -> region
*/
@Exclude
private Map<Long,MacroRegion> idRegionMap = new HashMap<Long,MacroRegion>();
/** /**
* List of roads * List of roads
*/ */
@ -173,6 +185,9 @@ public class MacroData {
for(VirtualStructure struct : this.structures){ for(VirtualStructure struct : this.structures){
this.idStructMap.put(struct.getId(),struct); 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; 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 * Gets the list of structures
* @return The list of structures * @return The list of structures

View File

@ -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;
}
}

View File

@ -1,5 +0,0 @@
package electrosphere.server.macro.settlement;
public class Settlement {
}

View File

@ -4,10 +4,10 @@ import electrosphere.engine.Globals;
import electrosphere.server.macro.MacroData; import electrosphere.server.macro.MacroData;
import electrosphere.server.macro.character.Character; import electrosphere.server.macro.character.Character;
import electrosphere.server.macro.civilization.Civilization; import electrosphere.server.macro.civilization.Civilization;
import electrosphere.server.macro.region.MacroRegion;
import electrosphere.server.macro.spatial.MacroAreaObject; import electrosphere.server.macro.spatial.MacroAreaObject;
import electrosphere.server.macro.spatial.MacroLODObject; import electrosphere.server.macro.spatial.MacroLODObject;
import electrosphere.server.macro.structure.VirtualStructure; import electrosphere.server.macro.structure.VirtualStructure;
import electrosphere.util.math.region.Region;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -72,9 +72,9 @@ public class Town implements MacroAreaObject, MacroLODObject {
private List<TownJob> jobs = new LinkedList<TownJob>(); private List<TownJob> jobs = new LinkedList<TownJob>();
/** /**
* The list of farm plot regions * The list of farm plot region idss
*/ */
private List<Region> farmPlots = new LinkedList<Region>(); private List<Long> farmPlotRegions = new LinkedList<Long>();
/** /**
* The id of the parent civilization * The id of the parent civilization
@ -139,18 +139,20 @@ public class Town implements MacroAreaObject, MacroLODObject {
/** /**
* Gets the farm plots in the town * Gets the farm plots in the town
* @param macroData The macro data
* @return The list of farm plots * @return The list of farm plots
*/ */
public List<Region> getFarmPlots(){ public List<MacroRegion> getFarmPlots(MacroData macroData){
return farmPlots; List<MacroRegion> regions = this.farmPlotRegions.stream().map((Long id) -> macroData.getRegion(id)).collect(Collectors.toList());
return regions;
} }
/** /**
* Adds a farm plot region * Adds a farm plot region
* @param farmPlotRegion The region for the farm plot * @param farmPlotRegion The region for the farm plot
*/ */
public void addFarmPlot(Region farmPlotRegion){ public void addFarmPlot(MacroRegion farmPlotRegion){
this.farmPlots.add(farmPlotRegion); this.farmPlotRegions.add(farmPlotRegion.getId());
} }
/** /**

View File

@ -18,6 +18,7 @@ import electrosphere.server.macro.MacroData;
import electrosphere.server.macro.civilization.Civilization; import electrosphere.server.macro.civilization.Civilization;
import electrosphere.server.macro.civilization.road.Road; import electrosphere.server.macro.civilization.road.Road;
import electrosphere.server.macro.race.Race; import electrosphere.server.macro.race.Race;
import electrosphere.server.macro.region.MacroRegion;
import electrosphere.server.macro.structure.VirtualStructure; import electrosphere.server.macro.structure.VirtualStructure;
import electrosphere.util.math.HashUtils; import electrosphere.util.math.HashUtils;
import electrosphere.util.math.VoronoiUtils; import electrosphere.util.math.VoronoiUtils;
@ -288,7 +289,7 @@ public class TownLayout {
plotPoint3.y = plotPoint1.y; plotPoint3.y = plotPoint1.y;
plotPoint4.y = plotPoint1.y; plotPoint4.y = plotPoint1.y;
//define a farm plot with these points //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); closedSet.add(openHash);
@ -408,20 +409,22 @@ public class TownLayout {
/** /**
* Creates a farm plot in the town at a given set of points * Creates a farm plot in the town at a given set of points
* @param realm The realm the town is in * @param realm The realm the town is in
* @param macroData The macro data
* @param town The town * @param town The town
* @param point1 The first point * @param point1 The first point
* @param point2 The second point * @param point2 The second point
* @param point3 The third point * @param point3 The third point
* @param point4 The fourth 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[]{ RegionPrism region = RegionPrism.create(new Vector3d[]{
new Vector3d(point1).sub(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0), 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(point2).sub(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0),
new Vector3d(point3).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), new Vector3d(point4).sub(0,FARM_PLOT_DEFAULT_HEIGHT/2.0f,0),
}, FARM_PLOT_DEFAULT_HEIGHT); }, FARM_PLOT_DEFAULT_HEIGHT);
town.addFarmPlot(region); MacroRegion macroRegion = MacroRegion.create(macroData, region);
town.addFarmPlot(macroRegion);
} }
/** /**

View File

@ -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.NoiseModuleSerializer;
import electrosphere.server.physics.terrain.generation.noise.NoiseSampler; import electrosphere.server.physics.terrain.generation.noise.NoiseSampler;
import electrosphere.util.annotation.AnnotationExclusionStrategy; import electrosphere.util.annotation.AnnotationExclusionStrategy;
import electrosphere.util.math.region.Region;
import electrosphere.util.math.region.RegionSerializer;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.BufferedReader; import java.io.BufferedReader;
@ -56,6 +58,7 @@ public class FileUtils {
gsonBuilder.registerTypeAdapter(AITreeData.class, new AITreeDataSerializer()); gsonBuilder.registerTypeAdapter(AITreeData.class, new AITreeDataSerializer());
gsonBuilder.registerTypeAdapter(NoiseSampler.class, new NoiseModuleSerializer()); gsonBuilder.registerTypeAdapter(NoiseSampler.class, new NoiseModuleSerializer());
gsonBuilder.registerTypeAdapter(CharacterData.class, new CharacterDataSerializer()); gsonBuilder.registerTypeAdapter(CharacterData.class, new CharacterDataSerializer());
gsonBuilder.registerTypeAdapter(Region.class, new RegionSerializer());
gsonBuilder.addDeserializationExclusionStrategy(new AnnotationExclusionStrategy()); gsonBuilder.addDeserializationExclusionStrategy(new AnnotationExclusionStrategy());
gsonBuilder.addSerializationExclusionStrategy(new AnnotationExclusionStrategy()); gsonBuilder.addSerializationExclusionStrategy(new AnnotationExclusionStrategy());
gson = gsonBuilder.create(); gson = gsonBuilder.create();

View File

@ -8,26 +8,12 @@ import org.joml.Vector3d;
* A region of 3d space * A region of 3d space
*/ */
public interface Region { 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 * Gets the type of region
* @return The type of region * @return The type of region
*/ */
public RegionType getType(); public String getType();
/** /**
* Checks if the region contains a point * Checks if the region contains a point

View File

@ -11,6 +11,16 @@ import electrosphere.util.math.GeomUtils;
*/ */
public class RegionPrism implements Region { 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 * The height of the prism
@ -80,8 +90,8 @@ public class RegionPrism implements Region {
} }
@Override @Override
public RegionType getType() { public String getType() {
return RegionType.Y_ALIGNED_PRISM; return type;
} }
@Override @Override

View File

@ -9,6 +9,16 @@ import org.joml.Vector3d;
*/ */
public class RegionRectangular implements Region { 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 * The AABB of the area selection
*/ */
@ -41,8 +51,8 @@ public class RegionRectangular implements Region {
} }
@Override @Override
public RegionType getType() { public String getType() {
return RegionType.RECTANGULAR; return type;
} }
@Override @Override
@ -52,7 +62,7 @@ public class RegionRectangular implements Region {
@Override @Override
public boolean intersects(Region other) { 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()); throw new Error("One of the areas to test is not rectangular! " + other.getType());
} }
return aabb.testAABB(other.getAABB()); return aabb.testAABB(other.getAABB());

View File

@ -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<Region>, JsonDeserializer<Region> {
@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());
}
}
}
}