macro structure data definitions
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2025-04-29 13:41:52 -04:00
parent a81e9e203d
commit a7ef1db485
14 changed files with 416 additions and 142 deletions

View File

@ -0,0 +1,16 @@
{
"data" : [
{
"id" : "test1",
"fabPath" : "Data/fab/disjointedroom1.block",
"dimensions" : {
"x" : 10,
"y" : 10,
"z" : 10
}
}
],
"files" : [
]
}

View File

@ -1795,8 +1795,6 @@ Upgrade terrain editing user experience further
Upgrade terrain generation algorithms
- This one should be an ongoing process in general as it is a matter of taste
- Make a route hard coded that throws you straight into a generated world
- This makes it easier to tweak algo and immediately get results
Documentation

View File

@ -19,6 +19,7 @@ import electrosphere.game.data.foliage.type.FoliageTypeLoader;
import electrosphere.game.data.foliage.type.model.FoliageTypeMap;
import electrosphere.game.data.item.ItemDataMap;
import electrosphere.game.data.projectile.ProjectileTypeHolder;
import electrosphere.game.data.struct.StructureDataLoader;
import electrosphere.game.data.tutorial.HintDefinition;
import electrosphere.game.data.units.UnitDefinitionFile;
import electrosphere.game.data.units.UnitLoader;
@ -89,6 +90,11 @@ public class Config {
* The list of sampler definitions
*/
List<SamplerFile> samplerDefinitions;
/**
* The structure data
*/
StructureDataLoader structureData;
/**
* Loads the default data
@ -112,6 +118,7 @@ public class Config {
config.recipeMap = RecipeDataMap.loadRecipeFiles("Data/game/recipes.json");
config.biomeMap = BiomeTypeMap.loadBiomeFile("Data/game/biomes.json");
config.samplerDefinitions = SamplerFile.readSamplerDefinitionFiles("Data/game/voxel");
config.structureData = StructureDataLoader.loadStructureFiles("Data/game/structure.json");
//create procedural item types
ItemDataMap.loadSpawnItems(config.itemMap, config.objectTypeLoader);
@ -360,5 +367,13 @@ public class Config {
public List<SamplerFile> getSamplerFiles(){
return this.samplerDefinitions;
}
/**
* Gets the structure data
* @return The structure data
*/
public StructureDataLoader getStructureData(){
return this.structureData;
}
}

View File

@ -0,0 +1,67 @@
package electrosphere.game.data.struct;
import org.joml.Vector3d;
/**
* Data about a structure
*/
public class StructureData {
/**
* The id of the structure
*/
String id;
/**
* The path to the fab for the structure
*/
String fabPath;
/**
* The dimensions of the structure
*/
Vector3d dimensions;
/**
* Sets the id of the structure
* @return The id
*/
public String getId() {
return id;
}
/**
* Gets the path to the fab for the structure
* @return The path
*/
public String getFabPath() {
return fabPath;
}
/**
* Sets the path to the fab for the struct
* @param fabPath The path
*/
public void setFabPath(String fabPath) {
this.fabPath = fabPath;
}
/**
* Gets the dimensions of the structure
* @return The dimensions
*/
public Vector3d getDimensions() {
return dimensions;
}
/**
* Sets the dimensions of the structure
* @param dimensions The dimensions
*/
public void setDimensions(Vector3d dimensions) {
this.dimensions = dimensions;
}
}

View File

@ -0,0 +1,52 @@
package electrosphere.game.data.struct;
import java.util.List;
/**
* A file that stores structure data
*/
public class StructureDataFile {
/**
* The list of structures
*/
List<StructureData> data;
/**
* All child files of this one
*/
List<String> files;
/**
* Gets the structure data in this file
* @return The structure data in this file
*/
public List<StructureData> getData() {
return data;
}
/**
* Sets the structure data in this file
* @param structure The structure data in this file
*/
public void setData(List<StructureData> data) {
this.data = data;
}
/**
* Gets all child files of this one
* @return All child files of this one
*/
public List<String> getFiles() {
return files;
}
/**
* Sets all child files of this one
* @param files All child files of this one
*/
public void setFiles(List<String> files) {
this.files = files;
}
}

View File

@ -0,0 +1,94 @@
package electrosphere.game.data.struct;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import electrosphere.util.FileUtils;
/**
* The structure type loader
*/
public class StructureDataLoader {
/**
* The map of structure id -> structure data
*/
Map<String,StructureData> idTypeMap = new HashMap<String,StructureData>();
/**
* Adds structure data to the loader
* @param name The id of the structure
* @param type The structure data
*/
public void putType(String name, StructureData type){
idTypeMap.put(name,type);
}
/**
* Gets structure data from the id of the type
* @param id The id of the type
* @return The structure data if it exists, null otherwise
*/
public StructureData getType(String id){
return idTypeMap.get(id);
}
/**
* Gets the collection of all structure data
* @return the collection of all structure data
*/
public Collection<StructureData> getTypes(){
return idTypeMap.values();
}
/**
* Gets the set of all structure data id's stored in the loader
* @return the set of all structure data ids
*/
public Set<String> getTypeIds(){
return idTypeMap.keySet();
}
/**
* Reads a child structure defintion file
* @param filename The filename
* @return The list of structure in the file
*/
static List<StructureData> recursiveReadStructureLoader(String filename){
List<StructureData> typeList = new LinkedList<StructureData>();
StructureDataFile loaderFile = FileUtils.loadObjectFromAssetPath(filename, StructureDataFile.class);
//push the types from this file
for(StructureData type : loaderFile.getData()){
typeList.add(type);
}
//push types from any other files
if(loaderFile.getFiles() != null){
for(String filepath : loaderFile.getFiles()){
List<StructureData> parsedTypeList = StructureDataLoader.recursiveReadStructureLoader(filepath);
for(StructureData type : parsedTypeList){
typeList.add(type);
}
}
}
return typeList;
}
/**
* Loads all structure definition files recursively
* @param initialPath The initial path to recurse from
* @return The structure defintion interface
*/
public static StructureDataLoader loadStructureFiles(String initialPath) {
StructureDataLoader rVal = new StructureDataLoader();
List<StructureData> typeList = StructureDataLoader.recursiveReadStructureLoader(initialPath);
for(StructureData type : typeList){
rVal.putType(type.getId(), type);
}
return rVal;
}
}

View File

@ -11,6 +11,7 @@ import electrosphere.game.data.biome.BiomeData;
import electrosphere.game.data.biome.BiomeFoliageDescription;
import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.ServerDataCell;
import electrosphere.server.macro.MacroData;
import electrosphere.server.physics.terrain.manager.ServerTerrainChunk;
import io.github.studiorailgun.NoiseUtils;
@ -33,11 +34,12 @@ public class ServerContentGenerator {
/**
* Generates content for a given data cell
* @param realm The realm
* @param macroData The macro data
* @param cell The cell
* @param worldPos The world position of the cell
* @param randomizer The randomizer
*/
public static void generateContent(Realm realm, ServerDataCell cell, Vector3i worldPos, long randomizer){
public static void generateContent(Realm realm, MacroData macroData, ServerDataCell cell, Vector3i worldPos, long randomizer){
//verify we have everything for chunk content gen
if(realm.getServerWorldData() == null && realm.getServerWorldData().getServerTerrainManager() == null && realm.getServerWorldData().getServerTerrainManager().getModel() == null){
throw new Error(

View File

@ -19,9 +19,14 @@ import electrosphere.util.math.HashUtils;
import electrosphere.server.macro.character.Character;
import electrosphere.server.macro.race.Race;
/**
* Manages creating/saving/loading/destroying content (ie entities) on the server
*/
public class ServerContentManager {
//controls whether the manager should generate content on loading a new scene
/**
* controls whether the manager should generate content on loading a new scene
*/
boolean generateContent = false;
/**
@ -64,7 +69,7 @@ public class ServerContentManager {
contentRaw.hydrateRawContent(realm,cell);
} else {
//else create from scratch
ServerContentGenerator.generateContent(realm, cell, worldPos, HashUtils.hashIVec(worldPos.x, worldPos.y, worldPos.z));
ServerContentGenerator.generateContent(realm, this.macroData, cell, worldPos, HashUtils.hashIVec(worldPos.x, worldPos.y, worldPos.z));
}
} else {
//just because content wasn't generated doesn't mean there isn't data saved under that key

View File

@ -108,6 +108,12 @@ public class MacroData {
Race.setRace(testChar, Race.create("human", "human"));
rVal.characters.add(testChar);
//add a test character
// Structure struct = Structure.
// testChar.setPos(new Vector3d(ServerWorldData.convertChunkToRealSpace(new Vector3i(32774, 1, 32770))));
// Race.setRace(testChar, Race.create("human", "human"));
// rVal.characters.add(testChar);
//spawn initial characters in each race
//find initial positions to place characters at per race
//generate initial characters

View File

@ -0,0 +1,23 @@
package electrosphere.server.macro.spatial;
import org.joml.Vector3d;
/**
* A macro object that takes up an area of space instead of just a point
*/
public interface MacroAreaObject extends MacroObject {
/**
* Gets the start position of the AABB for the object
* @return The start position
*/
public Vector3d getStartPos();
/**
* Gets the end position of the AABB for the object
* @return The end position
*/
public Vector3d getEndPos();
}

View File

@ -4,61 +4,87 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import org.joml.AABBd;
import org.joml.Vector3d;
import electrosphere.server.macro.character.CharacterData;
import electrosphere.server.macro.character.CharacterDataStrings;
import electrosphere.server.macro.spatial.MacroAreaObject;
/**
* Server representation of a structure
*/
public class Structure extends CharacterData {
int worldX;
int worldY;
float locationX;
float locationY;
public class Structure extends CharacterData implements MacroAreaObject {
/**
* The position of the structure
*/
Vector3d position;
/**
* The bounding box for the structure
*/
AABBd aabb;
/**
* The path to the block fab for the structure
*/
String fabPath;
/**
* The type of the structure
*/
String type;
/**
* Data associated with the structure
*/
HashMap<String,Object> data = new HashMap<String,Object>();
/**
* Data keys associated with the structure
*/
LinkedList<String> dataKeys = new LinkedList<String>();
public Structure(int worldX, int worldY, float locationX, float locationY, String type) {
/**
* Constructor
* @param dataType The data type of the structure
*/
public Structure(){
super(CharacterDataStrings.STRUCTURE);
this.worldX = worldX;
this.worldY = worldY;
this.locationX = locationX;
this.locationY = locationY;
this.type = type;
}
/**
* Puts some data in the structure
* @param key The key for the data
* @param o The data
*/
public void putData(String key, Object o){
data.put(key,o);
dataKeys.add(key);
}
/**
* Gets the data keys for the structure
* @return
*/
public List<String> getDataKeys(){
return dataKeys;
}
/**
* Gets a piece of data on the structure
* @param key The key of the data
* @return The data if it exists, null otherwise
*/
public Object getData(String key){
return data.get(key);
}
public int getWorldX() {
return worldX;
}
public int getWorldY() {
return worldY;
}
public float getLocationX() {
return locationX;
}
public float getLocationY() {
return locationY;
}
/**
* Gets the type of the structure
* @return The type
*/
public String getType() {
return type;
}
@ -67,6 +93,26 @@ public class Structure extends CharacterData {
public String getDataType() {
return CharacterDataStrings.HOMETOWN;
}
@Override
public Vector3d getPos() {
return this.position;
}
@Override
public void setPos(Vector3d pos) {
this.position = pos;
}
@Override
public Vector3d getStartPos() {
return new Vector3d(aabb.minX,aabb.minY,aabb.minZ);
}
@Override
public Vector3d getEndPos() {
return new Vector3d(aabb.maxX,aabb.maxY,aabb.maxZ);
}

View File

@ -1,60 +1,10 @@
package electrosphere.server.macro.structure;
import com.google.gson.Gson;
import electrosphere.engine.Globals;
import electrosphere.server.db.DatabaseResult;
import electrosphere.server.db.DatabaseResultRow;
import java.util.LinkedList;
import java.util.List;
/**
* Manages all server views of structures
*/
public class StructureManager {
static Gson serializer;
static {
serializer = new Gson();
}
static int structIDIterator = 0;
public static Structure createStructure(int worldX, int worldY, float localX, float localY, String type){
structIDIterator++;
Structure rVal = new Structure(worldX, worldY, localX, localY, type);
Globals.dbController.executePreparedStatement("INSERT INTO structWorldPositions (structID,posX,posY) VALUES (?,?,?);",structIDIterator,worldX,worldY);
Globals.dbController.executePreparedStatement("INSERT INTO structData(structID,propName,propValue) VALUES(?,'localX','?');",structIDIterator,localX);
Globals.dbController.executePreparedStatement("INSERT INTO structData(structID,propName,propValue) VALUES(?,'localY','?');",structIDIterator,localY);
return rVal;
}
public static List<Structure> getStructuresInChunk(int worldX, int worldY){
List<Structure> rVal = new LinkedList<Structure>();
DatabaseResult result = Globals.dbController.executePreparedQuery("SELECT * FROM structWorldPositions WHERE posX = ? AND posY = ?;",worldX,worldY);
List<Integer> returnedIDs = new LinkedList<Integer>();
if(result.success() && result.hasResult()){
for(DatabaseResultRow row : result){
returnedIDs.add(row.getAsInteger("structID"));
}
}
if(returnedIDs.size() > 0){
String ids = "";
for(int ID : returnedIDs){
ids = ids + ID + ",";
}
ids = ids.substring(0, ids.length() - 1);
result = Globals.dbController.executePreparedQuery("SELECT * FROM structData WHERE structID IN (?);",ids);
if(result.success() && result.hasResult()){
for(DatabaseResultRow row : result){
Structure newStruct = serializer.fromJson(row.getAsString("dataVal"), Structure.class);
rVal.add(newStruct);
}
}
}
return rVal;
}
}

View File

@ -14,30 +14,30 @@ import org.joml.Vector2f;
public class VirtualStructureUtils {
public static Structure placeStructureAtPoint(float posX, float posY, float posZ, String type){
Realm realm = Globals.realmManager.getRealms().iterator().next();
int worldX = realm.getServerWorldData().convertRealToChunkSpace(posX);
int worldY = realm.getServerWorldData().convertRealToChunkSpace(posY);
Structure rVal = new Structure(worldX,worldY,posX,posY,type);
Globals.macroData.addStructure(rVal);
// public static Structure placeStructureAtPoint(float posX, float posY, float posZ, String type){
// Realm realm = Globals.realmManager.getRealms().iterator().next();
// int worldX = realm.getServerWorldData().convertRealToChunkSpace(posX);
// int worldY = realm.getServerWorldData().convertRealToChunkSpace(posY);
// Structure rVal = new Structure(worldX,worldY,posX,posY,type);
// Globals.macroData.addStructure(rVal);
// double centerHeight = Globals.serverTerrainManager.getHeightAtPosition(posX, posY, posZ);
// StructureType currentTypeObject = Globals.gameConfigCurrent.getStructureTypeMap().getType(type);
// float radius = currentTypeObject.getRadius();
// for(int x = -(int)radius; x < radius; x++){
// for(int y = -(int)radius; y < radius; y++){
// int newWorldX = Globals.serverWorldData.convertRealToChunkSpace(posX + x);
// int newWorldY = Globals.serverWorldData.convertRealToChunkSpace(posY + y);
// double newLocationX = Globals.serverWorldData.getRelativeLocation(posX + x, newWorldX);
// double newLocationY = Globals.serverWorldData.getRelativeLocation(posY + y, newWorldY);
// // System.out.println("Set height: " + centerHeight);
// // System.out.println("Deform in chunk: " + newWorldX + "," + newWorldY);
// Globals.serverTerrainManager.deformTerrainAtLocationToValue(newWorldX, newWorldY, (int)(newLocationX), (int)(newLocationY), (float)centerHeight);
// }
// }
// StructureUtils.serverSpawnBasicStructure(type, realm, new Vector3d(posX,(float)centerHeight + 2.4f,posY), new Quaternionf());
return rVal;
}
// // double centerHeight = Globals.serverTerrainManager.getHeightAtPosition(posX, posY, posZ);
// // StructureType currentTypeObject = Globals.gameConfigCurrent.getStructureTypeMap().getType(type);
// // float radius = currentTypeObject.getRadius();
// // for(int x = -(int)radius; x < radius; x++){
// // for(int y = -(int)radius; y < radius; y++){
// // int newWorldX = Globals.serverWorldData.convertRealToChunkSpace(posX + x);
// // int newWorldY = Globals.serverWorldData.convertRealToChunkSpace(posY + y);
// // double newLocationX = Globals.serverWorldData.getRelativeLocation(posX + x, newWorldX);
// // double newLocationY = Globals.serverWorldData.getRelativeLocation(posY + y, newWorldY);
// // // System.out.println("Set height: " + centerHeight);
// // // System.out.println("Deform in chunk: " + newWorldX + "," + newWorldY);
// // Globals.serverTerrainManager.deformTerrainAtLocationToValue(newWorldX, newWorldY, (int)(newLocationX), (int)(newLocationY), (float)centerHeight);
// // }
// // }
// // StructureUtils.serverSpawnBasicStructure(type, realm, new Vector3d(posX,(float)centerHeight + 2.4f,posY), new Quaternionf());
// return rVal;
// }
public static boolean validStructurePlacementPosition(float posX, float posY, String type){
// StructureType toPlaceType = Globals.gameConfigCurrent.getStructureTypeMap().getType(type);

View File

@ -115,43 +115,43 @@ public class MacroSimulation {
if(!hasHometown && hasShelter){
Structure shelter = CharacterUtils.getShelter(chara);
//if there's at least one other structure nearby
Vector2i shelterDiscretePos = new Vector2i(shelter.getWorldX(),shelter.getWorldY());
List<Structure> nearbyPopulatedStructures = new LinkedList<Structure>();
for(Structure currentStruct : Globals.macroData.getStructures()){
if(currentStruct.getWorldX() == shelterDiscretePos.x && currentStruct.getWorldY() == shelterDiscretePos.y && currentStruct != shelter){
//if has a resident
if(shelter.getDataKeys().contains(StructureDataStrings.RESIDENTS) && VirtualStructureUtils.getResidents(shelter).size() > 0){
boolean noTown = true;
for(Town town : Globals.macroData.getTowns()){
if(town.getStructures().contains(currentStruct)){
noTown = false;
}
}
if(noTown){
nearbyPopulatedStructures.add(currentStruct);
}
}
}
}
if(nearbyPopulatedStructures.size() > 0){
int numStructures = 0;
int numResidents = 0;
//form town
Town newTown = Town.createTown(shelterDiscretePos.x, shelterDiscretePos.y);
for(Structure structure : nearbyPopulatedStructures){
numStructures++;
newTown.addStructure(structure);
for(Character resident : VirtualStructureUtils.getResidents(structure)){
numResidents++;
newTown.addResident(resident);
CharacterUtils.addHometown(resident, newTown);
}
}
newTown.addStructure(shelter);
newTown.addResident(chara);
CharacterUtils.addHometown(chara, newTown);
System.out.println("Formed town with " + numStructures + " structures and " + numResidents + " residents");
}
// Vector2i shelterDiscretePos = new Vector2i(shelter.getWorldX(),shelter.getWorldY());
// List<Structure> nearbyPopulatedStructures = new LinkedList<Structure>();
// for(Structure currentStruct : Globals.macroData.getStructures()){
// if(currentStruct.getWorldX() == shelterDiscretePos.x && currentStruct.getWorldY() == shelterDiscretePos.y && currentStruct != shelter){
// //if has a resident
// if(shelter.getDataKeys().contains(StructureDataStrings.RESIDENTS) && VirtualStructureUtils.getResidents(shelter).size() > 0){
// boolean noTown = true;
// for(Town town : Globals.macroData.getTowns()){
// if(town.getStructures().contains(currentStruct)){
// noTown = false;
// }
// }
// if(noTown){
// nearbyPopulatedStructures.add(currentStruct);
// }
// }
// }
// }
// if(nearbyPopulatedStructures.size() > 0){
// int numStructures = 0;
// int numResidents = 0;
// //form town
// Town newTown = Town.createTown(shelterDiscretePos.x, shelterDiscretePos.y);
// for(Structure structure : nearbyPopulatedStructures){
// numStructures++;
// newTown.addStructure(structure);
// for(Character resident : VirtualStructureUtils.getResidents(structure)){
// numResidents++;
// newTown.addResident(resident);
// CharacterUtils.addHometown(resident, newTown);
// }
// }
// newTown.addStructure(shelter);
// newTown.addResident(chara);
// CharacterUtils.addHometown(chara, newTown);
// System.out.println("Formed town with " + numStructures + " structures and " + numResidents + " residents");
// }
}
// }
}