From 53242a5280057373f675c2bab557f5ea44c282dd Mon Sep 17 00:00:00 2001 From: austin Date: Wed, 4 May 2022 23:30:41 -0400 Subject: [PATCH] fix server only drawcells --- .../electrosphere/engine/LoadingThread.java | 72 ++++++++------ .../electrosphere/entity/EntityUtils.java | 14 +++ .../game/client/cells/DrawCell.java | 7 ++ .../game/client/cells/DrawCellManager.java | 97 ++++++++++++++----- .../game/collision/CommonWorldData.java | 25 +++++ .../net/client/ClientNetworking.java | 55 ++++++----- 6 files changed, 191 insertions(+), 79 deletions(-) diff --git a/src/main/java/electrosphere/engine/LoadingThread.java b/src/main/java/electrosphere/engine/LoadingThread.java index 31e357d3..c423596d 100644 --- a/src/main/java/electrosphere/engine/LoadingThread.java +++ b/src/main/java/electrosphere/engine/LoadingThread.java @@ -158,6 +158,8 @@ public class LoadingThread extends Thread { initMicroSimulation(); //collision engine initCommonWorldData(Globals.RUN_SERVER); + //init draw cell manager + initDrawCellManager(); //init game specific stuff (ie different skybox colors) initGameGraphicalEntities(); //set simulations to ready if they exist @@ -187,6 +189,8 @@ public class LoadingThread extends Thread { initServerThread(); //collision engine initCommonWorldData(Globals.RUN_SERVER); + //init draw cell manager + initDrawCellManager(); //initialize the "virtual" objects simulation //not really relevant in arena mode // initMacroSimulation(); @@ -358,7 +362,7 @@ public class LoadingThread extends Thread { static void initServerArenaWorldData(){ Globals.serverWorldData = ServerWorldData.createArenaWorld(); - Globals.spawnPoint = new Vector3d(1,2.0,1); + Globals.spawnPoint = new Vector3d(1,0.1,1); // Globals.serverTerrainManager.getChunk(0, 0).addModification(new TerrainModification(0,0,5,5,5)); } @@ -412,6 +416,7 @@ public class LoadingThread extends Thread { Thread clientThread = null; if(Globals.RUN_CLIENT){ Globals.clientConnection = new ClientNetworking(NetUtils.getAddress(),NetUtils.getPort()); + System.out.println(Globals.clientConnection.socket); clientThread = new Thread(Globals.clientConnection); clientThread.start(); } @@ -419,37 +424,44 @@ public class LoadingThread extends Thread { static void initDrawCellManager(){ - Globals.drawCellManager = new DrawCellManager( - Globals.clientWorldData, - Globals.clientTerrainManager, - Globals.clientPlayerData.getWorldPositionX(), - Globals.clientPlayerData.getWorldPositionY() -// Globals.terrainManager.getDynamicInterpolationRatio(), -// Globals.terrainManager.getRandomDampener() - ); - - while(Globals.drawCellManager.containsInvalidCell()){ -// Globals.drawCellManager.updateInvalidCell(); - try { - TimeUnit.MILLISECONDS.sleep(10); - } catch (InterruptedException ex) { - } -// System.out.println("invalid cell"); + if(Globals.drawCellManager == null){ + Globals.drawCellManager = new DrawCellManager( + Globals.commonWorldData, + Globals.clientTerrainManager, + Globals.clientPlayerData.getWorldPositionX(), + Globals.clientPlayerData.getWorldPositionY() + // Globals.terrainManager.getDynamicInterpolationRatio(), + // Globals.terrainManager.getRandomDampener() + ); + } else { + //set our draw cell manager to actually generate drawable chunks + Globals.drawCellManager.setGenerateDrawables(true); } - - while(Globals.drawCellManager.containsUndrawableCell()){ -// Globals.drawCellManager.makeCellDrawable(); - try { - TimeUnit.MILLISECONDS.sleep(10); - } catch (InterruptedException ex) { + //wait for all the terrain data to arrive + if(Globals.RUN_CLIENT){ + while(Globals.drawCellManager.containsInvalidCell()){ + // Globals.drawCellManager.updateInvalidCell(); + try { + TimeUnit.MILLISECONDS.sleep(10); + } catch (InterruptedException ex) { + } + // System.out.println("invalid cell"); } -// System.out.println("undrawable"); - } - - while(Globals.drawCellManager.containsPhysicsNeedingCell()){ - try { - TimeUnit.MILLISECONDS.sleep(10); - } catch (InterruptedException ex) { + + while(Globals.drawCellManager.containsUndrawableCell()){ + // Globals.drawCellManager.makeCellDrawable(); + try { + TimeUnit.MILLISECONDS.sleep(10); + } catch (InterruptedException ex) { + } + // System.out.println("undrawable"); + } + + while(Globals.drawCellManager.containsPhysicsNeedingCell()){ + try { + TimeUnit.MILLISECONDS.sleep(10); + } catch (InterruptedException ex) { + } } } System.out.println("Draw Cell Manager ready"); diff --git a/src/main/java/electrosphere/entity/EntityUtils.java b/src/main/java/electrosphere/entity/EntityUtils.java index b59671b5..bd0bbf89 100644 --- a/src/main/java/electrosphere/entity/EntityUtils.java +++ b/src/main/java/electrosphere/entity/EntityUtils.java @@ -78,6 +78,20 @@ public class EntityUtils { Globals.entityManager.registerUIEntity(rVal); return rVal; } + + /** + * Spawns an entity that has a position in the world, but isn't necessarily drawable + * @return the entity + */ + public static Entity spawnSpatialEntity(){ + Entity rVal = new Entity(); +// rVal.putData(EntityDataStrings.DATA_STRING_MODEL_PATH, modelPath); + rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0)); + rVal.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaternionf().identity()); + rVal.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(1,1,1)); + Globals.entityManager.registerEntity(rVal); + return rVal; + } public static void cleanUpDrawableEntity(Entity e){ if(e != null){ diff --git a/src/main/java/electrosphere/game/client/cells/DrawCell.java b/src/main/java/electrosphere/game/client/cells/DrawCell.java index 3c33b484..ead7f130 100644 --- a/src/main/java/electrosphere/game/client/cells/DrawCell.java +++ b/src/main/java/electrosphere/game/client/cells/DrawCell.java @@ -125,6 +125,13 @@ public class DrawCell { } public void generatePhysics(){ + //if we're in no-graphics mode, need to generate the entity + if(modelEntity == null){ + modelEntity = EntityUtils.spawnSpatialEntity(); + modelEntity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true); + EntityUtils.getPosition(modelEntity).set(new Vector3f(cellX * dynamicInterpolationRatio, 0.0f, cellY * dynamicInterpolationRatio)); + } + //then actually perform the attach physicsObject = PhysicsUtils.attachTerrainRigidBody(modelEntity,heightmap); Globals.collisionEngine.registerPhysicsEntity(modelEntity); // System.out.println("generate physics"); diff --git a/src/main/java/electrosphere/game/client/cells/DrawCellManager.java b/src/main/java/electrosphere/game/client/cells/DrawCellManager.java index 5665bbda..f98510e6 100644 --- a/src/main/java/electrosphere/game/client/cells/DrawCellManager.java +++ b/src/main/java/electrosphere/game/client/cells/DrawCellManager.java @@ -2,7 +2,9 @@ package electrosphere.game.client.cells; import electrosphere.game.client.terrain.manager.ClientTerrainManager; import electrosphere.game.server.terrain.manager.ServerTerrainManager; +import electrosphere.game.terrain.processing.TerrainInterpolator; import electrosphere.game.client.world.ClientWorldData; +import electrosphere.game.collision.CommonWorldData; import electrosphere.main.Globals; import electrosphere.net.parser.net.message.TerrainMessage; import electrosphere.renderer.ShaderProgram; @@ -54,22 +56,25 @@ public class DrawCellManager { int worldBoundDiscreteMax = 0; //metadata about the game world - ClientWorldData clientWorldData; + CommonWorldData commonWorldData; //client terrain manager - ClientTerrainManager clientTerrainManager; + // ClientTerrainManager clientTerrainManager; //ready to start updating? boolean update = false; + + //controls whether we try to generate the drawable entities + //we want this to be false when in server-only mode + boolean generateDrawables = false; - public DrawCellManager(ClientWorldData clientWorldData, ClientTerrainManager clientTerrainManager, int discreteX, int discreteY){ - this.clientWorldData = clientWorldData; - worldBoundDiscreteMax = (int)(this.clientWorldData.getWorldBoundMax().x / this.clientWorldData.getDynamicInterpolationRatio() * 1.0f); - this.clientTerrainManager = clientTerrainManager; - this.miniCellWidth = miniCellWidth; + public DrawCellManager(CommonWorldData commonWorldData, ClientTerrainManager clientTerrainManager, int discreteX, int discreteY){ + this.commonWorldData = commonWorldData; + worldBoundDiscreteMax = (int)(commonWorldData.getWorldBoundMin().x / commonWorldData.getDynamicInterpolationRatio() * 1.0f); + // this.clientTerrainManager = clientTerrainManager; cells = new DrawCell[drawRadius * 2 + 1][drawRadius * 2 + 1]; valid = new boolean[drawRadius * 2 + 1][drawRadius * 2 + 1]; drawable = new boolean[drawRadius * 2 + 1][drawRadius * 2 + 1]; @@ -148,17 +153,17 @@ public class DrawCellManager { if( currentCellX >= 0 && - currentCellX < clientWorldData.getWorldDiscreteSize() && + currentCellX < commonWorldData.getWorldDiscreteSize() && currentCellY >= 0 && - currentCellY < clientWorldData.getWorldDiscreteSize() + currentCellY < commonWorldData.getWorldDiscreteSize() ){ - if(clientTerrainManager.containsHeightmapAtDiscretePoint(currentCellX, currentCellY)){ + if(containsHeightmapAtDiscretePoint(currentCellX, currentCellY)){ cells[targetX][targetY] = DrawCell.generateTerrainCell( currentCellX, currentCellY, - clientTerrainManager.getHeightmapAtPoint(currentCellX, currentCellY), - clientTerrainManager.getTextureMapAtPoint(currentCellX, currentCellY), - clientWorldData.getDynamicInterpolationRatio(), + getHeightmapAtPoint(currentCellX, currentCellY), + getTextureMapAtPoint(currentCellX, currentCellY), + commonWorldData.getDynamicInterpolationRatio(), program ); valid[targetX][targetY] = true; @@ -207,9 +212,9 @@ public class DrawCellManager { int currentCellY = cellY - drawRadius + targetY; if( currentCellX >= 0 && - currentCellX < clientWorldData.getWorldDiscreteSize() && + currentCellX < commonWorldData.getWorldDiscreteSize() && currentCellY >= 0 && - currentCellY < clientWorldData.getWorldDiscreteSize() + currentCellY < commonWorldData.getWorldDiscreteSize() ){ //physics radius calculation // if(Math.abs(physicsRadius + 1 - targetX) < physicsRadius && Math.abs(physicsRadius + 1 - targetY) < physicsRadius){ @@ -217,8 +222,8 @@ public class DrawCellManager { // } //calculation for stride int dist = (int)Math.sqrt((targetX - drawRadius)*(targetX - drawRadius) + (targetY - drawRadius) * (targetY - drawRadius));//Math.abs(targetX - drawRadius) * Math.abs(targetY - drawRadius); - int stride = Math.min(clientWorldData.getDynamicInterpolationRatio()/2, Math.max(1, dist / drawStepdownInterval * drawStepdownValue)); - while(clientWorldData.getDynamicInterpolationRatio() % stride != 0){ + int stride = Math.min(commonWorldData.getDynamicInterpolationRatio()/2, Math.max(1, dist / drawStepdownInterval * drawStepdownValue)); + while(commonWorldData.getDynamicInterpolationRatio() % stride != 0){ stride = stride + 1; } //make drawable entity @@ -251,16 +256,16 @@ public class DrawCellManager { int currentCellY = cellY - drawRadius + targetY; if( currentCellX >= 0 && - currentCellX < clientWorldData.getWorldDiscreteSize() && + currentCellX < commonWorldData.getWorldDiscreteSize() && currentCellY >= 0 && - currentCellY < clientWorldData.getWorldDiscreteSize() + currentCellY < commonWorldData.getWorldDiscreteSize() ){ // if(Math.abs(drawRadius + 1 - targetX) < physicsRadius && Math.abs(drawRadius + 1 - targetY) < physicsRadius){ // needsPhysics[targetX][targetY] = true; // } int dist = (int)Math.sqrt((targetX - drawRadius)*(targetX - drawRadius) + (targetY - drawRadius) * (targetY - drawRadius)); //Math.abs(targetX - drawRadius) * Math.abs(targetY - drawRadius); - int stride = Math.min(clientWorldData.getDynamicInterpolationRatio()/2, Math.max(1, dist / drawStepdownInterval * drawStepdownValue)); - while(clientWorldData.getDynamicInterpolationRatio() % stride != 0){ + int stride = Math.min(commonWorldData.getDynamicInterpolationRatio()/2, Math.max(1, dist / drawStepdownInterval * drawStepdownValue)); + while(commonWorldData.getDynamicInterpolationRatio() % stride != 0){ stride = stride + 1; } cells[targetX][targetY].generateDrawableEntity(stride); @@ -289,7 +294,7 @@ public class DrawCellManager { public boolean containsUndrawableCell(){ for(int x = 0;x < drawRadius * 2 + 1; x++){ for(int y = 0; y < drawRadius * 2 + 1; y++){ - if(!drawable[x][y]){ + if(!drawable[x][y] && this.generateDrawables){ return true; } } @@ -300,7 +305,7 @@ public class DrawCellManager { public boolean containsUpdateableCell(){ for(int x = 0;x < drawRadius * 2 + 1; x++){ for(int y = 0; y < drawRadius * 2 + 1; y++){ - if(updateable[x][y]){ + if(updateable[x][y] && this.generateDrawables){ return true; } } @@ -343,9 +348,9 @@ public class DrawCellManager { int currentCellY = cellY - physicsRadius + targetY; if( currentCellX >= 0 && - currentCellX < clientWorldData.getWorldDiscreteSize() && + currentCellX < commonWorldData.getWorldDiscreteSize() && currentCellY >= 0 && - currentCellY < clientWorldData.getWorldDiscreteSize() + currentCellY < commonWorldData.getWorldDiscreteSize() ){ // if(Math.abs(drawRadius + 1 - targetX) < physicsRadius && Math.abs(drawRadius + 1 - targetY) < physicsRadius){ // needsPhysics[targetX][targetY] = true; @@ -530,7 +535,7 @@ public class DrawCellManager { public int transformRealSpaceToCellSpace(double input){ - return (int)(input / clientWorldData.getDynamicInterpolationRatio()); + return (int)(input / commonWorldData.getDynamicInterpolationRatio()); } @@ -647,6 +652,46 @@ public class DrawCellManager { public boolean coordsInPhysicsSpace(int worldX, int worldY){ return worldX <= cellX + physicsRadius && worldX >= cellX - physicsRadius && worldY <= cellY + physicsRadius && worldY >= cellY - physicsRadius; } + + public void setGenerateDrawables(boolean generate){ + this.generateDrawables = generate; + } + + boolean containsHeightmapAtDiscretePoint(int currentCellX, int currentCellY){ + if(Globals.clientTerrainManager != null){ + return Globals.clientTerrainManager.containsHeightmapAtDiscretePoint(currentCellX, currentCellY); + } + return true; + } + + float[][] getHeightmapAtPoint(int currentCellX, int currentCellY){ + if(Globals.clientTerrainManager != null){ + return Globals.clientTerrainManager.getHeightmapAtPoint(currentCellX, currentCellY); + } + return Globals.serverTerrainManager.getChunk(currentCellX, currentCellY).getHeightMap(); + } + + float[][] getTextureMapAtPoint(int currentCellX, int currentCellY){ + if(Globals.clientTerrainManager != null){ + return Globals.clientTerrainManager.getTextureMapAtPoint(currentCellX,currentCellY); + } else { + //hacky fix to +2 to this, I think the interpolation ratio was different for server/client data + //now that we're merging/ambiguous within this class, it's out of bounds-ing unless I +2 + //TODO: investigate + float[][] rVal = new float[commonWorldData.getDynamicInterpolationRatio() + 2][commonWorldData.getDynamicInterpolationRatio() + 2]; + rVal[1][1] = 1; + rVal[2][1] = 1; + rVal[3][1] = 1; + rVal[4][1] = 1; + rVal[5][1] = 1; + rVal[5][2] = 1; + rVal[6][1] = 1; + rVal[6][2] = 1; + return rVal; + } + } + + // public diff --git a/src/main/java/electrosphere/game/collision/CommonWorldData.java b/src/main/java/electrosphere/game/collision/CommonWorldData.java index bfcc9391..0d3a9147 100644 --- a/src/main/java/electrosphere/game/collision/CommonWorldData.java +++ b/src/main/java/electrosphere/game/collision/CommonWorldData.java @@ -79,4 +79,29 @@ public class CommonWorldData { return serverWorldData.convertRealToChunkSpace(real); } } + + public int getDynamicInterpolationRatio(){ + if(clientWorldData != null){ + return clientWorldData.getDynamicInterpolationRatio(); + } else { + return serverWorldData.getDynamicInterpolationRatio(); + } + } + + public int getWorldDiscreteSize(){ + if(clientWorldData != null){ + return clientWorldData.getWorldDiscreteSize(); + } else { + return serverWorldData.getWorldSizeDiscrete(); + } + } + + public float getRandomDampener(){ + if(clientWorldData != null){ + return clientWorldData.getRandomDampener(); + } else { + return serverWorldData.getRandomDampener(); + } + } + } diff --git a/src/main/java/electrosphere/net/client/ClientNetworking.java b/src/main/java/electrosphere/net/client/ClientNetworking.java index 69aac6aa..798d5f2f 100644 --- a/src/main/java/electrosphere/net/client/ClientNetworking.java +++ b/src/main/java/electrosphere/net/client/ClientNetworking.java @@ -35,8 +35,10 @@ import org.apache.commons.crypto.stream.CryptoOutputStream; */ public class ClientNetworking implements Runnable{ + String address; + int port; - Socket socket; + public Socket socket; // CryptoInputStream inputStream; // CryptoOutputStream outputStream; InputStream inputStream; @@ -49,27 +51,8 @@ public class ClientNetworking implements Runnable{ static final int MAX_CONNECTION_ATTEMPTS = 10; public ClientNetworking(String address, int port){ - int connectionAttempts = 0; - boolean connected = false; - while(!connected){ - try { - this.socket = new Socket(address,port); - } catch (IOException ex) { - LoggerInterface.loggerNetworking.WARNING("Client failed to connect!"); - } finally { - connected = true; - } - if(!connected){ - try { - TimeUnit.MILLISECONDS.sleep(50); - } catch (InterruptedException e) {} - connectionAttempts++; - } - if(connectionAttempts > MAX_CONNECTION_ATTEMPTS){ - LoggerInterface.loggerNetworking.ERROR("Max client connection attempts!", new Exception()); - System.exit(1); - } - } + this.address = address; + this.port = port; } @@ -92,14 +75,39 @@ public class ClientNetworking implements Runnable{ // ex.printStackTrace(); // System.exit(1); // } + + //attempt connection + int connectionAttempts = 0; + boolean connected = false; + while(!connected){ + try { + this.socket = new Socket(address,port); + connected = true; + } catch (IOException ex) { + LoggerInterface.loggerNetworking.WARNING("Client failed to connect!"); + } + if(!connected){ + try { + TimeUnit.MILLISECONDS.sleep(50); + } catch (InterruptedException e) {} + connectionAttempts++; + } + if(connectionAttempts > MAX_CONNECTION_ATTEMPTS){ + LoggerInterface.loggerNetworking.ERROR("Max client connection attempts!", new Exception()); + System.exit(1); + } + } + + //create parser try { inputStream = socket.getInputStream(); outputStream = socket.getOutputStream(); parser = new NetworkParser(inputStream,outputStream); } catch (IOException ex) { - Logger.getLogger(ClientNetworking.class.getName()).log(Level.SEVERE, null, ex); + LoggerInterface.loggerNetworking.ERROR("Error on client socket", ex); } + //start parsing messages initialized = true; while(Main.isRunning()){ //attempt poll incoming messages @@ -107,6 +115,7 @@ public class ClientNetworking implements Runnable{ //outgoing messages parser.pushMessagesOut(); } + }