diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 3af447f1..53942765 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -1694,6 +1694,7 @@ Cleanup some TODOs Refactor block actions Placing fabs/blocks triggers structure scanning service Try closing ai manager threads on engine close +Ability to explicitly spawn new characters into macro data and have them then spawn into world diff --git a/src/main/java/electrosphere/client/ui/menu/debug/ImGuiAI.java b/src/main/java/electrosphere/client/ui/menu/debug/ImGuiAI.java index 5e1c50e5..168ab0ca 100644 --- a/src/main/java/electrosphere/client/ui/menu/debug/ImGuiAI.java +++ b/src/main/java/electrosphere/client/ui/menu/debug/ImGuiAI.java @@ -19,8 +19,10 @@ import electrosphere.renderer.ui.imgui.ImGuiWindow; import electrosphere.renderer.ui.imgui.ImGuiWindow.ImGuiWindowCallback; import electrosphere.server.ai.AI; import electrosphere.server.ai.nodes.plan.PathfindingNode; +import electrosphere.server.datacell.Realm; import electrosphere.server.datacell.gridded.GriddedDataCellManager; import electrosphere.server.datacell.utils.EntityLookupUtils; +import electrosphere.server.macro.character.CharacterUtils; import electrosphere.server.pathfinding.voxel.VoxelPathfinder; import electrosphere.server.pathfinding.voxel.VoxelPathfinder.PathfinderNode; import imgui.ImGui; @@ -82,6 +84,9 @@ public class ImGuiAI { if(ImGui.button("Draw current pathing")){ throw new Error("Unsupported currently!"); } + if(ImGui.button("Send off map")){ + throw new Error("Unsupported currently!"); + } } ImGui.unindent(); } @@ -161,6 +166,14 @@ public class ImGuiAI { } } } + + if(ImGui.button("Spawn test macro character")){ + Realm realm = Globals.realmManager.first(); + GriddedDataCellManager griddedDataCellManager = (GriddedDataCellManager)realm.getDataCellManager(); + Entity serverEnt = EntityLookupUtils.getServerEquivalent(Globals.playerEntity); + Vector3d spawnPos = griddedDataCellManager.getMacroEntryPoint(new Vector3d(EntityUtils.getPosition(serverEnt)).add(50,0,0)); + CharacterUtils.spawnCharacter(realm, spawnPos); + } } }); diff --git a/src/main/java/electrosphere/server/datacell/ServerWorldData.java b/src/main/java/electrosphere/server/datacell/ServerWorldData.java index 2d9ef860..8e95f1b6 100644 --- a/src/main/java/electrosphere/server/datacell/ServerWorldData.java +++ b/src/main/java/electrosphere/server/datacell/ServerWorldData.java @@ -281,6 +281,9 @@ public class ServerWorldData { * @return The real pos */ public static double convertVoxelToRealSpace(int voxelPos, int worldPos){ + if(voxelPos > ServerTerrainChunk.CHUNK_PLACEMENT_OFFSET){ + throw new Error("Voxel position outside of bounds, likely flipped args " + voxelPos + " " + worldPos); + } return voxelPos + ServerWorldData.convertWorldToReal(worldPos); } diff --git a/src/main/java/electrosphere/server/datacell/ViewportDataCellManager.java b/src/main/java/electrosphere/server/datacell/ViewportDataCellManager.java index 910b83ac..83d2caa0 100644 --- a/src/main/java/electrosphere/server/datacell/ViewportDataCellManager.java +++ b/src/main/java/electrosphere/server/datacell/ViewportDataCellManager.java @@ -13,6 +13,7 @@ import electrosphere.entity.EntityUtils; import electrosphere.entity.scene.Scene; import electrosphere.net.server.player.Player; import electrosphere.server.datacell.interfaces.DataCellManager; +import electrosphere.server.macro.spatial.MacroObject; /** * A viewport data cell manager @@ -145,5 +146,15 @@ public class ViewportDataCellManager implements DataCellManager { } return rVal; } + + @Override + public Vector3d getMacroEntryPoint(Vector3d point) { + return new Vector3d(); + } + + @Override + public void evaluateMacroObject(MacroObject object) { + throw new Error("ViewportDataCellManager does not support macro objects currently"); + } } diff --git a/src/main/java/electrosphere/server/datacell/gridded/GriddedDataCellManager.java b/src/main/java/electrosphere/server/datacell/gridded/GriddedDataCellManager.java index 0c30533e..d1704020 100644 --- a/src/main/java/electrosphere/server/datacell/gridded/GriddedDataCellManager.java +++ b/src/main/java/electrosphere/server/datacell/gridded/GriddedDataCellManager.java @@ -38,6 +38,7 @@ import electrosphere.server.datacell.interfaces.VoxelCellManager; import electrosphere.server.datacell.physics.PhysicsDataCell; import electrosphere.server.entity.ServerContentManager; import electrosphere.server.entity.serialization.ContentSerialization; +import electrosphere.server.macro.spatial.MacroObject; import electrosphere.server.pathfinding.recast.PathingProgressiveData; import electrosphere.server.pathfinding.voxel.VoxelPathfinder; import electrosphere.server.physics.block.manager.ServerBlockManager; @@ -79,6 +80,11 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager */ static final ExecutorService generationService = Executors.newFixedThreadPool(ThreadCounts.GRIDDED_DATACELL_PHYSICS_GEN_THREADS); + /** + * Big number used when scanning for a data cell to spawn a macro object within + */ + static final double MACRO_SCANNING_BIG_NUMBER = 10000; + /** * Tracks whether this manager has been flagged to unload cells or not */ @@ -1147,4 +1153,58 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager return Globals.aiManager.getPathfindingService().queuePathfinding(start, end, this.pathfinder, this); } + @Override + public Vector3d getMacroEntryPoint(Vector3d point){ + Vector3d rVal = null; + + //find the closest data cell + ServerDataCell closestCell = null; + double closestDist = MACRO_SCANNING_BIG_NUMBER; + for(ServerDataCell cell : this.groundDataCells.values()){ + Vector3i cellChunkPos = this.cellPositionMap.get(cell); + Vector3d cellRealPos = ServerWorldData.convertChunkToRealSpace(cellChunkPos); + double dist = cellRealPos.distance(point); + if(dist < closestDist){ + closestCell = cell; + closestDist = dist; + } + } + if(closestDist == MACRO_SCANNING_BIG_NUMBER || closestCell == null){ + throw new Error("Failed to find closer cell"); + } + + //get surface height at the (1,?,1) point of this cell + Vector3i cellChunkPos = this.cellPositionMap.get(closestCell); + double elevation = this.serverTerrainManager.getElevation(cellChunkPos.x, cellChunkPos.z, 1, 1); + + //store as return vec + rVal = new Vector3d( + ServerWorldData.convertVoxelToRealSpace(1, cellChunkPos.x), + elevation, + ServerWorldData.convertVoxelToRealSpace(1, cellChunkPos.z) + ); + + + return rVal; + } + + @Override + public void evaluateMacroObject(MacroObject object){ + //figure out if a cell should contain this object + Vector3i macroObjectChunkPos = ServerWorldData.convertRealToChunkSpace(object.getPos()); + ServerDataCell container = null; + for(ServerDataCell serverDataCell : this.groundDataCells.values()){ + Vector3i pos = this.getCellWorldPosition(serverDataCell); + if(pos.equals(macroObjectChunkPos)){ + container = serverDataCell; + break; + } + } + + //if it is in real space, spawn the object + if(container != null){ + this.serverContentManager.spawnMacroObject(parent, object); + } + } + } diff --git a/src/main/java/electrosphere/server/datacell/interfaces/DataCellManager.java b/src/main/java/electrosphere/server/datacell/interfaces/DataCellManager.java index 156d606c..0b9366d9 100644 --- a/src/main/java/electrosphere/server/datacell/interfaces/DataCellManager.java +++ b/src/main/java/electrosphere/server/datacell/interfaces/DataCellManager.java @@ -8,6 +8,7 @@ import org.joml.Vector3i; import electrosphere.entity.Entity; import electrosphere.net.server.player.Player; import electrosphere.server.datacell.ServerDataCell; +import electrosphere.server.macro.spatial.MacroObject; /** * Interface for manager class for creating and destroying cells with respect to spatial locations @@ -97,5 +98,18 @@ public interface DataCellManager { * @return The list of entities within the bounding sphere */ public Collection entityLookup(Vector3d pos, double radius); + + /** + * Gets the point to have the macro object enter a data cell managed by this manager + * @param point The point to try to spawn near + * @return The point to enter by + */ + public Vector3d getMacroEntryPoint(Vector3d point); + + /** + * Evaluates the realm's view of a macro object (ie, should it be spawned in or not) + * @param object The object to evaluate + */ + public void evaluateMacroObject(MacroObject object); } diff --git a/src/main/java/electrosphere/server/datacell/utils/EntityLookupUtils.java b/src/main/java/electrosphere/server/datacell/utils/EntityLookupUtils.java index 8ffe23ee..2df35e63 100644 --- a/src/main/java/electrosphere/server/datacell/utils/EntityLookupUtils.java +++ b/src/main/java/electrosphere/server/datacell/utils/EntityLookupUtils.java @@ -4,6 +4,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; +import electrosphere.engine.Globals; import electrosphere.entity.Entity; /** @@ -59,5 +60,19 @@ public class EntityLookupUtils { public static Collection getAllEntities(){ return idToEntityMap.values(); } + + /** + * Gets the server equivalent of a client entity + * @param clientEntity The client entity + * @return The equivalent entity on the server if it exists, null otherwise + */ + public static Entity getServerEquivalent(Entity clientEntity){ + if(EntityLookupUtils.isServerEntity(clientEntity)){ + throw new Error("Trying to get server equivalent of a server entity!"); + } + int serverIdForClientEntity = Globals.clientSceneWrapper.mapClientToServerId(clientEntity.getId()); + Entity serverEntity = EntityLookupUtils.getEntityById(serverIdForClientEntity); + return serverEntity; + } } diff --git a/src/main/java/electrosphere/server/entity/ServerContentManager.java b/src/main/java/electrosphere/server/entity/ServerContentManager.java index 5126f36a..e05d2368 100644 --- a/src/main/java/electrosphere/server/entity/ServerContentManager.java +++ b/src/main/java/electrosphere/server/entity/ServerContentManager.java @@ -18,6 +18,7 @@ import electrosphere.util.FileUtils; import electrosphere.util.math.HashUtils; import electrosphere.server.macro.character.Character; import electrosphere.server.macro.race.Race; +import electrosphere.server.macro.spatial.MacroObject; /** * Manages creating/saving/loading/destroying content (ie entities) on the server @@ -84,16 +85,7 @@ public class ServerContentManager { //ie, imagine a puzzle room or something like that if(macroData != null){ for(Character character : macroData.getCharacters(worldPos)){ - if(Race.hasRace(character)){ - Race race = Race.getRace(character); - String creatureName = race.getAssociatedCreature(); - if(creatureName == null){ - throw new Error("Creature name not defined! " + character.getId()); - } - //place macro object - Entity characterEntity = CreatureUtils.serverSpawnBasicCreature(realm, character.getPos(), creatureName, null); - ServerCharacterData.attachServerCharacterData(characterEntity, character.getId()); - } + this.spawnMacroObject(realm, character); } } Globals.profiler.endCpuSample(); @@ -130,6 +122,24 @@ public class ServerContentManager { FileUtils.serializeObjectToFilePath(fullPath, serialization); } + /** + * Spawns a macro object + * @param realm The realm + * @param object The object + */ + public void spawnMacroObject(Realm realm, MacroObject object){ + if(object instanceof Character && Race.hasRace((Character)object)){ + Race race = Race.getRace((Character)object); + String creatureName = race.getAssociatedCreature(); + if(creatureName == null){ + throw new Error("Creature name not defined! " + ((Character)object).getId()); + } + //place macro object + Entity characterEntity = CreatureUtils.serverSpawnBasicCreature(realm, object.getPos(), creatureName, null); + ServerCharacterData.attachServerCharacterData(characterEntity, ((Character)object).getId()); + } + } + /** * Gets the macro data * @return The macro data diff --git a/src/main/java/electrosphere/server/macro/MacroData.java b/src/main/java/electrosphere/server/macro/MacroData.java index 8ca4de60..e4a1dd5a 100644 --- a/src/main/java/electrosphere/server/macro/MacroData.java +++ b/src/main/java/electrosphere/server/macro/MacroData.java @@ -7,8 +7,8 @@ import electrosphere.engine.Globals; import electrosphere.logger.LoggerInterface; import electrosphere.server.datacell.ServerWorldData; import electrosphere.server.macro.character.Character; -import electrosphere.server.macro.character.CharacterDataStrings; import electrosphere.server.macro.character.CharacterUtils; +import electrosphere.server.macro.character.data.CharacterDataStrings; import electrosphere.server.macro.character.diety.Diety; import electrosphere.server.macro.civilization.Civilization; import electrosphere.server.macro.race.Race; @@ -239,6 +239,14 @@ public class MacroData { public void addStructure(Structure structure){ structures.add(structure); } + + /** + * Adds a character to the macro data + * @param character The character + */ + public void addCharacter(Character character){ + characters.add(character); + } /** * Describes the world diff --git a/src/main/java/electrosphere/server/macro/character/AdvancedPersonality.java b/src/main/java/electrosphere/server/macro/character/AdvancedPersonality.java deleted file mode 100644 index 57d2ce44..00000000 --- a/src/main/java/electrosphere/server/macro/character/AdvancedPersonality.java +++ /dev/null @@ -1,5 +0,0 @@ -package electrosphere.server.macro.character; - -public class AdvancedPersonality { - -} diff --git a/src/main/java/electrosphere/server/macro/character/BasicPersonality.java b/src/main/java/electrosphere/server/macro/character/BasicPersonality.java deleted file mode 100644 index f33edf0c..00000000 --- a/src/main/java/electrosphere/server/macro/character/BasicPersonality.java +++ /dev/null @@ -1,5 +0,0 @@ -package electrosphere.server.macro.character; - -public class BasicPersonality { - -} diff --git a/src/main/java/electrosphere/server/macro/character/Character.java b/src/main/java/electrosphere/server/macro/character/Character.java index c0ced7b9..2a0f9b8f 100644 --- a/src/main/java/electrosphere/server/macro/character/Character.java +++ b/src/main/java/electrosphere/server/macro/character/Character.java @@ -5,6 +5,7 @@ import java.util.Map; import org.joml.Vector3d; +import electrosphere.server.macro.character.data.CharacterData; import electrosphere.server.macro.spatial.MacroObject; /** diff --git a/src/main/java/electrosphere/server/macro/character/CharacterUtils.java b/src/main/java/electrosphere/server/macro/character/CharacterUtils.java index 053175e4..7c3c76d1 100644 --- a/src/main/java/electrosphere/server/macro/character/CharacterUtils.java +++ b/src/main/java/electrosphere/server/macro/character/CharacterUtils.java @@ -1,6 +1,12 @@ package electrosphere.server.macro.character; +import org.joml.Vector3d; + +import electrosphere.server.datacell.Realm; +import electrosphere.server.macro.MacroData; +import electrosphere.server.macro.character.data.CharacterDataStrings; import electrosphere.server.macro.character.diety.Diety; +import electrosphere.server.macro.race.Race; import electrosphere.server.macro.structure.Structure; import electrosphere.server.macro.town.Town; @@ -43,4 +49,19 @@ public class CharacterUtils { return (Town)character.getData(CharacterDataStrings.HOMETOWN); } + /** + * Spawns a character + * @param realm The realm to spawn the character within + * @return The character + */ + public static Character spawnCharacter(Realm realm, Vector3d position){ + Character rVal = new Character(); + rVal.setPos(position); + Race.setRace(rVal, Race.create("human", "human")); + MacroData macroData = realm.getServerContentManager().getMacroData(); + macroData.addCharacter(rVal); + realm.getDataCellManager().evaluateMacroObject(rVal); + return rVal; + } + } diff --git a/src/main/java/electrosphere/server/macro/character/CharacterData.java b/src/main/java/electrosphere/server/macro/character/data/CharacterData.java similarity index 90% rename from src/main/java/electrosphere/server/macro/character/CharacterData.java rename to src/main/java/electrosphere/server/macro/character/data/CharacterData.java index 0abee20d..55e3b5a7 100644 --- a/src/main/java/electrosphere/server/macro/character/CharacterData.java +++ b/src/main/java/electrosphere/server/macro/character/data/CharacterData.java @@ -1,4 +1,4 @@ -package electrosphere.server.macro.character; +package electrosphere.server.macro.character.data; /** * A type of data for a character diff --git a/src/main/java/electrosphere/server/macro/character/CharacterDataSerializer.java b/src/main/java/electrosphere/server/macro/character/data/CharacterDataSerializer.java similarity index 97% rename from src/main/java/electrosphere/server/macro/character/CharacterDataSerializer.java rename to src/main/java/electrosphere/server/macro/character/data/CharacterDataSerializer.java index 28273e8a..cbab1a09 100644 --- a/src/main/java/electrosphere/server/macro/character/CharacterDataSerializer.java +++ b/src/main/java/electrosphere/server/macro/character/data/CharacterDataSerializer.java @@ -1,4 +1,4 @@ -package electrosphere.server.macro.character; +package electrosphere.server.macro.character.data; import java.lang.reflect.Type; diff --git a/src/main/java/electrosphere/server/macro/character/CharacterDataStrings.java b/src/main/java/electrosphere/server/macro/character/data/CharacterDataStrings.java similarity index 92% rename from src/main/java/electrosphere/server/macro/character/CharacterDataStrings.java rename to src/main/java/electrosphere/server/macro/character/data/CharacterDataStrings.java index 4b414905..497014f3 100644 --- a/src/main/java/electrosphere/server/macro/character/CharacterDataStrings.java +++ b/src/main/java/electrosphere/server/macro/character/data/CharacterDataStrings.java @@ -1,4 +1,4 @@ -package electrosphere.server.macro.character; +package electrosphere.server.macro.character.data; /** * Data strings for characters diff --git a/src/main/java/electrosphere/server/macro/character/diety/Diety.java b/src/main/java/electrosphere/server/macro/character/diety/Diety.java index 0117184a..80abf23b 100644 --- a/src/main/java/electrosphere/server/macro/character/diety/Diety.java +++ b/src/main/java/electrosphere/server/macro/character/diety/Diety.java @@ -1,8 +1,8 @@ package electrosphere.server.macro.character.diety; import electrosphere.engine.Globals; -import electrosphere.server.macro.character.CharacterData; -import electrosphere.server.macro.character.CharacterDataStrings; +import electrosphere.server.macro.character.data.CharacterData; +import electrosphere.server.macro.character.data.CharacterDataStrings; import electrosphere.server.macro.symbolism.Symbol; import electrosphere.server.macro.symbolism.SymbolMap; diff --git a/src/main/java/electrosphere/server/macro/race/Race.java b/src/main/java/electrosphere/server/macro/race/Race.java index 525d832e..c031acb2 100644 --- a/src/main/java/electrosphere/server/macro/race/Race.java +++ b/src/main/java/electrosphere/server/macro/race/Race.java @@ -1,8 +1,8 @@ package electrosphere.server.macro.race; -import electrosphere.server.macro.character.CharacterDataStrings; import electrosphere.server.macro.character.Character; -import electrosphere.server.macro.character.CharacterData; +import electrosphere.server.macro.character.data.CharacterData; +import electrosphere.server.macro.character.data.CharacterDataStrings; /** * The race of a creature diff --git a/src/main/java/electrosphere/server/macro/structure/Structure.java b/src/main/java/electrosphere/server/macro/structure/Structure.java index 49dee5c1..0b84621b 100644 --- a/src/main/java/electrosphere/server/macro/structure/Structure.java +++ b/src/main/java/electrosphere/server/macro/structure/Structure.java @@ -5,8 +5,8 @@ import org.joml.Vector3d; import electrosphere.game.data.block.BlockFab; import electrosphere.game.data.struct.StructureData; -import electrosphere.server.macro.character.CharacterData; -import electrosphere.server.macro.character.CharacterDataStrings; +import electrosphere.server.macro.character.data.CharacterData; +import electrosphere.server.macro.character.data.CharacterDataStrings; import electrosphere.server.macro.spatial.MacroAreaObject; import electrosphere.util.annotation.Exclude; diff --git a/src/main/java/electrosphere/server/macro/town/Town.java b/src/main/java/electrosphere/server/macro/town/Town.java index 7c1e157b..53c46356 100644 --- a/src/main/java/electrosphere/server/macro/town/Town.java +++ b/src/main/java/electrosphere/server/macro/town/Town.java @@ -1,8 +1,8 @@ package electrosphere.server.macro.town; import electrosphere.server.macro.character.Character; -import electrosphere.server.macro.character.CharacterData; -import electrosphere.server.macro.character.CharacterDataStrings; +import electrosphere.server.macro.character.data.CharacterData; +import electrosphere.server.macro.character.data.CharacterDataStrings; import electrosphere.server.macro.spatial.MacroAreaObject; import electrosphere.server.macro.structure.Structure; diff --git a/src/main/java/electrosphere/server/simulation/MacroSimulation.java b/src/main/java/electrosphere/server/simulation/MacroSimulation.java index a70aabf8..ccf15c74 100644 --- a/src/main/java/electrosphere/server/simulation/MacroSimulation.java +++ b/src/main/java/electrosphere/server/simulation/MacroSimulation.java @@ -1,7 +1,7 @@ package electrosphere.server.simulation; import electrosphere.server.macro.character.Character; -import electrosphere.server.macro.character.CharacterDataStrings; +import electrosphere.server.macro.character.data.CharacterDataStrings; /** * Performs the macro-level (ie virtual, non-physics based) simulation diff --git a/src/main/java/electrosphere/util/FileUtils.java b/src/main/java/electrosphere/util/FileUtils.java index 605494a2..c779e75e 100644 --- a/src/main/java/electrosphere/util/FileUtils.java +++ b/src/main/java/electrosphere/util/FileUtils.java @@ -8,8 +8,8 @@ import electrosphere.game.data.creature.type.ai.AITreeDataSerializer; import electrosphere.game.data.creature.type.movement.MovementSystem; import electrosphere.game.data.creature.type.movement.MovementSystemSerializer; import electrosphere.logger.LoggerInterface; -import electrosphere.server.macro.character.CharacterData; -import electrosphere.server.macro.character.CharacterDataSerializer; +import electrosphere.server.macro.character.data.CharacterData; +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; diff --git a/src/main/java/electrosphere/util/SerializationUtils.java b/src/main/java/electrosphere/util/SerializationUtils.java index 218320ba..d0491893 100644 --- a/src/main/java/electrosphere/util/SerializationUtils.java +++ b/src/main/java/electrosphere/util/SerializationUtils.java @@ -7,8 +7,8 @@ import electrosphere.game.data.creature.type.ai.AITreeData; import electrosphere.game.data.creature.type.ai.AITreeDataSerializer; import electrosphere.game.data.creature.type.movement.MovementSystem; import electrosphere.game.data.creature.type.movement.MovementSystemSerializer; -import electrosphere.server.macro.character.CharacterDataSerializer; -import electrosphere.server.macro.character.CharacterData; +import electrosphere.server.macro.character.data.CharacterData; +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;