diff --git a/assets/Data/game/structure.json b/assets/Data/game/structure.json new file mode 100644 index 00000000..586573c0 --- /dev/null +++ b/assets/Data/game/structure.json @@ -0,0 +1,16 @@ +{ + "data" : [ + { + "id" : "test1", + "fabPath" : "Data/fab/disjointedroom1.block", + "dimensions" : { + "x" : 10, + "y" : 10, + "z" : 10 + } + } + ], + "files" : [ + + ] +} \ No newline at end of file diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 0ed5cfcd..8e4d565a 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -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 diff --git a/src/main/java/electrosphere/game/data/Config.java b/src/main/java/electrosphere/game/data/Config.java index 57db20de..6d2f3a3b 100644 --- a/src/main/java/electrosphere/game/data/Config.java +++ b/src/main/java/electrosphere/game/data/Config.java @@ -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 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 getSamplerFiles(){ return this.samplerDefinitions; } + + /** + * Gets the structure data + * @return The structure data + */ + public StructureDataLoader getStructureData(){ + return this.structureData; + } } diff --git a/src/main/java/electrosphere/game/data/struct/StructureData.java b/src/main/java/electrosphere/game/data/struct/StructureData.java new file mode 100644 index 00000000..6b35427a --- /dev/null +++ b/src/main/java/electrosphere/game/data/struct/StructureData.java @@ -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; + } + + + +} diff --git a/src/main/java/electrosphere/game/data/struct/StructureDataFile.java b/src/main/java/electrosphere/game/data/struct/StructureDataFile.java new file mode 100644 index 00000000..5bcae67c --- /dev/null +++ b/src/main/java/electrosphere/game/data/struct/StructureDataFile.java @@ -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 data; + + /** + * All child files of this one + */ + List files; + + /** + * Gets the structure data in this file + * @return The structure data in this file + */ + public List getData() { + return data; + } + + /** + * Sets the structure data in this file + * @param structure The structure data in this file + */ + public void setData(List data) { + this.data = data; + } + + /** + * Gets all child files of this one + * @return All child files of this one + */ + public List getFiles() { + return files; + } + + /** + * Sets all child files of this one + * @param files All child files of this one + */ + public void setFiles(List files) { + this.files = files; + } + +} diff --git a/src/main/java/electrosphere/game/data/struct/StructureDataLoader.java b/src/main/java/electrosphere/game/data/struct/StructureDataLoader.java new file mode 100644 index 00000000..a044baf1 --- /dev/null +++ b/src/main/java/electrosphere/game/data/struct/StructureDataLoader.java @@ -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 idTypeMap = new HashMap(); + + /** + * 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 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 getTypeIds(){ + return idTypeMap.keySet(); + } + + /** + * Reads a child structure defintion file + * @param filename The filename + * @return The list of structure in the file + */ + static List recursiveReadStructureLoader(String filename){ + List typeList = new LinkedList(); + 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 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 typeList = StructureDataLoader.recursiveReadStructureLoader(initialPath); + for(StructureData type : typeList){ + rVal.putType(type.getId(), type); + } + return rVal; + } + +} diff --git a/src/main/java/electrosphere/server/entity/ServerContentGenerator.java b/src/main/java/electrosphere/server/entity/ServerContentGenerator.java index c4b3c810..3e81b7f7 100644 --- a/src/main/java/electrosphere/server/entity/ServerContentGenerator.java +++ b/src/main/java/electrosphere/server/entity/ServerContentGenerator.java @@ -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( diff --git a/src/main/java/electrosphere/server/entity/ServerContentManager.java b/src/main/java/electrosphere/server/entity/ServerContentManager.java index 5a770ebf..5126f36a 100644 --- a/src/main/java/electrosphere/server/entity/ServerContentManager.java +++ b/src/main/java/electrosphere/server/entity/ServerContentManager.java @@ -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 diff --git a/src/main/java/electrosphere/server/macro/MacroData.java b/src/main/java/electrosphere/server/macro/MacroData.java index bfe42bb5..9d4c7563 100644 --- a/src/main/java/electrosphere/server/macro/MacroData.java +++ b/src/main/java/electrosphere/server/macro/MacroData.java @@ -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 diff --git a/src/main/java/electrosphere/server/macro/spatial/MacroAreaObject.java b/src/main/java/electrosphere/server/macro/spatial/MacroAreaObject.java new file mode 100644 index 00000000..4161d7cd --- /dev/null +++ b/src/main/java/electrosphere/server/macro/spatial/MacroAreaObject.java @@ -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(); + + +} diff --git a/src/main/java/electrosphere/server/macro/structure/Structure.java b/src/main/java/electrosphere/server/macro/structure/Structure.java index 7353cda8..588b06ba 100644 --- a/src/main/java/electrosphere/server/macro/structure/Structure.java +++ b/src/main/java/electrosphere/server/macro/structure/Structure.java @@ -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 data = new HashMap(); + /** + * Data keys associated with the structure + */ LinkedList dataKeys = new LinkedList(); - 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 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); + } diff --git a/src/main/java/electrosphere/server/macro/structure/StructureManager.java b/src/main/java/electrosphere/server/macro/structure/StructureManager.java index 4bd43de5..412bbfb3 100644 --- a/src/main/java/electrosphere/server/macro/structure/StructureManager.java +++ b/src/main/java/electrosphere/server/macro/structure/StructureManager.java @@ -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 getStructuresInChunk(int worldX, int worldY){ - List rVal = new LinkedList(); - DatabaseResult result = Globals.dbController.executePreparedQuery("SELECT * FROM structWorldPositions WHERE posX = ? AND posY = ?;",worldX,worldY); - List returnedIDs = new LinkedList(); - 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; - } } diff --git a/src/main/java/electrosphere/server/macro/structure/VirtualStructureUtils.java b/src/main/java/electrosphere/server/macro/structure/VirtualStructureUtils.java index 1563f904..caf021cc 100644 --- a/src/main/java/electrosphere/server/macro/structure/VirtualStructureUtils.java +++ b/src/main/java/electrosphere/server/macro/structure/VirtualStructureUtils.java @@ -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); diff --git a/src/main/java/electrosphere/server/simulation/MacroSimulation.java b/src/main/java/electrosphere/server/simulation/MacroSimulation.java index 7b2dc13e..81a85933 100644 --- a/src/main/java/electrosphere/server/simulation/MacroSimulation.java +++ b/src/main/java/electrosphere/server/simulation/MacroSimulation.java @@ -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 nearbyPopulatedStructures = new LinkedList(); - 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 nearbyPopulatedStructures = new LinkedList(); + // 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"); + // } } // } }