package electrosphere.server.macro; import java.util.LinkedList; import java.util.List; 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.diety.Diety; import electrosphere.server.macro.civilization.Civilization; import electrosphere.server.macro.race.Race; import electrosphere.server.macro.race.RaceMap; import electrosphere.server.macro.spatial.MacroAreaObject; import electrosphere.server.macro.structure.Structure; import electrosphere.server.macro.symbolism.Symbol; import electrosphere.server.macro.town.Town; import electrosphere.util.FileUtils; import java.util.Random; import org.joml.Vector3i; /** * Server macro level data */ public class MacroData { /** * The maximum number of attempts to try placing something */ static final int MAX_PLACEMENT_ATTEMPTS = 50; /** * List of initial dieties */ List initialDieties = new LinkedList(); /** * List of races */ List races = new LinkedList(); /** * List of characters */ List characters = new LinkedList(); /** * List of alive characters */ List aliveCharacters = new LinkedList(); /** * List of civilizations */ List civilizations = new LinkedList(); /** * List of towns */ List towns = new LinkedList(); /** * List of structures */ List structures = new LinkedList(); /** * Generates a world * @param seed The seed for the world * @return The world */ public static MacroData generateWorld(long seed, ServerWorldData serverWorldData){ 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); } //generate initial races if(Globals.gameConfigCurrent.getRaceMap().getSymbolismMap().size() < 3){ for(Race race : Globals.gameConfigCurrent.getRaceMap().getSymbolismMap()){ rVal.races.add(race); } } else { RaceMap raceMap = Globals.gameConfigCurrent.getRaceMap(); int numRacesToGenerate = 3 + random.nextInt(Math.min(raceMap.getSymbolismMap().size() - 3,7)); for(int i = 0; i < numRacesToGenerate; i++){ Race raceToAdd = raceMap.getSymbolismMap().get(random.nextInt(raceMap.getSymbolismMap().size())); while(rVal.races.contains(raceToAdd)){ raceToAdd = raceMap.getSymbolismMap().get(random.nextInt(raceMap.getSymbolismMap().size())); } rVal.races.add(raceToAdd); } } //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 //place them // List occupiedStartingPositions = new LinkedList(); // for(Race race : rVal.races){ // boolean foundPlacementLocation = false; // int attempts = 0; // while(!foundPlacementLocation){ // // Vector2i start = new Vector2i(random.nextInt(Globals.serverTerrainManager.getWorldDiscreteSize()),random.nextInt(Globals.serverTerrainManager.getWorldDiscreteSize())); // // //are we above sea level? // // if(Globals.serverTerrainManager.getDiscreteValue(start.x, start.y) > 25){ // // //is this position already occupied? // // boolean match = false; // // for(Vector2i known : occupiedStartingPositions){ // // if(known.x == start.x && known.y == start.y){ // // match = true; // // break; // // } // // } // // if(!match){ // // //occupy position // // occupiedStartingPositions.add(start); // // foundPlacementLocation = true; // // //make characters // // int numCharactersToMake = 5 + random.nextInt(20); // // for(int i = 0; i < numCharactersToMake; i++){ // // Character character = new Character(); // // CharacterUtils.addDiscretePosition(character, start.x, start.y); // // CharacterUtils.addRace(character, race); // // rVal.characters.add(character); // // rVal.aliveCharacters.add(character); // // } // // } // // } // // attempts++; // // if(attempts > MAX_PLACEMENT_ATTEMPTS){ // // break; // // } // } // } return rVal; } /** * Saves this macro data to a save path * @param saveName The name of the save */ public void save(String saveName){ 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 all alive characters * @return The list of all characters */ public List getAliveCharacters(){ return aliveCharacters; } /** * Gets the list of civilizations * @return The list of civilizations */ public List getCivilizations(){ return civilizations; } /** * Adds a civilization * @param civilization The civilization */ public void addCivilization(Civilization civilization){ civilizations.add(civilization); } /** * Gets the list of towns * @return The list of towns */ public List getTowns(){ return towns; } /** * Adds a town * @param town The town */ public void addTown(Town town){ towns.add(town); } /** * Gets the list of structures * @return The list of structures */ public List getStructures(){ return structures; } /** * Adds a structure * @param structure The structure */ public void addStructure(Structure structure){ structures.add(structure); } /** * Describes the world */ public void describeWorld(){ LoggerInterface.loggerEngine.WARNING("Initial dieties"); LoggerInterface.loggerEngine.WARNING("=========================="); for(Character chara : initialDieties){ LoggerInterface.loggerEngine.WARNING("Diety"); Diety diety = CharacterUtils.getDiety(chara); for(Symbol symbol : diety.getSymbols()){ LoggerInterface.loggerEngine.WARNING(symbol.getName() + " "); } LoggerInterface.loggerEngine.WARNING("\n"); } LoggerInterface.loggerEngine.WARNING("=========================="); LoggerInterface.loggerEngine.WARNING("\n\n"); LoggerInterface.loggerEngine.WARNING("Initial races"); LoggerInterface.loggerEngine.WARNING("=========================="); for(Race race : races){ LoggerInterface.loggerEngine.WARNING(race.getName()); int numCharsOfRace = 0; //n*m complexity - yikes! - as long as we're not making a million chars at start this should be _ok_ for(Character chara : characters){ if(chara.containsKey(CharacterDataStrings.RACE)){ if(Race.getRace(chara).equals(race)){ numCharsOfRace++; } } } LoggerInterface.loggerEngine.WARNING(numCharsOfRace + " initial characters"); LoggerInterface.loggerEngine.WARNING("\n"); } LoggerInterface.loggerEngine.WARNING("=========================="); } /** * Gets the characters at a given world position * @param worldPos The world position * @return The list of characters occupying that world position */ public List getCharacters(Vector3i worldPos){ List rVal = new LinkedList(); for(Character character : this.characters){ if(ServerWorldData.convertRealToChunkSpace(character.getPos()).equals(worldPos.x, worldPos.y, worldPos.z)){ rVal.add(character); } } return rVal; } /** * Gets the list of content-blocking macro objects * @return The list */ public List getContentBlockers(){ List blockers = new LinkedList(); blockers.addAll(this.structures); return blockers; } /** * Gets a character by its id * @param id The id * @return The character if it exists, null otherwise */ public Character getCharacter(int id){ for(Character character : this.characters){ if(character.getId() == id){ return character; } } return null; } }