From b2bac5f540b3a5d2810fcf7f7ab4783f4664eb35 Mon Sep 17 00:00:00 2001 From: austin Date: Fri, 23 May 2025 17:06:57 -0400 Subject: [PATCH] town layout work --- docs/src/progress/renderertodo.md | 3 + .../server/macro/town/TownLayout.java | 154 ++++++++++++++++-- 2 files changed, 144 insertions(+), 13 deletions(-) diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index e1ce2d9f..806b788e 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -1945,6 +1945,9 @@ GriddedDataCellManager filtering optimization StandardUniformManager implementation Small fixes +(05/23/2025) +Town layout work + diff --git a/src/main/java/electrosphere/server/macro/town/TownLayout.java b/src/main/java/electrosphere/server/macro/town/TownLayout.java index 32b1c7d4..805337e6 100644 --- a/src/main/java/electrosphere/server/macro/town/TownLayout.java +++ b/src/main/java/electrosphere/server/macro/town/TownLayout.java @@ -17,6 +17,7 @@ import electrosphere.server.macro.civilization.Civilization; import electrosphere.server.macro.civilization.road.Road; import electrosphere.server.macro.race.Race; import electrosphere.server.macro.structure.VirtualStructure; +import electrosphere.util.math.HashUtils; import electrosphere.util.math.VoronoiUtils; /** @@ -29,10 +30,34 @@ public class TownLayout { */ public static final double TOWN_LAYOUT_SCALER = 64; + /** + * The maximum radius of towns + */ + public static final double TOWN_MAX_RADIUS = 256; + /** * Relaxation factor for regularizing placement of town center nodes */ - public static final double VORONOI_RELAXATION_FACTOR = 0.4; + public static final double VORONOI_RELAXATION_FACTOR = 0.3; + + /** + * Offset applied to breadth search hashing + */ + private static final int HASH_OFFSET = 1000; + + /** + * Offset used to search for town centers + */ + static final int[] offsetX = new int[]{ + -1,1,0,0 + }; + + /** + * Offset used to search for town centers + */ + static final int[] offsetZ = new int[]{ + 0,0,-1,1 + }; /** * Lays out structures for a town @@ -67,6 +92,8 @@ public class TownLayout { //find the nodes to connect Vector3d townCenter = town.getPos(); Vector3d scanPoint = new Vector3d(); + Vector3d currPoint = new Vector3d(); + Vector3d nearPoint = null; //get center loc scanPoint.set(townCenter); @@ -88,23 +115,126 @@ public class TownLayout { scanPoint.set(townCenter).add(0,0,-TOWN_LAYOUT_SCALER); Vector3d downNodeLoc = TownLayout.getTownCenter(realm, scanPoint); + + + // //generate roads - Road upRoad = Road.createRoad(macroData, upNodeLoc, centerNodeLoc); - Road rightRoad = Road.createRoad(macroData, rightNodeLoc, centerNodeLoc); - Road leftRoad = Road.createRoad(macroData, leftNodeLoc, centerNodeLoc); - Road downRoad = Road.createRoad(macroData, downNodeLoc, centerNodeLoc); + Road.createRoad(macroData, upNodeLoc, centerNodeLoc); + Road.createRoad(macroData, rightNodeLoc, centerNodeLoc); + Road.createRoad(macroData, leftNodeLoc, centerNodeLoc); + Road.createRoad(macroData, downNodeLoc, centerNodeLoc); // //place structures along roads - TownLayout.generateStructuresAlongRoad(realm, town, upRoad, allowedStructures); - TownLayout.generateStructuresAlongRoad(realm, town, rightRoad, allowedStructures); - TownLayout.generateStructuresAlongRoad(realm, town, leftRoad, allowedStructures); - TownLayout.generateStructuresAlongRoad(realm, town, downRoad, allowedStructures); + // TownLayout.generateStructuresAlongRoad(realm, town, upRoad, allowedStructures); + // TownLayout.generateStructuresAlongRoad(realm, town, rightRoad, allowedStructures); + // TownLayout.generateStructuresAlongRoad(realm, town, leftRoad, allowedStructures); + // TownLayout.generateStructuresAlongRoad(realm, town, downRoad, allowedStructures); + + + + // + //Breadth search other nodes to branch outwards + // + + // + //sets for breadth search + LinkedList openSet = new LinkedList(); + LinkedList closedSet = new LinkedList(); + 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)); + 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); + + //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); + } + + //build road and structures between curr and next node + if(closedSet.contains(newHash)){ + Road.createRoad(macroData, nearPoint, currPoint); + // TownLayout.generateStructuresAlongRoad(realm, town, newRoad, allowedStructures); + } + } + } + + closedSet.add(openHash); + } + + + // + //Breadth search other nodes to branch outwards + // + + // + //sets for breadth search + openSet = new LinkedList(); + closedSet = new LinkedList(); + 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)); + 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); + + //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); + } + + //build road and structures between curr and next node + if(closedSet.contains(newHash)){ + // Road newRoad = Road.createRoad(macroData, nearPoint, currPoint); + TownLayout.generateStructuresAlongRoad(realm, town, nearPoint, currPoint, Road.DEFAULT_RADIUS, allowedStructures); + } + } + } + + closedSet.add(openHash); + } town.setResolution(Town.TOWN_RES_MAX); } + // /** + // * Generates structures along a road + // * @param realm The realm + // * @param town The town + // * @param road The road + // * @param allowedStructures The list of allowed structure types + // */ + // private static void generateStructuresAlongRoad(Realm realm, Town town, Road road, List allowedStructures){ + // TownLayout.generateStructuresAlongRoad(realm, town, road.getPoint1(), road.getPoint2(), road.getRadius(), allowedStructures); + // } + /** * Generates structures along a road * @param realm The realm @@ -112,12 +242,10 @@ public class TownLayout { * @param road The road * @param allowedStructures The list of allowed structure types */ - private static void generateStructuresAlongRoad(Realm realm, Town town, Road road, List allowedStructures){ + private static void generateStructuresAlongRoad(Realm realm, Town town, Vector3d startPoint, Vector3d endPoint, double radius, List allowedStructures){ MacroData macroData = realm.getMacroData(); //get values to scan along - Vector3d startPoint = road.getPoint1(); - Vector3d endPoint = road.getPoint2(); Vector3d dir = new Vector3d(endPoint).sub(startPoint).normalize(); int len = (int)startPoint.distance(endPoint); @@ -129,7 +257,7 @@ public class TownLayout { isNorthSouth = true; } - int roadRadiusOffsetRaw = (int)(road.getRadius() + 3); + int roadRadiusOffsetRaw = (int)(radius + 4); //offset applied to the scan location to not place it on top of the road Vector3d roadOffset = null;