diff --git a/pom.xml b/pom.xml index 5218b444..d1fa0bbd 100644 --- a/pom.xml +++ b/pom.xml @@ -255,7 +255,19 @@ exec - + + java + false + true + electrosphere.engine.Main + + + -cp + target/classes;target/Renderer-0.1-jar-with-dependencies.jar + electrosphere.engine.Main + + + + + + org.codehaus.mojo + buildnumber-maven-plugin + 1.4 + + + buildnumber + validate + + create + + + - java - false - true - electrosphere.engine.Main - - - -cp - target/classes;target/Renderer-0.1-jar-with-dependencies.jar - electrosphere.engine.Main - - + {0,number} + + buildNumber + + false + false + unknownbuild - \ No newline at end of file diff --git a/src/main/java/electrosphere/client/fluid/cells/FluidDrawCell.java b/src/main/java/electrosphere/client/fluid/cells/FluidDrawCell.java index 7ddfab15..55ddcd33 100644 --- a/src/main/java/electrosphere/client/fluid/cells/FluidDrawCell.java +++ b/src/main/java/electrosphere/client/fluid/cells/FluidDrawCell.java @@ -60,7 +60,6 @@ public class FluidDrawCell { rVal.worldPos = worldPos; rVal.program = program; rVal.data = data; - System.out.println("Create cell"); return rVal; } diff --git a/src/main/java/electrosphere/client/fluid/cells/DrawCellManager.java b/src/main/java/electrosphere/client/fluid/cells/FluidDrawCellManager.java similarity index 98% rename from src/main/java/electrosphere/client/fluid/cells/DrawCellManager.java rename to src/main/java/electrosphere/client/fluid/cells/FluidDrawCellManager.java index e6813cb9..51754d5a 100644 --- a/src/main/java/electrosphere/client/fluid/cells/DrawCellManager.java +++ b/src/main/java/electrosphere/client/fluid/cells/FluidDrawCellManager.java @@ -19,7 +19,7 @@ import electrosphere.renderer.ShaderProgram; * * @author satellite */ -public class DrawCellManager { +public class FluidDrawCellManager { //the center of this cell manager's array in cell space @@ -78,7 +78,7 @@ public class DrawCellManager { * @param discreteX The initial discrete position X coordinate * @param discreteY The initial discrete position Y coordinate */ - public DrawCellManager(ClientTerrainManager clientTerrainManager, int discreteX, int discreteY, int discreteZ){ + public FluidDrawCellManager(ClientTerrainManager clientTerrainManager, int discreteX, int discreteY, int discreteZ){ worldBoundDiscreteMax = (int)(Globals.clientWorldData.getWorldBoundMin().x / Globals.clientWorldData.getDynamicInterpolationRatio() * 1.0f); cells = new HashSet(); hasNotRequested = new HashSet(); @@ -102,7 +102,7 @@ public class DrawCellManager { update = true; } - DrawCellManager(){ + FluidDrawCellManager(){ } diff --git a/src/main/java/electrosphere/client/terrain/cells/DrawCell.java b/src/main/java/electrosphere/client/terrain/cells/DrawCell.java index 82ea9a28..74129eb1 100644 --- a/src/main/java/electrosphere/client/terrain/cells/DrawCell.java +++ b/src/main/java/electrosphere/client/terrain/cells/DrawCell.java @@ -61,7 +61,6 @@ public class DrawCell { rVal.worldPos = worldPos; rVal.program = program; rVal.data = data; - System.out.println("Create cell"); return rVal; } diff --git a/src/main/java/electrosphere/client/terrain/cells/DrawCellManager.java b/src/main/java/electrosphere/client/terrain/cells/DrawCellManager.java index 13106226..ba80057d 100644 --- a/src/main/java/electrosphere/client/terrain/cells/DrawCellManager.java +++ b/src/main/java/electrosphere/client/terrain/cells/DrawCellManager.java @@ -52,7 +52,7 @@ public class DrawCellManager { int drawStepdownInterval = 3; int drawStepdownValue = 25; - double drawRadius = 200; + double drawRadius = 50; int physicsRadius = 3; @@ -272,6 +272,7 @@ public class DrawCellManager { updateable.remove(key); keyCellMap.remove(key); hasRequested.remove(key); + cell.destroy(); } } @@ -324,14 +325,12 @@ public class DrawCellManager { * Updates cells that need updating in this manager */ public void update(){ - if(update){ - if(containsUnrequestedCell() && !containsUndrawableCell()){ - updateUnrequestedCell(); - } else if(containsUndrawableCell()){ - makeCellDrawable(); - } else if(containsUpdateableCell()){ - updateCellModel(); - } + if(containsUnrequestedCell() && !containsUndrawableCell()){ + updateUnrequestedCell(); + } else if(containsUndrawableCell()){ + makeCellDrawable(); + } else if(containsUpdateableCell()){ + updateCellModel(); } } diff --git a/src/main/java/electrosphere/engine/Globals.java b/src/main/java/electrosphere/engine/Globals.java index 4e41c798..ce87e7de 100644 --- a/src/main/java/electrosphere/engine/Globals.java +++ b/src/main/java/electrosphere/engine/Globals.java @@ -443,7 +443,7 @@ public class Globals { //init default shaderProgram defaultMeshShader = ShaderProgram.smart_assemble_shader(false,true); //init terrain shader program - terrainShaderProgram = ShaderProgram.loadSpecificShader("/Shaders/terrain2/terrain.vs", "/Shaders/terrain2/terrain.fs"); + terrainShaderProgram = ShaderProgram.loadSpecificShader("/Shaders/terrain2/terrain2.vs", "/Shaders/terrain2/terrain2.fs"); TerrainChunkModelGeneration.terrainChunkShaderProgram = ShaderProgram.loadSpecificShader("/Shaders/terrain2/terrain2.vs", "/Shaders/terrain2/terrain2.fs"); //init fluid shader program terrainShaderProgram = ShaderProgram.loadSpecificShader("/Shaders/fluid1/fluid1.vs", "/Shaders/fluid1/fluid1.fs"); diff --git a/src/main/java/electrosphere/engine/Main.java b/src/main/java/electrosphere/engine/Main.java index 5da5e629..d6141157 100644 --- a/src/main/java/electrosphere/engine/Main.java +++ b/src/main/java/electrosphere/engine/Main.java @@ -238,7 +238,7 @@ public class Main { /// C L I E N T N E T W O R K I N G S T U F F /// //Why is this its own function? Just to get the networking code out of main() - if(Globals.RUN_CLIENT && Globals.clientConnection != null){ + if(Globals.clientConnection != null){ Globals.clientConnection.parseMessages(); } diff --git a/src/main/java/electrosphere/engine/loadingthreads/ClientLoading.java b/src/main/java/electrosphere/engine/loadingthreads/ClientLoading.java index 1e82a361..e699bc2d 100644 --- a/src/main/java/electrosphere/engine/loadingthreads/ClientLoading.java +++ b/src/main/java/electrosphere/engine/loadingthreads/ClientLoading.java @@ -119,6 +119,9 @@ public class ClientLoading { + /** + * Inits the client networking thread and socket + */ private static void initClientThread(){ //start client networking Thread clientThread = null; @@ -253,6 +256,7 @@ public class ClientLoading { try { TimeUnit.MILLISECONDS.sleep(10); } catch (InterruptedException ex) { + ex.printStackTrace(); } // System.out.println("invalid cell"); } @@ -262,6 +266,7 @@ public class ClientLoading { try { TimeUnit.MILLISECONDS.sleep(10); } catch (InterruptedException ex) { + ex.printStackTrace(); } // System.out.println("undrawable"); } diff --git a/src/main/java/electrosphere/engine/loadingthreads/DebugSPWorldLoading.java b/src/main/java/electrosphere/engine/loadingthreads/DebugSPWorldLoading.java index 33d165e2..99ce0155 100644 --- a/src/main/java/electrosphere/engine/loadingthreads/DebugSPWorldLoading.java +++ b/src/main/java/electrosphere/engine/loadingthreads/DebugSPWorldLoading.java @@ -14,6 +14,7 @@ import electrosphere.menu.MenuGenerators; import electrosphere.menu.WindowStrings; import electrosphere.menu.WindowUtils; import electrosphere.net.parser.net.message.TerrainMessage; +import electrosphere.net.server.ServerConnectionHandler; import electrosphere.renderer.ui.Window; import electrosphere.server.saves.SaveUtils; import electrosphere.server.terrain.manager.ServerTerrainManager; @@ -30,7 +31,7 @@ public class DebugSPWorldLoading { WindowUtils.replaceMainMenuContents(MenuGenerators.createEmptyMainMenu()); loadingWindow.setVisible(true); - Globals.serverTerrainManager = new ServerTerrainManager(2000,50,ServerTerrainManager.SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO,0.0f,0); + Globals.serverTerrainManager = new ServerTerrainManager(2000,50,0.0f,0); if(!SaveUtils.getSaves().contains("random_sp_world")){ // //the juicy server GENERATION part @@ -39,7 +40,7 @@ public class DebugSPWorldLoading { SaveUtils.createOrOverwriteSave("random_sp_world"); //create terrain Globals.serverTerrainManager.generate(); - Globals.serverTerrainManager.save(SaveUtils.deriveSaveDirectoryPath("random_sp_world")); + Globals.serverTerrainManager.save("random_sp_world"); //create world.json Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager); FileUtils.serializeObjectToSavePath("random_sp_world", "./world.json", Globals.serverWorldData); @@ -59,7 +60,7 @@ public class DebugSPWorldLoading { //initialize the local connection Globals.clientUsername = "testuser"; Globals.clientPassword = AuthenticationManager.getHashedString("testpass"); - LoadingUtils.initLocalConnection(); + ServerConnectionHandler serverPlayerConnection = LoadingUtils.initLocalConnection(); //wait for player object creation while(Globals.playerManager.getPlayers().size() < 1){ try { @@ -85,7 +86,7 @@ public class DebugSPWorldLoading { } //spawn player character - LoadingUtils.spawnLocalPlayerTestEntity(); + LoadingUtils.spawnLocalPlayerTestEntity(serverPlayerConnection); //request terrain data Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestMetadataMessage()); diff --git a/src/main/java/electrosphere/engine/loadingthreads/LoadingUtils.java b/src/main/java/electrosphere/engine/loadingthreads/LoadingUtils.java index 4a1ae1f0..70e9850c 100644 --- a/src/main/java/electrosphere/engine/loadingthreads/LoadingUtils.java +++ b/src/main/java/electrosphere/engine/loadingthreads/LoadingUtils.java @@ -1,6 +1,10 @@ package electrosphere.engine.loadingthreads; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.util.concurrent.TimeUnit; @@ -28,7 +32,9 @@ import electrosphere.game.server.world.MacroData; import electrosphere.game.server.world.ServerWorldData; import electrosphere.net.NetUtils; import electrosphere.net.client.ClientNetworking; +import electrosphere.net.parser.net.message.CharacterMessage; import electrosphere.net.server.Server; +import electrosphere.net.server.ServerConnectionHandler; import electrosphere.net.server.player.Player; import electrosphere.server.datacell.GriddedDataCellManager; import electrosphere.server.datacell.Realm; @@ -54,7 +60,7 @@ public class LoadingUtils { Actually initialize the terrain manager */ float randomDampener = 0.0f; //0.25f; - Globals.serverTerrainManager = new ServerTerrainManager(2000,50,ServerTerrainManager.SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO,randomDampener,0); + Globals.serverTerrainManager = new ServerTerrainManager(2000,50,randomDampener,0); if(Globals.RUN_SERVER){ if(Globals.userSettings.gameplayGenerateWorld()){ Globals.serverTerrainManager.generate(); @@ -70,7 +76,6 @@ public class LoadingUtils { int playerStartX = 0; int playerStartY = 0; int discreteSize = Globals.serverTerrainManager.getWorldDiscreteSize(); - int chunkSize = Globals.serverTerrainManager.getChunkWidth(); boolean found = false; for(int x = 0; x < discreteSize; x++){ for(int y = 0; y < discreteSize; y++){ @@ -164,25 +169,30 @@ public class LoadingUtils { } } - static void initLocalConnection(){ - Globals.server = new Server(NetUtils.getPort()); + static final int STREAM_BUFFER_SIZE = 32 * 1024 * 1024; + static ServerConnectionHandler initLocalConnection(){ + ServerConnectionHandler rVal = null; try { + Globals.server = new Server(NetUtils.getPort()); //client -> server pipe - PipedInputStream clientInput = new PipedInputStream(); + PipedInputStream clientInput = new PipedInputStream(STREAM_BUFFER_SIZE); PipedOutputStream serverOutput = new PipedOutputStream(clientInput); //server -> client pipe PipedInputStream serverInput = new PipedInputStream(); - PipedOutputStream clientOutput = new PipedOutputStream(serverInput); + PipedOutputStream clientOutput; + clientOutput = new PipedOutputStream(serverInput); //start server communication thread - Globals.server.addLocalPlayer(serverInput, serverOutput); + rVal = Globals.server.addLocalPlayer(serverInput, serverOutput); //start client communication thread Globals.clientConnection = new ClientNetworking(clientInput,clientOutput); Thread clientThread = null; clientThread = new Thread(Globals.clientConnection); clientThread.start(); } catch (IOException e) { + // TODO Auto-generated catch block e.printStackTrace(); } + return rVal; } /** @@ -219,7 +229,7 @@ public class LoadingUtils { /** * Spawns the character, and sets server side connection player object values to the appropriate chunk */ - static void spawnLocalPlayerTestEntity(){ + static void spawnLocalPlayerTestEntity(ServerConnectionHandler serverPlayerConnection){ // //Create entity // @@ -238,11 +248,9 @@ public class LoadingUtils { template.putValue(attribute.getAttributeId(), attribute.getVariants().get(0).getId()); } } - Realm realm = Globals.realmManager.getRealms().iterator().next(); - //create player - //spawn entity - Entity newPlayerEntity = CreatureUtils.serverSpawnBasicCreature(realm,Globals.spawnPoint,template.getCreatureType(),template); - Globals.playerEntity = newPlayerEntity; + //set player character template + serverPlayerConnection.setCreatureTemplate(template); + Globals.clientConnection.queueOutgoingMessage(CharacterMessage.constructRequestSpawnCharacterMessage()); //set player world-space coordinates Player playerObject = Globals.playerManager.getPlayerFromId(0); @@ -251,12 +259,6 @@ public class LoadingUtils { Globals.serverWorldData.convertRealToChunkSpace(Globals.spawnPoint.y), Globals.serverWorldData.convertRealToChunkSpace(Globals.spawnPoint.z) )); - //set client entity data - Globals.clientPlayerData.setWorldPos(playerObject.getWorldPos()); - //initially position entity - ServerEntityUtils.initiallyPositionEntity(realm, newPlayerEntity, new Vector3d(Globals.spawnPoint.x + 1,Globals.spawnPoint.y + 5,Globals.spawnPoint.z + 1)); - //add entity to correct cells - realm.getDataCellManager().addPlayerToRealm(playerObject); } static void initMacroSimulation(){ diff --git a/src/main/java/electrosphere/engine/loadingthreads/ServerLoading.java b/src/main/java/electrosphere/engine/loadingthreads/ServerLoading.java index 53ef2bd8..370eb9d2 100644 --- a/src/main/java/electrosphere/engine/loadingthreads/ServerLoading.java +++ b/src/main/java/electrosphere/engine/loadingthreads/ServerLoading.java @@ -15,7 +15,7 @@ public class ServerLoading { // } //TODO: Globals.serverTerrainManager = new ServerTerrainManager(2000,50,100,randomDampener,0); - Globals.serverTerrainManager = new ServerTerrainManager(2000,50,ServerTerrainManager.SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO,0.0f,0); + Globals.serverTerrainManager = new ServerTerrainManager(2000,50,0.0f,0); SaveUtils.loadSave(Globals.currentSaveName); // LoadingUtils.initTerrainDataCellManager(); //TODO: set spawnpoint diff --git a/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java b/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java index e48c3b89..d0f3f478 100644 --- a/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java +++ b/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java @@ -492,7 +492,6 @@ public class CreatureUtils { */ public static Entity serverSpawnBasicCreature(Realm realm, Vector3d position, String type, CreatureTemplate template){ CreatureType rawType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(type); - System.out.println("Creature"); Entity rVal = EntityCreationUtils.createServerEntity(realm, position); EntityCreationUtils.makeEntityPoseable(rVal, rawType.getModelPath()); diff --git a/src/main/java/electrosphere/game/server/world/MacroData.java b/src/main/java/electrosphere/game/server/world/MacroData.java index 78191c82..eb8ce976 100644 --- a/src/main/java/electrosphere/game/server/world/MacroData.java +++ b/src/main/java/electrosphere/game/server/world/MacroData.java @@ -44,6 +44,9 @@ public class MacroData { return rVal; } + + static final int MAX_PLACEMENT_ATTEMPTS = 50; + public static MacroData generateWorld(long seed){ Random random = new Random(seed); MacroData rVal = new MacroData(); @@ -80,6 +83,7 @@ public class MacroData { 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? @@ -107,6 +111,10 @@ public class MacroData { } } } + attempts++; + if(attempts > MAX_PLACEMENT_ATTEMPTS){ + break; + } } } diff --git a/src/main/java/electrosphere/game/server/world/ServerWorldData.java b/src/main/java/electrosphere/game/server/world/ServerWorldData.java index 67714a20..b5e9ef6e 100644 --- a/src/main/java/electrosphere/game/server/world/ServerWorldData.java +++ b/src/main/java/electrosphere/game/server/world/ServerWorldData.java @@ -1,6 +1,7 @@ package electrosphere.game.server.world; import electrosphere.server.datacell.ServerDataCell; +import electrosphere.server.terrain.manager.ServerTerrainChunk; import electrosphere.server.terrain.manager.ServerTerrainManager; import java.util.List; @@ -67,7 +68,7 @@ public class ServerWorldData { rVal.type = WorldType.GAME_WORLD; rVal.worldMinPoint = new Vector3f(0,0,0); - int worldDim = terrainManager.getWorldDiscreteSize() * terrainManager.getChunkWidth(); + int worldDim = terrainManager.getWorldDiscreteSize() * ServerTerrainChunk.CHUNK_DIMENSION; rVal.worldMaxPoint = new Vector3f(worldDim,0,worldDim); rVal.dynamicInterpolationRatio = terrainManager.getDynamicInterpolationRatio(); diff --git a/src/main/java/electrosphere/menu/MenuGenerators.java b/src/main/java/electrosphere/menu/MenuGenerators.java index 18116b8b..f6a237c4 100644 --- a/src/main/java/electrosphere/menu/MenuGenerators.java +++ b/src/main/java/electrosphere/menu/MenuGenerators.java @@ -130,7 +130,7 @@ public class MenuGenerators { //create save dir SaveUtils.createOrOverwriteSave(saveName); //create and save terrain - ServerTerrainManager terrainManager = new ServerTerrainManager(2000,50,100,0.0f,0); + ServerTerrainManager terrainManager = new ServerTerrainManager(2000,50,0.0f,0); terrainManager.generate(); terrainManager.save(SaveUtils.deriveSaveDirectoryPath(saveName)); WindowUtils.replaceMainMenuContents(MenuGenerators.createWorldSelectMenu()); diff --git a/src/main/java/electrosphere/net/client/ClientNetworking.java b/src/main/java/electrosphere/net/client/ClientNetworking.java index 2fa2a4f5..a3205968 100644 --- a/src/main/java/electrosphere/net/client/ClientNetworking.java +++ b/src/main/java/electrosphere/net/client/ClientNetworking.java @@ -164,7 +164,7 @@ public class ClientNetworking implements Runnable{ //disconnected from the server LoggerInterface.loggerNetworking.WARNING("Disconnected from server"); //close socket - if(socket.isConnected()){ + if(socket != null && socket.isConnected()){ try { socket.close(); } catch (IOException e) { @@ -205,13 +205,13 @@ public class ClientNetworking implements Runnable{ (((ServerMessage)message).getMessageSubtype()) == ServerMessageType.PONG ){ if(this.echoPings == true){ - LoggerInterface.loggerNetworking.DEBUG("[Server] New message " + message.getType()); + LoggerInterface.loggerNetworking.DEBUG("[CLIENT] New message " + message.getType()); } } else { - LoggerInterface.loggerNetworking.DEBUG("[Server] New message " + message.getType()); + LoggerInterface.loggerNetworking.DEBUG("[CLIENT] New message " + message.getType()); } } else { - LoggerInterface.loggerNetworking.DEBUG("[Server] New message " + message.getType()); + LoggerInterface.loggerNetworking.DEBUG("[CLIENT] New message " + message.getType()); } } diff --git a/src/main/java/electrosphere/net/parser/net/raw/NetworkParser.java b/src/main/java/electrosphere/net/parser/net/raw/NetworkParser.java index 325a7302..7b2cd548 100644 --- a/src/main/java/electrosphere/net/parser/net/raw/NetworkParser.java +++ b/src/main/java/electrosphere/net/parser/net/raw/NetworkParser.java @@ -1,6 +1,6 @@ -package electrosphere.net.parser.net.raw; - -import electrosphere.net.parser.net.message.NetworkMessage; +package electrosphere.net.parser.net.raw; + +import electrosphere.net.parser.net.message.NetworkMessage; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -15,7 +15,7 @@ public class NetworkParser { CopyOnWriteArrayList incomingMessageQueue = new CopyOnWriteArrayList(); CopyOnWriteArrayList outgoingMessageQueue = new CopyOnWriteArrayList(); - CircularByteBuffer incomingByteBuffer = new CircularByteBuffer(64 * 1024 * 124); + CircularByteBuffer incomingByteBuffer = new CircularByteBuffer(64 * 1024 * 1024); CopyOnWriteArrayList outgoingByteQueue = new CopyOnWriteArrayList(); diff --git a/src/main/java/electrosphere/net/server/Server.java b/src/main/java/electrosphere/net/server/Server.java index f6ffd708..fb66ab6f 100644 --- a/src/main/java/electrosphere/net/server/Server.java +++ b/src/main/java/electrosphere/net/server/Server.java @@ -90,9 +90,10 @@ public class Server implements Runnable{ } } - public void addLocalPlayer(InputStream serverInputStream, OutputStream serverOutputStream){ + public ServerConnectionHandler addLocalPlayer(InputStream serverInputStream, OutputStream serverOutputStream){ ServerConnectionHandler newClient = new ServerConnectionHandler(serverInputStream,serverOutputStream); clientMap.put("127.0.0.1", newClient); new Thread(newClient).start(); + return newClient; } } diff --git a/src/main/java/electrosphere/server/datacell/GriddedDataCellManager.java b/src/main/java/electrosphere/server/datacell/GriddedDataCellManager.java index 53fa79e9..42f72589 100644 --- a/src/main/java/electrosphere/server/datacell/GriddedDataCellManager.java +++ b/src/main/java/electrosphere/server/datacell/GriddedDataCellManager.java @@ -28,6 +28,7 @@ import electrosphere.server.terrain.manager.ServerTerrainChunk; public class GriddedDataCellManager implements DataCellManager, VoxelCellManager { //these are going to be the natural ground grid of data cells, but we're going to have more than this Map groundDataCells = new HashMap(); + Map cellPositionMap = new HashMap(); //loaded cells Semaphore loadedCellsLock = new Semaphore(1); Set loadedCells; @@ -211,6 +212,25 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager return playerChangedChunk; } + //Used for cleaning server data cells no longer in use from the realm + Set toCleanQueue = new HashSet(); + /** + * Unloads all chunks that haven't had players in them for a set amount of time + */ + public void unloadPlayerlessChunks(){ + //TODO: improve to make have less performance impact + for(ServerDataCell cell : loadedCells){ + if(cell.getPlayers().size() < 1){ + System.out.println("Unload cell"); + toCleanQueue.add(cell); + } + } + for(ServerDataCell cell : toCleanQueue){ + parent.deregisterCell(cell); + } + toCleanQueue.clear(); + } + /** * Get data cell at a given real point in this realm * @param point The real point @@ -341,6 +361,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager private ServerDataCell createServerDataCell(Vector3i worldPos){ ServerDataCell rVal = parent.createNewCell(); groundDataCells.put(getServerDataCellKey(worldPos),rVal); + cellPositionMap.put(rVal,new Vector3i(worldPos)); return rVal; } @@ -396,4 +417,14 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager terrainEditLock.release(); } + + /** + * Gets the world position of a given data cell + * @param cell The data cell + * @return The world position + */ + private Vector3i getCellWorldPosition(ServerDataCell cell){ + return cellPositionMap.get(cell); + } + } diff --git a/src/main/java/electrosphere/server/datacell/Realm.java b/src/main/java/electrosphere/server/datacell/Realm.java index f9adf5e8..89a4b6ba 100644 --- a/src/main/java/electrosphere/server/datacell/Realm.java +++ b/src/main/java/electrosphere/server/datacell/Realm.java @@ -83,24 +83,6 @@ public class Realm { ServerDataCell cell = Globals.entityDataCellMapper.getEntityDataCell(e); cell.broadcastNetworkMessage(message); } - - //Used for cleaning server data cells no longer in use from the realm - Set toCleanQueue = new HashSet(); - /** - * Unloads all chunks that haven't had players in them for a set amount of time - */ - public void unloadPlayerlessChunks(){ - //TODO: improve to make have less performance impact - for(ServerDataCell cell : loadedDataCells){ - if(cell.getPlayers().size() < 1){ - toCleanQueue.add(cell); - } - } - for(ServerDataCell cell : toCleanQueue){ - deregisterCell(cell); - } - toCleanQueue.clear(); - } /** @@ -179,10 +161,7 @@ public class Realm { dataCellManager.simulate(); //data cell manager update misc variables (player positions, unload not-in-use cells) if(dataCellManager != null){ - // boolean playerHasChangedChunk = dataCellManager.updatePlayerGroundCellPositions(); - // if(playerHasChangedChunk){ - // dataCellManager.unloadPlayerlessChunks(); - // } + dataCellManager.unloadPlayerlessChunks(); } //clear collidable impulse lists collisionEngine.clearCollidableImpulseLists(); diff --git a/src/main/java/electrosphere/server/datacell/interfaces/DataCellManager.java b/src/main/java/electrosphere/server/datacell/interfaces/DataCellManager.java index 1f1f383b..d7479b03 100644 --- a/src/main/java/electrosphere/server/datacell/interfaces/DataCellManager.java +++ b/src/main/java/electrosphere/server/datacell/interfaces/DataCellManager.java @@ -55,5 +55,10 @@ public interface DataCellManager { * Calls the simulate function on all loaded cells */ public void simulate(); + + /** + * Unloads playerless chunks. Strategy for doing this is defined per data cell manager. + */ + public void unloadPlayerlessChunks(); } diff --git a/src/main/java/electrosphere/server/pathfinding/NavMeshUtils.java b/src/main/java/electrosphere/server/pathfinding/NavMeshUtils.java index 427487fb..569a6852 100644 --- a/src/main/java/electrosphere/server/pathfinding/NavMeshUtils.java +++ b/src/main/java/electrosphere/server/pathfinding/NavMeshUtils.java @@ -31,11 +31,11 @@ public class NavMeshUtils { float currentMax = 0; int startPos = 0; int endPos = 0; - for(int x = 0; x < Globals.serverTerrainManager.getAugmentedChunkWidth() - 1; x++){ + for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION - 1; x++){ numInCurrent = 0; currentMin = 0; currentMax = 0; - for(int y = 0; y < Globals.serverTerrainManager.getAugmentedChunkWidth(); y++){ + for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){ //create node if(navMeshGeneratorMask[x][y]){ if(numInCurrent > 0){ @@ -183,12 +183,12 @@ public class NavMeshUtils { //why the -1? I think the array fiddling above is causing the bounds to be off normally //this fixes that NavCube cube = new NavCube( - box.boundMinX + chunk.getWorldX() * Globals.serverTerrainManager.getChunkWidth(), + box.boundMinX + chunk.getWorldX() * ServerTerrainChunk.CHUNK_DIMENSION, box.minHeight - 0.5f, - box.boundMinY + chunk.getWorldY() * Globals.serverTerrainManager.getChunkWidth(), - box.boundMaxX + chunk.getWorldX() * Globals.serverTerrainManager.getChunkWidth(), + box.boundMinY + chunk.getWorldY() * ServerTerrainChunk.CHUNK_DIMENSION, + box.boundMaxX + chunk.getWorldX() * ServerTerrainChunk.CHUNK_DIMENSION, box.maxHeight + 0.5f, - box.boundMaxY + chunk.getWorldY() * Globals.serverTerrainManager.getChunkWidth() + box.boundMaxY + chunk.getWorldY() * ServerTerrainChunk.CHUNK_DIMENSION ); rVal.addNode(cube); } diff --git a/src/main/java/electrosphere/server/pathfinding/blocker/NavBlocker.java b/src/main/java/electrosphere/server/pathfinding/blocker/NavBlocker.java index b09a3a6a..b9b03e99 100644 --- a/src/main/java/electrosphere/server/pathfinding/blocker/NavBlocker.java +++ b/src/main/java/electrosphere/server/pathfinding/blocker/NavBlocker.java @@ -1,6 +1,7 @@ package electrosphere.server.pathfinding.blocker; import electrosphere.engine.Globals; +import electrosphere.server.terrain.manager.ServerTerrainChunk; /** * @@ -13,7 +14,7 @@ public class NavBlocker { boolean[][] heightfieldBlocker; public NavBlocker(){ - heightfieldBlocker = new boolean[Globals.serverTerrainManager.getAugmentedChunkWidth()][Globals.serverTerrainManager.getAugmentedChunkWidth()]; + heightfieldBlocker = new boolean[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION]; } public NavBlocker(boolean[][] field){ diff --git a/src/main/java/electrosphere/server/saves/SaveUtils.java b/src/main/java/electrosphere/server/saves/SaveUtils.java index e35b35cf..d8f54f03 100644 --- a/src/main/java/electrosphere/server/saves/SaveUtils.java +++ b/src/main/java/electrosphere/server/saves/SaveUtils.java @@ -89,8 +89,8 @@ public class SaveUtils { String dbFilePath = FileUtils.sanitizeFilePath(dirPath) + "/central.db"; Globals.dbController.connect(dbFilePath); if(!saveName.equals("arena")){ - Globals.serverTerrainManager.load(saveName); Globals.serverWorldData = FileUtils.loadObjectFromSavePath(saveName, "world.json", ServerWorldData.class); + Globals.serverTerrainManager.load(saveName); } return true; } @@ -106,7 +106,7 @@ public class SaveUtils { } public static boolean loadTerrainAndCreateWorldData(String currentSaveName){ - Globals.serverTerrainManager = new ServerTerrainManager(2000,50,ServerTerrainManager.SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO,0.0f,0); + Globals.serverTerrainManager = new ServerTerrainManager(2000,50,0.0f,0); SaveUtils.loadTerrainAndDB(currentSaveName); Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager); Globals.realmManager.createGriddedRealm(Globals.serverWorldData); diff --git a/src/main/java/electrosphere/server/terrain/diskcache/ChunkDiskCache.java b/src/main/java/electrosphere/server/terrain/diskcache/ChunkDiskCache.java new file mode 100644 index 00000000..bb1ce681 --- /dev/null +++ b/src/main/java/electrosphere/server/terrain/diskcache/ChunkDiskCache.java @@ -0,0 +1,92 @@ +package electrosphere.server.terrain.diskcache; + +import java.util.Map; + +import electrosphere.net.server.Server; +import electrosphere.server.terrain.manager.ServerTerrainChunk; +import electrosphere.util.FileUtils; + +/** + * An interface for accessing the disk cache of chunk information + */ +public class ChunkDiskCache { + + //The map of world position+chunk type to the file that actually houses that information + Map worldPosFileMap; + + /** + * Constructor + */ + public ChunkDiskCache(){ + + } + + /** + * Gets a key for a given chunk file based on a world coordinate + * @param worldX The x component + * @param worldY The y component + * @param worldZ The z component + * @return The key + */ + private static String getTerrainChunkKey(int worldX, int worldY, int worldZ){ + return worldX + "_" + worldY + "_" + worldZ + "t"; + } + + /** + * Gets a key for a given chunk file based on a world coordinate + * @param worldX The x component + * @param worldY The y component + * @param worldZ The z component + * @return The key + */ + private static String getFluidChunkKey(int worldX, int worldY, int worldZ){ + return worldX + "_" + worldY + "_" + worldZ + "f"; + } + + /** + * Initializes a diskcache based on a given save name + * @param saveName The save name + */ + public void init(String saveName){ + worldPosFileMap = FileUtils.loadObjectFromSavePath(saveName, "ChunkCache.map", Map.class); + } + + /** + * Checks if the cache contains a given chunk position + * @param worldX The x component + * @param worldY The y component + * @param worldZ The z component + * @return True if the cache contains the chunk, false otherwise + */ + public boolean containsTerrainAtPosition(int worldX, int worldY, int worldZ){ + return worldPosFileMap.containsKey(getTerrainChunkKey(worldX, worldY, worldZ)); + } + + /** + * Checks if the cache contains a given chunk position + * @param worldX The x component + * @param worldY The y component + * @param worldZ The z component + * @return True if the cache contains the chunk, false otherwise + */ + public boolean containsFluidAtPosition(int worldX, int worldY, int worldZ){ + return worldPosFileMap.containsKey(getFluidChunkKey(worldX, worldY, worldZ)); + } + + /** + * Gets the server terrain chunk from disk if it exists, otherwise returns null + * @param worldX The x coordinate + * @param worldY The y coordinate + * @param worldZ The z coordinate + * @return The server terrain chunk if it exists, null otherwise + */ + public ServerTerrainChunk getTerrainChunk(int worldX, int worldY, int worldZ){ + ServerTerrainChunk rVal = null; + if(containsTerrainAtPosition(worldX, worldY, worldZ)){ + String fileName = worldPosFileMap.get(getTerrainChunkKey(worldX, worldY, worldZ)); + //TODO: implement + } + return rVal; + } + +} diff --git a/src/main/java/electrosphere/server/terrain/editing/TerrainEditing.java b/src/main/java/electrosphere/server/terrain/editing/TerrainEditing.java index dfcda246..627897ac 100644 --- a/src/main/java/electrosphere/server/terrain/editing/TerrainEditing.java +++ b/src/main/java/electrosphere/server/terrain/editing/TerrainEditing.java @@ -49,13 +49,16 @@ public class TerrainEditing { float distance = (float)new Vector3d(Math.floor(offsetPos.x),Math.floor(offsetPos.y),Math.floor(offsetPos.z)).distance(position); float currentPositionMagnitude = editMagnitude - distance; - ServerTerrainChunk data = voxelCellManager.getChunkAtPosition(chunkPos); + ServerTerrainChunk data; if( voxelPos.x < ServerTerrainChunk.CHUNK_DIMENSION && voxelPos.y < ServerTerrainChunk.CHUNK_DIMENSION && voxelPos.z < ServerTerrainChunk.CHUNK_DIMENSION && + voxelPos.x > 0 && + voxelPos.y > 0 && + voxelPos.z > 0 && currentPositionMagnitude > 0 && - data != null + (data = voxelCellManager.getChunkAtPosition(chunkPos)) != null ){ float current = data.getWeights()[voxelPos.x][voxelPos.y][voxelPos.z]; //hard clamp so it doesn't go over 1 diff --git a/src/main/java/electrosphere/server/terrain/generation/TerrainGenerator.java b/src/main/java/electrosphere/server/terrain/generation/TerrainGenerator.java index e3227f45..15440fa7 100644 --- a/src/main/java/electrosphere/server/terrain/generation/TerrainGenerator.java +++ b/src/main/java/electrosphere/server/terrain/generation/TerrainGenerator.java @@ -171,29 +171,29 @@ public class TerrainGenerator { //create internal renderer - createRenderer(); + // createRenderer(); - boolean test = true; - while(test){ - if(brightnessIncreasing){ - if(brightness < 100){ - brightness++; - } else { - } - } else { - if(brightness > 0){ - brightness--; - } else { - brightnessIncreasing = true; - displayToggle++; - if(displayToggle > 1){ - displayToggle = 0; - } - } - } - frame.repaint(); - Utilities.sleep(10); - } + // boolean test = true; + // while(test){ + // if(brightnessIncreasing){ + // if(brightness < 100){ + // brightness++; + // } else { + // } + // } else { + // if(brightness > 0){ + // brightness--; + // } else { + // brightnessIncreasing = true; + // displayToggle++; + // if(displayToggle > 1){ + // displayToggle = 0; + // } + // } + // } + // frame.repaint(); + // Utilities.sleep(10); + // } return rVal; } diff --git a/src/main/java/electrosphere/server/terrain/manager/ServerTerrainManager.java b/src/main/java/electrosphere/server/terrain/manager/ServerTerrainManager.java index 90f345a6..e4972e7c 100644 --- a/src/main/java/electrosphere/server/terrain/manager/ServerTerrainManager.java +++ b/src/main/java/electrosphere/server/terrain/manager/ServerTerrainManager.java @@ -1,20 +1,18 @@ package electrosphere.server.terrain.manager; import com.google.gson.Gson; + +import electrosphere.engine.Globals; import electrosphere.game.terrain.processing.TerrainInterpolator; import electrosphere.server.terrain.generation.TerrainGenerator; -import electrosphere.server.terrain.models.ModificationList; import electrosphere.server.terrain.models.TerrainModel; import electrosphere.server.terrain.models.TerrainModification; -import electrosphere.engine.Globals; import electrosphere.util.FileUtils; -import electrosphere.util.Utilities; import java.io.File; import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.FloatBuffer; import java.nio.file.Files; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -36,8 +34,6 @@ public class ServerTerrainManager { //The vertical multiplier applied to the statically generated terrain int verticalInterpolationRatio; - int dynamicInterpolationRatio; - float interpolationRandomDampener; long seed; @@ -59,10 +55,9 @@ public class ServerTerrainManager { - public ServerTerrainManager(int worldSizeDiscrete, int verticalInterpolationRatio, int dynamicInterpolationRatio, float interpolationRandomDampener, long seed){ + public ServerTerrainManager(int worldSizeDiscrete, int verticalInterpolationRatio, float interpolationRandomDampener, long seed){ this.worldSizeDiscrete = worldSizeDiscrete; this.verticalInterpolationRatio = verticalInterpolationRatio; - this.dynamicInterpolationRatio = dynamicInterpolationRatio; this.chunkCache = new ConcurrentHashMap(); this.chunkCacheContents = new CopyOnWriteArrayList(); this.interpolationRandomDampener = interpolationRandomDampener; @@ -77,7 +72,6 @@ public class ServerTerrainManager { ServerTerrainManager rVal = new ServerTerrainManager(); rVal.worldSizeDiscrete = 2; rVal.verticalInterpolationRatio = 0; - rVal.dynamicInterpolationRatio = SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO; rVal.chunkCache = new ConcurrentHashMap(); rVal.chunkCacheContents = new CopyOnWriteArrayList(); rVal.interpolationRandomDampener = 0.0f; @@ -88,115 +82,47 @@ public class ServerTerrainManager { TerrainGenerator terrainGen = new TerrainGenerator(); terrainGen.setInterpolationRatio(worldSizeDiscrete/200); terrainGen.setVerticalInterpolationRatio(verticalInterpolationRatio); - terrainGen.setDynamicInterpolationRatio(dynamicInterpolationRatio); terrainGen.setRandomSeed(seed); model = terrainGen.generateModel(); model.setInterpolationRandomDampener(interpolationRandomDampener); } - public void save(String path){ - Gson gson = new Gson(); - String terrainOutRaw = gson.toJson(model); - try { - Files.write(new File(path + "./terrain.json").toPath(), terrainOutRaw.getBytes()); - } catch (IOException ex) { - ex.printStackTrace(); + /** + * Saves the terrain model backing this manager to a save file + * @param saveName The name of the save + */ + public void save(String saveName){ + ByteBuffer buffer = ByteBuffer.allocate(model.getElevation().length * model.getElevation()[0].length * 4); + FloatBuffer floatView = buffer.asFloatBuffer(); + for(int x = 0; x < model.getElevation().length; x++){ + floatView.put(model.getElevation()[x]); } + floatView.flip(); + FileUtils.saveBinaryToSavePath(saveName, "./terrain.dat", buffer.array()); + FileUtils.serializeObjectToSavePath(saveName, "./terrain.json", model); } public void load(String saveName){ model = FileUtils.loadObjectFromSavePath(saveName, "./terrain.json", TerrainModel.class); + byte[] data = FileUtils.loadBinaryFromSavePath(saveName, "./terrain.dat"); + ByteBuffer buffer = ByteBuffer.wrap(data); + FloatBuffer floatView = buffer.asFloatBuffer(); + float[][] elevation = new float[Globals.serverWorldData.getWorldSizeDiscrete()][Globals.serverWorldData.getWorldSizeDiscrete()]; + for(int x = 0; x < Globals.serverWorldData.getWorldSizeDiscrete(); x++){ + for(int y = 0; y < Globals.serverWorldData.getWorldSizeDiscrete(); y++){ + elevation[x][y] = floatView.get(); + } + } + model.setElevationArray(elevation); } public float[][] getTerrainAtChunk(int x, int y){ return model.getElevationForChunk(x, y); } -// public ServerTerrainChunk getAugmentedTerrainAtChunk(int x, int y){ -// //THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING -// if(model != null){ -// String key = getKey(x,y); -// ServerTerrainChunk returnedChunk; -// if(elevationMapCache.containsKey(key)){ -// elevationMapCacheContents.remove(key); -// elevationMapCacheContents.add(0, key); -// returnedChunk = elevationMapCache.get(key); -// return returnedChunk; -// } else { -// float[][] macroValues = model.getRad5MacroValuesAtPosition(x, y); -// long[][] randomizer = model.getRad5RandomizerValuesAtPosition(x, y); -// float[][] heightmap = TerrainInterpolator.getBicubicInterpolatedChunk( -// macroValues, -// randomizer, -// model.getDynamicInterpolationRatio(), -// model.getRandomDampener() -// ); -// ModificationList modificationList = model.getModifications(x, y); -// for(TerrainModification modification : modificationList.getModifications()){ -// modification.applyToHeightfield(heightmap); -// } -// if(elevationMapCacheContents.size() > cacheSize){ -// String oldChunk = elevationMapCacheContents.remove(elevationMapCacheContents.size() - 1); -// elevationMapCache.remove(oldChunk); -// } -// returnedChunk = new ServerTerrainChunk(x, y, heightmap, macroValues, randomizer); -// elevationMapCache.put(key, returnedChunk); -// elevationMapCacheContents.add(key); -// return returnedChunk; -// } -// } else { -// //THIS FIRES IF THERE IS AN ARENA WORLD RUNNING -// return ServerTerrainChunk.getArenaChunk(dynamicInterpolationRatio + 1); -// } -// } - public double getHeightAtPosition(double x, double y, double z){ - //get chunk coordinate space of input x,y - // int chunkX = (int)Math.floor(x / dynamicInterpolationRatio); - // int chunkY = (int)Math.floor(y / dynamicInterpolationRatio); - // int chunkZ = (int)Math.floor(z / dynamicInterpolationRatio); - // //get local coordinate space of input x,y - // double localX = x - chunkX * dynamicInterpolationRatio; - // double localY = y - chunkY * dynamicInterpolationRatio; - // double localZ = z - chunkZ * dynamicInterpolationRatio; - // //get chunk elevation map - // float[][] chunkElevationMap = getChunk(chunkX,chunkY,chunkZ).heightMap; - // //floored variants of local values - // int localXf = (int)Math.floor(localX); - // int localYf = (int)Math.floor(localY); - // int localZf = (int)Math.floor(localZ); - - // /* - // Average some inner value. - - // 01 11 - // 0.3 0.4 0.5 - // 0.1 0.2 0.3 - // 00 10 - // */ - // //interp elevation from map - // float elevation00 = chunkElevationMap[(int)localX+0][(int)localY+0]; - // float elevation10 = chunkElevationMap[(int)localX+1][(int)localY+0]; - // float elevation01 = chunkElevationMap[(int)localX+0][(int)localY+1]; - // float elevation11 = chunkElevationMap[(int)localX+1][(int)localY+1]; - - // double rVal = - // (1-(localX-localXf))*(1-(localY-localYf)) * elevation00 + - // ( (localX-localXf))*(1-(localY-localYf)) * elevation10 + - // (1-(localX-localXf))*( (localY-localYf)) * elevation01 + - // ( (localX-localXf))*( (localY-localYf)) * elevation11 - // ; - return y; } - - public int getChunkWidth(){ - return dynamicInterpolationRatio; - } - - public int getAugmentedChunkWidth(){ - return dynamicInterpolationRatio + 1; - } public int getWorldDiscreteSize(){ return worldSizeDiscrete; @@ -229,36 +155,6 @@ public class ServerTerrainManager { return 0.0f; } } - -// public float[][] getMacroValues(int x, int y){ -// //THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING -// if(model != null){ -// return model.getMacroValuesAtPosition(x, y); -// } else { -// //THIS FIRES IF THERE IS AN ARENA WORLD RUNNING -// return new float[3][3]; -// } -// } - -// public float[][] getRad5MacroValues(int x, int y){ -// //THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING -// if(model != null){ -// return model.getRad5MacroValuesAtPosition(x, y); -// } else { -// //THIS FIRES IF THERE IS AN ARENA WORLD RUNNING -// return new float[5][5]; -// } -// } - -// public long[][] getRandomizer(int x, int y){ -// //THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING -// if(model != null){ -// return model.getRad5RandomizerValuesAtPosition(x, y); -// } else { -// //THIS FIRES IF THERE IS AN ARENA WORLD RUNNING -// return new long[5][5]; -// } -// } public TerrainModel getModel() { return model; @@ -294,9 +190,13 @@ public class ServerTerrainManager { for(int weightX = 0; weightX < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; weightX++){ for(int weightY = 0; weightY < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; weightY++){ for(int weightZ = 0; weightZ < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; weightZ++){ - if(weightY < heightmap[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE * worldX + weightX][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE * worldZ + weightZ]){ + float height = heightmap[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE * worldX + weightX][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE * worldZ + weightZ]; + if(weightY < height){ weights[weightX][weightY][weightZ] = 1; values[weightX][weightY][weightZ] = 1; + } else if(height == 0 && weightY == 0 && worldY == 0) { + weights[weightX][weightY][weightZ] = 0.1f; + values[weightX][weightY][weightZ] = 1; } else { weights[weightX][weightY][weightZ] = -1; values[weightX][weightY][weightZ] = 0; @@ -304,12 +204,6 @@ public class ServerTerrainManager { } } } - // ModificationList modificationList = model.getModifications(x, y); - // if(modificationList != null){ - // for(TerrainModification modification : modificationList.getModifications()){ - // heightmap = modification.applyToHeightfield(heightmap); - // } - // } if(chunkCacheContents.size() > cacheSize){ String oldChunk = chunkCacheContents.remove(chunkCacheContents.size() - 1); chunkCache.remove(oldChunk); diff --git a/src/main/java/electrosphere/server/terrain/models/TerrainModel.java b/src/main/java/electrosphere/server/terrain/models/TerrainModel.java index 254c3b8e..0c3a4eff 100644 --- a/src/main/java/electrosphere/server/terrain/models/TerrainModel.java +++ b/src/main/java/electrosphere/server/terrain/models/TerrainModel.java @@ -6,13 +6,16 @@ import java.util.List; import java.util.Map; import java.util.Random; +import electrosphere.util.annotation.Exclude; + public class TerrainModel { int dynamicInterpolationRatio; float interpolationRandomDampener = 0.4f; int discreteArrayDimension; - float[][] elevation; + @Exclude + private float[][] elevation; float realMountainThreshold; float realOceanThreshold; @@ -345,5 +348,13 @@ public class TerrainModel { // System.out.println("Got modifications at " + worldX + " " + worldY); return modifications.get(getModificationKey(worldX, worldY, worldZ)); } + + /** + * Sets the elevation array (For instance when read from save file on loading a save) + * @param elevation The elevation array to set to + */ + public void setElevationArray(float[][] elevation){ + this.elevation = elevation; + } } diff --git a/src/main/java/electrosphere/util/FileUtils.java b/src/main/java/electrosphere/util/FileUtils.java index b64f4576..68a86e19 100644 --- a/src/main/java/electrosphere/util/FileUtils.java +++ b/src/main/java/electrosphere/util/FileUtils.java @@ -6,6 +6,7 @@ import com.google.gson.GsonBuilder; import electrosphere.engine.Main; import electrosphere.game.data.creature.type.movement.MovementSystem; import electrosphere.game.data.creature.type.movement.MovementSystemSerializer; +import electrosphere.util.annotation.AnnotationExclusionStrategy; import java.io.BufferedReader; import java.io.File; @@ -26,6 +27,8 @@ public class FileUtils { static { GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(MovementSystem.class, new MovementSystemSerializer()); + gsonBuilder.addDeserializationExclusionStrategy(new AnnotationExclusionStrategy()); + gsonBuilder.addSerializationExclusionStrategy(new AnnotationExclusionStrategy()); gson = gsonBuilder.create(); } @@ -209,6 +212,39 @@ public class FileUtils { ex.printStackTrace(); } } + + /** + * Reads a binary file as an array of bytes + * @param saveName The save name + * @param pathName The path within the save folder + * @return The array of bytes + */ + public static byte[] loadBinaryFromSavePath(String saveName, String pathName){ + byte[] rVal = null; + String sanitizedFilePath = sanitizeFilePath(pathName); + try { + rVal = Files.readAllBytes(getSaveFile(saveName,sanitizedFilePath).toPath()); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return rVal; + } + + /** + * Writes a binary file to a save folder's file + * @param saveName The name of the save + * @param pathName The path within the save folder + * @param data The data to write + */ + public static void saveBinaryToSavePath(String saveName, String pathName, byte[] data){ + String sanitizedFilePath = sanitizeFilePath(pathName); + try { + Files.write(getSaveFile(saveName,sanitizedFilePath).toPath(), data); + } catch (IOException ex) { + ex.printStackTrace(); + } + } /** * Checks if a directory exists diff --git a/src/main/java/electrosphere/util/annotation/AnnotationExclusionStrategy.java b/src/main/java/electrosphere/util/annotation/AnnotationExclusionStrategy.java new file mode 100644 index 00000000..f5a09ec8 --- /dev/null +++ b/src/main/java/electrosphere/util/annotation/AnnotationExclusionStrategy.java @@ -0,0 +1,22 @@ +package electrosphere.util.annotation; + +import com.google.gson.ExclusionStrategy; +import com.google.gson.FieldAttributes; + +/** + * Used to exclude single fields from a gson serialization in a black list manner. + * Refer to https://stackoverflow.com/a/27986860/ for reference for why this works and what it is. + */ +public class AnnotationExclusionStrategy implements ExclusionStrategy { + + @Override + public boolean shouldSkipField(FieldAttributes f) { + return f.getAnnotation(Exclude.class) != null; + } + + @Override + public boolean shouldSkipClass(Class clazz) { + return false; + } + +} diff --git a/src/main/java/electrosphere/util/annotation/Exclude.java b/src/main/java/electrosphere/util/annotation/Exclude.java new file mode 100644 index 00000000..968aa4f2 --- /dev/null +++ b/src/main/java/electrosphere/util/annotation/Exclude.java @@ -0,0 +1,17 @@ +package electrosphere.util.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +/** + * Used to exclude single fields from a gson serialization in a black list manner. + * Refer to https://stackoverflow.com/a/27986860/ for reference for why this works and what it is. + */ +public @interface Exclude { + +} diff --git a/src/main/java/electrosphere/util/worldviewer/TerrainViewer.java b/src/main/java/electrosphere/util/worldviewer/TerrainViewer.java index a50f79bd..340de321 100644 --- a/src/main/java/electrosphere/util/worldviewer/TerrainViewer.java +++ b/src/main/java/electrosphere/util/worldviewer/TerrainViewer.java @@ -19,7 +19,7 @@ public class TerrainViewer { TerrainModel terrainModel; - ServerTerrainManager terrainManager = new ServerTerrainManager(2000, 1000, 100, 0.05f, new Random().nextLong()); + ServerTerrainManager terrainManager = new ServerTerrainManager(2000, 1000, 0.05f, new Random().nextLong()); terrainManager.generate(); terrainModel = terrainManager.getModel();