diff --git a/Scripts/createTables.sql b/Scripts/createTables.sql index ced20e0f..271e1788 100644 --- a/Scripts/createTables.sql +++ b/Scripts/createTables.sql @@ -17,7 +17,7 @@ CREATE INDEX charaDataIDIndex ON charaData (charID); --towns --positions -CREATE TABLE townWorldPositions (id INTEGER PRIMARY KEY, townID INTEGER, posX INTEGER, posY INTEGER, bbRadiusX INTEGER, bbRadiusY INTEGER); +CREATE TABLE townWorldPositions (id INTEGER PRIMARY KEY, townID INTEGER, posX INTEGER, posY INTEGER); CREATE INDEX townWorldPositionsIDIndex ON townWorldPositions (townID); CREATE INDEX townWorldPositionsPosIndex ON townWorldPositions (posX, posY); diff --git a/Scripts/towns/createTown.sql b/Scripts/towns/createTown.sql index 5966aae7..c8a0e546 100644 --- a/Scripts/towns/createTown.sql +++ b/Scripts/towns/createTown.sql @@ -1,6 +1,6 @@ --positions -INSERT INTO townWorldPositions (townID,posX,posY,bbRadiusX,bbRadiusY) VALUES (0,10,10,1,1); +INSERT INTO townWorldPositions (townID,posX,posY) VALUES (0,10,10); --data INSERT INTO townData(townID,propName,propValue) VALUES(0,"name","someTown"); diff --git a/Scripts/towns/getTownsAtWorldPos.sql b/Scripts/towns/getTownsAtWorldPos.sql index 5d1a1530..886c2c27 100644 --- a/Scripts/towns/getTownsAtWorldPos.sql +++ b/Scripts/towns/getTownsAtWorldPos.sql @@ -1 +1,2 @@ -SELECT * FROM townWorldPositions WHERE posX = 10 AND posY = 10; \ No newline at end of file +--given x=10, y=11 +SELECT townID FROM townWorldPositions WHERE posX = 10 AND posY = 11; \ No newline at end of file diff --git a/src/main/java/electrosphere/engine/LoadingThread.java b/src/main/java/electrosphere/engine/LoadingThread.java index 8217b860..c4e0889b 100644 --- a/src/main/java/electrosphere/engine/LoadingThread.java +++ b/src/main/java/electrosphere/engine/LoadingThread.java @@ -349,7 +349,7 @@ public class LoadingThread extends Thread { int chunkSize = Globals.serverTerrainManager.getChunkWidth(); Globals.spawnPoint = new Vector3f(townLoc.x * chunkSize, (float)Globals.serverTerrainManager.getHeightAtPosition(townLoc.x * chunkSize,townLoc.y * chunkSize), townLoc.y * chunkSize); // System.out.println("Setting spawn point @ " + Globals.spawnPoint); - Town.createTown(townLoc.x,townLoc.y); +// Town.createTown(townLoc.x,townLoc.y); } } diff --git a/src/main/java/electrosphere/game/server/character/Character.java b/src/main/java/electrosphere/game/server/character/Character.java index 5a889858..63acfbf1 100644 --- a/src/main/java/electrosphere/game/server/character/Character.java +++ b/src/main/java/electrosphere/game/server/character/Character.java @@ -6,7 +6,7 @@ import java.util.LinkedList; import java.util.List; public class Character { - static int entity_id_iterator = 0; + static int character_id_iterator = 0; int id; diff --git a/src/main/java/electrosphere/game/server/character/CharacterDataStrings.java b/src/main/java/electrosphere/game/server/character/CharacterDataStrings.java index 54843631..8873dbe1 100644 --- a/src/main/java/electrosphere/game/server/character/CharacterDataStrings.java +++ b/src/main/java/electrosphere/game/server/character/CharacterDataStrings.java @@ -11,5 +11,7 @@ public class CharacterDataStrings { public static final String PERSONALTIY_BASIC = "personalityBasic"; public static final String PERSONALITY_ADVANCED = "personalityAdvanced"; public static final String RACE = "race"; + public static final String SHELTER = "shelter"; + public static final String HOMETOWN = "hometown"; } diff --git a/src/main/java/electrosphere/game/server/character/CharacterUtils.java b/src/main/java/electrosphere/game/server/character/CharacterUtils.java index 9a406baa..e9cf08f4 100644 --- a/src/main/java/electrosphere/game/server/character/CharacterUtils.java +++ b/src/main/java/electrosphere/game/server/character/CharacterUtils.java @@ -3,6 +3,8 @@ package electrosphere.game.server.character; import electrosphere.game.server.character.Character; import electrosphere.game.server.character.diety.Diety; import electrosphere.game.server.race.model.Race; +import electrosphere.game.server.structure.virtual.Structure; +import electrosphere.game.server.town.Town; import org.joml.Vector2i; /** @@ -35,4 +37,20 @@ public class CharacterUtils { return (Race)character.getData(CharacterDataStrings.RACE); } + public static void addShelter(Character character, Structure shelter){ + character.putData(CharacterDataStrings.SHELTER, shelter); + } + + public static Structure getShelter(Character character){ + return (Structure)character.getData(CharacterDataStrings.SHELTER); + } + + public static void addHometown(Character character, Town town){ + character.putData(CharacterDataStrings.HOMETOWN, town); + } + + public static Town getHometown(Character character){ + return (Town)character.getData(CharacterDataStrings.HOMETOWN); + } + } diff --git a/src/main/java/electrosphere/game/server/structure/virtual/Structure.java b/src/main/java/electrosphere/game/server/structure/virtual/Structure.java index cf63cfe8..c6e79f8b 100644 --- a/src/main/java/electrosphere/game/server/structure/virtual/Structure.java +++ b/src/main/java/electrosphere/game/server/structure/virtual/Structure.java @@ -1,5 +1,9 @@ package electrosphere.game.server.structure.virtual; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; + /** * * @author amaterasu @@ -10,6 +14,10 @@ public class Structure { float locationX; float locationY; String type; + + HashMap data = new HashMap(); + + LinkedList dataKeys = new LinkedList(); public Structure(int worldX, int worldY, float locationX, float locationY, String type) { this.worldX = worldX; @@ -18,6 +26,19 @@ public class Structure { this.locationY = locationY; this.type = type; } + + public void putData(String key, Object o){ + data.put(key,o); + dataKeys.add(key); + } + + public List getDataKeys(){ + return dataKeys; + } + + public Object getData(String key){ + return data.get(key); + } public int getWorldX() { return worldX; @@ -40,4 +61,5 @@ public class Structure { } + } diff --git a/src/main/java/electrosphere/game/server/structure/virtual/StructureDataStrings.java b/src/main/java/electrosphere/game/server/structure/virtual/StructureDataStrings.java new file mode 100644 index 00000000..c781916d --- /dev/null +++ b/src/main/java/electrosphere/game/server/structure/virtual/StructureDataStrings.java @@ -0,0 +1,11 @@ +package electrosphere.game.server.structure.virtual; + +/** + * + * @author satellite + */ +public class StructureDataStrings { + + public static final String RESIDENTS = "residents"; + +} diff --git a/src/main/java/electrosphere/game/server/structure/virtual/StructurePlacer.java b/src/main/java/electrosphere/game/server/structure/virtual/VirtualStructureUtils.java similarity index 54% rename from src/main/java/electrosphere/game/server/structure/virtual/StructurePlacer.java rename to src/main/java/electrosphere/game/server/structure/virtual/VirtualStructureUtils.java index 6d3abcbc..dc24a1ab 100644 --- a/src/main/java/electrosphere/game/server/structure/virtual/StructurePlacer.java +++ b/src/main/java/electrosphere/game/server/structure/virtual/VirtualStructureUtils.java @@ -3,20 +3,25 @@ package electrosphere.game.server.structure.virtual; import electrosphere.entity.types.structure.StructureUtils; import electrosphere.game.config.structure.type.model.StructureType; import electrosphere.main.Globals; +import electrosphere.game.server.character.Character; +import java.util.LinkedList; +import java.util.List; import org.joml.Quaternionf; +import org.joml.Vector2f; import org.joml.Vector3f; /** * * @author amaterasu */ -public class StructurePlacer { +public class VirtualStructureUtils { public static Structure placeStructureAtPoint(float posX, float posY, String type){ int worldX = Globals.serverWorldData.convertRealToChunkSpace(posX); int worldY = Globals.serverWorldData.convertRealToChunkSpace(posY); Structure rVal = new Structure(worldX,worldY,posX,posY,type); + Globals.macroData.addStructure(rVal); double centerHeight = Globals.serverTerrainManager.getHeightAtPosition(posX, posY); StructureType currentTypeObject = Globals.gameConfigCurrent.getStructureTypeMap().getType(type); @@ -35,4 +40,33 @@ public class StructurePlacer { StructureUtils.spawnBasicStructure(type, new Vector3f(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); + Vector2f toPlacePos = new Vector2f(posX, posY); + for(Structure virtualStruct : Globals.macroData.getStructures()){ + StructureType existantType = Globals.gameConfigCurrent.getStructureTypeMap().getType(virtualStruct.getType()); + Vector2f existantPos = new Vector2f(virtualStruct.getLocationX(),virtualStruct.getLocationY()); + if(existantPos.distance(toPlacePos) < toPlaceType.getRadius() + existantType.getRadius()){ + return false; + } + } + return true; + } + + + public static void addResident(Structure structure, Character character){ + List residents = null; + if(structure.getDataKeys().contains(StructureDataStrings.RESIDENTS)){ + residents = (List)structure.getData(StructureDataStrings.RESIDENTS); + } else { + residents = new LinkedList(); + structure.putData(StructureDataStrings.RESIDENTS, residents); + } + residents.add(character); + } + + public static List getResidents(Structure structure){ + return (List)structure.getData(StructureDataStrings.RESIDENTS); + } } diff --git a/src/main/java/electrosphere/game/server/town/Town.java b/src/main/java/electrosphere/game/server/town/Town.java index 588489b0..73884a5b 100644 --- a/src/main/java/electrosphere/game/server/town/Town.java +++ b/src/main/java/electrosphere/game/server/town/Town.java @@ -1,9 +1,19 @@ package electrosphere.game.server.town; -import electrosphere.game.server.structure.virtual.StructurePlacer; +import electrosphere.game.server.db.DatabaseResult; +import electrosphere.game.server.structure.virtual.Structure; +import electrosphere.game.server.structure.virtual.VirtualStructureUtils; import electrosphere.game.server.terrain.manager.ServerTerrainChunk; +import electrosphere.game.server.character.Character; +import electrosphere.logger.LoggerInterface; import electrosphere.main.Globals; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.LinkedList; +import java.util.List; import java.util.Random; +import java.util.logging.Level; +import java.util.logging.Logger; import org.joml.Vector2i; /** @@ -15,7 +25,13 @@ public class Town { int id; static int idIncrementer = 0; + List positions = new LinkedList(); + + List structures = new LinkedList(); + List residents = new LinkedList(); + final static int avgDiffThreshold = 10; + public static Vector2i findValidTownLocation(){ for(int x = 0; x < Globals.serverTerrainManager.getWorldDiscreteSize(); x++){ for(int y = 0; y < Globals.serverTerrainManager.getWorldDiscreteSize(); y++){ @@ -54,13 +70,58 @@ public class Town { public static Town createTown(int x, int y){ Town rVal = new Town(); - Random rand = new Random(); - int structCount = (rand.nextInt(3) + 2); - int chunkSize = Globals.serverTerrainManager.getChunkWidth(); - for(int i = 0; i < structCount; i++){ - StructurePlacer.placeStructureAtPoint(x * chunkSize + rand.nextFloat() * 100, y * chunkSize + rand.nextFloat() * 100, "building1"); + rVal.positions.add(new Vector2i(x,y)); + Globals.macroData.addTown(rVal); +// Random rand = new Random(); +// int structCount = (rand.nextInt(3) + 2); +// int chunkSize = Globals.serverTerrainManager.getChunkWidth(); +// for(int i = 0; i < structCount; i++){ +// StructurePlacer.placeStructureAtPoint(x * chunkSize + rand.nextFloat() * 100, y * chunkSize + rand.nextFloat() * 100, "building1"); +// } + return rVal; + } + + public static Town getTownAtPosition(int x, int y){ + Town rVal = null; +// DatabaseResult locationLookupResult = Globals.dbController.executeQuery("SELECT townID FROM townWorldPositions WHERE posX = " + x + " AND posY = " + y + ";"); +// if(locationLookupResult.hasResultSet()){ +// ResultSet rs = locationLookupResult.getResultSet(); +// int townID = -1; +// try { +// if(rs.next()){ +// townID = rs.getInt("townID"); +// } +// } catch (SQLException ex) { +// LoggerInterface.loggerEngine.ERROR("Error reading result set from getTownAtPosition", ex); +// } +// if(townID != -1){ +// +// } +// } + for(Town town : Globals.macroData.getTowns()){ + for(Vector2i position : town.positions){ + if(position.x == x && position.y == y){ + return town; + } + } } return rVal; } + public void addStructure(Structure structure){ + structures.add(structure); + } + + public List getStructures(){ + return structures; + } + + public void addResident(Character resident){ + residents.add(resident); + } + + public List getResidents(){ + return residents; + } + } diff --git a/src/main/java/electrosphere/game/server/town/TownUtils.java b/src/main/java/electrosphere/game/server/town/TownUtils.java new file mode 100644 index 00000000..00977c7c --- /dev/null +++ b/src/main/java/electrosphere/game/server/town/TownUtils.java @@ -0,0 +1,9 @@ +package electrosphere.game.server.town; + +/** + * + * @author satellite + */ +public class TownUtils { + +} diff --git a/src/main/java/electrosphere/game/server/world/MacroData.java b/src/main/java/electrosphere/game/server/world/MacroData.java index 57d20b7f..b929103c 100644 --- a/src/main/java/electrosphere/game/server/world/MacroData.java +++ b/src/main/java/electrosphere/game/server/world/MacroData.java @@ -6,9 +6,12 @@ import electrosphere.game.server.character.Character; import electrosphere.game.server.character.CharacterDataStrings; import electrosphere.game.server.character.CharacterUtils; import electrosphere.game.server.character.diety.Diety; +import electrosphere.game.server.civilization.Civilization; import electrosphere.game.server.race.model.Race; import electrosphere.game.server.race.model.RaceMap; +import electrosphere.game.server.structure.virtual.Structure; import electrosphere.game.server.symbolism.model.Symbol; +import electrosphere.game.server.town.Town; import electrosphere.main.Globals; import java.util.Random; import org.joml.Vector2i; @@ -23,6 +26,9 @@ public class MacroData { List races = new LinkedList(); List characters = new LinkedList(); List aliveCharacters = new LinkedList(); + List civilizations = new LinkedList(); + List towns = new LinkedList(); + List structures = new LinkedList(); static Character generateInitialDiety(long seed){ @@ -109,6 +115,30 @@ public class MacroData { return aliveCharacters; } + public List getCivilizations(){ + return civilizations; + } + + public void addCivilization(Civilization civilization){ + civilizations.add(civilization); + } + + public List getTowns(){ + return towns; + } + + public void addTown(Town town){ + towns.add(town); + } + + public List getStructures(){ + return structures; + } + + public void addStructure(Structure structure){ + structures.add(structure); + } + public void describeWorld(){ System.out.println("Initial dieties"); System.out.println("=========================="); diff --git a/src/main/java/electrosphere/game/state/MacroSimulation.java b/src/main/java/electrosphere/game/state/MacroSimulation.java index f639c3b5..907704f7 100644 --- a/src/main/java/electrosphere/game/state/MacroSimulation.java +++ b/src/main/java/electrosphere/game/state/MacroSimulation.java @@ -10,10 +10,17 @@ import electrosphere.game.server.structure.virtual.Structure; import electrosphere.game.server.town.Town; import electrosphere.main.Globals; import electrosphere.game.server.character.Character; +import electrosphere.game.server.character.CharacterDataStrings; +import electrosphere.game.server.character.CharacterUtils; +import electrosphere.game.server.structure.virtual.StructureDataStrings; +import electrosphere.game.server.structure.virtual.VirtualStructureUtils; import electrosphere.util.FileLoadingUtils; import electrosphere.util.Utilities; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import org.joml.Vector2f; +import org.joml.Vector2i; public class MacroSimulation { @@ -39,6 +46,121 @@ public class MacroSimulation { public void simulate(){ for(Character character : Globals.macroData.getAliveCharacters()){ //do something + checkForShelter(); + checkTownMembership(); + } + } + + static final int MAX_PLACE_ATTEMPTS = 10; + + static void checkForShelter(){ + for(Character chara : Globals.macroData.getAliveCharacters()){ + /* + If doesn’t have shelter, check if in town + If in town, + check if there’s an inn/church/friendly family + if so, try to stay there + if can’t find place to stay, fashion makeshift shelter + If no town + fashion makeshift shelter + */ + if(!chara.getDataKeys().contains(CharacterDataStrings.SHELTER)){ + Vector2i charPos = CharacterUtils.getDiscretePosition(chara); + Town nearbyTown = Town.getTownAtPosition(charPos.x,charPos.y); + if(nearbyTown != null){ + //if town has a place to day + if(false){ + + } else { + //try to find a place to put down a structure + + } + } else { + //cry + //TODO: Get building type to place + String buildingTypeToPlace = "building1"; + //try to find a place to put down a structure + int dynamicInterpRatio = Globals.serverTerrainManager.getDynamicInterpolationRatio(); + Vector2f placementPos = new Vector2f( + (float)(charPos.x * dynamicInterpRatio + Math.random() * dynamicInterpRatio), + (float)(charPos.y * dynamicInterpRatio + Math.random() * dynamicInterpRatio) + ); + int attempts = 0; + while(!VirtualStructureUtils.validStructurePlacementPosition(placementPos.x, placementPos.y, buildingTypeToPlace)){ + placementPos = new Vector2f( + (float)(charPos.x * dynamicInterpRatio + Math.random() * dynamicInterpRatio), + (float)(charPos.y * dynamicInterpRatio + Math.random() * dynamicInterpRatio) + ); + attempts++; + if(attempts > MAX_PLACE_ATTEMPTS){ + placementPos = null; + break; + } + } + if(placementPos != null){ + System.out.println("Added shelter"); + Structure placedStructure = VirtualStructureUtils.placeStructureAtPoint(placementPos.x, placementPos.y, buildingTypeToPlace); + CharacterUtils.addShelter(chara, placedStructure); + VirtualStructureUtils.addResident(placedStructure, chara); + } + } + } + } + } + + static void checkTownMembership(){ + //TODO: eventually exclude people who shouldn't belong to a town (traders, bandits, etc) + for(Character chara : Globals.macroData.getAliveCharacters()){ + boolean hasHometown = chara.getDataKeys().contains(CharacterDataStrings.HOMETOWN); + boolean hasShelter = chara.getDataKeys().contains(CharacterDataStrings.SHELTER); + //if has structure & no hometown + 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"); + } + } + } + } + + static void checkInitCombat(){ + for(Character chara : Globals.macroData.getAliveCharacters()){ + Vector2i position = CharacterUtils.getDiscretePosition(chara); } } } diff --git a/src/main/java/electrosphere/main/Main.java b/src/main/java/electrosphere/main/Main.java index 66282072..de455e2f 100644 --- a/src/main/java/electrosphere/main/Main.java +++ b/src/main/java/electrosphere/main/Main.java @@ -18,6 +18,7 @@ import electrosphere.game.client.ClientFunctions; import electrosphere.game.config.UserSettings; import electrosphere.game.server.terrain.manager.ServerTerrainManager; import electrosphere.game.server.world.MacroData; +import electrosphere.game.server.world.ServerWorldData; import electrosphere.game.state.MacroSimulation; import electrosphere.game.state.MicroSimulation; import electrosphere.logger.LoggerInterface; @@ -121,13 +122,19 @@ public class Main { //gen terrain Globals.serverTerrainManager = new ServerTerrainManager(2000,50,100,0.0f,0); Globals.serverTerrainManager.load(); + Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager); //gen world - MacroData world = MacroData.generateWorld(0); - world.describeWorld(); + Globals.macroData = MacroData.generateWorld(0); + Globals.macroData.describeWorld(); boolean run = true; Globals.macroSimulation = new MacroSimulation(); while(run){ Globals.macroSimulation.simulate(); + try { + TimeUnit.MILLISECONDS.sleep(1000); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } } //debug: create terrain/world viewer