macro character spawning work
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This commit is contained in:
austin 2025-05-06 16:03:28 -04:00
parent 6ab5c3de67
commit 51f9cde57f
23 changed files with 184 additions and 37 deletions

View File

@ -1694,6 +1694,7 @@ Cleanup some TODOs
Refactor block actions Refactor block actions
Placing fabs/blocks triggers structure scanning service Placing fabs/blocks triggers structure scanning service
Try closing ai manager threads on engine close Try closing ai manager threads on engine close
Ability to explicitly spawn new characters into macro data and have them then spawn into world

View File

@ -19,8 +19,10 @@ import electrosphere.renderer.ui.imgui.ImGuiWindow;
import electrosphere.renderer.ui.imgui.ImGuiWindow.ImGuiWindowCallback; import electrosphere.renderer.ui.imgui.ImGuiWindow.ImGuiWindowCallback;
import electrosphere.server.ai.AI; import electrosphere.server.ai.AI;
import electrosphere.server.ai.nodes.plan.PathfindingNode; import electrosphere.server.ai.nodes.plan.PathfindingNode;
import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.gridded.GriddedDataCellManager; import electrosphere.server.datacell.gridded.GriddedDataCellManager;
import electrosphere.server.datacell.utils.EntityLookupUtils; import electrosphere.server.datacell.utils.EntityLookupUtils;
import electrosphere.server.macro.character.CharacterUtils;
import electrosphere.server.pathfinding.voxel.VoxelPathfinder; import electrosphere.server.pathfinding.voxel.VoxelPathfinder;
import electrosphere.server.pathfinding.voxel.VoxelPathfinder.PathfinderNode; import electrosphere.server.pathfinding.voxel.VoxelPathfinder.PathfinderNode;
import imgui.ImGui; import imgui.ImGui;
@ -82,6 +84,9 @@ public class ImGuiAI {
if(ImGui.button("Draw current pathing")){ if(ImGui.button("Draw current pathing")){
throw new Error("Unsupported currently!"); throw new Error("Unsupported currently!");
} }
if(ImGui.button("Send off map")){
throw new Error("Unsupported currently!");
}
} }
ImGui.unindent(); ImGui.unindent();
} }
@ -162,6 +167,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);
}
} }
}); });
aiWindow.setOpen(false); aiWindow.setOpen(false);

View File

@ -281,6 +281,9 @@ public class ServerWorldData {
* @return The real pos * @return The real pos
*/ */
public static double convertVoxelToRealSpace(int voxelPos, int worldPos){ 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); return voxelPos + ServerWorldData.convertWorldToReal(worldPos);
} }

View File

@ -13,6 +13,7 @@ import electrosphere.entity.EntityUtils;
import electrosphere.entity.scene.Scene; import electrosphere.entity.scene.Scene;
import electrosphere.net.server.player.Player; import electrosphere.net.server.player.Player;
import electrosphere.server.datacell.interfaces.DataCellManager; import electrosphere.server.datacell.interfaces.DataCellManager;
import electrosphere.server.macro.spatial.MacroObject;
/** /**
* A viewport data cell manager * A viewport data cell manager
@ -146,4 +147,14 @@ public class ViewportDataCellManager implements DataCellManager {
return rVal; 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");
}
} }

View File

@ -38,6 +38,7 @@ import electrosphere.server.datacell.interfaces.VoxelCellManager;
import electrosphere.server.datacell.physics.PhysicsDataCell; import electrosphere.server.datacell.physics.PhysicsDataCell;
import electrosphere.server.entity.ServerContentManager; import electrosphere.server.entity.ServerContentManager;
import electrosphere.server.entity.serialization.ContentSerialization; import electrosphere.server.entity.serialization.ContentSerialization;
import electrosphere.server.macro.spatial.MacroObject;
import electrosphere.server.pathfinding.recast.PathingProgressiveData; import electrosphere.server.pathfinding.recast.PathingProgressiveData;
import electrosphere.server.pathfinding.voxel.VoxelPathfinder; import electrosphere.server.pathfinding.voxel.VoxelPathfinder;
import electrosphere.server.physics.block.manager.ServerBlockManager; 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); 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 * 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); 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);
}
}
} }

View File

@ -8,6 +8,7 @@ import org.joml.Vector3i;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.net.server.player.Player; import electrosphere.net.server.player.Player;
import electrosphere.server.datacell.ServerDataCell; 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 * Interface for manager class for creating and destroying cells with respect to spatial locations
@ -98,4 +99,17 @@ public interface DataCellManager {
*/ */
public Collection<Entity> entityLookup(Vector3d pos, double radius); public Collection<Entity> 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);
} }

View File

@ -4,6 +4,7 @@ import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
/** /**
@ -60,4 +61,18 @@ public class EntityLookupUtils {
return idToEntityMap.values(); 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;
}
} }

View File

@ -18,6 +18,7 @@ import electrosphere.util.FileUtils;
import electrosphere.util.math.HashUtils; import electrosphere.util.math.HashUtils;
import electrosphere.server.macro.character.Character; import electrosphere.server.macro.character.Character;
import electrosphere.server.macro.race.Race; import electrosphere.server.macro.race.Race;
import electrosphere.server.macro.spatial.MacroObject;
/** /**
* Manages creating/saving/loading/destroying content (ie entities) on the server * 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 //ie, imagine a puzzle room or something like that
if(macroData != null){ if(macroData != null){
for(Character character : macroData.getCharacters(worldPos)){ for(Character character : macroData.getCharacters(worldPos)){
if(Race.hasRace(character)){ this.spawnMacroObject(realm, 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());
}
} }
} }
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
@ -130,6 +122,24 @@ public class ServerContentManager {
FileUtils.serializeObjectToFilePath(fullPath, serialization); 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 * Gets the macro data
* @return The macro data * @return The macro data

View File

@ -7,8 +7,8 @@ import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.server.datacell.ServerWorldData; import electrosphere.server.datacell.ServerWorldData;
import electrosphere.server.macro.character.Character; import electrosphere.server.macro.character.Character;
import electrosphere.server.macro.character.CharacterDataStrings;
import electrosphere.server.macro.character.CharacterUtils; import electrosphere.server.macro.character.CharacterUtils;
import electrosphere.server.macro.character.data.CharacterDataStrings;
import electrosphere.server.macro.character.diety.Diety; import electrosphere.server.macro.character.diety.Diety;
import electrosphere.server.macro.civilization.Civilization; import electrosphere.server.macro.civilization.Civilization;
import electrosphere.server.macro.race.Race; import electrosphere.server.macro.race.Race;
@ -240,6 +240,14 @@ public class MacroData {
structures.add(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 * Describes the world
*/ */

View File

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

View File

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

View File

@ -5,6 +5,7 @@ import java.util.Map;
import org.joml.Vector3d; import org.joml.Vector3d;
import electrosphere.server.macro.character.data.CharacterData;
import electrosphere.server.macro.spatial.MacroObject; import electrosphere.server.macro.spatial.MacroObject;
/** /**

View File

@ -1,6 +1,12 @@
package electrosphere.server.macro.character; 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.character.diety.Diety;
import electrosphere.server.macro.race.Race;
import electrosphere.server.macro.structure.Structure; import electrosphere.server.macro.structure.Structure;
import electrosphere.server.macro.town.Town; import electrosphere.server.macro.town.Town;
@ -43,4 +49,19 @@ public class CharacterUtils {
return (Town)character.getData(CharacterDataStrings.HOMETOWN); 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;
}
} }

View File

@ -1,4 +1,4 @@
package electrosphere.server.macro.character; package electrosphere.server.macro.character.data;
/** /**
* A type of data for a character * A type of data for a character

View File

@ -1,4 +1,4 @@
package electrosphere.server.macro.character; package electrosphere.server.macro.character.data;
import java.lang.reflect.Type; import java.lang.reflect.Type;

View File

@ -1,4 +1,4 @@
package electrosphere.server.macro.character; package electrosphere.server.macro.character.data;
/** /**
* Data strings for characters * Data strings for characters

View File

@ -1,8 +1,8 @@
package electrosphere.server.macro.character.diety; package electrosphere.server.macro.character.diety;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.server.macro.character.CharacterData; import electrosphere.server.macro.character.data.CharacterData;
import electrosphere.server.macro.character.CharacterDataStrings; import electrosphere.server.macro.character.data.CharacterDataStrings;
import electrosphere.server.macro.symbolism.Symbol; import electrosphere.server.macro.symbolism.Symbol;
import electrosphere.server.macro.symbolism.SymbolMap; import electrosphere.server.macro.symbolism.SymbolMap;

View File

@ -1,8 +1,8 @@
package electrosphere.server.macro.race; package electrosphere.server.macro.race;
import electrosphere.server.macro.character.CharacterDataStrings;
import electrosphere.server.macro.character.Character; 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 * The race of a creature

View File

@ -5,8 +5,8 @@ import org.joml.Vector3d;
import electrosphere.game.data.block.BlockFab; import electrosphere.game.data.block.BlockFab;
import electrosphere.game.data.struct.StructureData; import electrosphere.game.data.struct.StructureData;
import electrosphere.server.macro.character.CharacterData; import electrosphere.server.macro.character.data.CharacterData;
import electrosphere.server.macro.character.CharacterDataStrings; import electrosphere.server.macro.character.data.CharacterDataStrings;
import electrosphere.server.macro.spatial.MacroAreaObject; import electrosphere.server.macro.spatial.MacroAreaObject;
import electrosphere.util.annotation.Exclude; import electrosphere.util.annotation.Exclude;

View File

@ -1,8 +1,8 @@
package electrosphere.server.macro.town; package electrosphere.server.macro.town;
import electrosphere.server.macro.character.Character; import electrosphere.server.macro.character.Character;
import electrosphere.server.macro.character.CharacterData; import electrosphere.server.macro.character.data.CharacterData;
import electrosphere.server.macro.character.CharacterDataStrings; import electrosphere.server.macro.character.data.CharacterDataStrings;
import electrosphere.server.macro.spatial.MacroAreaObject; import electrosphere.server.macro.spatial.MacroAreaObject;
import electrosphere.server.macro.structure.Structure; import electrosphere.server.macro.structure.Structure;

View File

@ -1,7 +1,7 @@
package electrosphere.server.simulation; package electrosphere.server.simulation;
import electrosphere.server.macro.character.Character; 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 * Performs the macro-level (ie virtual, non-physics based) simulation

View File

@ -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.MovementSystem;
import electrosphere.game.data.creature.type.movement.MovementSystemSerializer; import electrosphere.game.data.creature.type.movement.MovementSystemSerializer;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.server.macro.character.CharacterData; import electrosphere.server.macro.character.data.CharacterData;
import electrosphere.server.macro.character.CharacterDataSerializer; 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;

View File

@ -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.ai.AITreeDataSerializer;
import electrosphere.game.data.creature.type.movement.MovementSystem; import electrosphere.game.data.creature.type.movement.MovementSystem;
import electrosphere.game.data.creature.type.movement.MovementSystemSerializer; import electrosphere.game.data.creature.type.movement.MovementSystemSerializer;
import electrosphere.server.macro.character.CharacterDataSerializer; import electrosphere.server.macro.character.data.CharacterData;
import electrosphere.server.macro.character.CharacterData; 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;