town road nav graph construction
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
This commit is contained in:
parent
cde8f35887
commit
4b1efb2bcf
@ -2074,6 +2074,7 @@ Sprinting/physics work
|
||||
(05/30/2025)
|
||||
Reorganizing macro classes
|
||||
Start work on macro pathfinding storage
|
||||
Town constructs nav graph of road nodes
|
||||
|
||||
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ import electrosphere.server.macro.civilization.town.Town;
|
||||
import electrosphere.server.macro.region.MacroRegion;
|
||||
import electrosphere.server.macro.spatial.MacroAreaObject;
|
||||
import electrosphere.server.macro.spatial.MacroObject;
|
||||
import electrosphere.server.macro.spatial.path.MacroPathCache;
|
||||
import electrosphere.server.macro.structure.VirtualStructure;
|
||||
import electrosphere.util.FileUtils;
|
||||
import electrosphere.util.annotation.Exclude;
|
||||
@ -34,35 +35,30 @@ import org.joml.Vector3d;
|
||||
*/
|
||||
public class MacroData {
|
||||
|
||||
/**
|
||||
* The maximum number of attempts to try placing something
|
||||
*/
|
||||
static final int MAX_PLACEMENT_ATTEMPTS = 50;
|
||||
|
||||
/**
|
||||
* List of races
|
||||
*/
|
||||
List<Race> races = new LinkedList<Race>();
|
||||
private List<Race> races = new LinkedList<Race>();
|
||||
|
||||
/**
|
||||
* List of civilizations
|
||||
*/
|
||||
List<Civilization> civilizations = new LinkedList<Civilization>();
|
||||
private List<Civilization> civilizations = new LinkedList<Civilization>();
|
||||
|
||||
/**
|
||||
* List of towns
|
||||
*/
|
||||
List<Town> towns = new LinkedList<Town>();
|
||||
private List<Town> towns = new LinkedList<Town>();
|
||||
|
||||
/**
|
||||
* List of structures
|
||||
*/
|
||||
List<VirtualStructure> structures = new LinkedList<VirtualStructure>();
|
||||
private List<VirtualStructure> structures = new LinkedList<VirtualStructure>();
|
||||
|
||||
/**
|
||||
* The list of all regions
|
||||
*/
|
||||
List<MacroRegion> regions = new LinkedList<MacroRegion>();
|
||||
private List<MacroRegion> regions = new LinkedList<MacroRegion>();
|
||||
|
||||
/**
|
||||
* Maps structure id -> structure
|
||||
@ -79,7 +75,12 @@ public class MacroData {
|
||||
/**
|
||||
* List of roads
|
||||
*/
|
||||
List<Road> roads = new LinkedList<Road>();
|
||||
private List<Road> roads = new LinkedList<Road>();
|
||||
|
||||
/**
|
||||
* The pathing cache
|
||||
*/
|
||||
private MacroPathCache pathingCache = new MacroPathCache();
|
||||
|
||||
/**
|
||||
* Generates a world
|
||||
@ -90,15 +91,6 @@ public class MacroData {
|
||||
Random random = new Random(seed);
|
||||
MacroData rVal = new MacroData();
|
||||
|
||||
//generate initial dieties
|
||||
// int numDieties = 3 + Math.abs(random.nextInt()) % 7;
|
||||
// for(int i = 0; i < numDieties; i++){
|
||||
// Character diety = generateInitialDiety(random.nextLong());
|
||||
// rVal.initialDieties.add(diety);
|
||||
// rVal.characters.add(diety);
|
||||
// CharacterService.createCharacter(null, i);
|
||||
// }
|
||||
|
||||
|
||||
//generate initial races
|
||||
if(Globals.gameConfigCurrent.getRaceMap().getRaces().size() < 3){
|
||||
@ -120,19 +112,6 @@ public class MacroData {
|
||||
//init civilizations
|
||||
CivilizationGenerator.generate(serverWorldData, rVal, Globals.gameConfigCurrent);
|
||||
|
||||
//add a test character
|
||||
// Character testChar = new Character();
|
||||
// testChar.setPos(new Vector3d(ServerWorldData.convertChunkToRealSpace(new Vector3i(32774, 3, 32769))));
|
||||
// Race.setRace(testChar, Race.create("human", "human"));
|
||||
// rVal.characters.add(testChar);
|
||||
|
||||
//add a test character
|
||||
// Vector3d structPos = ServerWorldData.convertChunkToRealSpace(new Vector3i(32774, 0, 32770));
|
||||
// double elevationAtStruct = serverWorldData.getServerTerrainManager().getElevation(32774, 32770, 0, 0);
|
||||
// structPos.y = elevationAtStruct;
|
||||
// Structure struct = Structure.createStructure(Globals.gameConfigCurrent.getStructureData().getType("test1"),structPos);
|
||||
// rVal.structures.add(struct);
|
||||
|
||||
//spawn initial characters in each race
|
||||
//find initial positions to place characters at per race
|
||||
//generate initial characters
|
||||
@ -188,6 +167,9 @@ public class MacroData {
|
||||
for(MacroRegion region : this.regions){
|
||||
this.idRegionMap.put(region.getId(),region);
|
||||
}
|
||||
if(this.pathingCache != null){
|
||||
this.pathingCache.reconstruct();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -198,22 +180,6 @@ public class MacroData {
|
||||
FileUtils.serializeObjectToSavePath(saveName, "./macro.json", this);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Generates an initial diety
|
||||
// * @param seed The seed
|
||||
// * @return The character for the diety
|
||||
// */
|
||||
// static Character generateInitialDiety(long seed){
|
||||
// Character rVal = new Character();
|
||||
|
||||
|
||||
// Diety diety = Diety.generateDiety(seed);
|
||||
// CharacterUtils.addDiety(rVal, diety);
|
||||
|
||||
|
||||
// return rVal;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Gets the list of civilizations
|
||||
* @return The list of civilizations
|
||||
@ -423,4 +389,12 @@ public class MacroData {
|
||||
return blockers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the path cache in the macro data
|
||||
* @return The macro pathing cache
|
||||
*/
|
||||
public MacroPathCache getPathCache(){
|
||||
return this.pathingCache;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
package electrosphere.server.macro.civilization.town;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.joml.AABBd;
|
||||
@ -19,6 +21,8 @@ import electrosphere.server.macro.character.race.Race;
|
||||
import electrosphere.server.macro.civilization.Civilization;
|
||||
import electrosphere.server.macro.civilization.road.Road;
|
||||
import electrosphere.server.macro.region.MacroRegion;
|
||||
import electrosphere.server.macro.spatial.path.MacroPathCache;
|
||||
import electrosphere.server.macro.spatial.path.MacroPathNode;
|
||||
import electrosphere.server.macro.structure.VirtualStructure;
|
||||
import electrosphere.util.math.HashUtils;
|
||||
import electrosphere.util.math.VoronoiUtils;
|
||||
@ -80,6 +84,8 @@ public class TownLayout {
|
||||
*/
|
||||
public static void layoutTown(Realm realm, MacroData macroData, Town town){
|
||||
|
||||
MacroPathCache pathCache = macroData.getPathCache();
|
||||
|
||||
//
|
||||
//figure out what structures we're allowed to place
|
||||
Civilization parentCiv = town.getParent(macroData);
|
||||
@ -183,6 +189,76 @@ public class TownLayout {
|
||||
closedSet.add(openHash);
|
||||
}
|
||||
|
||||
//
|
||||
// Construct pathfinding nodes for roads and link them
|
||||
//
|
||||
//
|
||||
//sets for breadth search
|
||||
Map<Long,MacroPathNode> positionNodeMap = new HashMap<Long,MacroPathNode>();
|
||||
openSet.clear();
|
||||
closedSet.clear();
|
||||
closedSet.add(HashUtils.hashIVec(HASH_OFFSET, 0, HASH_OFFSET));
|
||||
openSet.add(HashUtils.hashIVec(HASH_OFFSET - 1, 0, HASH_OFFSET));
|
||||
openSet.add(HashUtils.hashIVec(HASH_OFFSET + 1, 0, HASH_OFFSET));
|
||||
openSet.add(HashUtils.hashIVec(HASH_OFFSET, 0, HASH_OFFSET - 1));
|
||||
openSet.add(HashUtils.hashIVec(HASH_OFFSET, 0, HASH_OFFSET + 1));
|
||||
//add pathing nodes for initial entries
|
||||
MacroPathNode currentPathingNode = MacroPathNode.createRoadNode(pathCache, new Vector3d(centerNodeLoc));
|
||||
positionNodeMap.put(HashUtils.hashIVec(HASH_OFFSET, 0, HASH_OFFSET), currentPathingNode);
|
||||
|
||||
//up
|
||||
currentPathingNode = MacroPathNode.createRoadNode(pathCache, new Vector3d(upNodeLoc));
|
||||
positionNodeMap.put(HashUtils.hashIVec(HASH_OFFSET, 0, HASH_OFFSET + 1), currentPathingNode);
|
||||
|
||||
//left
|
||||
currentPathingNode = MacroPathNode.createRoadNode(pathCache, new Vector3d(leftNodeLoc));
|
||||
positionNodeMap.put(HashUtils.hashIVec(HASH_OFFSET - 1, 0, HASH_OFFSET), currentPathingNode);
|
||||
|
||||
//right
|
||||
currentPathingNode = MacroPathNode.createRoadNode(pathCache, new Vector3d(rightNodeLoc));
|
||||
positionNodeMap.put(HashUtils.hashIVec(HASH_OFFSET + 1, 0, HASH_OFFSET), currentPathingNode);
|
||||
|
||||
//down
|
||||
currentPathingNode = MacroPathNode.createRoadNode(pathCache, new Vector3d(downNodeLoc));
|
||||
positionNodeMap.put(HashUtils.hashIVec(HASH_OFFSET, 0, HASH_OFFSET - 1), currentPathingNode);
|
||||
|
||||
while(openSet.size() > 0){
|
||||
long openHash = openSet.poll();
|
||||
int x = HashUtils.unhashIVec(openHash, HashUtils.UNHASH_COMPONENT_X) - HASH_OFFSET;
|
||||
int z = HashUtils.unhashIVec(openHash, HashUtils.UNHASH_COMPONENT_Z) - HASH_OFFSET;
|
||||
scanPoint.set(townCenter).add(TOWN_LAYOUT_SCALER * x,0,TOWN_LAYOUT_SCALER * z);
|
||||
currPoint = TownLayout.getTownCenter(realm, scanPoint);
|
||||
currentPathingNode = positionNodeMap.get(openHash);
|
||||
if(currentPathingNode == null){
|
||||
throw new Error("Failed to find pathing node for hash");
|
||||
}
|
||||
|
||||
//check below
|
||||
for(int i = 0; i < 4; i++){
|
||||
int oX = x + offsetX[i];
|
||||
int oZ = z + offsetZ[i];
|
||||
scanPoint.set(townCenter).add(TOWN_LAYOUT_SCALER * oX,0,TOWN_LAYOUT_SCALER * oZ);
|
||||
nearPoint = TownLayout.getTownCenter(realm, scanPoint);
|
||||
long newHash = HashUtils.hashIVec(HASH_OFFSET + oX, 0, HASH_OFFSET + oZ);
|
||||
if(nearPoint.distance(townCenter) < TOWN_MAX_RADIUS){
|
||||
if(!openSet.contains(newHash) && !closedSet.contains(newHash)){
|
||||
openSet.add(newHash);
|
||||
}
|
||||
|
||||
//link the neighbor to this node
|
||||
MacroPathNode neighborPathingNode;
|
||||
if(positionNodeMap.containsKey(newHash)){
|
||||
neighborPathingNode = positionNodeMap.get(newHash);
|
||||
} else {
|
||||
neighborPathingNode = MacroPathNode.createRoadNode(pathCache, new Vector3d(nearPoint));
|
||||
positionNodeMap.put(newHash,neighborPathingNode);
|
||||
}
|
||||
currentPathingNode.addNeighbor(neighborPathingNode);
|
||||
}
|
||||
}
|
||||
closedSet.add(openHash);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//Breadth search other nodes to branch outwards
|
||||
|
||||
@ -22,7 +22,7 @@ public class MacroPathCache {
|
||||
* Map of node id -> node
|
||||
*/
|
||||
@Exclude
|
||||
private Map<Integer,MacroPathNode> idNodeMap = new HashMap<Integer,MacroPathNode>();
|
||||
private Map<Long,MacroPathNode> idNodeMap = new HashMap<Long,MacroPathNode>();
|
||||
|
||||
/**
|
||||
* Reconstructs the datastructures for this cache after deserialization
|
||||
@ -46,7 +46,7 @@ public class MacroPathCache {
|
||||
* @param id The id
|
||||
* @return The corresponding node if it exists, null otherwise
|
||||
*/
|
||||
public MacroPathNode getNodeById(int id){
|
||||
public MacroPathNode getNodeById(long id){
|
||||
return idNodeMap.get(id);
|
||||
}
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.server.macro.region.MacroRegion;
|
||||
import electrosphere.server.macro.structure.VirtualStructure;
|
||||
|
||||
/**
|
||||
@ -27,6 +28,11 @@ public class MacroPathNode {
|
||||
*/
|
||||
private static final int TYPE_VIRTUAL_STRUCTURE = 1;
|
||||
|
||||
/**
|
||||
* A region
|
||||
*/
|
||||
private static final int TYPE_REGION = 2;
|
||||
|
||||
|
||||
//
|
||||
// cost values
|
||||
@ -37,6 +43,11 @@ public class MacroPathNode {
|
||||
*/
|
||||
private static final int COST_VIRTUAL_STRUCTURE = 10;
|
||||
|
||||
/**
|
||||
* Cost of a region object
|
||||
*/
|
||||
private static final int COST_REGION = 8;
|
||||
|
||||
/**
|
||||
* Cost of a road node
|
||||
*/
|
||||
@ -50,12 +61,12 @@ public class MacroPathNode {
|
||||
/**
|
||||
* The id of this node
|
||||
*/
|
||||
private int id;
|
||||
private long id;
|
||||
|
||||
/**
|
||||
* The id of the object that this node corresponds to
|
||||
*/
|
||||
private int objectId;
|
||||
private long objectId;
|
||||
|
||||
/**
|
||||
* The type of object at the node
|
||||
@ -65,7 +76,7 @@ public class MacroPathNode {
|
||||
/**
|
||||
* The ids of neighboring path nodes
|
||||
*/
|
||||
private List<Integer> neighborNodes = new LinkedList<Integer>();
|
||||
private List<Long> neighborNodes = new LinkedList<Long>();
|
||||
|
||||
/**
|
||||
* The position of the node
|
||||
@ -102,6 +113,10 @@ public class MacroPathNode {
|
||||
rVal.cost = COST_VIRTUAL_STRUCTURE;
|
||||
rVal.objectId = structObj.getId();
|
||||
rVal.objectType = TYPE_VIRTUAL_STRUCTURE;
|
||||
} else if(correspondingObject instanceof MacroRegion regionObj){
|
||||
rVal.cost = COST_REGION;
|
||||
rVal.objectId = regionObj.getId();
|
||||
rVal.objectType = TYPE_REGION;
|
||||
} else {
|
||||
throw new Error("Unsupported object type! " + correspondingObject);
|
||||
}
|
||||
@ -134,7 +149,7 @@ public class MacroPathNode {
|
||||
* Gets the associated id
|
||||
* @return
|
||||
*/
|
||||
public int getId() {
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@ -142,7 +157,7 @@ public class MacroPathNode {
|
||||
* Sets the id of this path node
|
||||
* @param id The id of this path node
|
||||
*/
|
||||
public void setId(int id) {
|
||||
protected void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@ -166,7 +181,7 @@ public class MacroPathNode {
|
||||
* Gets the id of the object associated with this node
|
||||
* @return The id of the object
|
||||
*/
|
||||
public int getObjectId() {
|
||||
public long getObjectId() {
|
||||
return objectId;
|
||||
}
|
||||
|
||||
@ -184,7 +199,7 @@ public class MacroPathNode {
|
||||
* @return The list of node ids
|
||||
*/
|
||||
public List<MacroPathNode> getNeighborNodes(MacroPathCache cache) {
|
||||
return this.neighborNodes.stream().map((Integer id) -> cache.getNodeById(objectId)).collect(Collectors.toList());
|
||||
return this.neighborNodes.stream().map((Long id) -> cache.getNodeById(objectId)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -192,7 +207,9 @@ public class MacroPathNode {
|
||||
* @param neighbor The neighbor
|
||||
*/
|
||||
public void addNeighbor(MacroPathNode neighbor){
|
||||
this.neighborNodes.add(neighbor.getId());
|
||||
if(!this.neighborNodes.contains(neighbor.getId())){
|
||||
this.neighborNodes.add(neighbor.getId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user