First terrain commit

This commit is contained in:
austin 2023-06-03 17:27:30 -04:00
parent e02a02eb5f
commit 8f06a025f0
75 changed files with 2746 additions and 4255 deletions

View File

@ -33,6 +33,14 @@
"name" : "worldMaxY", "name" : "worldMaxY",
"type" : "FIXED_INT" "type" : "FIXED_INT"
}, },
{
"name" : "value",
"type" : "FIXED_FLOAT"
},
{ {
"name" : "worldX", "name" : "worldX",
"type" : "FIXED_INT" "type" : "FIXED_INT"
@ -45,26 +53,8 @@
"name" : "worldZ", "name" : "worldZ",
"type" : "FIXED_INT" "type" : "FIXED_INT"
}, },
{
"name" : "value",
"type" : "FIXED_FLOAT"
},
{
"name" : "locationX",
"type" : "FIXED_INT"
},
{
"name" : "locationY",
"type" : "FIXED_INT"
},
{
"name" : "locationZ",
"type" : "FIXED_INT"
},
{ {
@ -82,215 +72,18 @@
{
"name" : "macroValue00",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue01",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue02",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue03",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue04",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue10",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue11",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue12",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue13",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue14",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue20",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue21",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue22",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue23",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue24",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue30",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue31",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue32",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue33",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue34",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue40",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue41",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue42",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue43",
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue44",
"type" : "FIXED_FLOAT"
},
{
"name" : "randomizerValue00",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue01",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue02",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue03",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue04",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue10",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue11",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue12",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue13",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue14",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue20",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue21",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue22",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue23",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue24",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue30",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue31",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue32",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue33",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue34",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue40",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue41",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue42",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue43",
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue44",
"type" : "FIXED_LONG"
},
{ {
"name" : "chunkData", "name" : "chunkData",
"type" : "BYTE_ARRAY" "type" : "BYTE_ARRAY"
},
{
"name" : "terrainWeight",
"type" : "FIXED_FLOAT"
},
{
"name" : "terrainValue",
"type" : "FIXED_INT"
} }
], ],
"messageTypes" : [ "messageTypes" : [
@ -319,87 +112,10 @@
}, },
{ {
"messageName" : "Update", "messageName" : "Update",
"data" : [
"locationX",
"locationY",
"locationZ"
]
},
{
"messageName" : "chunkLoadStart",
"data" : [ "data" : [
"worldX", "worldX",
"worldY", "worldY",
"value" "worldZ"
]
},
{
"messageName" : "MacroValue",
"data" : [
"worldX",
"worldY",
"macroValue00",
"macroValue01",
"macroValue02",
"macroValue03",
"macroValue04",
"macroValue10",
"macroValue11",
"macroValue12",
"macroValue13",
"macroValue14",
"macroValue20",
"macroValue21",
"macroValue22",
"macroValue23",
"macroValue24",
"macroValue30",
"macroValue31",
"macroValue32",
"macroValue33",
"macroValue34",
"macroValue40",
"macroValue41",
"macroValue42",
"macroValue43",
"macroValue44",
"randomizerValue00",
"randomizerValue01",
"randomizerValue02",
"randomizerValue03",
"randomizerValue04",
"randomizerValue10",
"randomizerValue11",
"randomizerValue12",
"randomizerValue13",
"randomizerValue14",
"randomizerValue20",
"randomizerValue21",
"randomizerValue22",
"randomizerValue23",
"randomizerValue24",
"randomizerValue30",
"randomizerValue31",
"randomizerValue32",
"randomizerValue33",
"randomizerValue34",
"randomizerValue40",
"randomizerValue41",
"randomizerValue42",
"randomizerValue43",
"randomizerValue44"
]
},
{
"messageName" : "heightMapModification",
"data" : [
"value",
"worldX",
"worldY",
"worldZ",
"locationX",
"locationY",
"locationZ"
] ]
}, },
{ {

View File

@ -143,6 +143,15 @@
<version>0.1</version> <version>0.1</version>
</dependency> </dependency>
<!--Ode4J-->
<!--License: Dual LGPL 2.1 OR BSD 3-clause-->
<!--https://github.com/tzaeschke/ode4j-->
<dependency>
<groupId>org.ode4j</groupId>
<artifactId>core</artifactId>
<version>0.5.0</version>
</dependency>
<!--SQLITE-JDBC--> <!--SQLITE-JDBC-->
<!--License: Apache--> <!--License: Apache-->
<!-- https://mvnrepository.com/artifact/org.xerial/sqlite-jdbc --> <!-- https://mvnrepository.com/artifact/org.xerial/sqlite-jdbc -->

View File

@ -43,9 +43,9 @@ public class ClientEntityCullingManager {
public void clearOutOfBoundsEntities(){ public void clearOutOfBoundsEntities(){
if(Globals.commonWorldData != null && Globals.playerEntity != null && Globals.clientPlayerData != null){ if(Globals.commonWorldData != null && Globals.playerEntity != null && Globals.clientPlayerData != null){
Vector3d playerCharacterPos = EntityUtils.getPosition(Globals.playerEntity); Vector3d playerCharacterPos = EntityUtils.getPosition(Globals.playerEntity);
int playerCharacterWorldX = Globals.commonWorldData.convertRealToWorld(playerCharacterPos.x); int playerCharacterWorldX = Globals.clientWorldData.convertRealToWorld(playerCharacterPos.x);
int playerCharacterWorldY = Globals.commonWorldData.convertRealToWorld(playerCharacterPos.y); int playerCharacterWorldY = Globals.clientWorldData.convertRealToWorld(playerCharacterPos.y);
int playerCharacterWorldZ = Globals.commonWorldData.convertRealToWorld(playerCharacterPos.z); int playerCharacterWorldZ = Globals.clientWorldData.convertRealToWorld(playerCharacterPos.z);
if( if(
playerCharacterWorldX != Globals.clientPlayerData.getWorldPos().x|| playerCharacterWorldX != Globals.clientPlayerData.getWorldPos().x||
playerCharacterWorldY != Globals.clientPlayerData.getWorldPos().y || playerCharacterWorldY != Globals.clientPlayerData.getWorldPos().y ||
@ -59,22 +59,14 @@ public class ClientEntityCullingManager {
//common world data is initialized with the collision data //common world data is initialized with the collision data
//if this is null then the engine hasn't fully started up yet //if this is null then the engine hasn't fully started up yet
if(position != null){ if(position != null){
int worldX = Globals.commonWorldData.convertRealToWorld(position.x); int worldX = Globals.clientWorldData.convertRealToWorld(position.x);
int worldY = Globals.commonWorldData.convertRealToWorld(position.z); int worldZ = Globals.clientWorldData.convertRealToWorld(position.z);
if(!Globals.drawCellManager.coordsInPhysicsSpace(worldX, worldY)){ if(!Globals.drawCellManager.coordsInPhysicsSpace(worldX, worldZ)){
//if we're running the server we need to just hide the entity //we need to just hide the entity
//otherwise delete it recursiveHide(entity);
if(Globals.RUN_SERVER && Globals.RUN_CLIENT){
recursiveHide(entity);
} else {
scene.recursiveDeregister(entity);
}
} else { } else {
//if the entity is within range, we're running server, //if the entity is within range and it's not set to visible, make it visible
//and it's not set to visible, make it visible recursiveShow(entity);
if(Globals.RUN_SERVER && Globals.RUN_CLIENT){
recursiveShow(entity);
}
} }
} }
} }

View File

@ -1,7 +1,9 @@
package electrosphere.client.foliagemanager; package electrosphere.client.foliagemanager;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
@ -42,6 +44,15 @@ public class ClientFoliageManager {
//Used to prevent concurrent usage of grassEntities set //Used to prevent concurrent usage of grassEntities set
boolean ready = false; boolean ready = false;
//The list of voxel type ids that should have grass generated on top of them
static final List<Integer> grassGeneratingVoxelIds = new ArrayList<Integer>();
//FoliageCells that are active and have foliage that is being drawn
Set<FoliageCell> activeCells = new HashSet<FoliageCell>();
//The maximum distance a cell can be away from the player before being destroyed
static final float CELL_DISTANCE_MAX = 25f;
//The maximum number of foliage cells
static final int CELL_COUNT_MAX = 100;
@ -59,6 +70,9 @@ public class ClientFoliageManager {
}; };
modelMatrixAttribute = new ShaderAttribute(attributeIndices); modelMatrixAttribute = new ShaderAttribute(attributeIndices);
attributes.put(modelMatrixAttribute,HomogenousBufferTypes.MAT4F); attributes.put(modelMatrixAttribute,HomogenousBufferTypes.MAT4F);
//set grass generating voxel ids
grassGeneratingVoxelIds.add(2);
} }
//shader paths //shader paths
@ -119,14 +133,6 @@ public class ClientFoliageManager {
grassPosition.set(getNewPosition(playerPosition)); grassPosition.set(getNewPosition(playerPosition));
grassRotation.set(getNewRotation()); grassRotation.set(getNewRotation());
} }
//update uniforms
// instancedActor.setUniform("position", grassPosition);
// instancedActor.setUniform("rotation", new Vector4d(
// grassRotation.x,
// grassRotation.y,
// grassRotation.z,
// grassRotation.w));
// instancedActor.setUniform("scale", new Vector3d(EntityUtils.getScale(grassEntity)));
modelMatrix = modelMatrix.identity(); modelMatrix = modelMatrix.identity();
Vector3f cameraModifiedPosition = new Vector3f((float)grassPosition.x,(float)grassPosition.y,(float)grassPosition.z).sub(cameraCenter); Vector3f cameraModifiedPosition = new Vector3f((float)grassPosition.x,(float)grassPosition.y,(float)grassPosition.z).sub(cameraCenter);
@ -137,7 +143,7 @@ public class ClientFoliageManager {
instancedActor.setAttribute(modelMatrixAttribute, modelMatrix); instancedActor.setAttribute(modelMatrixAttribute, modelMatrix);
//draw //draw
instancedActor.draw(Globals.renderingEngine.getRenderPipelineState()); // instancedActor.draw(Globals.renderingEngine.getRenderPipelineState());
} }
} }
} }
@ -166,13 +172,6 @@ public class ClientFoliageManager {
} }
/** /**
* Makes an already created entity a drawable, instanced entity (client only) by backing it with an InstancedActor * Makes an already created entity a drawable, instanced entity (client only) by backing it with an InstancedActor
* @param entity The entity * @param entity The entity
@ -188,6 +187,19 @@ public class ClientFoliageManager {
Globals.clientScene.registerEntityToTag(entity, EntityTags.DRAW_INSTANCED); Globals.clientScene.registerEntityToTag(entity, EntityTags.DRAW_INSTANCED);
} }
/**
* Evaluate all foliage cells to see if any should be deconstructed and any new ones should be created
*/
protected void evaluateFoliageCells(){
Vector3d playerPosition = EntityUtils.getPosition(Globals.playerEntity);
for(FoliageCell activeCell : activeCells){
//if cell is outside of range of player, disable cell
if(activeCell.position.distance(playerPosition) > CELL_DISTANCE_MAX){
//TODO: destroy cell
}
}
}

View File

@ -0,0 +1,18 @@
package electrosphere.client.foliagemanager;
import java.util.Set;
import org.joml.Vector3d;
import electrosphere.entity.Entity;
/**
* Contains a set of foliage entities and groups them together.
*/
public class FoliageCell {
//position of the foliage cell
Vector3d position;
//constituent entities
Set<Entity> containedEntities;
}

View File

@ -3,7 +3,6 @@ package electrosphere.client.scene;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.Scene; import electrosphere.entity.Scene;
import electrosphere.game.collision.CollisionEngine; import electrosphere.game.collision.CollisionEngine;

View File

@ -1,11 +1,5 @@
package electrosphere.client.scene; package electrosphere.client.scene;
import electrosphere.game.server.world.*;
import electrosphere.server.datacell.ServerDataCell;
import electrosphere.server.terrain.manager.ServerTerrainManager;
import java.util.List;
import org.joml.Vector2f;
import org.joml.Vector3f; import org.joml.Vector3f;
/** /**
@ -44,7 +38,13 @@ public class ClientWorldData {
int worldDiscreteSize; int worldDiscreteSize;
public ClientWorldData(Vector3f worldMinPoint, Vector3f worldMaxPoint, int dynamicInterpolationRatio, float randomDampener, int worldDiscreteSize) { public ClientWorldData(
Vector3f worldMinPoint,
Vector3f worldMaxPoint,
int dynamicInterpolationRatio,
float randomDampener,
int worldDiscreteSize
) {
this.worldMinPoint = worldMinPoint; this.worldMinPoint = worldMinPoint;
this.worldMaxPoint = worldMaxPoint; this.worldMaxPoint = worldMaxPoint;
this.dynamicInterpolationRatio = dynamicInterpolationRatio; this.dynamicInterpolationRatio = dynamicInterpolationRatio;
@ -84,4 +84,12 @@ public class ClientWorldData {
return chunk * dynamicInterpolationRatio; return chunk * dynamicInterpolationRatio;
} }
public int convertRealToWorld(double real){
return convertRealToChunkSpace(real);
}
public double convertWorldToReal(int world){
return convertChunkToRealSpace(world);
}
} }

View File

@ -3,10 +3,8 @@ package electrosphere.client.sim;
import electrosphere.client.terrain.manager.ClientTerrainManager; import electrosphere.client.terrain.manager.ClientTerrainManager;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
import electrosphere.entity.types.camera.CameraEntityUtils;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector3f;
/** /**
* *
@ -45,7 +43,6 @@ public class ClientFunctions {
public static void loadTerrain(){ public static void loadTerrain(){
if(Globals.clientTerrainManager != null){ if(Globals.clientTerrainManager != null){
Globals.clientTerrainManager.handleMessages(); Globals.clientTerrainManager.handleMessages();
Globals.clientTerrainManager.ejectLoadedChunks();
updateCellManager(); updateCellManager();
} }
} }
@ -59,7 +56,7 @@ public class ClientFunctions {
newPlayerCharacterPosition = EntityUtils.getPosition(Globals.playerEntity); newPlayerCharacterPosition = EntityUtils.getPosition(Globals.playerEntity);
} }
//Cell manager do your things //Cell manager do your things
Globals.drawCellManager.calculateDeltas(oldPlayerCharacterPosition, newPlayerCharacterPosition); Globals.drawCellManager.calculateDeltas(newPlayerCharacterPosition);
Globals.drawCellManager.update(); Globals.drawCellManager.update();
} }
} }

View File

@ -0,0 +1,52 @@
package electrosphere.client.terrain.cache;
import electrosphere.server.terrain.manager.ServerTerrainChunk;
/**
* A container of data about a chunk of terrain
*/
public class ChunkData {
//The size of a chunk
public static final int CHUNK_SIZE = ServerTerrainChunk.CHUNK_DIMENSION;
//What type of terrain is in this voxel, eg stone vs dirt vs grass, etc
int[][][] voxelType;
//How much of that terrain type is in this voxel
float[][][] voxelWeight;
/**
* Gets the voxel type array in this container
* @return The voxel type array
*/
public int[][][] getVoxelType(){
return voxelType;
}
/**
* Sets the voxel type array in this container
* @param voxelType The voxel type array
*/
public void setVoxelType(int[][][] voxelType){
this.voxelType = voxelType;
}
/**
* Gets the voxel weight array in this container
* @return The voxel weight array
*/
public float[][][] getVoxelWeight(){
return voxelWeight;
}
/**
* Sets the voxel weight array in this container
* @param voxelWeight The voxel weight array
*/
public void setVoxelWeight(float[][][] voxelWeight){
this.voxelWeight = voxelWeight;
}
}

View File

@ -1,48 +0,0 @@
package electrosphere.client.terrain.cache;
/**
*
* @author amaterasu
*/
public class ChunkModification {
int worldX;
int worldY;
int locationX;
int locationY;
float value;
public ChunkModification(int worldX, int worldY, int locationX, int locationY, float value) {
this.worldX = worldX;
this.worldY = worldY;
this.locationX = locationX;
this.locationY = locationY;
this.value = value;
}
public int getWorldX() {
return worldX;
}
public int getLocationX() {
return locationX;
}
public int getLocationY() {
return locationY;
}
public float getValue() {
return value;
}
public int getWorldY() {
return worldY;
}
public float[][] applyModification(float[][] heightmap){
heightmap[locationX][locationY] = value;
return heightmap;
}
}

View File

@ -1,73 +1,40 @@
package electrosphere.client.terrain.cache; package electrosphere.client.terrain.cache;
import electrosphere.client.scene.ClientWorldData;
import electrosphere.game.terrain.processing.TerrainInterpolator;
import electrosphere.server.terrain.models.TerrainModel;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
/**
* Acts as a cache in front of terrain model to streamline receiving chunks
*/
public class ClientTerrainCache { public class ClientTerrainCache {
/* //cache capacity
Acts as a cache in front of terrain model to streamline receiving heightmaps
on both client and server
*/
ClientWorldData clientWorldData;
int cacheSize; int cacheSize;
Map<String,float[][]> cacheMap = new ConcurrentHashMap<String,float[][]> (); //the map of chunk key -> chunk data
Map<String,ChunkData> cacheMap = new ConcurrentHashMap<String,ChunkData>();
//the list of keys in the cache
List<String> cacheList = new CopyOnWriteArrayList<String>(); List<String> cacheList = new CopyOnWriteArrayList<String>();
/**
* Constructor
* @param cacheSize The capacity of the cache
*/
public ClientTerrainCache(int cacheSize){ public ClientTerrainCache(int cacheSize){
this.cacheSize = cacheSize; this.cacheSize = cacheSize;
} }
// TerrainChunkValues getChunkValuesAtPoint(int x, int y){ /**
// if(terrainModel != null){ * Adds a chunk data to the terrain cache
// return new TerrainChunkValues( * @param worldX The x world position
// terrainModel.getMacroValuesAtPosition(x, y), * @param worldY The y world position
// terrainModel.getRandomizerValuesAtPosition(x, y) * @param worldZ The z world position
// ); * @param chunkData The chunk data to add at the specified positions
// } else { */
// return new TerrainChunkValues( public void addChunkDataToCache(int worldX, int worldY, int worldZ, ChunkData chunkData){
// new float[3][3], cacheMap.put(getKey(worldX,worldY,worldZ),chunkData);
// new long[3][3]
// );
// }
// }
//USED TO ADD macro values
public void addChunkValuesToCache(int x, int y, float[][] macroValues, long[][] randomizer){
// TerrainChunkValues chunk = new TerrainChunkValues(macroValues, randomizer);
assert clientWorldData != null;
float[][] heightmap = TerrainInterpolator.getBicubicInterpolatedChunk(
macroValues,
randomizer,
clientWorldData.getDynamicInterpolationRatio(),
clientWorldData.getRandomDampener()
);
cacheMap.put(getKey(x,y),heightmap);
while(cacheList.size() > cacheSize){
String currentChunk = cacheList.remove(0);
cacheMap.remove(currentChunk);
}
}
public void addFloatsToCache(int x, int y, float[][] values){
cacheMap.put(getKey(x,y),values);
while(cacheList.size() > cacheSize){ while(cacheList.size() > cacheSize){
String currentChunk = cacheList.remove(0); String currentChunk = cacheList.remove(0);
cacheMap.remove(currentChunk); cacheMap.remove(currentChunk);
@ -75,29 +42,41 @@ public class ClientTerrainCache {
} }
/**
public String getKey(int x, int y){ * Generates a key for the cache based on the position provided
return x + "-" + y; * @param worldX The x world position
* @param worldY The y world position
* @param worldZ The z world position
* @return The cache key
*/
public String getKey(int worldX, int worldY, int worldZ){
return worldX + "_" + worldY + "_" + worldZ;
} }
/**
public boolean containsHeightmapAtChunkPoint(int x, int y){ * Checks whether the cache contains chunk data at a given world point
return cacheMap.containsKey(getKey(x,y)); * @param worldX The x world position
* @param worldY The y world position
* @param worldZ The z world position
* @return True if the cache contains chunk data at the specified point, false otherwise
*/
public boolean containsChunkDataAtWorldPoint(int worldX, int worldY, int worldZ){
return cacheMap.containsKey(getKey(worldX,worldY,worldZ));
} }
//ALL RETRIEVE /**
public float[][] getHeightmapAtChunkPoint(int x, int y){ * Gets chunk data at the given world point
return cacheMap.get(getKey(x,y)); * @param worldX The x world position
} * @param worldY The y world position
* @param worldZ The z world position
* @return The chunk data if it exists, null otherwise
*/
public ChunkData getSubChunkDataAtPoint(int worldX, int worldY, int worldZ){
public void setClientWorldData(ClientWorldData clientWorldData){ return cacheMap.get(getKey(worldX,worldY,worldZ));
this.clientWorldData = clientWorldData;
} }
} }

View File

@ -1,83 +0,0 @@
package electrosphere.client.terrain.cache;
import electrosphere.client.scene.ClientWorldData;
import electrosphere.game.terrain.processing.TerrainInterpolator;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author amaterasu
*/
public class LoadingChunk {
int worldX, worldY;
int totalNumMessages;
int numReceivedMessages = 0;
ClientWorldData clientWorldData;
float[][] macroValues;
long[][] randomizer;
List<ChunkModification> modification = new ArrayList<ChunkModification>();
public LoadingChunk(int worldX, int worldY, int numMessages, ClientWorldData clientWorldData){
this.worldX = worldX;
this.worldY = worldY;
this.totalNumMessages = numMessages;
this.clientWorldData = clientWorldData;
}
public void addMacroValues(float[][] macroValues){
this.macroValues = macroValues;
}
public void addRandomizer(long[][] randomizer){
this.randomizer = randomizer;
}
public void addModification(int worldX, int worldY, int locationX, int locationY, float value){
// System.out.println("Client add modification");
ChunkModification newModification = new ChunkModification(worldX, worldY, locationX, locationY, value);
modification.add(newModification);
}
public void incrementMessageCount(){
numReceivedMessages++;
}
public boolean isComplete(){
return numReceivedMessages >= totalNumMessages && macroValues != null && randomizer != null;
}
public float[][] exportFloats(){
float[][] heightmap = TerrainInterpolator.getBicubicInterpolatedChunk(
macroValues,
randomizer,
clientWorldData.getDynamicInterpolationRatio(),
clientWorldData.getRandomDampener()
);
if(modification != null){
for(ChunkModification modification : modification){
// System.out.println("Apply modification");
heightmap = modification.applyModification(heightmap);
}
}
return heightmap;
}
public int getWorldX() {
return worldX;
}
public int getWorldY() {
return worldY;
}
public ClientWorldData getClientWorldData(){
return this.clientWorldData;
}
}

View File

@ -1,50 +0,0 @@
package electrosphere.client.terrain.cache;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
/**
*
* @author amaterasu
*/
public class LoadingChunkCache {
Map<String,LoadingChunk> cacheMap = new ConcurrentHashMap<String,LoadingChunk>();
List<String> cacheList = new CopyOnWriteArrayList<String>();
public LoadingChunkCache(){
}
//USED TO ADD macro values
public void addLoadingChunkToCache(LoadingChunk chunk){
cacheMap.put(getKey(chunk.worldX, chunk.worldY),chunk);
}
public LoadingChunk fetch(String key){
return cacheMap.get(key);
}
public String getKey(int worldX, int worldY){
return worldX + "-" + worldY;
}
public boolean containsKey(String key){
return cacheMap.containsKey(key);
}
public Collection<LoadingChunk> getChunks(){
return cacheMap.values();
}
public void remove(LoadingChunk chunk){
cacheMap.remove(getKey(chunk.worldX,chunk.worldY));
cacheList.remove(getKey(chunk.worldX,chunk.worldY));
}
}

View File

@ -1,27 +0,0 @@
package electrosphere.client.terrain.cells;
import electrosphere.entity.Entity;
import java.util.LinkedList;
import java.util.List;
/**
*
* @author amaterasu
*/
public class ClientDataCell {
List<Entity> entities = new LinkedList<Entity>();
public ClientDataCell(){
}
public void addEntity(Entity e){
entities.add(e);
}
public void removeEntity(Entity e){
entities.remove(e);
}
}

View File

@ -1,12 +1,16 @@
package electrosphere.client.terrain.cells; package electrosphere.client.terrain.cells;
import electrosphere.client.terrain.cache.ChunkData;
import electrosphere.client.terrain.manager.ClientTerrainManager;
import electrosphere.collision.dispatch.CollisionObject; import electrosphere.collision.dispatch.CollisionObject;
import electrosphere.dynamics.RigidBody; import electrosphere.dynamics.RigidBody;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.entity.ClientEntityUtils;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityCreationUtils; import electrosphere.entity.EntityCreationUtils;
import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
import electrosphere.entity.types.terrain.TerrainChunk;
import electrosphere.game.collision.PhysicsUtils; import electrosphere.game.collision.PhysicsUtils;
import electrosphere.game.collision.collidable.Collidable; import electrosphere.game.collision.collidable.Collidable;
import electrosphere.game.terrain.processing.TerrainInterpolator; import electrosphere.game.terrain.processing.TerrainInterpolator;
@ -24,20 +28,19 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import org.joml.Quaternionf; import org.joml.Quaternionf;
import org.joml.Vector3d;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.joml.Vector3i;
/** /**
* *
* @author satellite * @author satellite
*/ */
public class DrawCell { public class DrawCell {
int cellX; //the position of the draw cell in world coordinates
int cellY; Vector3i worldPos;
float[][] heightmap; ChunkData data;
float[][] texturemap;
int dynamicInterpolationRatio;
Entity modelEntity; Entity modelEntity;
@ -64,31 +67,17 @@ public class DrawCell {
/** /**
* Catches for this function: drawArray's dimensions need to be equal to drawWidth and 1 greater than cellWidth * Constructs a drawcell object
* because the model creation code for terrain heightmaps sucks :D
* 06/03/2021
*
*
* ITS NOT EVEN UP TO DATE!
* 06/13/2021
*
* //@param drawArray
*/ */
public static DrawCell generateTerrainCell( public static DrawCell generateTerrainCell(
int cellX, Vector3i worldPos,
int cellY, ChunkData data,
float[][] heightmap,
float[][] texturemap,
int dynamicInterpolationRatio,
ShaderProgram program ShaderProgram program
){ ){
DrawCell rVal = new DrawCell(); DrawCell rVal = new DrawCell();
rVal.cellX = cellX; rVal.worldPos = worldPos;
rVal.cellY = cellY;
rVal.program = program; rVal.program = program;
rVal.dynamicInterpolationRatio = dynamicInterpolationRatio; rVal.data = data;
rVal.heightmap = heightmap;
rVal.texturemap = texturemap;
return rVal; return rVal;
} }
@ -96,52 +85,63 @@ public class DrawCell {
* Generates a drawable entity based on this chunk * Generates a drawable entity based on this chunk
* @param stride The stride between indices used to generate "sparse" meshes * @param stride The stride between indices used to generate "sparse" meshes
*/ */
public void generateDrawableEntity(int stride){ public void generateDrawableEntity(){
if(modelEntity != null){ if(modelEntity != null){
Globals.clientScene.deregisterEntity(modelEntity); Globals.clientScene.deregisterEntity(modelEntity);
} }
Model terrainModel = RenderUtils.createMinimizedTerrainModelPrecomputedShader(heightmap, texturemap, program, stride); modelEntity = TerrainChunk.clientCreateTerrainChunkEntity(data.getVoxelWeight(), data.getVoxelType());
Mesh terrainMesh = terrainModel.meshes.get(0); // TerrainChunk.createTerrainChunkEntity();
List<Texture> textureList = new LinkedList<Texture>(); // Model terrainModel = RenderUtils.createMinimizedTerrainModelPrecomputedShader(heightmap, texturemap, program, stride);
textureList.add(groundTextureOne); // Mesh terrainMesh = terrainModel.meshes.get(0);
textureList.add(groundTextureTwo); // List<Texture> textureList = new LinkedList<Texture>();
textureList.add(groundTextureThree); // textureList.add(groundTextureOne);
textureList.add(groundTextureFour); // textureList.add(groundTextureTwo);
List<String> uniformList = new LinkedList<String>(); // textureList.add(groundTextureThree);
uniformList.add("groundTextures[0]"); // textureList.add(groundTextureFour);
uniformList.add("groundTextures[1]"); // List<String> uniformList = new LinkedList<String>();
uniformList.add("groundTextures[2]"); // uniformList.add("groundTextures[0]");
uniformList.add("groundTextures[3]"); // uniformList.add("groundTextures[1]");
String terrainModelPath = Globals.assetManager.registerModel(terrainModel); // uniformList.add("groundTextures[2]");
modelEntity = EntityCreationUtils.createClientSpatialEntity(); // uniformList.add("groundTextures[3]");
EntityCreationUtils.makeEntityDrawable(modelEntity, terrainModelPath); // String terrainModelPath = Globals.assetManager.registerModel(terrainModel);
EntityUtils.getActor(modelEntity).addTextureMask(new ActorTextureMask("terrain",textureList,uniformList)); // modelEntity = EntityCreationUtils.createClientSpatialEntity();
modelEntity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true); // EntityCreationUtils.makeEntityDrawable(modelEntity, terrainModelPath);
modelEntity.putData(EntityDataStrings.DRAW_CAST_SHADOW, true); // EntityUtils.getActor(modelEntity).addTextureMask(new ActorTextureMask("terrain",textureList,uniformList));
LoggerInterface.loggerRenderer.INFO("New cell @ " + cellX * dynamicInterpolationRatio + "," + cellY * dynamicInterpolationRatio); // modelEntity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
EntityUtils.getPosition(modelEntity).set(new Vector3f(cellX * dynamicInterpolationRatio, 0.0f, cellY * dynamicInterpolationRatio)); // modelEntity.putData(EntityDataStrings.DRAW_CAST_SHADOW, true);
// LoggerInterface.loggerRenderer.INFO("New cell @ " + cellX * dynamicInterpolationRatio + "," + cellY * dynamicInterpolationRatio);
// EntityUtils.getPosition(modelEntity).set(getRealPos());
ClientEntityUtils.initiallyPositionEntity(modelEntity, getRealPos());
} }
public void retireCell(){ public void retireCell(){
EntityUtils.cleanUpEntity(modelEntity); EntityUtils.cleanUpEntity(modelEntity);
} }
public void generatePhysics(){ protected Vector3d getRealPos(){
//if we're in no-graphics mode, need to generate the entity return new Vector3d(
if(modelEntity == null){ worldPos.x * ChunkData.CHUNK_SIZE,
modelEntity = EntityCreationUtils.createClientSpatialEntity(); worldPos.y * ChunkData.CHUNK_SIZE,
modelEntity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true); worldPos.z * ChunkData.CHUNK_SIZE
EntityUtils.getPosition(modelEntity).set(new Vector3f(cellX * dynamicInterpolationRatio, 0.0f, cellY * dynamicInterpolationRatio)); );
}
//then actually perform the attach
physicsObject = PhysicsUtils.attachTerrainRigidBody(modelEntity,heightmap,false);
Globals.clientSceneWrapper.getCollisionEngine().registerPhysicsEntity(modelEntity);
// System.out.println("generate physics");
} }
public void destroyPhysics(){ // public void generatePhysics(){
Globals.clientSceneWrapper.getCollisionEngine().deregisterCollidableEntity(modelEntity); // //if we're in no-graphics mode, need to generate the entity
Globals.clientSceneWrapper.getCollisionEngine().deregisterRigidBody((RigidBody)physicsObject); // if(modelEntity == null){
} // modelEntity = EntityCreationUtils.createClientSpatialEntity();
// 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,false);
// Globals.clientSceneWrapper.getCollisionEngine().registerPhysicsEntity(modelEntity);
// // System.out.println("generate physics");
// }
// public void destroyPhysics(){
// Globals.clientSceneWrapper.getCollisionEngine().deregisterCollidableEntity(modelEntity);
// Globals.clientSceneWrapper.getCollisionEngine().deregisterRigidBody((RigidBody)physicsObject);
// }
} }

View File

@ -1,20 +1,25 @@
package electrosphere.client.terrain.cells; package electrosphere.client.terrain.cells;
import electrosphere.client.scene.ClientWorldData; import electrosphere.client.scene.ClientWorldData;
import electrosphere.client.terrain.cache.ChunkData;
import electrosphere.client.terrain.manager.ClientTerrainManager; import electrosphere.client.terrain.manager.ClientTerrainManager;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.entity.EntityUtils;
import electrosphere.game.terrain.processing.TerrainInterpolator; import electrosphere.game.terrain.processing.TerrainInterpolator;
import electrosphere.game.collision.CommonWorldData;
import electrosphere.net.parser.net.message.TerrainMessage; import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.renderer.ShaderProgram; import electrosphere.renderer.ShaderProgram;
import electrosphere.server.terrain.manager.ServerTerrainManager; import electrosphere.server.terrain.manager.ServerTerrainManager;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.joml.Vector2i; import org.joml.Vector2i;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.joml.Vector3i;
/** /**
* *
@ -26,41 +31,40 @@ public class DrawCellManager {
//the center of this cell manager's array in cell space //the center of this cell manager's array in cell space
int cellX; int cellX;
int cellY; int cellY;
int cellZ;
//the dimensions of the world that this cell manager can handles //the dimensions of the world that this cell manager can handles
int cellWidth; int cellWidth;
int cellHeight;
//the width of a minicell in this manager //the width of a minicell in this manager
int miniCellWidth; int miniCellWidth;
//all currently displaying mini cells //all currently displaying mini cells
DrawCell[][] cells; Set<DrawCell> cells;
boolean[][] valid; Map<String,DrawCell> keyCellMap = new HashMap<String,DrawCell>();
boolean[][] drawable; Set<String> hasNotRequested;
boolean[][] updateable; Set<String> hasRequested;
boolean[][] hasRequested; Set<String> drawable;
boolean[][] needsPhysics; Set<String> undrawable;
boolean[][] hasPhysics; Set<String> updateable;
ShaderProgram program; ShaderProgram program;
int drawRadius = 5; // int drawRadius = 5;
int drawStepdownInterval = 3; int drawStepdownInterval = 3;
int drawStepdownValue = 25; int drawStepdownValue = 25;
double drawRadius = 200;
int physicsRadius = 3; int physicsRadius = 3;
int worldBoundDiscreteMin = 0; int worldBoundDiscreteMin = 0;
int worldBoundDiscreteMax = 0; int worldBoundDiscreteMax = 0;
//metadata about the game world
CommonWorldData commonWorldData;
//client terrain manager //client terrain manager
// ClientTerrainManager clientTerrainManager; // ClientTerrainManager clientTerrainManager;
@ -80,600 +84,273 @@ public class DrawCellManager {
* @param discreteX The initial discrete position X coordinate * @param discreteX The initial discrete position X coordinate
* @param discreteY The initial discrete position Y coordinate * @param discreteY The initial discrete position Y coordinate
*/ */
public DrawCellManager(CommonWorldData commonWorldData, ClientTerrainManager clientTerrainManager, int discreteX, int discreteY){ public DrawCellManager(ClientTerrainManager clientTerrainManager, int discreteX, int discreteY, int discreteZ){
this.commonWorldData = commonWorldData; worldBoundDiscreteMax = (int)(Globals.clientWorldData.getWorldBoundMin().x / Globals.clientWorldData.getDynamicInterpolationRatio() * 1.0f);
worldBoundDiscreteMax = (int)(commonWorldData.getWorldBoundMin().x / commonWorldData.getDynamicInterpolationRatio() * 1.0f); cells = new HashSet<DrawCell>();
// this.clientTerrainManager = clientTerrainManager; hasNotRequested = new HashSet<String>();
cells = new DrawCell[drawRadius * 2 + 1][drawRadius * 2 + 1]; drawable = new HashSet<String>();
valid = new boolean[drawRadius * 2 + 1][drawRadius * 2 + 1]; undrawable = new HashSet<String>();
drawable = new boolean[drawRadius * 2 + 1][drawRadius * 2 + 1]; updateable = new HashSet<String>();
updateable = new boolean[drawRadius * 2 + 1][drawRadius * 2 + 1]; hasRequested = new HashSet<String>();
hasRequested = new boolean[drawRadius * 2 + 1][drawRadius * 2 + 1];
needsPhysics = new boolean[physicsRadius * 2 + 1][physicsRadius * 2 + 1];
hasPhysics = new boolean[physicsRadius * 2 + 1][physicsRadius * 2 + 1];
for(int x = 0; x < drawRadius * 2 + 1; x++){
for(int y = 0; y < drawRadius * 2 + 1; y++){
valid[x][y] = false;
drawable[x][y] = false;
updateable[x][y] = false;
hasRequested[x][y] = false;
}
}
for(int x = 0; x < physicsRadius * 2 + 1; x++){
for(int y = 0; y < physicsRadius * 2 + 1; y++){
needsPhysics[x][y] = true;
hasPhysics[x][y] = false;
}
}
cellX = discreteX; cellX = discreteX;
cellY = discreteY; cellY = discreteY;
cellZ = discreteZ;
program = Globals.terrainShaderProgram; program = Globals.terrainShaderProgram;
drawRadius = Globals.userSettings.getGraphicsPerformanceLODChunkRadius(); // drawRadius = Globals.userSettings.getGraphicsPerformanceLODChunkRadius();
drawStepdownInterval = Globals.userSettings.getGameplayPhysicsCellRadius(); drawStepdownInterval = Globals.userSettings.getGameplayPhysicsCellRadius();
physicsRadius = Globals.userSettings.getGameplayPhysicsCellRadius(); physicsRadius = Globals.userSettings.getGameplayPhysicsCellRadius();
invalidateAllCells();
update = true; update = true;
} }
DrawCellManager(){ DrawCellManager(){
} }
public int getCellX(){
return cellX;
}
public int getCellY(){
return cellY;
}
public void setCellX(int x){
cellX = x;
}
public void setCellY(int y){
cellY = y;
}
public void setCell(Vector2i cellPos){ public void setCell(Vector3i cellPos){
cellX = cellPos.x; cellX = cellPos.x;
cellY = cellPos.y; cellY = cellPos.y;
cellZ = cellPos.z;
} }
void updateInvalidCell(){ void updateUnrequestedCell(){
int targetX = 0; if(hasNotRequested.size() > 0){
int targetY = 0; String targetKey = hasNotRequested.iterator().next();
boolean found = false; hasNotRequested.remove(targetKey);
for(int x = 0; x < drawRadius * 2 + 1; x++){ Vector3i worldPos = getVectorFromKey(targetKey);
targetX = x; // Vector3i vector = getVectorFromKey(targetKey);
for(int y = 0; y < drawRadius * 2 + 1; y++){ // int currentCellX = cellX - drawRadius + vector.x;
targetY = y; // int currentCellY = cellY - drawRadius + vector.y;
if(!valid[x][y]){ // int currentCellZ = cellZ - drawRadius + vector.z;
found = true;
break;
}
}
if(found){
break;
}
}
if(found){
int currentCellX = cellX - drawRadius + targetX;
int currentCellY = cellY - drawRadius + targetY;
if( if(
currentCellX >= 0 && worldPos.x >= 0 &&
currentCellX < commonWorldData.getWorldDiscreteSize() && worldPos.x < Globals.clientWorldData.getWorldDiscreteSize() &&
currentCellY >= 0 && worldPos.y >= 0 &&
currentCellY < commonWorldData.getWorldDiscreteSize() worldPos.y < Globals.clientWorldData.getWorldDiscreteSize() &&
){ worldPos.z >= 0 &&
if(containsHeightmapAtDiscretePoint(currentCellX, currentCellY)){ worldPos.z < Globals.clientWorldData.getWorldDiscreteSize()
cells[targetX][targetY] = DrawCell.generateTerrainCell( ){
currentCellX, // if(!hasRequested.contains(targetKey)){
currentCellY, //client should request chunk data from server
getHeightmapAtPoint(currentCellX, currentCellY), Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestChunkDataMessage(
getTextureMapAtPoint(currentCellX, currentCellY), worldPos.x,
commonWorldData.getDynamicInterpolationRatio(), worldPos.y,
program worldPos.z
); ));
valid[targetX][targetY] = true; undrawable.add(targetKey);
drawable[targetX][targetY] = false; hasRequested.add(targetKey);
updateable[targetX][targetY] = false; // }
hasRequested[targetX][targetY] = false;
hasPhysics[targetX][targetY] = false;
needsPhysics[targetX][targetY] = true;
// if(Math.abs(physicsRadius + 1 - targetX) < physicsRadius && Math.abs(physicsRadius + 1 - targetY) < physicsRadius){
// needsPhysics[targetX][targetY] = true;
// }
} else {
if(hasRequested[targetX][targetY] == false){
//client should request macro values from server
Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestChunkMessage(currentCellX, currentCellY));
hasRequested[targetX][targetY] = true;
}
}
} else {
valid[targetX][targetY] = true;
drawable[targetX][targetY] = false;
updateable[targetX][targetY] = false;
hasRequested[targetX][targetY] = false;
hasPhysics[targetX][targetY] = false;
needsPhysics[targetX][targetY] = true;
} }
} }
} }
/**
* Makes one of the undrawable cells drawable
*/
void makeCellDrawable(){ void makeCellDrawable(){
int targetX = 0;
int targetY = 0;
boolean found = false;
for(int x = 0; x < drawRadius * 2 + 1; x++){
targetX = x;
for(int y = 0; y < drawRadius * 2 + 1; y++){
targetY = y;
if(valid[x][y] && !drawable[x][y]){
found = true;
break;
}
}
if(found){
break;
}
}
if(found){ if(undrawable.size() > 0){
int currentCellX = cellX - drawRadius + targetX; String targetKey = undrawable.iterator().next();
int currentCellY = cellY - drawRadius + targetY; Vector3i worldPos = getVectorFromKey(targetKey);
if( if(
currentCellX >= 0 && worldPos.x >= 0 &&
currentCellX < commonWorldData.getWorldDiscreteSize() && worldPos.x < Globals.clientWorldData.getWorldDiscreteSize() &&
currentCellY >= 0 && worldPos.y >= 0 &&
currentCellY < commonWorldData.getWorldDiscreteSize() worldPos.y < Globals.clientWorldData.getWorldDiscreteSize() &&
){ worldPos.z >= 0 &&
//physics radius calculation worldPos.z < Globals.clientWorldData.getWorldDiscreteSize()
// if(Math.abs(physicsRadius + 1 - targetX) < physicsRadius && Math.abs(physicsRadius + 1 - targetY) < physicsRadius){ ){
// needsPhysics[targetX][targetY] = true; if(containsChunkDataAtWorldPoint(worldPos.x, worldPos.y, worldPos.z)){
// } DrawCell cell = DrawCell.generateTerrainCell(
//calculation for stride worldPos,
int dist = (int)Math.sqrt((targetX - drawRadius)*(targetX - drawRadius) + (targetY - drawRadius) * (targetY - drawRadius));//Math.abs(targetX - drawRadius) * Math.abs(targetY - drawRadius); Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldPos.x, worldPos.y, worldPos.z),
int stride = Math.min(commonWorldData.getDynamicInterpolationRatio()/2, Math.max(1, dist / drawStepdownInterval * drawStepdownValue)); program
while(commonWorldData.getDynamicInterpolationRatio() % stride != 0){ );
stride = stride + 1; cells.add(cell);
keyCellMap.put(targetKey,cell);
// undrawable.add(targetKey);
undrawable.remove(targetKey);
drawable.add(targetKey);
//make drawable entity
keyCellMap.get(targetKey).generateDrawableEntity();
} }
//make drawable entity
cells[targetX][targetY].generateDrawableEntity(stride);
} }
drawable[targetX][targetY] = true;
} }
} }
/**
* Updates a cell that can be updated
*/
void updateCellModel(){ void updateCellModel(){
int targetX = 0; if(updateable.size() > 0){
int targetY = 0; String targetKey = updateable.iterator().next();
boolean found = false; updateable.remove(targetKey);
for(int x = 0; x < drawRadius * 2 + 1; x++){ Vector3i worldPos = getVectorFromKey(targetKey);
targetX = x;
for(int y = 0; y < drawRadius * 2 + 1; y++){
targetY = y;
if(updateable[x][y]){
found = true;
break;
}
}
if(found){
break;
}
}
if(found){
int currentCellX = cellX - drawRadius + targetX;
int currentCellY = cellY - drawRadius + targetY;
if( if(
currentCellX >= 0 && worldPos.x >= 0 &&
currentCellX < commonWorldData.getWorldDiscreteSize() && worldPos.x < Globals.clientWorldData.getWorldDiscreteSize() &&
currentCellY >= 0 && worldPos.y >= 0 &&
currentCellY < commonWorldData.getWorldDiscreteSize() worldPos.y < Globals.clientWorldData.getWorldDiscreteSize() &&
worldPos.z >= 0 &&
worldPos.z < Globals.clientWorldData.getWorldDiscreteSize()
){ ){
// if(Math.abs(drawRadius + 1 - targetX) < physicsRadius && Math.abs(drawRadius + 1 - targetY) < physicsRadius){ // if(Math.abs(drawRadius + 1 - targetX) < physicsRadius && Math.abs(drawRadius + 1 - targetY) < physicsRadius){
// needsPhysics[targetX][targetY] = true; // 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 dist = (int)Math.sqrt((targetX - drawRadius)*(targetX - drawRadius) + (targetY - drawRadius) * (targetY - drawRadius)); //Math.abs(targetX - drawRadius) * Math.abs(targetY - drawRadius);
int stride = Math.min(commonWorldData.getDynamicInterpolationRatio()/2, Math.max(1, dist / drawStepdownInterval * drawStepdownValue)); // int stride = Math.min(commonWorldData.getDynamicInterpolationRatio()/2, Math.max(1, dist / drawStepdownInterval * drawStepdownValue));
while(commonWorldData.getDynamicInterpolationRatio() % stride != 0){ // while(commonWorldData.getDynamicInterpolationRatio() % stride != 0){
stride = stride + 1; // stride = stride + 1;
} // }
cells[targetX][targetY].generateDrawableEntity(stride); keyCellMap.get(targetKey).generateDrawableEntity();
} }
updateable[targetX][targetY] = false; drawable.add(targetKey);
drawable[targetX][targetY] = true;
} }
} }
public boolean containsInvalidCell(){ public boolean containsUnrequestedCell(){
// if(DRAW_CELL_MANAGER_FLAG_UPDATE_DYNAMIC_TERRAIN){ return hasNotRequested.size() > 0;
for(int x = 0;x < drawRadius * 2 + 1; x++){
for(int y = 0; y < drawRadius * 2 + 1; y++){
if(!valid[x][y]){
return true;
}
}
}
// } else if(DRAW_CELL_MANAGER_FLAG_GENERATE_ARENA){
// return cells[0][0] == null || cells[1][0] == null || cells[0][1] == null | cells[1][1] == null;
// }
return false;
} }
public boolean containsUndrawableCell(){ public boolean containsUndrawableCell(){
for(int x = 0;x < drawRadius * 2 + 1; x++){ return undrawable.size() > 0;
for(int y = 0; y < drawRadius * 2 + 1; y++){
if(!drawable[x][y] && this.generateDrawables){
return true;
}
}
}
return false;
} }
public boolean containsUpdateableCell(){ public boolean containsUpdateableCell(){
for(int x = 0;x < drawRadius * 2 + 1; x++){ return updateable.size() > 0;
for(int y = 0; y < drawRadius * 2 + 1; y++){
if(updateable[x][y] && this.generateDrawables){
return true;
}
}
}
return false;
}
public boolean containsPhysicsNeedingCell(){
for(int x = 0; x < physicsRadius * 2 + 1; x++){
for(int y = 0; y < physicsRadius * 2 + 1; y++){
if(needsPhysics[x][y]){
return true;
}
}
}
return false;
}
public void addPhysicsToCell(){
int targetX = 0;
int targetY = 0;
boolean found = false;
for(int x = 0; x < physicsRadius * 2 + 1; x++){
targetX = x;
for(int y = 0; y < physicsRadius * 2 + 1; y++){
targetY = y;
// System.out.println(x + " <=>w " + y);
if(needsPhysics[x][y]){
found = true;
break;
}
}
if(found){
break;
}
}
if(found){
int currentCellX = cellX - physicsRadius + targetX;
int currentCellY = cellY - physicsRadius + targetY;
if(
currentCellX >= 0 &&
currentCellX < commonWorldData.getWorldDiscreteSize() &&
currentCellY >= 0 &&
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){
// stride = stride + 1;
// }
// if(cells[targetX][targetY + drawRadius] != null){
// System.out.println(targetX + " - " + targetY);
cells[targetX + drawRadius - physicsRadius][targetY + drawRadius - physicsRadius].generatePhysics();
// } else {
// System.out.println("Current cell is null: " + currentCellX + " - " + currentCellY);
// }
}
needsPhysics[targetX][targetY] = false;
hasPhysics[targetX][targetY] = true;
}
} }
public void shiftChunksNegX(){
//retire old graphics
for(int y = 0; y < drawRadius * 2 + 1; y++){
if(cells[drawRadius * 2][y] != null){
cells[drawRadius * 2][y].retireCell();
}
}
//shift draw array
for(int x = drawRadius * 2; x > 0; x--){
for(int y = 0; y < drawRadius * 2 + 1; y++){
cells[x][y] = cells[x-1][y];
updateable[x][y] = true;
hasRequested[x][y] = hasRequested[x-1][y];
}
}
//invalidate edge of draw array
for(int y = 0; y < drawRadius * 2 + 1; y++){
valid[0][y] = false;
hasRequested[0][y] = false;
}
//retire physics of cells
for(int x = 0; x < physicsRadius * 2 + 1; x++){
if(hasPhysics[x][physicsRadius * 2]){
if(cells[x + drawRadius - physicsRadius][physicsRadius * 2 + drawRadius - physicsRadius] != null){
cells[x + drawRadius - physicsRadius][physicsRadius * 2 + drawRadius - physicsRadius].destroyPhysics();
}
}
}
//shift physics array
for(int x = physicsRadius * 2; x > 0; x--){
for(int y = 0; y < physicsRadius * 2 + 1; y++){
needsPhysics[x][y] = needsPhysics[x-1][y];
hasPhysics[x][y] = hasPhysics[x-1][y];
}
}
//invalidate edge of physics array
for(int y = 0; y < physicsRadius * 2 + 1; y++){
needsPhysics[0][y] = true;
hasPhysics[0][y] = false;
}
}
public void shiftChunksPosX(){
//retire old graphics
for(int y = 0; y < drawRadius * 2 + 1; y++){
if(cells[0][y] != null){
cells[0][y].retireCell();
}
}
//shift draw array
for(int x = 0; x < drawRadius * 2; x++){
for(int y = 0; y < drawRadius * 2 + 1; y++){
cells[x][y] = cells[x+1][y];
updateable[x][y] = true;
hasRequested[x][y] = hasRequested[x+1][y];
}
}
//invalidate edge of draw array
for(int y = 0; y < drawRadius * 2 + 1; y++){
valid[drawRadius * 2][y] = false;
hasRequested[drawRadius * 2][y] = false;
}
//retire physics of cells
for(int x = 0; x < physicsRadius * 2 + 1; x++){
if(hasPhysics[x][physicsRadius * 2]){
if(cells[x + drawRadius - physicsRadius][physicsRadius * 2 + drawRadius - physicsRadius] != null){
cells[x + drawRadius - physicsRadius][physicsRadius * 2 + drawRadius - physicsRadius].destroyPhysics();
}
}
}
//shift physics array
for(int x = 0; x < physicsRadius * 2; x++){
for(int y = 0; y < physicsRadius * 2 + 1; y++){
needsPhysics[x][y] = needsPhysics[x+1][y];
hasPhysics[x][y] = hasPhysics[x+1][y];
}
}
//invalidate edge of physics array
for(int y = 0; y < physicsRadius * 2 + 1; y++){
needsPhysics[physicsRadius * 2][y] = true;
hasPhysics[physicsRadius * 2][y] = false;
}
}
public void shiftChunksNegY(){
//retire cells
for(int x = 0; x < drawRadius * 2 + 1; x++){
if(cells[x][drawRadius * 2] != null){
cells[x][drawRadius * 2].retireCell();
}
}
//shift draw array
for(int x = 0; x < drawRadius * 2 + 1; x++){
for(int y = drawRadius * 2; y > 0; y--){
cells[x][y] = cells[x][y-1];
updateable[x][y] = true;
hasRequested[x][y] = hasRequested[x][y-1];
}
}
//invalidate edge of draw array
for(int x = 0; x < drawRadius * 2 + 1; x++){
valid[x][0] = false;
hasRequested[x][0] = false;
}
//retire physics of cells
for(int x = 0; x < physicsRadius * 2 + 1; x++){
if(hasPhysics[x][physicsRadius * 2]){
if(cells[x + drawRadius - physicsRadius][physicsRadius * 2 + drawRadius - physicsRadius] != null){
cells[x + drawRadius - physicsRadius][physicsRadius * 2 + drawRadius - physicsRadius].destroyPhysics();
}
}
}
//shift physics array
for(int x = 0; x < physicsRadius * 2 + 1; x++){
for(int y = physicsRadius * 2; y > 0; y--){
needsPhysics[x][y] = needsPhysics[x][y-1];
hasPhysics[x][y] = hasPhysics[x][y-1];
}
}
//invalidate edge of physics array
for(int x = 0; x < physicsRadius * 2 + 1; x++){
needsPhysics[x][0] = true;
hasPhysics[x][0] = false;
}
}
public void shiftChunksPosY(){
//retire old graphics
for(int x = 0; x < drawRadius * 2 + 1; x++){
if(cells[x][0] != null){
cells[x][0].retireCell();
}
}
//shift draw array
for(int x = 0; x < drawRadius * 2 + 1; x++){
for(int y = 0; y < drawRadius * 2; y++){
cells[x][y] = cells[x][y+1];
updateable[x][y] = true;
hasRequested[x][y] = hasRequested[x][y+1];
}
}
//invalidate edge of draw array
for(int x = 0; x < drawRadius * 2 + 1; x++){
valid[x][drawRadius * 2] = false;
hasRequested[x][drawRadius * 2] = false;
}
//retire physics of cells
for(int x = 0; x < physicsRadius * 2 + 1; x++){
if(hasPhysics[x][0]){
if(cells[x + drawRadius - physicsRadius][0 + drawRadius - physicsRadius] != null){
cells[x + drawRadius - physicsRadius][0 + drawRadius - physicsRadius].destroyPhysics();
}
}
}
//shift physics array
for(int x = 0; x < physicsRadius * 2 + 1; x++){
for(int y = 0; y < physicsRadius * 2; y++){
needsPhysics[x][y] = needsPhysics[x][y+1];
hasPhysics[x][y] = hasPhysics[x][y+1];
}
}
//invalidate edge of physics array
for(int x = 0; x < physicsRadius * 2 + 1; x++){
needsPhysics[x][physicsRadius * 2] = true;
hasPhysics[x][physicsRadius * 2] = false;
}
}
public int transformRealSpaceToCellSpace(double input){ public int transformRealSpaceToCellSpace(double input){
return (int)(input / commonWorldData.getDynamicInterpolationRatio()); return (int)(input / Globals.clientWorldData.getDynamicInterpolationRatio());
} }
/**
* Clears the valid set and adds all keys to invalid set
*/
public void invalidateAllCells(){ public void invalidateAllCells(){
for(int x = 0; x < drawRadius * 2 + 1; x++){ drawable.clear();
for(int y = 0; y < drawRadius * 2 + 1; y++){ hasNotRequested.clear();
valid[x][y] = false; clearOutOfBoundsCells();
queueNewCells();
}
/**
* Calculates whether the position of the player has changed and if so, invalidates and cleans up cells accordingly
* @param position The position of the player entity on current frame
*/
public void calculateDeltas(Vector3d position){
//check if any not requested cells no longer need to be requested
clearOutOfBoundsCells();
//check if any cells should be added
queueNewCells();
}
/**
* Clears all cells outside of draw radius
*/
private void clearOutOfBoundsCells(){
Set<DrawCell> cellsToRemove = new HashSet<DrawCell>();
for(DrawCell cell : cells){
Vector3d realPos = cell.getRealPos();
if(Globals.playerEntity != null && EntityUtils.getPosition(Globals.playerEntity).distance(realPos) > drawRadius){
cellsToRemove.add(cell);
}
}
for(DrawCell cell : cellsToRemove){
cells.remove(cell);
String key = getCellKey(cell.worldPos.x, cell.worldPos.y, cell.worldPos.z);
hasNotRequested.remove(key);
drawable.remove(key);
undrawable.remove(key);
updateable.remove(key);
keyCellMap.remove(key);
hasRequested.remove(key);
}
}
/**
* Queues new cells that are in bounds but not currently accounted for
*/
private void queueNewCells(){
if(Globals.playerEntity != null && Globals.clientWorldData != null){
Vector3d playerPos = EntityUtils.getPosition(Globals.playerEntity);
for(int x = -(int)drawRadius; x < drawRadius; x = x + ChunkData.CHUNK_SIZE){
for(int y = -(int)drawRadius; y < drawRadius; y = y + ChunkData.CHUNK_SIZE){
for(int z = -(int)drawRadius; z < drawRadius; z = z + ChunkData.CHUNK_SIZE){
Vector3d newPos = new Vector3d(playerPos.x + x, playerPos.y + y, playerPos.z + z);
Vector3i worldPos = new Vector3i(
Globals.clientWorldData.convertRealToChunkSpace(newPos.x),
Globals.clientWorldData.convertRealToChunkSpace(newPos.y),
Globals.clientWorldData.convertRealToChunkSpace(newPos.z)
);
Vector3d chunkRealSpace = new Vector3d(
Globals.clientWorldData.convertChunkToRealSpace(worldPos.x),
Globals.clientWorldData.convertChunkToRealSpace(worldPos.y),
Globals.clientWorldData.convertChunkToRealSpace(worldPos.z)
);
if(
playerPos.distance(chunkRealSpace) < drawRadius &&
worldPos.x >= 0 &&
worldPos.x < Globals.clientWorldData.getWorldDiscreteSize() &&
worldPos.y >= 0 &&
worldPos.y < Globals.clientWorldData.getWorldDiscreteSize() &&
worldPos.z >= 0 &&
worldPos.z < Globals.clientWorldData.getWorldDiscreteSize()
){
String key = getCellKey(
Globals.clientWorldData.convertRealToChunkSpace(chunkRealSpace.x),
Globals.clientWorldData.convertRealToChunkSpace(chunkRealSpace.y),
Globals.clientWorldData.convertRealToChunkSpace(chunkRealSpace.z)
);
if(!keyCellMap.containsKey(key) && !hasNotRequested.contains(key) && !undrawable.contains(key) && !drawable.contains(key) &&
!hasRequested.contains(key)){
hasNotRequested.add(key);
}
}
}
}
} }
} }
} }
public void calculateDeltas(Vector3d oldPosition, Vector3d newPosition){ /**
// if(DRAW_CELL_MANAGER_FLAG_UPDATE_DYNAMIC_TERRAIN){ * Updates cells that need updating in this manager
if(transformRealSpaceToCellSpace(newPosition.x()) < transformRealSpaceToCellSpace(oldPosition.x())){ */
shiftChunksNegX();
setCellX(transformRealSpaceToCellSpace(newPosition.x()));
setCellY(transformRealSpaceToCellSpace(newPosition.z()));
} else if(transformRealSpaceToCellSpace(newPosition.x()) > transformRealSpaceToCellSpace(oldPosition.x())){
shiftChunksPosX();
setCellX(transformRealSpaceToCellSpace(newPosition.x()));
setCellY(transformRealSpaceToCellSpace(newPosition.z()));
}
if(transformRealSpaceToCellSpace(newPosition.z()) < transformRealSpaceToCellSpace(oldPosition.z())){
shiftChunksNegY();
setCellX(transformRealSpaceToCellSpace(newPosition.x()));
setCellY(transformRealSpaceToCellSpace(newPosition.z()));
} else if(transformRealSpaceToCellSpace(newPosition.z()) > transformRealSpaceToCellSpace(oldPosition.z())){
shiftChunksPosY();
setCellX(transformRealSpaceToCellSpace(newPosition.x()));
setCellY(transformRealSpaceToCellSpace(newPosition.z()));
}
// }
}
public void update(){ public void update(){
if(update){ if(update){
// if(DRAW_CELL_MANAGER_FLAG_UPDATE_DYNAMIC_TERRAIN){ if(containsUnrequestedCell() && !containsUndrawableCell()){
if(containsInvalidCell()){ updateUnrequestedCell();
updateInvalidCell();
} else if(containsUndrawableCell()){ } else if(containsUndrawableCell()){
makeCellDrawable(); makeCellDrawable();
} else if(containsUpdateableCell()){ } else if(containsUpdateableCell()){
updateCellModel(); updateCellModel();
} else if(containsPhysicsNeedingCell()){
addPhysicsToCell();
} }
} }
// } else if(DRAW_CELL_MANAGER_FLAG_GENERATE_ARENA){
// if(cells[0][0] == null){
// int arenaChunkWidth = 100;
// cells[0][0] = new DrawCell(
// new float[arenaChunkWidth + 1][arenaChunkWidth + 1],
// arenaChunkWidth + 1,
// 0,
// 0,
// arenaChunkWidth,
// program
// );
// cells[0][0].generateDrawableEntity(1);
// } else if(cells[0][1] == null){
// int arenaChunkWidth = 100;
// cells[0][1] = new DrawCell(
// new float[arenaChunkWidth + 1][arenaChunkWidth + 1],
// arenaChunkWidth + 1,
// 0,
// 1,
// arenaChunkWidth,
// program
// );
// cells[0][1].generateDrawableEntity(1);
// } else if(cells[1][0] == null){
// int arenaChunkWidth = 100;
// cells[1][0] = new DrawCell(
// new float[arenaChunkWidth + 1][arenaChunkWidth + 1],
// arenaChunkWidth + 1,
// 1,
// 0,
// arenaChunkWidth,
// program
// );
// cells[1][0].generateDrawableEntity(1);
// } else if(cells[1][1] == null){
// int arenaChunkWidth = 100;
// cells[1][1] = new DrawCell(
// new float[arenaChunkWidth + 1][arenaChunkWidth + 1],
// arenaChunkWidth + 1,
// 1,
// 1,
// arenaChunkWidth,
// program
// );
// cells[1][1].generateDrawableEntity(1);
// }
// }
}
// public float getElevationAtRealPoint(float realPointX, float realPointY){
//// if(DRAW_CELL_MANAGER_FLAG_UPDATE_DYNAMIC_TERRAIN){
// return terrainManager.getHeightAtPosition(realPointX, realPointY);
//// }
//// if(DRAW_CELL_MANAGER_FLAG_GENERATE_ARENA){
//// return 0;
//// }
//// return 0;
// }
public boolean canValidateCell(){
boolean rVal = false;
return rVal;
} }
/**
* Splits a cell key into its constituent coordinates in array format.
* @param cellKey The cell key to split
* @return The coordinates in array format
*/
// private int[] splitKeyToCoordinates(String cellKey){
// int[] rVal = new int[3];
// String[] components = cellKey.split("_");
// for(int i = 0; i < 3; i++){
// rVal[i] = Integer.parseInt(components[i]);
// }
// return rVal;
// }
public boolean coordsInPhysicsSpace(int worldX, int worldY){ public boolean coordsInPhysicsSpace(int worldX, int worldY){
return worldX <= cellX + physicsRadius && worldX >= cellX - physicsRadius && worldY <= cellY + physicsRadius && worldY >= cellY - physicsRadius; return worldX <= cellX + physicsRadius && worldX >= cellX - physicsRadius && worldY <= cellY + physicsRadius && worldY >= cellY - physicsRadius;
@ -683,38 +360,44 @@ public class DrawCellManager {
this.generateDrawables = generate; this.generateDrawables = generate;
} }
boolean containsHeightmapAtDiscretePoint(int currentCellX, int currentCellY){ boolean containsChunkDataAtWorldPoint(int worldX, int worldY, int worldZ){
if(Globals.clientTerrainManager != null){ if(Globals.clientTerrainManager != null){
return Globals.clientTerrainManager.containsHeightmapAtDiscretePoint(currentCellX, currentCellY); return Globals.clientTerrainManager.containsChunkDataAtWorldPoint(worldX,worldY,worldZ);
} }
return true; return true;
} }
float[][] getHeightmapAtPoint(int currentCellX, int currentCellY){ /**
if(Globals.clientTerrainManager != null){ * Gets the chunk data at a given point
return Globals.clientTerrainManager.getHeightmapAtPoint(currentCellX, currentCellY); * @param worldX The world position x component of the cell
} * @param worldY The world position y component of the cell
return Globals.serverTerrainManager.getChunk(currentCellX, currentCellY).getHeightMap(); * @param worldZ The world position z component of the cell
* @return The chunk data at the specified points
*/
ChunkData getChunkDataAtPoint(int worldX, int worldY, int worldZ){
return Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldX,worldY,worldZ);
} }
float[][] getTextureMapAtPoint(int currentCellX, int currentCellY){
if(Globals.clientTerrainManager != null){ /**
return Globals.clientTerrainManager.getTextureMapAtPoint(currentCellX,currentCellY); * Gets a unique key for the cell
} else { * @param worldX The world position x component of the cell
//hacky fix to +2 to this, I think the interpolation ratio was different for server/client data * @param worldY The world position y component of the cell
//now that we're merging/ambiguous within this class, it's out of bounds-ing unless I +2 * @param worldZ The world position z component of the cell
//TODO: investigate * @return The key
float[][] rVal = new float[commonWorldData.getDynamicInterpolationRatio() + 2][commonWorldData.getDynamicInterpolationRatio() + 2]; */
rVal[1][1] = 1; private String getCellKey(int worldX, int worldY, int worldZ){
rVal[2][1] = 1; return worldX + "_" + worldY + "_" + worldZ;
rVal[3][1] = 1; }
rVal[4][1] = 1;
rVal[5][1] = 1; /**
rVal[5][2] = 1; * Parses a vector3i from the cell key
rVal[6][1] = 1; * @param key The cell key
rVal[6][2] = 1; * @return The vector3i containing the components of the cell key
return rVal; */
} private Vector3i getVectorFromKey(String key){
String[] keyComponents = key.split("_");
return new Vector3i(Integer.parseInt(keyComponents[0]),Integer.parseInt(keyComponents[1]),Integer.parseInt(keyComponents[2]));
} }

View File

@ -1,27 +1,34 @@
package electrosphere.client.terrain.manager; package electrosphere.client.terrain.manager;
import electrosphere.client.scene.ClientWorldData; import electrosphere.client.scene.ClientWorldData;
import electrosphere.client.terrain.cache.ChunkData;
import electrosphere.client.terrain.cache.ClientTerrainCache; import electrosphere.client.terrain.cache.ClientTerrainCache;
import electrosphere.client.terrain.cache.LoadingChunk;
import electrosphere.client.terrain.cache.LoadingChunkCache;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.entity.types.terrain.TerrainChunkData; import electrosphere.entity.types.terrain.TerrainChunkData;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.TerrainMessage; import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.renderer.Model; import electrosphere.renderer.Model;
import electrosphere.renderer.meshgen.TerrainChunkModelGeneration; import electrosphere.renderer.meshgen.TerrainChunkModelGeneration;
import electrosphere.server.terrain.manager.ServerTerrainManager;
import java.util.Collections; import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
/**
* Manages terrain storage and access on the client
*/
public class ClientTerrainManager { public class ClientTerrainManager {
//queues messages from server //queues messages from server
List<TerrainMessage> messageQueue = new CopyOnWriteArrayList<TerrainMessage>(); List<TerrainMessage> messageQueue = new CopyOnWriteArrayList<TerrainMessage>();
//The interpolation ratio of terrain
public static final int INTERPOLATION_RATIO = ServerTerrainManager.SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO;
//caches chunks from server //caches chunks from server
static final int CACHE_SIZE = 50; static final int CACHE_SIZE = 50;
@ -29,18 +36,17 @@ public class ClientTerrainManager {
//used for caching the macro values //used for caching the macro values
ClientTerrainCache terrainCache; ClientTerrainCache terrainCache;
//used for caching loading chunks that are still streaming over the net //The world data for the client
LoadingChunkCache loadingChunkCache;
ClientWorldData clientWorldData; ClientWorldData clientWorldData;
//The queue of terrain chunk data to be buffered to gpu
static List<TerrainChunkGenQueueItem> terrainChunkGenerationQueue = new CopyOnWriteArrayList<TerrainChunkGenQueueItem>(); static List<TerrainChunkGenQueueItem> terrainChunkGenerationQueue = new CopyOnWriteArrayList<TerrainChunkGenQueueItem>();
/**
* Constructor
*/
public ClientTerrainManager(){ public ClientTerrainManager(){
terrainCache = new ClientTerrainCache(CACHE_SIZE); terrainCache = new ClientTerrainCache(CACHE_SIZE);
loadingChunkCache = new LoadingChunkCache();
} }
@ -49,89 +55,35 @@ public class ClientTerrainManager {
for(TerrainMessage message : messageQueue){ for(TerrainMessage message : messageQueue){
messageQueue.remove(message); messageQueue.remove(message);
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case MACROVALUE: case SENDCHUNKDATA: {
// terrainCache.addChunkValuesToCache(message.getlocationX(), message.getlocationY(), macroValues, randomizer); int[][][] values = new int[ChunkData.CHUNK_SIZE][ChunkData.CHUNK_SIZE][ChunkData.CHUNK_SIZE];
if(loadingChunkCache.containsKey(loadingChunkCache.getKey(message.getworldX(), message.getworldY()))){ float[][][] weights = new float[ChunkData.CHUNK_SIZE][ChunkData.CHUNK_SIZE][ChunkData.CHUNK_SIZE];
float[][] macroValues = new float[5][5]; ByteBuffer buffer = ByteBuffer.wrap(message.getchunkData());
long[][] randomizer = new long[5][5]; FloatBuffer floatBuffer = buffer.asFloatBuffer();
//macro values for(int x = 0; x < ChunkData.CHUNK_SIZE; x++){
macroValues[0][0] = message.getmacroValue00(); for(int y = 0; y < ChunkData.CHUNK_SIZE; y++){
macroValues[0][1] = message.getmacroValue01(); for(int z = 0; z < ChunkData.CHUNK_SIZE; z++){
macroValues[0][2] = message.getmacroValue02(); weights[x][y][z] = floatBuffer.get();
macroValues[0][3] = message.getmacroValue03(); }
macroValues[0][4] = message.getmacroValue04(); }
macroValues[1][0] = message.getmacroValue10();
macroValues[1][1] = message.getmacroValue11();
macroValues[1][2] = message.getmacroValue12();
macroValues[1][3] = message.getmacroValue13();
macroValues[1][4] = message.getmacroValue14();
macroValues[2][0] = message.getmacroValue20();
macroValues[2][1] = message.getmacroValue21();
macroValues[2][2] = message.getmacroValue22();
macroValues[2][3] = message.getmacroValue23();
macroValues[2][4] = message.getmacroValue24();
macroValues[3][0] = message.getmacroValue30();
macroValues[3][1] = message.getmacroValue31();
macroValues[3][2] = message.getmacroValue32();
macroValues[3][3] = message.getmacroValue33();
macroValues[3][4] = message.getmacroValue34();
macroValues[4][0] = message.getmacroValue40();
macroValues[4][1] = message.getmacroValue41();
macroValues[4][2] = message.getmacroValue42();
macroValues[4][3] = message.getmacroValue43();
macroValues[4][4] = message.getmacroValue44();
//randomizer
randomizer[0][0] = message.getrandomizerValue00();
randomizer[0][1] = message.getrandomizerValue01();
randomizer[0][2] = message.getrandomizerValue02();
randomizer[0][3] = message.getrandomizerValue03();
randomizer[0][4] = message.getrandomizerValue04();
randomizer[1][0] = message.getrandomizerValue10();
randomizer[1][1] = message.getrandomizerValue11();
randomizer[1][2] = message.getrandomizerValue12();
randomizer[1][3] = message.getrandomizerValue13();
randomizer[1][4] = message.getrandomizerValue14();
randomizer[2][0] = message.getrandomizerValue20();
randomizer[2][1] = message.getrandomizerValue21();
randomizer[2][2] = message.getrandomizerValue22();
randomizer[2][3] = message.getrandomizerValue23();
randomizer[2][4] = message.getrandomizerValue24();
randomizer[3][0] = message.getrandomizerValue30();
randomizer[3][1] = message.getrandomizerValue31();
randomizer[3][2] = message.getrandomizerValue32();
randomizer[3][3] = message.getrandomizerValue33();
randomizer[3][4] = message.getrandomizerValue34();
randomizer[4][0] = message.getrandomizerValue40();
randomizer[4][1] = message.getrandomizerValue41();
randomizer[4][2] = message.getrandomizerValue42();
randomizer[4][3] = message.getrandomizerValue43();
randomizer[4][4] = message.getrandomizerValue44();
LoadingChunk inProgressChunk = loadingChunkCache.fetch(loadingChunkCache.getKey(message.getworldX(), message.getworldY()));
inProgressChunk.addMacroValues(macroValues);
inProgressChunk.addRandomizer(randomizer);
inProgressChunk.incrementMessageCount();
} else {
bouncedMessages.add(message);
} }
break; IntBuffer intView = buffer.asIntBuffer();
case CHUNKLOADSTART: intView.position(floatBuffer.position());
if(clientWorldData != null){ for(int x = 0; x < ChunkData.CHUNK_SIZE; x++){
LoadingChunk newChunk = new LoadingChunk(message.getworldX(),message.getworldY(),(int)message.getvalue(),clientWorldData); for(int y = 0; y < ChunkData.CHUNK_SIZE; y++){
loadingChunkCache.addLoadingChunkToCache(newChunk); for(int z = 0; z < ChunkData.CHUNK_SIZE; z++){
newChunk.incrementMessageCount(); values[x][y][z] = intView.get();
} else { }
bouncedMessages.add(message); }
} }
break; ChunkData data = new ChunkData();
case HEIGHTMAPMODIFICATION: data.setVoxelType(values);
if(loadingChunkCache.containsKey(loadingChunkCache.getKey(message.getworldX(), message.getworldY()))){ data.setVoxelWeight(weights);
LoadingChunk inProgressChunk = loadingChunkCache.fetch(loadingChunkCache.getKey(message.getworldX(), message.getworldY())); terrainCache.addChunkDataToCache(
inProgressChunk.addModification(message.getworldX(), message.getworldZ(), message.getlocationX(), message.getlocationZ(), message.getvalue()); message.getworldX(), message.getworldY(), message.getworldZ(),
inProgressChunk.incrementMessageCount(); data
} else { );
bouncedMessages.add(message); } break;
}
break;
default: default:
LoggerInterface.loggerEngine.WARNING("ClientTerrainManager: unhandled network message of type" + message.getMessageSubtype()); LoggerInterface.loggerEngine.WARNING("ClientTerrainManager: unhandled network message of type" + message.getMessageSubtype());
break; break;
@ -146,88 +98,30 @@ public class ClientTerrainManager {
messageQueue.add(message); messageQueue.add(message);
} }
public boolean containsHeightmapAtDiscretePoint(int x, int y){ public boolean containsChunkDataAtWorldPoint(int worldX, int worldY, int worldZ){
return terrainCache.containsHeightmapAtChunkPoint(x, y); return terrainCache.containsChunkDataAtWorldPoint(worldX, worldY, worldZ);
} }
public boolean containsHeightmapAtRealPoint(double x, double z){ public boolean containsChunkDataAtRealPoint(double x, double y, double z){
assert clientWorldData != null; assert clientWorldData != null;
return terrainCache.containsHeightmapAtChunkPoint(clientWorldData.convertRealToChunkSpace(x), clientWorldData.convertRealToChunkSpace(z)); return terrainCache.containsChunkDataAtWorldPoint(
clientWorldData.convertRealToChunkSpace(x),
clientWorldData.convertRealToChunkSpace(y),
clientWorldData.convertRealToChunkSpace(z)
);
} }
public float[][] getHeightmapAtPoint(int x, int y){ public ChunkData getChunkDataAtWorldPoint(int worldX, int worldY, int worldZ){
return terrainCache.getHeightmapAtChunkPoint(x, y); return terrainCache.getSubChunkDataAtPoint(worldX, worldY, worldZ);
} }
public double getHeightAtPosition(double x, double y){
assert clientWorldData != null;
//get chunk coordinate space of input x,y
int chunkX = (int)Math.floor(x / clientWorldData.getDynamicInterpolationRatio());
int chunkY = (int)Math.floor(y / clientWorldData.getDynamicInterpolationRatio());
//get local coordinate space of input x,y
double localX = x - chunkX * clientWorldData.getDynamicInterpolationRatio();
double localY = y - chunkY * clientWorldData.getDynamicInterpolationRatio();
//get chunk elevation map
float[][] chunkElevationMap = getHeightmapAtPoint(chunkX,chunkY);
//floored variants of local values
int localXf = (int)Math.floor(localX);
int localYf = (int)Math.floor(localY);
/*
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 rVal;
}
public float[][] getTextureMapAtPoint(int x, int y){
assert clientWorldData != null;
float[][] rVal = new float[clientWorldData.getDynamicInterpolationRatio()][clientWorldData.getDynamicInterpolationRatio()];
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 void ejectLoadedChunks(){
if(clientWorldData != null){
List<LoadingChunk> chunksToEject = new LinkedList<LoadingChunk>();
for(LoadingChunk chunk : loadingChunkCache.getChunks()){
if(chunk.isComplete() && chunk.getClientWorldData() != null){
float[][] heightMap = chunk.exportFloats();
terrainCache.addFloatsToCache(chunk.getWorldX(), chunk.getWorldY(), heightMap);
chunksToEject.add(chunk);
}
}
for(LoadingChunk loadedChunk : chunksToEject){
loadingChunkCache.remove(loadedChunk);
}
}
}
/**
* Queues a terrain chunk to be pushed to GPU based on chunk data
* @param data The chunk data (triangles, normals, etc)
* @return The model path that is promised to eventually reflect the terrain model when it makes it to gpu
*/
public static String queueTerrainGridGeneration(TerrainChunkData data){ public static String queueTerrainGridGeneration(TerrainChunkData data){
String promisedHash = ""; String promisedHash = "";
UUID newUUID = UUID.randomUUID(); UUID newUUID = UUID.randomUUID();
@ -237,6 +131,9 @@ public class ClientTerrainManager {
return promisedHash; return promisedHash;
} }
/**
* Pushes all terrain data in queue to the gpu and registers the resulting models
*/
public static void generateTerrainChunkGeometry(){ public static void generateTerrainChunkGeometry(){
for(TerrainChunkGenQueueItem queueItem : terrainChunkGenerationQueue){ for(TerrainChunkGenQueueItem queueItem : terrainChunkGenerationQueue){
Model terrainModel = TerrainChunkModelGeneration.generateTerrainModel(queueItem.getData()); Model terrainModel = TerrainChunkModelGeneration.generateTerrainModel(queueItem.getData());
@ -244,14 +141,5 @@ public class ClientTerrainManager {
} }
terrainChunkGenerationQueue.clear(); terrainChunkGenerationQueue.clear();
} }
/**
* Sets the client world data that this terrain manager references
* @param clientWorldData The client world data
*/
public void setClientWorldData(ClientWorldData clientWorldData){
this.clientWorldData = clientWorldData;
this.terrainCache.setClientWorldData(clientWorldData);
}
} }

View File

@ -31,7 +31,7 @@ import electrosphere.entity.Entity;
import electrosphere.entity.Scene; import electrosphere.entity.Scene;
import electrosphere.entity.types.hitbox.HitboxManager; import electrosphere.entity.types.hitbox.HitboxManager;
import electrosphere.game.collision.CollisionEngine; import electrosphere.game.collision.CollisionEngine;
import electrosphere.game.collision.CommonWorldData; import electrosphere.game.collision.CollisionWorldData;
import electrosphere.game.config.UserSettings; import electrosphere.game.config.UserSettings;
import electrosphere.game.server.structure.virtual.StructureManager; import electrosphere.game.server.structure.virtual.StructureManager;
import electrosphere.game.server.world.MacroData; import electrosphere.game.server.world.MacroData;
@ -64,7 +64,6 @@ import electrosphere.server.ai.AIManager;
import electrosphere.server.datacell.EntityDataCellMapper; import electrosphere.server.datacell.EntityDataCellMapper;
import electrosphere.server.datacell.GriddedDataCellManager; import electrosphere.server.datacell.GriddedDataCellManager;
import electrosphere.server.datacell.RealmManager; import electrosphere.server.datacell.RealmManager;
import electrosphere.server.datacell.physics.DataCellPhysicsManager;
import electrosphere.server.db.DatabaseController; import electrosphere.server.db.DatabaseController;
import electrosphere.server.pathfinding.NavMeshManager; import electrosphere.server.pathfinding.NavMeshManager;
import electrosphere.server.simulation.MacroSimulation; import electrosphere.server.simulation.MacroSimulation;
@ -157,7 +156,6 @@ public class Globals {
public static ServerWorldData serverWorldData; public static ServerWorldData serverWorldData;
public static RealmManager realmManager; public static RealmManager realmManager;
public static EntityDataCellMapper entityDataCellMapper; public static EntityDataCellMapper entityDataCellMapper;
public static DataCellPhysicsManager dataCellPhysicsManager;
// //
//Player manager //Player manager
@ -299,7 +297,7 @@ public class Globals {
public static int openInventoriesCount = 0; public static int openInventoriesCount = 0;
//collision world data //collision world data
public static CommonWorldData commonWorldData; public static CollisionWorldData commonWorldData;
//structure manager //structure manager
public static StructureManager structureManager; public static StructureManager structureManager;

View File

@ -36,8 +36,6 @@ public class ArenaLoading {
LoadingUtils.initAuthenticationManager(); LoadingUtils.initAuthenticationManager();
//initialize the server thread (server only) //initialize the server thread (server only)
LoadingUtils.initServerThread(); LoadingUtils.initServerThread();
//collision engine
LoadingUtils.initCommonWorldData(Globals.RUN_SERVER);
//init gridded datacell manager //init gridded datacell manager
LoadingUtils.initGriddedRealm(); LoadingUtils.initGriddedRealm();
//initialize the "virtual" objects simulation //initialize the "virtual" objects simulation

View File

@ -75,10 +75,6 @@ public class ClientLoading {
loadingWindow.setVisible(true); loadingWindow.setVisible(true);
//disable menu input //disable menu input
Globals.controlHandler.setHandlerState(ControlHandler.ControlsState.NO_INPUT); Globals.controlHandler.setHandlerState(ControlHandler.ControlsState.NO_INPUT);
//collision engine
if(!Globals.RUN_SERVER){
LoadingUtils.initCommonWorldData(Globals.RUN_SERVER);
}
//initialize the "real" objects simulation //initialize the "real" objects simulation
initClientSimulation(); initClientSimulation();
//initialize the cell manager (client) //initialize the cell manager (client)
@ -212,14 +208,20 @@ public class ClientLoading {
} }
static void initDrawCellManager(){ static void initDrawCellManager(){
while(Globals.clientWorldData == null){
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException ex) {
}
}
//initialize draw cell manager //initialize draw cell manager
Globals.drawCellManager = new DrawCellManager(Globals.commonWorldData, Globals.clientTerrainManager, 0, 0); Globals.drawCellManager = new DrawCellManager(Globals.clientTerrainManager, 0, 0, 0);
//set our draw cell manager to actually generate drawable chunks //set our draw cell manager to actually generate drawable chunks
Globals.drawCellManager.setGenerateDrawables(true); Globals.drawCellManager.setGenerateDrawables(true);
//Alerts the client simulation that it should start loading terrain //Alerts the client simulation that it should start loading terrain
Globals.clientSimulation.setLoadingTerrain(true); Globals.clientSimulation.setLoadingTerrain(true);
//wait for all the terrain data to arrive //wait for all the terrain data to arrive
while(Globals.drawCellManager.containsInvalidCell()){ while(Globals.drawCellManager.containsUnrequestedCell()){
// Globals.drawCellManager.updateInvalidCell(); // Globals.drawCellManager.updateInvalidCell();
try { try {
TimeUnit.MILLISECONDS.sleep(10); TimeUnit.MILLISECONDS.sleep(10);
@ -237,12 +239,12 @@ public class ClientLoading {
// System.out.println("undrawable"); // System.out.println("undrawable");
} }
while(Globals.drawCellManager.containsPhysicsNeedingCell()){ // while(Globals.drawCellManager.containsPhysicsNeedingCell()){
try { // try {
TimeUnit.MILLISECONDS.sleep(10); // TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException ex) { // } catch (InterruptedException ex) {
} // }
} // }
// System.out.println("Draw Cell Manager ready"); // System.out.println("Draw Cell Manager ready");
} }

View File

@ -29,7 +29,7 @@ public class DebugSPWorldLoading {
WindowUtils.replaceMainMenuContents(MenuGenerators.createEmptyMainMenu()); WindowUtils.replaceMainMenuContents(MenuGenerators.createEmptyMainMenu());
loadingWindow.setVisible(true); loadingWindow.setVisible(true);
Globals.serverTerrainManager = new ServerTerrainManager(2000,50,100,0.0f,0); Globals.serverTerrainManager = new ServerTerrainManager(2000,50,ServerTerrainManager.SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO,0.0f,0);
if(!SaveUtils.getSaves().contains("random_sp_world")){ if(!SaveUtils.getSaves().contains("random_sp_world")){
// //
//the juicy server GENERATION part //the juicy server GENERATION part
@ -63,8 +63,6 @@ public class DebugSPWorldLoading {
LoadingUtils.initLocalConnection(); LoadingUtils.initLocalConnection();
//initialize the "real" objects simulation //initialize the "real" objects simulation
LoadingUtils.initMicroSimulation(); LoadingUtils.initMicroSimulation();
//collision engine
LoadingUtils.initCommonWorldData(Globals.RUN_SERVER);
//init game specific stuff (ie different skybox colors) //init game specific stuff (ie different skybox colors)
LoadingUtils.initGameGraphicalEntities(); LoadingUtils.initGameGraphicalEntities();
//set simulations to ready if they exist //set simulations to ready if they exist

View File

@ -20,7 +20,7 @@ import electrosphere.entity.ServerEntityUtils;
import electrosphere.entity.state.movement.ApplyRotationTree; import electrosphere.entity.state.movement.ApplyRotationTree;
import electrosphere.entity.types.creature.CreatureTemplate; import electrosphere.entity.types.creature.CreatureTemplate;
import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.game.collision.CommonWorldData; import electrosphere.game.collision.CollisionWorldData;
import electrosphere.game.data.creature.type.CreatureType; import electrosphere.game.data.creature.type.CreatureType;
import electrosphere.game.data.creature.type.visualattribute.VisualAttribute; import electrosphere.game.data.creature.type.visualattribute.VisualAttribute;
import electrosphere.game.server.town.Town; import electrosphere.game.server.town.Town;
@ -54,7 +54,7 @@ public class LoadingUtils {
Actually initialize the terrain manager Actually initialize the terrain manager
*/ */
float randomDampener = 0.0f; //0.25f; float randomDampener = 0.0f; //0.25f;
Globals.serverTerrainManager = new ServerTerrainManager(2000,50,100,randomDampener,0); Globals.serverTerrainManager = new ServerTerrainManager(2000,50,ServerTerrainManager.SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO,randomDampener,0);
if(Globals.RUN_SERVER){ if(Globals.RUN_SERVER){
if(Globals.userSettings.gameplayGenerateWorld()){ if(Globals.userSettings.gameplayGenerateWorld()){
Globals.serverTerrainManager.generate(); Globals.serverTerrainManager.generate();
@ -108,32 +108,32 @@ public class LoadingUtils {
Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager); Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager);
} }
static void initCommonWorldData(boolean FLAG_INIT_SERVER){ // static void initCommonWorldData(boolean FLAG_INIT_SERVER){
if(Globals.commonWorldData == null){ // if(Globals.commonWorldData == null){
if(FLAG_INIT_SERVER){ // if(FLAG_INIT_SERVER){
Globals.commonWorldData = new CommonWorldData(Globals.serverWorldData, Globals.serverTerrainManager); // Globals.commonWorldData = new CommonWorldData(Globals.serverWorldData, Globals.serverTerrainManager);
if(Globals.macroSimulation != null){ // if(Globals.macroSimulation != null){
Town startTown = Globals.macroData.getTowns().get(0); // Town startTown = Globals.macroData.getTowns().get(0);
Vector2i firstPos = startTown.getPositions().get(0); // Vector2i firstPos = startTown.getPositions().get(0);
// double startX = firstPos.x * Globals.serverTerrainManager.getChunkWidth(); // // double startX = firstPos.x * Globals.serverTerrainManager.getChunkWidth();
// double startZ = firstPos.y * Globals.serverTerrainManager.getChunkWidth(); // // double startZ = firstPos.y * Globals.serverTerrainManager.getChunkWidth();
double startX = Globals.commonWorldData.convertWorldToReal(firstPos.x); // double startX = Globals.commonWorldData.convertWorldToReal(firstPos.x);
double startZ = Globals.commonWorldData.convertWorldToReal(firstPos.y); // double startZ = Globals.commonWorldData.convertWorldToReal(firstPos.y);
Globals.spawnPoint.set((float)startX,(float)Globals.commonWorldData.getElevationAtPoint(new Vector3d(startX,0,startZ)),(float)startZ); // Globals.spawnPoint.set((float)startX,(float)Globals.commonWorldData.getElevationAtPoint(new Vector3d(startX,0,startZ)),(float)startZ);
} // }
} else { // } else {
//basically wait for the client to receive the world metadata // //basically wait for the client to receive the world metadata
while(!Globals.clientConnection.getClientProtocol().hasReceivedWorld()){ // while(!Globals.clientConnection.getClientProtocol().hasReceivedWorld()){
try { // try {
TimeUnit.MILLISECONDS.sleep(5); // TimeUnit.MILLISECONDS.sleep(5);
} catch (InterruptedException ex) { // } catch (InterruptedException ex) {
} // }
} // }
//then create common world data // //then create common world data
Globals.commonWorldData = new CommonWorldData(Globals.clientWorldData, Globals.clientTerrainManager); // Globals.commonWorldData = new CommonWorldData(Globals.clientWorldData, Globals.clientTerrainManager);
} // }
} // }
} // }

View File

@ -15,7 +15,7 @@ public class ServerLoading {
// } // }
//TODO: Globals.serverTerrainManager = new ServerTerrainManager(2000,50,100,randomDampener,0); //TODO: Globals.serverTerrainManager = new ServerTerrainManager(2000,50,100,randomDampener,0);
Globals.serverTerrainManager = new ServerTerrainManager(2000,50,100,0.0f,0); Globals.serverTerrainManager = new ServerTerrainManager(2000,50,ServerTerrainManager.SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO,0.0f,0);
SaveUtils.loadSave(Globals.currentSaveName); SaveUtils.loadSave(Globals.currentSaveName);
// LoadingUtils.initTerrainDataCellManager(); // LoadingUtils.initTerrainDataCellManager();
//TODO: set spawnpoint //TODO: set spawnpoint
@ -32,8 +32,6 @@ public class ServerLoading {
LoadingUtils.initMacroSimulation(); LoadingUtils.initMacroSimulation();
//initialize the "real" objects simulation //initialize the "real" objects simulation
LoadingUtils.initMicroSimulation(); LoadingUtils.initMicroSimulation();
//collision engine
LoadingUtils.initCommonWorldData(Globals.RUN_SERVER);
//init game specific stuff (ie different skybox colors) //init game specific stuff (ie different skybox colors)
LoadingUtils.initGameGraphicalEntities(); LoadingUtils.initGameGraphicalEntities();
//set simulations to ready if they exist //set simulations to ready if they exist

View File

@ -103,4 +103,20 @@ public class EntityCreationUtils {
Globals.clientScene.registerEntityToTag(entity, EntityTags.DRAWABLE); Globals.clientScene.registerEntityToTag(entity, EntityTags.DRAWABLE);
} }
/**
* MAkes an already created entity a drawable entity (client only) by backing it with an Actor
* @param entity The entity
* @param modelPath The model path for the model to back the actor
*/
public static void makeEntityDrawablePreexistingModel(Entity entity, String modelPath){
entity.putData(EntityDataStrings.DATA_STRING_ACTOR, ActorUtils.createActorOfLoadingModel(modelPath));
entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
entity.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaternionf().identity());
entity.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(1,1,1));
entity.putData(EntityDataStrings.DATA_STRING_DRAW, true);
entity.putData(EntityDataStrings.DRAW_SOLID_PASS, true);
Globals.clientScene.registerEntity(entity);
Globals.clientScene.registerEntityToTag(entity, EntityTags.DRAWABLE);
}
} }

View File

@ -136,6 +136,11 @@ public class EntityUtils {
if(Globals.realmManager != null){ if(Globals.realmManager != null){
Realm realm = Globals.realmManager.getEntityRealm(e); Realm realm = Globals.realmManager.getEntityRealm(e);
if(realm != null){ if(realm != null){
//get data cell
ServerDataCell dataCell = realm.getEntityDataCellMapper().getEntityDataCell(e);
if(dataCell != null){
dataCell.getScene().deregisterEntity(e);
}
realm.getEntityDataCellMapper().ejectEntity(e); realm.getEntityDataCellMapper().ejectEntity(e);
} }
Globals.realmManager.removeEntity(e); Globals.realmManager.removeEntity(e);

View File

@ -44,9 +44,9 @@ public class ServerEntityUtils {
public static void repositionEntity(Entity entity, Vector3d position){ public static void repositionEntity(Entity entity, Vector3d position){
Realm realm = Globals.realmManager.getEntityRealm(entity); Realm realm = Globals.realmManager.getEntityRealm(entity);
//if server, get current server data cell //if server, get current server data cell
if(Globals.RUN_SERVER){ ServerDataCell oldDataCell = realm.getDataCellManager().getDataCellAtPoint(EntityUtils.getPosition(entity));
ServerDataCell oldDataCell = realm.getDataCellManager().getDataCellAtPoint(EntityUtils.getPosition(entity)); ServerDataCell newDataCell = realm.getDataCellManager().getDataCellAtPoint(position);
ServerDataCell newDataCell = realm.getDataCellManager().getDataCellAtPoint(position); if(oldDataCell != newDataCell){
if(newDataCell != null){ if(newDataCell != null){
ServerDataCell.moveEntityFromCellToCell(entity, oldDataCell, newDataCell); ServerDataCell.moveEntityFromCellToCell(entity, oldDataCell, newDataCell);
ServerBehaviorTreeUtils.updateCell(entity, oldDataCell); ServerBehaviorTreeUtils.updateCell(entity, oldDataCell);
@ -58,13 +58,13 @@ public class ServerEntityUtils {
ServerBehaviorTreeUtils.updateCell(entity, oldDataCell); ServerBehaviorTreeUtils.updateCell(entity, oldDataCell);
} }
} }
// //if the server is also a client, update the drawcell manager to know to pull new chunks
// if(Globals.RUN_CLIENT){
// Globals.drawCellManager.invalidateAllCells();
// Globals.drawCellManager.setCellX(Globals.clientPlayerData.getWorldPos().x);
// Globals.drawCellManager.setCellY(Globals.clientPlayerData.getWorldPos().z);
// }
} }
// //if the server is also a client, update the drawcell manager to know to pull new chunks
// if(Globals.RUN_CLIENT){
// Globals.drawCellManager.invalidateAllCells();
// Globals.drawCellManager.setCellX(Globals.clientPlayerData.getWorldPos().x);
// Globals.drawCellManager.setCellY(Globals.clientPlayerData.getWorldPos().z);
// }
//reposition entity //reposition entity
CollisionObjUtils.positionCharacter(entity, Globals.spawnPoint); CollisionObjUtils.positionCharacter(entity, Globals.spawnPoint);
} }

View File

@ -71,7 +71,7 @@ public class ServerCollidableTree implements BehaviorTree {
Vector3d impulseForce = new Vector3d(impulse.getDirection()).mul(impulse.getForce()); Vector3d impulseForce = new Vector3d(impulse.getDirection()).mul(impulse.getForce());
if(impulse.type.matches(Collidable.TYPE_TERRAIN)){ if(impulse.type.matches(Collidable.TYPE_TERRAIN)){
hitTerrain = true; hitTerrain = true;
// System.out.println("Impulse force: " + impulseForce); // System.out.println("Impulse force: " + impulseForce);
// System.out.println("Position: " + position); // System.out.println("Position: " + position);
} }
if(impulse.type.matches(Collidable.TYPE_ITEM)){ if(impulse.type.matches(Collidable.TYPE_ITEM)){

View File

@ -12,11 +12,8 @@ import electrosphere.engine.Globals;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.BehaviorTree; import electrosphere.entity.state.BehaviorTree;
import electrosphere.entity.state.collidable.ClientCollidableTree;
import electrosphere.entity.state.collidable.Impulse; import electrosphere.entity.state.collidable.Impulse;
import electrosphere.entity.state.collidable.ServerCollidableTree; import electrosphere.entity.state.collidable.ServerCollidableTree;
import electrosphere.entity.state.movement.FallTree;
import electrosphere.entity.state.movement.JumpTree;
import electrosphere.entity.state.movement.ServerFallTree; import electrosphere.entity.state.movement.ServerFallTree;
import electrosphere.entity.state.movement.ServerJumpTree; import electrosphere.entity.state.movement.ServerJumpTree;
import electrosphere.game.collision.collidable.Collidable; import electrosphere.game.collision.collidable.Collidable;
@ -212,6 +209,7 @@ public class ServerGravityTree implements BehaviorTree {
boolean rVal = false; boolean rVal = false;
for(Impulse impulse : collidable.getImpulses()){ for(Impulse impulse : collidable.getImpulses()){
if(impulse.getType().equals(Collidable.TYPE_TERRAIN)){ if(impulse.getType().equals(Collidable.TYPE_TERRAIN)){
System.out.println(rVal);
rVal = true; rVal = true;
break; break;
} else if( } else if(

View File

@ -496,6 +496,7 @@ public class CreatureUtils {
*/ */
public static Entity serverSpawnBasicCreature(Realm realm, Vector3d position, String type, CreatureTemplate template){ public static Entity serverSpawnBasicCreature(Realm realm, Vector3d position, String type, CreatureTemplate template){
CreatureType rawType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(type); CreatureType rawType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(type);
System.out.println("Creature");
Entity rVal = EntityCreationUtils.createServerEntity(realm, position); Entity rVal = EntityCreationUtils.createServerEntity(realm, position);
EntityCreationUtils.makeEntityPoseable(rVal, rawType.getModelPath()); EntityCreationUtils.makeEntityPoseable(rVal, rawType.getModelPath());

View File

@ -285,46 +285,49 @@ public class HitboxUtils {
Entity generatorParent = (Entity)generatorHitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT); Entity generatorParent = (Entity)generatorHitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT);
Realm generatorRealm = Globals.realmManager.getEntityRealm(generatorParent); Realm generatorRealm = Globals.realmManager.getEntityRealm(generatorParent);
HitboxManager realmHitboxManager = generatorRealm.getHitboxManager(); if(generatorRealm != null){
HitboxManager realmHitboxManager = generatorRealm.getHitboxManager();
for(Entity receiverHitbox : realmHitboxManager.getAllHitboxes()){ for(Entity receiverHitbox : realmHitboxManager.getAllHitboxes()){
Entity receiverParent = (Entity)receiverHitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT);
HitboxData generatorData = getHitboxData(generatorHitbox);
HitboxData receiverData = getHitboxData(receiverHitbox);
//check projectile filters
List<Entity> generatorFilter = generatorData.getEntityFilter();
if(generatorFilter != null && generatorFilter.contains(receiverParent)){
continue;
}
List<Entity> receiverFilter = receiverData.getEntityFilter();
if(receiverFilter != null && receiverFilter.contains(generatorParent)){
continue;
}
//if there is a collision
//and the collision isn't against itself
//and both hitboxes are active
if(
receiverParent != generatorParent &&
generatorRealm.getCollisionEngine().collisionSphereCheck(generatorHitbox, generatorData, receiverHitbox, receiverData) &&
generatorData.isActive() &&
receiverData.isActive()){
//if two spheres collide, grab their hitbox types (eg hurt, hit, fire, etc)
String generatorType = generatorData.getType();
String receiverType = receiverData.getType();
if(generatorType.equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT) && receiverType.equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT)){ Entity receiverParent = (Entity)receiverHitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT);
serverDamageHitboxColision(generatorHitbox, receiverHitbox);
HitboxData generatorData = getHitboxData(generatorHitbox);
HitboxData receiverData = getHitboxData(receiverHitbox);
//check projectile filters
List<Entity> generatorFilter = generatorData.getEntityFilter();
if(generatorFilter != null && generatorFilter.contains(receiverParent)){
continue;
}
List<Entity> receiverFilter = receiverData.getEntityFilter();
if(receiverFilter != null && receiverFilter.contains(generatorParent)){
continue;
} }
if(generatorType.equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT) && receiverType.equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT)){ //if there is a collision
serverDamageHitboxColision(receiverHitbox, generatorHitbox); //and the collision isn't against itself
//and both hitboxes are active
if(
receiverParent != generatorParent &&
generatorRealm.getCollisionEngine().collisionSphereCheck(generatorHitbox, generatorData, receiverHitbox, receiverData) &&
generatorData.isActive() &&
receiverData.isActive()){
//if two spheres collide, grab their hitbox types (eg hurt, hit, fire, etc)
String generatorType = generatorData.getType();
String receiverType = receiverData.getType();
if(generatorType.equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT) && receiverType.equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT)){
serverDamageHitboxColision(generatorHitbox, receiverHitbox);
}
if(generatorType.equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT) && receiverType.equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT)){
serverDamageHitboxColision(receiverHitbox, generatorHitbox);
}
} }
} }
} }
} }

View File

@ -1,171 +1,68 @@
package electrosphere.entity.types.terrain; package electrosphere.entity.types.terrain;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector3f;
import electrosphere.client.terrain.manager.ClientTerrainManager; import electrosphere.client.terrain.manager.ClientTerrainManager;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityCreationUtils; import electrosphere.entity.EntityCreationUtils;
import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.ServerEntityUtils; import electrosphere.entity.ServerEntityUtils;
import electrosphere.game.collision.PhysicsUtils; import electrosphere.game.collision.PhysicsUtils;
import electrosphere.renderer.Model;
import electrosphere.renderer.meshgen.TerrainChunkModelGeneration; import electrosphere.renderer.meshgen.TerrainChunkModelGeneration;
import electrosphere.server.datacell.Realm;
/**
* Utilities for creating terrain chunk entities
*/
public class TerrainChunk { public class TerrainChunk {
public static Entity createTerrainChunkEntity(){ /**
* Creates a client terrain chunk based on weights and values provided
float[][][] terrainGrid = new float[][][]{ * @param weights The terrain weights
//plane 1 * @param values The values (block types)
{ * @return The terrain chunk entity
//row 1 */
{1.0f,1.0f,-1.0f,-1.0f,-1.0f,}, public static Entity clientCreateTerrainChunkEntity(float[][][] weights, int[][][] values){
//row 2
{-1.0f,1.0f,-1.0f,-1.0f,-1.0f,},
//row 3
{-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,},
//row 4
{-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,},
//row 5
{-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,},
},
//plane 2
{
//row 1
{-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,},
//row 2
{-1.0f,0.3f,0.6f,0.3f,-1.0f,},
//row 3
{-1.0f,0.6f,1.0f,0.6f,-1.0f,},
//row 4
{-1.0f,0.3f,0.6f,0.3f,-1.0f,},
//row 5
{-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,},
},
//plane 3
{
//row 1
{-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,},
//row 2
{-1.0f,0.7f,1.0f,0.7f,-1.0f,},
//row 3
{-1.0f,1.0f,1.0f,1.0f,-1.0f,},
//row 4
{-1.0f,0.7f,1.0f,0.7f,-1.0f,},
//row 5
{-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,},
},
//plane 4
{
//row 1
{-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,},
//row 2
{-1.0f,0.3f,0.6f,0.3f,-1.0f,},
//row 3
{-1.0f,0.6f,1.0f,0.6f,-1.0f,},
//row 4
{-1.0f,0.3f,0.6f,0.3f,-1.0f,},
//row 5
{-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,},
},
//plane 5
{
//row 1
{-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,},
//row 2
{-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,},
//row 3
{-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,},
//row 4
{-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,},
//row 5
{-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,},
},
};
int[][][] textureGrid = new int[][][]{
//plane 1
{
//row 1
{0, 0, 0, 0, 0},
//row 2
{0, 0, 0, 0, 0},
//row 3
{0, 0, 0, 0, 0},
//row 4
{0, 0, 0, 0, 0},
//row 5
{0, 0, 0, 0, 0},
},
//plane 2
{
//row 1
{0, 0, 0, 0, 0},
//row 2
{0, 0, 0, 0, 0},
//row 3
{0, 0, 0, 0, 0},
//row 4
{0, 0, 0, 0, 0},
//row 5
{0, 0, 0, 0, 0},
},
//plane 3
{
//row 1
{0, 0, 0, 0, 0},
//row 2
{0, 0, 0, 0, 0},
//row 3
{0, 0, 0, 0, 0},
//row 4
{0, 0, 0, 0, 0},
//row 5
{0, 0, 0, 0, 0},
},
//plane 4
{
//row 1
{0, 0, 0, 0, 0},
//row 2
{0, 0, 0, 0, 0},
//row 3
{0, 0, 0, 0, 0},
//row 4
{0, 0, 0, 0, 0},
//row 5
{0, 0, 0, 0, 0},
},
//plane 5
{
//row 1
{0, 0, 0, 0, 0},
//row 2
{0, 0, 0, 0, 0},
//row 3
{0, 0, 0, 0, 0},
//row 4
{0, 0, 0, 0, 0},
//row 5
{0, 0, 0, 0, 0},
},
};
TerrainChunkData data = TerrainChunkModelGeneration.generateTerrainChunkData(terrainGrid, textureGrid); TerrainChunkData data = TerrainChunkModelGeneration.generateTerrainChunkData(weights, values);
String modelPath = ClientTerrainManager.queueTerrainGridGeneration(data); String modelPath = ClientTerrainManager.queueTerrainGridGeneration(data);
Entity rVal = EntityCreationUtils.createClientSpatialEntity(); Entity rVal = EntityCreationUtils.createClientSpatialEntity();
EntityCreationUtils.makeEntityDrawable(rVal, modelPath); EntityCreationUtils.makeEntityDrawablePreexistingModel(rVal, modelPath);
// Entity rVal = EntityUtils.spawnDrawableEntityWithPreexistingModel(modelPath); if(data.vertices.size() > 0){
PhysicsUtils.clientAttachTerrainChunkRigidBody(rVal, data); PhysicsUtils.clientAttachTerrainChunkRigidBody(rVal, data);
}
rVal.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
rVal.putData(EntityDataStrings.DRAW_CAST_SHADOW, true); rVal.putData(EntityDataStrings.DRAW_CAST_SHADOW, true);
ServerEntityUtils.repositionEntity(rVal, new Vector3d(1,-1,1)); return rVal;
}
/**
* Creates a terrain chunk entity on the server
* @param realm The realm
* @param position The position of the chunk
* @param weights The weights for the terrain chunk
* @param values The values of each voxel in the chunk
* @return The terrain entity
*/
public static Entity serverCreateTerrainChunkEntity(Realm realm, Vector3d position, float[][][] weights, int[][][] values){
TerrainChunkData data = TerrainChunkModelGeneration.generateTerrainChunkData(weights, values);
Entity rVal = EntityCreationUtils.createServerEntity(realm, position);
if(data.vertices.size() > 0){
PhysicsUtils.serverAttachTerrainChunkRigidBody(rVal, data);
rVal.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
ServerEntityUtils.initiallyPositionEntity(realm, rVal, position);
// physicsObject = PhysicsUtils.attachTerrainRigidBody(physicsEntity,heightmap,true);
// Realm realm = Globals.realmManager.getEntityRealm(physicsEntity);
// realm.getCollisionEngine().registerPhysicsEntity(physicsEntity);
}
return rVal; return rVal;
} }

View File

@ -1,6 +1,7 @@
package electrosphere.game.collision; package electrosphere.game.collision;
import electrosphere.collision.dispatch.CollisionWorld.ClosestConvexResultCallback; import electrosphere.collision.dispatch.CollisionWorld.ClosestConvexResultCallback;
import electrosphere.collision.dispatch.CollisionWorld.ConvexResultCallback;
import electrosphere.collision.dispatch.CollisionWorld.LocalConvexResult; import electrosphere.collision.dispatch.CollisionWorld.LocalConvexResult;
import electrosphere.collision.broadphase.BroadphaseInterface; import electrosphere.collision.broadphase.BroadphaseInterface;
import electrosphere.collision.broadphase.BroadphasePair; import electrosphere.collision.broadphase.BroadphasePair;
@ -38,10 +39,13 @@ import org.joml.Vector3f;
/** /**
* *
* @author amaterasu * TODO: https://stackoverflow.com/questions/32445679/3d-java-collision-detection-with-jbullet
*/ */
public class CollisionEngine { public class CollisionEngine {
//world data that the collision engine leverages for position correction and the like
CollisionWorldData collisionWorldData;
DiscreteDynamicsWorld world; DiscreteDynamicsWorld world;
SequentialImpulseConstraintSolver solver; SequentialImpulseConstraintSolver solver;
BroadphaseInterface broadphase; BroadphaseInterface broadphase;
@ -211,16 +215,16 @@ public class CollisionEngine {
* @param positionToCheck the position that it wants to move to * @param positionToCheck the position that it wants to move to
* @return true if it can occupy that position, false otherwise * @return true if it can occupy that position, false otherwise
*/ */
public boolean checkCanOccupyPosition(CommonWorldData w, Entity e, Vector3d positionToCheck){ public boolean checkCanOccupyPosition(CollisionWorldData w, Entity e, Vector3d positionToCheck){
boolean rVal = true; boolean rVal = true;
// //
// check world bounds // check world bounds
// //
if( if(
positionToCheck.x < w.getWorldBoundMin().x || positionToCheck.x < collisionWorldData.getWorldBoundMin().x ||
positionToCheck.z < w.getWorldBoundMin().z || positionToCheck.z < collisionWorldData.getWorldBoundMin().z ||
positionToCheck.x > w.getWorldBoundMax().x || positionToCheck.x > collisionWorldData.getWorldBoundMax().x ||
positionToCheck.z > w.getWorldBoundMax().z positionToCheck.z > collisionWorldData.getWorldBoundMax().z
){ ){
return false; return false;
} }
@ -246,7 +250,7 @@ public class CollisionEngine {
* @return the position the engine recommends it move to instead (this is * @return the position the engine recommends it move to instead (this is
* guaranteed to be a valid position) * guaranteed to be a valid position)
*/ */
public Vector3d suggestMovementPosition(CommonWorldData w, Entity e, Vector3d positionToCheck){ public Vector3d suggestMovementPosition(CollisionWorldData w, Entity e, Vector3d positionToCheck){
Vector3d suggestedPosition = new Vector3d(positionToCheck); Vector3d suggestedPosition = new Vector3d(positionToCheck);
// //
// adjust for minimum height (Terrain) // adjust for minimum height (Terrain)
@ -258,17 +262,17 @@ public class CollisionEngine {
// //
// adjust for world bounds // adjust for world bounds
// //
if(suggestedPosition.x < w.getWorldBoundMin().x){ if(suggestedPosition.x < collisionWorldData.getWorldBoundMin().x){
suggestedPosition.x = w.getWorldBoundMin().x; suggestedPosition.x = collisionWorldData.getWorldBoundMin().x;
} }
if(suggestedPosition.z < w.getWorldBoundMin().z){ if(suggestedPosition.z < collisionWorldData.getWorldBoundMin().z){
suggestedPosition.z = w.getWorldBoundMin().z; suggestedPosition.z = collisionWorldData.getWorldBoundMin().z;
} }
if(suggestedPosition.x > w.getWorldBoundMax().x){ if(suggestedPosition.x > collisionWorldData.getWorldBoundMax().x){
suggestedPosition.x = w.getWorldBoundMax().x; suggestedPosition.x = collisionWorldData.getWorldBoundMax().x;
} }
if(suggestedPosition.z > w.getWorldBoundMax().z){ if(suggestedPosition.z > collisionWorldData.getWorldBoundMax().z){
suggestedPosition.z = w.getWorldBoundMax().z; suggestedPosition.z = collisionWorldData.getWorldBoundMax().z;
} }
return suggestedPosition; return suggestedPosition;
} }
@ -282,6 +286,13 @@ public class CollisionEngine {
return collisionEntities; return collisionEntities;
} }
/**
* Sets the collision world data
* @param collisionWorldData The collision world data
*/
public void setCollisionWorldData(CollisionWorldData collisionWorldData){
this.collisionWorldData = collisionWorldData;
}
public boolean collisionSphereCheck(Entity hitbox1, HitboxData hitbox1data, Entity hitbox2, HitboxData hitbox2data){ public boolean collisionSphereCheck(Entity hitbox1, HitboxData hitbox1data, Entity hitbox2, HitboxData hitbox2data){
@ -384,17 +395,6 @@ public class CollisionEngine {
// private static class SpecificConvexResultCallback extends ConvexResultCallback {
//
// @Override
// public float addSingleResult(LocalConvexResult convexResult, boolean bln) {
// }
//
// }
private static class ClosestConvexResultCallbackImpl extends ClosestConvexResultCallback { private static class ClosestConvexResultCallbackImpl extends ClosestConvexResultCallback {
CollisionObject me; CollisionObject me;

View File

@ -8,7 +8,7 @@ import electrosphere.server.terrain.manager.ServerTerrainManager;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector3f; import org.joml.Vector3f;
public class CommonWorldData { public class CollisionWorldData {
@ -20,17 +20,12 @@ public class CommonWorldData {
ServerWorldData serverWorldData; ServerWorldData serverWorldData;
ServerTerrainManager serverTerrainManager; ServerTerrainManager serverTerrainManager;
public CollisionWorldData(ServerWorldData serverWorldData){
public CommonWorldData(ClientWorldData clientWorldData, ClientTerrainManager clientTerrainManager){
this.clientWorldData = clientWorldData;
this.clientTerrainManager = clientTerrainManager;
}
public CommonWorldData(ServerWorldData serverWorldData, ServerTerrainManager serverTerrainManager){
this.serverWorldData = serverWorldData; this.serverWorldData = serverWorldData;
this.serverTerrainManager = serverTerrainManager; }
public CollisionWorldData(ClientWorldData clientWorldData){
this.clientWorldData = clientWorldData;
} }
@ -44,17 +39,17 @@ public class CommonWorldData {
* @param position * @param position
* @return * @return
*/ */
public double getElevationAtPoint(Vector3d position){ // public double getElevationAtPoint(Vector3d position){
if(clientWorldData != null){ // if(clientWorldData != null){
if(clientTerrainManager.containsHeightmapAtRealPoint(position.x, position.z)){ // if(clientTerrainManager.containsHeightmapAtRealPoint(position.x, position.z)){
return clientTerrainManager.getHeightAtPosition(position.x, position.z); // return clientTerrainManager.getHeightAtPosition(position.x, position.z);
} else { // } else {
return 0; // return 0;
} // }
} else { // } else {
return serverTerrainManager.getHeightAtPosition(position.x, position.z); // return serverTerrainManager.getHeightAtPosition(position.x, position.z);
} // }
} // }
public Vector3f getWorldBoundMin(){ public Vector3f getWorldBoundMin(){

View File

@ -15,6 +15,7 @@ import electrosphere.server.datacell.Realm;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
import electrosphere.entity.ServerEntityUtils;
import electrosphere.entity.types.terrain.TerrainChunkData; import electrosphere.entity.types.terrain.TerrainChunkData;
import electrosphere.game.collision.collidable.Collidable; import electrosphere.game.collision.collidable.Collidable;
@ -380,7 +381,6 @@ public class PhysicsUtils {
Realm terrainRealm = Globals.realmManager.getEntityRealm(terrain); Realm terrainRealm = Globals.realmManager.getEntityRealm(terrain);
terrainRealm.getCollisionEngine().registerCollisionObject(terrainRigidBody, new Collidable(terrain,Collidable.TYPE_TERRAIN)); terrainRealm.getCollisionEngine().registerCollisionObject(terrainRigidBody, new Collidable(terrain,Collidable.TYPE_TERRAIN));
// terrainRigidBody.getAabb(aabbMin, aabbMax); // terrainRigidBody.getAabb(aabbMin, aabbMax);
// //
// System.out.println("aabbMin: " + aabbMin + " aabbMax: " + aabbMax); // System.out.println("aabbMin: " + aabbMin + " aabbMax: " + aabbMax);
@ -598,6 +598,18 @@ public class PhysicsUtils {
return transform; return transform;
} }
public static electrosphere.linearmath.Transform jomlVecToTransform(Vector3d vector){
electrosphere.linearmath.Transform transform = new electrosphere.linearmath.Transform();
javax.vecmath.Matrix4f transformMatrix = new javax.vecmath.Matrix4f();
transformMatrix.setIdentity();
transformMatrix.setTranslation(new javax.vecmath.Vector3f((float)vector.x, (float)vector.y, (float)vector.z));
transform.set(transformMatrix);
return transform;
}
public static void setRigidBodyTransform(Vector3f position, Quaternionf rotation, CollisionObject body){ public static void setRigidBodyTransform(Vector3f position, Quaternionf rotation, CollisionObject body){
electrosphere.linearmath.Transform transform = new electrosphere.linearmath.Transform(); electrosphere.linearmath.Transform transform = new electrosphere.linearmath.Transform();

View File

@ -20,28 +20,28 @@ import org.joml.Vector3f;
public class VirtualStructureUtils { public class VirtualStructureUtils {
public static Structure placeStructureAtPoint(float posX, float posY, String type){ public static Structure placeStructureAtPoint(float posX, float posY, float posZ, String type){
int worldX = Globals.serverWorldData.convertRealToChunkSpace(posX); int worldX = Globals.serverWorldData.convertRealToChunkSpace(posX);
int worldY = Globals.serverWorldData.convertRealToChunkSpace(posY); int worldY = Globals.serverWorldData.convertRealToChunkSpace(posY);
Structure rVal = new Structure(worldX,worldY,posX,posY,type); Structure rVal = new Structure(worldX,worldY,posX,posY,type);
Globals.macroData.addStructure(rVal); Globals.macroData.addStructure(rVal);
double centerHeight = Globals.serverTerrainManager.getHeightAtPosition(posX, posY); // double centerHeight = Globals.serverTerrainManager.getHeightAtPosition(posX, posY, posZ);
StructureType currentTypeObject = Globals.gameConfigCurrent.getStructureTypeMap().getType(type); // StructureType currentTypeObject = Globals.gameConfigCurrent.getStructureTypeMap().getType(type);
float radius = currentTypeObject.getRadius(); // float radius = currentTypeObject.getRadius();
for(int x = -(int)radius; x < radius; x++){ // for(int x = -(int)radius; x < radius; x++){
for(int y = -(int)radius; y < radius; y++){ // for(int y = -(int)radius; y < radius; y++){
int newWorldX = Globals.serverWorldData.convertRealToChunkSpace(posX + x); // int newWorldX = Globals.serverWorldData.convertRealToChunkSpace(posX + x);
int newWorldY = Globals.serverWorldData.convertRealToChunkSpace(posY + y); // int newWorldY = Globals.serverWorldData.convertRealToChunkSpace(posY + y);
double newLocationX = Globals.serverWorldData.getRelativeLocation(posX + x, newWorldX); // double newLocationX = Globals.serverWorldData.getRelativeLocation(posX + x, newWorldX);
double newLocationY = Globals.serverWorldData.getRelativeLocation(posY + y, newWorldY); // double newLocationY = Globals.serverWorldData.getRelativeLocation(posY + y, newWorldY);
// System.out.println("Set height: " + centerHeight); // // System.out.println("Set height: " + centerHeight);
// System.out.println("Deform in chunk: " + newWorldX + "," + newWorldY); // // System.out.println("Deform in chunk: " + newWorldX + "," + newWorldY);
Globals.serverTerrainManager.deformTerrainAtLocationToValue(newWorldX, newWorldY, (int)(newLocationX), (int)(newLocationY), (float)centerHeight); // Globals.serverTerrainManager.deformTerrainAtLocationToValue(newWorldX, newWorldY, (int)(newLocationX), (int)(newLocationY), (float)centerHeight);
} // }
} // }
Realm realm = Globals.realmManager.getRealms().iterator().next(); Realm realm = Globals.realmManager.getRealms().iterator().next();
StructureUtils.serverSpawnBasicStructure(type, realm, new Vector3d(posX,(float)centerHeight + 2.4f,posY), new Quaternionf()); // StructureUtils.serverSpawnBasicStructure(type, realm, new Vector3d(posX,(float)centerHeight + 2.4f,posY), new Quaternionf());
return rVal; return rVal;
} }

View File

@ -36,29 +36,29 @@ public class Town {
public static Vector2i findValidTownLocation(){ public static Vector2i findValidTownLocation(){
for(int x = 0; x < Globals.serverTerrainManager.getWorldDiscreteSize(); x++){ for(int x = 0; x < Globals.serverTerrainManager.getWorldDiscreteSize(); x++){
for(int y = 0; y < Globals.serverTerrainManager.getWorldDiscreteSize(); y++){ for(int y = 0; y < Globals.serverTerrainManager.getWorldDiscreteSize(); y++){
ServerTerrainChunk chunk = Globals.serverTerrainManager.getChunk(x, y); // ServerTerrainChunk chunk = Globals.serverTerrainManager.getChunk(x, y);
float[][] macroValues = chunk.getMacroValues(); // float[][] macroValues = chunk.getMacroValues();
float sum = 0; // float sum = 0;
int count = 0; // int count = 0;
for(int i = 0; i < 5; i++){ // for(int i = 0; i < 5; i++){
for(int j = 0; j < 5; j++){ // for(int j = 0; j < 5; j++){
sum = sum + macroValues[i][j]; // sum = sum + macroValues[i][j];
count++; // count++;
} // }
} // }
float average = sum / (float)count; // float average = sum / (float)count;
if(average > 1000){ // if(average > 1000){
float diffSum = 0; // float diffSum = 0;
for(int i = 0; i < 5; i++){ // for(int i = 0; i < 5; i++){
for(int j = 0; j < 5; j++){ // for(int j = 0; j < 5; j++){
diffSum = diffSum + (float)Math.abs(average - macroValues[i][j]); // diffSum = diffSum + (float)Math.abs(average - macroValues[i][j]);
} // }
} // }
float averageDiff = diffSum / (float)count; // float averageDiff = diffSum / (float)count;
if(averageDiff < avgDiffThreshold){ // if(averageDiff < avgDiffThreshold){
return new Vector2i(x,y); // return new Vector2i(x,y);
} // }
} // }
} }
} }
return null; return null;

View File

@ -21,7 +21,7 @@ public class LoggerInterface {
public static void initLoggers(){ public static void initLoggers(){
loggerStartup = new Logger(LogLevel.WARNING); loggerStartup = new Logger(LogLevel.WARNING);
loggerNetworking = new Logger(LogLevel.DEBUG); loggerNetworking = new Logger(LogLevel.WARNING);
loggerFileIO = new Logger(LogLevel.WARNING); loggerFileIO = new Logger(LogLevel.WARNING);
loggerGameLogic = new Logger(LogLevel.WARNING); loggerGameLogic = new Logger(LogLevel.WARNING);
loggerRenderer = new Logger(LogLevel.WARNING); loggerRenderer = new Logger(LogLevel.WARNING);

View File

@ -5,7 +5,11 @@ import javax.vecmath.Vector3d;
import org.joml.Vector3f; import org.joml.Vector3f;
import electrosphere.client.scene.ClientWorldData; import electrosphere.client.scene.ClientWorldData;
import electrosphere.client.terrain.cache.ChunkData;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.entity.types.terrain.TerrainChunk;
import electrosphere.entity.types.terrain.TerrainChunkData;
import electrosphere.game.collision.CollisionWorldData;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.TerrainMessage; import electrosphere.net.parser.net.message.TerrainMessage;
@ -17,24 +21,18 @@ public class TerrainProtocol {
Globals.clientWorldData = new ClientWorldData( Globals.clientWorldData = new ClientWorldData(
//Vector3f worldMinPoint, Vector3f worldMaxPoint, int dynamicInterpolationRatio, float randomDampener, int worldDiscreteSize //Vector3f worldMinPoint, Vector3f worldMaxPoint, int dynamicInterpolationRatio, float randomDampener, int worldDiscreteSize
new Vector3f(message.getworldMinX(),0,message.getworldMinY()), new Vector3f(message.getworldMinX(),0,message.getworldMinY()),
new Vector3f(message.getworldMaxX(),0,message.getworldMaxY()), new Vector3f(message.getworldMaxX(),3,message.getworldMaxY()),
message.getdynamicInterpolationRatio(), ChunkData.CHUNK_SIZE,
message.getrandomDampener(), message.getrandomDampener(),
message.getworldSizeDiscrete() message.getworldSizeDiscrete()
); );
Globals.clientTerrainManager.setClientWorldData(Globals.clientWorldData); Globals.clientSceneWrapper.getCollisionEngine().setCollisionWorldData(new CollisionWorldData(Globals.clientWorldData));
Globals.clientConnection.getClientProtocol().setHasReceivedWorld(true); Globals.clientConnection.getClientProtocol().setHasReceivedWorld(true);
break; break;
case MACROVALUE:
Globals.clientTerrainManager.attachTerrainMessage(message);
break;
case SPAWNPOSITION: case SPAWNPOSITION:
Globals.spawnPoint.set(message.getrealLocationX(),0.25,message.getrealLocationZ()); Globals.spawnPoint.set(message.getrealLocationX(),0.25,message.getrealLocationZ());
break; break;
case CHUNKLOADSTART: case SENDCHUNKDATA:
Globals.clientTerrainManager.attachTerrainMessage(message);
break;
case HEIGHTMAPMODIFICATION:
Globals.clientTerrainManager.attachTerrainMessage(message); Globals.clientTerrainManager.attachTerrainMessage(message);
break; break;
default: default:

View File

@ -1,6 +1,7 @@
package electrosphere.net.parser.net.message; package electrosphere.net.parser.net.message;
import electrosphere.net.parser.util.ByteStreamUtils; import electrosphere.net.parser.util.ByteStreamUtils;
import electrosphere.net.parser.net.raw.CircularByteBuffer;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -42,29 +43,28 @@ public class AuthMessage extends NetworkMessage {
this.pass = pass; this.pass = pass;
} }
static void stripPacketHeader(List<Byte> byteStream){ static void stripPacketHeader(CircularByteBuffer byteBuffer){
byteStream.remove(0); byteBuffer.read(2);
byteStream.remove(0);
} }
public static boolean canParseMessage(List<Byte> byteStream, byte secondByte){ public static boolean canParseMessage(CircularByteBuffer byteBuffer, byte secondByte){
switch(secondByte){ switch(secondByte){
case TypeBytes.AUTH_MESSAGE_TYPE_AUTHREQUEST: case TypeBytes.AUTH_MESSAGE_TYPE_AUTHREQUEST:
if(byteStream.size() >= TypeBytes.AUTH_MESSAGE_TYPE_AUTHREQUEST_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.AUTH_MESSAGE_TYPE_AUTHREQUEST_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.AUTH_MESSAGE_TYPE_AUTHDETAILS: case TypeBytes.AUTH_MESSAGE_TYPE_AUTHDETAILS:
return AuthMessage.canParseAuthDetailsMessage(byteStream); return AuthMessage.canParseAuthDetailsMessage(byteBuffer);
case TypeBytes.AUTH_MESSAGE_TYPE_AUTHSUCCESS: case TypeBytes.AUTH_MESSAGE_TYPE_AUTHSUCCESS:
if(byteStream.size() >= TypeBytes.AUTH_MESSAGE_TYPE_AUTHSUCCESS_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.AUTH_MESSAGE_TYPE_AUTHSUCCESS_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.AUTH_MESSAGE_TYPE_AUTHFAILURE: case TypeBytes.AUTH_MESSAGE_TYPE_AUTHFAILURE:
if(byteStream.size() >= TypeBytes.AUTH_MESSAGE_TYPE_AUTHFAILURE_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.AUTH_MESSAGE_TYPE_AUTHFAILURE_SIZE){
return true; return true;
} else { } else {
return false; return false;
@ -73,9 +73,9 @@ public class AuthMessage extends NetworkMessage {
return false; return false;
} }
public static AuthMessage parseAuthRequestMessage(List<Byte> byteStream){ public static AuthMessage parseAuthRequestMessage(CircularByteBuffer byteBuffer){
AuthMessage rVal = new AuthMessage(AuthMessageType.AUTHREQUEST); AuthMessage rVal = new AuthMessage(AuthMessageType.AUTHREQUEST);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
return rVal; return rVal;
} }
@ -85,17 +85,17 @@ public class AuthMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static boolean canParseAuthDetailsMessage(List<Byte> byteStream){ public static boolean canParseAuthDetailsMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteStream.size(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList();
int userSize = 0; int userSize = 0;
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} else { } else {
temporaryByteQueue.add(byteStream.get(2 + 0)); temporaryByteQueue.add(byteBuffer.peek(2 + 0));
temporaryByteQueue.add(byteStream.get(2 + 1)); temporaryByteQueue.add(byteBuffer.peek(2 + 1));
temporaryByteQueue.add(byteStream.get(2 + 2)); temporaryByteQueue.add(byteBuffer.peek(2 + 2));
temporaryByteQueue.add(byteStream.get(2 + 3)); temporaryByteQueue.add(byteBuffer.peek(2 + 3));
userSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue); userSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
} }
if(currentStreamLength < 6 + userSize){ if(currentStreamLength < 6 + userSize){
@ -105,10 +105,10 @@ public class AuthMessage extends NetworkMessage {
if(currentStreamLength < 10){ if(currentStreamLength < 10){
return false; return false;
} else { } else {
temporaryByteQueue.add(byteStream.get(6 + userSize + 0)); temporaryByteQueue.add(byteBuffer.peek(6 + userSize + 0));
temporaryByteQueue.add(byteStream.get(6 + userSize + 1)); temporaryByteQueue.add(byteBuffer.peek(6 + userSize + 1));
temporaryByteQueue.add(byteStream.get(6 + userSize + 2)); temporaryByteQueue.add(byteBuffer.peek(6 + userSize + 2));
temporaryByteQueue.add(byteStream.get(6 + userSize + 3)); temporaryByteQueue.add(byteBuffer.peek(6 + userSize + 3));
passSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue); passSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
} }
if(currentStreamLength < 10 + userSize + passSize){ if(currentStreamLength < 10 + userSize + passSize){
@ -117,11 +117,11 @@ public class AuthMessage extends NetworkMessage {
return true; return true;
} }
public static AuthMessage parseAuthDetailsMessage(List<Byte> byteStream){ public static AuthMessage parseAuthDetailsMessage(CircularByteBuffer byteBuffer){
AuthMessage rVal = new AuthMessage(AuthMessageType.AUTHDETAILS); AuthMessage rVal = new AuthMessage(AuthMessageType.AUTHDETAILS);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setuser(ByteStreamUtils.popStringFromByteQueue(byteStream)); rVal.setuser(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
rVal.setpass(ByteStreamUtils.popStringFromByteQueue(byteStream)); rVal.setpass(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -133,9 +133,9 @@ public class AuthMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static AuthMessage parseAuthSuccessMessage(List<Byte> byteStream){ public static AuthMessage parseAuthSuccessMessage(CircularByteBuffer byteBuffer){
AuthMessage rVal = new AuthMessage(AuthMessageType.AUTHSUCCESS); AuthMessage rVal = new AuthMessage(AuthMessageType.AUTHSUCCESS);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
return rVal; return rVal;
} }
@ -145,9 +145,9 @@ public class AuthMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static AuthMessage parseAuthFailureMessage(List<Byte> byteStream){ public static AuthMessage parseAuthFailureMessage(CircularByteBuffer byteBuffer){
AuthMessage rVal = new AuthMessage(AuthMessageType.AUTHFAILURE); AuthMessage rVal = new AuthMessage(AuthMessageType.AUTHFAILURE);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
return rVal; return rVal;
} }

View File

@ -1,6 +1,7 @@
package electrosphere.net.parser.net.message; package electrosphere.net.parser.net.message;
import electrosphere.net.parser.util.ByteStreamUtils; import electrosphere.net.parser.util.ByteStreamUtils;
import electrosphere.net.parser.net.raw.CircularByteBuffer;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -36,50 +37,49 @@ public class CharacterMessage extends NetworkMessage {
this.data = data; this.data = data;
} }
static void stripPacketHeader(List<Byte> byteStream){ static void stripPacketHeader(CircularByteBuffer byteBuffer){
byteStream.remove(0); byteBuffer.read(2);
byteStream.remove(0);
} }
public static boolean canParseMessage(List<Byte> byteStream, byte secondByte){ public static boolean canParseMessage(CircularByteBuffer byteBuffer, byte secondByte){
switch(secondByte){ switch(secondByte){
case TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTCHARACTERLIST: case TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTCHARACTERLIST:
if(byteStream.size() >= TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTCHARACTERLIST_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTCHARACTERLIST_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECHARACTERLIST: case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECHARACTERLIST:
return CharacterMessage.canParseResponseCharacterListMessage(byteStream); return CharacterMessage.canParseResponseCharacterListMessage(byteBuffer);
case TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTCREATECHARACTER: case TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTCREATECHARACTER:
return CharacterMessage.canParseRequestCreateCharacterMessage(byteStream); return CharacterMessage.canParseRequestCreateCharacterMessage(byteBuffer);
case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERSUCCESS: case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERSUCCESS:
if(byteStream.size() >= TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERSUCCESS_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERSUCCESS_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERFAILURE: case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERFAILURE:
if(byteStream.size() >= TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERFAILURE_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERFAILURE_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTSPAWNCHARACTER: case TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTSPAWNCHARACTER:
if(byteStream.size() >= TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTSPAWNCHARACTER_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTSPAWNCHARACTER_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSESPAWNCHARACTER: case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSESPAWNCHARACTER:
return CharacterMessage.canParseResponseSpawnCharacterMessage(byteStream); return CharacterMessage.canParseResponseSpawnCharacterMessage(byteBuffer);
} }
return false; return false;
} }
public static CharacterMessage parseRequestCharacterListMessage(List<Byte> byteStream){ public static CharacterMessage parseRequestCharacterListMessage(CircularByteBuffer byteBuffer){
CharacterMessage rVal = new CharacterMessage(CharacterMessageType.REQUESTCHARACTERLIST); CharacterMessage rVal = new CharacterMessage(CharacterMessageType.REQUESTCHARACTERLIST);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
return rVal; return rVal;
} }
@ -89,17 +89,17 @@ public class CharacterMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static boolean canParseResponseCharacterListMessage(List<Byte> byteStream){ public static boolean canParseResponseCharacterListMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteStream.size(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList();
int dataSize = 0; int dataSize = 0;
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} else { } else {
temporaryByteQueue.add(byteStream.get(2 + 0)); temporaryByteQueue.add(byteBuffer.peek(2 + 0));
temporaryByteQueue.add(byteStream.get(2 + 1)); temporaryByteQueue.add(byteBuffer.peek(2 + 1));
temporaryByteQueue.add(byteStream.get(2 + 2)); temporaryByteQueue.add(byteBuffer.peek(2 + 2));
temporaryByteQueue.add(byteStream.get(2 + 3)); temporaryByteQueue.add(byteBuffer.peek(2 + 3));
dataSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue); dataSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
} }
if(currentStreamLength < 6 + dataSize){ if(currentStreamLength < 6 + dataSize){
@ -108,10 +108,10 @@ public class CharacterMessage extends NetworkMessage {
return true; return true;
} }
public static CharacterMessage parseResponseCharacterListMessage(List<Byte> byteStream){ public static CharacterMessage parseResponseCharacterListMessage(CircularByteBuffer byteBuffer){
CharacterMessage rVal = new CharacterMessage(CharacterMessageType.RESPONSECHARACTERLIST); CharacterMessage rVal = new CharacterMessage(CharacterMessageType.RESPONSECHARACTERLIST);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setdata(ByteStreamUtils.popStringFromByteQueue(byteStream)); rVal.setdata(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -122,17 +122,17 @@ public class CharacterMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static boolean canParseRequestCreateCharacterMessage(List<Byte> byteStream){ public static boolean canParseRequestCreateCharacterMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteStream.size(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList();
int dataSize = 0; int dataSize = 0;
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} else { } else {
temporaryByteQueue.add(byteStream.get(2 + 0)); temporaryByteQueue.add(byteBuffer.peek(2 + 0));
temporaryByteQueue.add(byteStream.get(2 + 1)); temporaryByteQueue.add(byteBuffer.peek(2 + 1));
temporaryByteQueue.add(byteStream.get(2 + 2)); temporaryByteQueue.add(byteBuffer.peek(2 + 2));
temporaryByteQueue.add(byteStream.get(2 + 3)); temporaryByteQueue.add(byteBuffer.peek(2 + 3));
dataSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue); dataSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
} }
if(currentStreamLength < 6 + dataSize){ if(currentStreamLength < 6 + dataSize){
@ -141,10 +141,10 @@ public class CharacterMessage extends NetworkMessage {
return true; return true;
} }
public static CharacterMessage parseRequestCreateCharacterMessage(List<Byte> byteStream){ public static CharacterMessage parseRequestCreateCharacterMessage(CircularByteBuffer byteBuffer){
CharacterMessage rVal = new CharacterMessage(CharacterMessageType.REQUESTCREATECHARACTER); CharacterMessage rVal = new CharacterMessage(CharacterMessageType.REQUESTCREATECHARACTER);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setdata(ByteStreamUtils.popStringFromByteQueue(byteStream)); rVal.setdata(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -155,9 +155,9 @@ public class CharacterMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static CharacterMessage parseResponseCreateCharacterSuccessMessage(List<Byte> byteStream){ public static CharacterMessage parseResponseCreateCharacterSuccessMessage(CircularByteBuffer byteBuffer){
CharacterMessage rVal = new CharacterMessage(CharacterMessageType.RESPONSECREATECHARACTERSUCCESS); CharacterMessage rVal = new CharacterMessage(CharacterMessageType.RESPONSECREATECHARACTERSUCCESS);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
return rVal; return rVal;
} }
@ -167,9 +167,9 @@ public class CharacterMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static CharacterMessage parseResponseCreateCharacterFailureMessage(List<Byte> byteStream){ public static CharacterMessage parseResponseCreateCharacterFailureMessage(CircularByteBuffer byteBuffer){
CharacterMessage rVal = new CharacterMessage(CharacterMessageType.RESPONSECREATECHARACTERFAILURE); CharacterMessage rVal = new CharacterMessage(CharacterMessageType.RESPONSECREATECHARACTERFAILURE);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
return rVal; return rVal;
} }
@ -179,9 +179,9 @@ public class CharacterMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static CharacterMessage parseRequestSpawnCharacterMessage(List<Byte> byteStream){ public static CharacterMessage parseRequestSpawnCharacterMessage(CircularByteBuffer byteBuffer){
CharacterMessage rVal = new CharacterMessage(CharacterMessageType.REQUESTSPAWNCHARACTER); CharacterMessage rVal = new CharacterMessage(CharacterMessageType.REQUESTSPAWNCHARACTER);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
return rVal; return rVal;
} }
@ -191,17 +191,17 @@ public class CharacterMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static boolean canParseResponseSpawnCharacterMessage(List<Byte> byteStream){ public static boolean canParseResponseSpawnCharacterMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteStream.size(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList();
int dataSize = 0; int dataSize = 0;
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} else { } else {
temporaryByteQueue.add(byteStream.get(2 + 0)); temporaryByteQueue.add(byteBuffer.peek(2 + 0));
temporaryByteQueue.add(byteStream.get(2 + 1)); temporaryByteQueue.add(byteBuffer.peek(2 + 1));
temporaryByteQueue.add(byteStream.get(2 + 2)); temporaryByteQueue.add(byteBuffer.peek(2 + 2));
temporaryByteQueue.add(byteStream.get(2 + 3)); temporaryByteQueue.add(byteBuffer.peek(2 + 3));
dataSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue); dataSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
} }
if(currentStreamLength < 6 + dataSize){ if(currentStreamLength < 6 + dataSize){
@ -210,10 +210,10 @@ public class CharacterMessage extends NetworkMessage {
return true; return true;
} }
public static CharacterMessage parseResponseSpawnCharacterMessage(List<Byte> byteStream){ public static CharacterMessage parseResponseSpawnCharacterMessage(CircularByteBuffer byteBuffer){
CharacterMessage rVal = new CharacterMessage(CharacterMessageType.RESPONSESPAWNCHARACTER); CharacterMessage rVal = new CharacterMessage(CharacterMessageType.RESPONSESPAWNCHARACTER);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setdata(ByteStreamUtils.popStringFromByteQueue(byteStream)); rVal.setdata(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
return rVal; return rVal;
} }

View File

@ -1,6 +1,7 @@
package electrosphere.net.parser.net.message; package electrosphere.net.parser.net.message;
import electrosphere.net.parser.util.ByteStreamUtils; import electrosphere.net.parser.util.ByteStreamUtils;
import electrosphere.net.parser.net.raw.CircularByteBuffer;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -272,107 +273,106 @@ public class EntityMessage extends NetworkMessage {
this.propertyValueString = propertyValueString; this.propertyValueString = propertyValueString;
} }
static void stripPacketHeader(List<Byte> byteStream){ static void stripPacketHeader(CircularByteBuffer byteBuffer){
byteStream.remove(0); byteBuffer.read(2);
byteStream.remove(0);
} }
public static boolean canParseMessage(List<Byte> byteStream, byte secondByte){ public static boolean canParseMessage(CircularByteBuffer byteBuffer, byte secondByte){
switch(secondByte){ switch(secondByte){
case TypeBytes.ENTITY_MESSAGE_TYPE_CREATE: case TypeBytes.ENTITY_MESSAGE_TYPE_CREATE:
return EntityMessage.canParseCreateMessage(byteStream); return EntityMessage.canParseCreateMessage(byteBuffer);
case TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNCREATURE: case TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNCREATURE:
return EntityMessage.canParseSpawnCreatureMessage(byteStream); return EntityMessage.canParseSpawnCreatureMessage(byteBuffer);
case TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNITEM: case TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNITEM:
return EntityMessage.canParseSpawnItemMessage(byteStream); return EntityMessage.canParseSpawnItemMessage(byteBuffer);
case TypeBytes.ENTITY_MESSAGE_TYPE_SETPOSITION: case TypeBytes.ENTITY_MESSAGE_TYPE_SETPOSITION:
if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETPOSITION_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETPOSITION_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.ENTITY_MESSAGE_TYPE_SETFACING: case TypeBytes.ENTITY_MESSAGE_TYPE_SETFACING:
if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETFACING_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETFACING_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.ENTITY_MESSAGE_TYPE_MOVEUPDATE: case TypeBytes.ENTITY_MESSAGE_TYPE_MOVEUPDATE:
if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_MOVEUPDATE_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_MOVEUPDATE_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.ENTITY_MESSAGE_TYPE_ATTACKUPDATE: case TypeBytes.ENTITY_MESSAGE_TYPE_ATTACKUPDATE:
if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_ATTACKUPDATE_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_ATTACKUPDATE_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.ENTITY_MESSAGE_TYPE_MOVE: case TypeBytes.ENTITY_MESSAGE_TYPE_MOVE:
if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_MOVE_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_MOVE_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.ENTITY_MESSAGE_TYPE_KILL: case TypeBytes.ENTITY_MESSAGE_TYPE_KILL:
if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_KILL_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_KILL_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.ENTITY_MESSAGE_TYPE_DESTROY: case TypeBytes.ENTITY_MESSAGE_TYPE_DESTROY:
if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_DESTROY_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_DESTROY_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.ENTITY_MESSAGE_TYPE_SETBEHAVIORTREE: case TypeBytes.ENTITY_MESSAGE_TYPE_SETBEHAVIORTREE:
if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETBEHAVIORTREE_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETBEHAVIORTREE_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.ENTITY_MESSAGE_TYPE_SETPROPERTY: case TypeBytes.ENTITY_MESSAGE_TYPE_SETPROPERTY:
if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETPROPERTY_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETPROPERTY_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYINT: case TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYINT:
if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYINT_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYINT_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYFLOAT: case TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYFLOAT:
if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYFLOAT_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYFLOAT_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYDOUBLE: case TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYDOUBLE:
if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYDOUBLE_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYDOUBLE_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYSTRING: case TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYSTRING:
return EntityMessage.canParsesetBTreePropertyStringMessage(byteStream); return EntityMessage.canParsesetBTreePropertyStringMessage(byteBuffer);
case TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYENUM: case TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYENUM:
if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYENUM_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYENUM_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.ENTITY_MESSAGE_TYPE_ATTACHENTITYTOENTITY: case TypeBytes.ENTITY_MESSAGE_TYPE_ATTACHENTITYTOENTITY:
return EntityMessage.canParseattachEntityToEntityMessage(byteStream); return EntityMessage.canParseattachEntityToEntityMessage(byteBuffer);
} }
return false; return false;
} }
public static boolean canParseCreateMessage(List<Byte> byteStream){ public static boolean canParseCreateMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteStream.size(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
@ -384,10 +384,10 @@ public class EntityMessage extends NetworkMessage {
if(currentStreamLength < 14){ if(currentStreamLength < 14){
return false; return false;
} else { } else {
temporaryByteQueue.add(byteStream.get(10 + 0)); temporaryByteQueue.add(byteBuffer.peek(10 + 0));
temporaryByteQueue.add(byteStream.get(10 + 1)); temporaryByteQueue.add(byteBuffer.peek(10 + 1));
temporaryByteQueue.add(byteStream.get(10 + 2)); temporaryByteQueue.add(byteBuffer.peek(10 + 2));
temporaryByteQueue.add(byteStream.get(10 + 3)); temporaryByteQueue.add(byteBuffer.peek(10 + 3));
entitySubtypeSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue); entitySubtypeSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
} }
if(currentStreamLength < 14 + entitySubtypeSize){ if(currentStreamLength < 14 + entitySubtypeSize){
@ -405,15 +405,15 @@ public class EntityMessage extends NetworkMessage {
return true; return true;
} }
public static EntityMessage parseCreateMessage(List<Byte> byteStream){ public static EntityMessage parseCreateMessage(CircularByteBuffer byteBuffer){
EntityMessage rVal = new EntityMessage(EntityMessageType.CREATE); EntityMessage rVal = new EntityMessage(EntityMessageType.CREATE);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setentityCategory(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityCategory(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setentitySubtype(ByteStreamUtils.popStringFromByteQueue(byteStream)); rVal.setentitySubtype(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -429,8 +429,8 @@ public class EntityMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static boolean canParseSpawnCreatureMessage(List<Byte> byteStream){ public static boolean canParseSpawnCreatureMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteStream.size(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
@ -439,10 +439,10 @@ public class EntityMessage extends NetworkMessage {
if(currentStreamLength < 10){ if(currentStreamLength < 10){
return false; return false;
} else { } else {
temporaryByteQueue.add(byteStream.get(6 + 0)); temporaryByteQueue.add(byteBuffer.peek(6 + 0));
temporaryByteQueue.add(byteStream.get(6 + 1)); temporaryByteQueue.add(byteBuffer.peek(6 + 1));
temporaryByteQueue.add(byteStream.get(6 + 2)); temporaryByteQueue.add(byteBuffer.peek(6 + 2));
temporaryByteQueue.add(byteStream.get(6 + 3)); temporaryByteQueue.add(byteBuffer.peek(6 + 3));
creatureTemplateSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue); creatureTemplateSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
} }
if(currentStreamLength < 10 + creatureTemplateSize){ if(currentStreamLength < 10 + creatureTemplateSize){
@ -460,14 +460,14 @@ public class EntityMessage extends NetworkMessage {
return true; return true;
} }
public static EntityMessage parseSpawnCreatureMessage(List<Byte> byteStream){ public static EntityMessage parseSpawnCreatureMessage(CircularByteBuffer byteBuffer){
EntityMessage rVal = new EntityMessage(EntityMessageType.SPAWNCREATURE); EntityMessage rVal = new EntityMessage(EntityMessageType.SPAWNCREATURE);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setcreatureTemplate(ByteStreamUtils.popStringFromByteQueue(byteStream)); rVal.setcreatureTemplate(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -482,8 +482,8 @@ public class EntityMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static boolean canParseSpawnItemMessage(List<Byte> byteStream){ public static boolean canParseSpawnItemMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteStream.size(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
@ -492,10 +492,10 @@ public class EntityMessage extends NetworkMessage {
if(currentStreamLength < 10){ if(currentStreamLength < 10){
return false; return false;
} else { } else {
temporaryByteQueue.add(byteStream.get(6 + 0)); temporaryByteQueue.add(byteBuffer.peek(6 + 0));
temporaryByteQueue.add(byteStream.get(6 + 1)); temporaryByteQueue.add(byteBuffer.peek(6 + 1));
temporaryByteQueue.add(byteStream.get(6 + 2)); temporaryByteQueue.add(byteBuffer.peek(6 + 2));
temporaryByteQueue.add(byteStream.get(6 + 3)); temporaryByteQueue.add(byteBuffer.peek(6 + 3));
creatureTemplateSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue); creatureTemplateSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
} }
if(currentStreamLength < 10 + creatureTemplateSize){ if(currentStreamLength < 10 + creatureTemplateSize){
@ -513,14 +513,14 @@ public class EntityMessage extends NetworkMessage {
return true; return true;
} }
public static EntityMessage parseSpawnItemMessage(List<Byte> byteStream){ public static EntityMessage parseSpawnItemMessage(CircularByteBuffer byteBuffer){
EntityMessage rVal = new EntityMessage(EntityMessageType.SPAWNITEM); EntityMessage rVal = new EntityMessage(EntityMessageType.SPAWNITEM);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setcreatureTemplate(ByteStreamUtils.popStringFromByteQueue(byteStream)); rVal.setcreatureTemplate(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -535,14 +535,14 @@ public class EntityMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static EntityMessage parseSetPositionMessage(List<Byte> byteStream){ public static EntityMessage parseSetPositionMessage(CircularByteBuffer byteBuffer){
EntityMessage rVal = new EntityMessage(EntityMessageType.SETPOSITION); EntityMessage rVal = new EntityMessage(EntityMessageType.SETPOSITION);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream)); rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -557,14 +557,14 @@ public class EntityMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static EntityMessage parsesetFacingMessage(List<Byte> byteStream){ public static EntityMessage parsesetFacingMessage(CircularByteBuffer byteBuffer){
EntityMessage rVal = new EntityMessage(EntityMessageType.SETFACING); EntityMessage rVal = new EntityMessage(EntityMessageType.SETFACING);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream)); rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
rVal.setrotationX(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setrotationX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setrotationY(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setrotationY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setrotationZ(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setrotationZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -579,20 +579,20 @@ public class EntityMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static EntityMessage parsemoveUpdateMessage(List<Byte> byteStream){ public static EntityMessage parsemoveUpdateMessage(CircularByteBuffer byteBuffer){
EntityMessage rVal = new EntityMessage(EntityMessageType.MOVEUPDATE); EntityMessage rVal = new EntityMessage(EntityMessageType.MOVEUPDATE);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream)); rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setrotationX(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setrotationX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setrotationY(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setrotationY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setrotationZ(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setrotationZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setrotationW(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setrotationW(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setvelocity(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setvelocity(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.settreeState(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.settreeState(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -613,19 +613,19 @@ public class EntityMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static EntityMessage parseattackUpdateMessage(List<Byte> byteStream){ public static EntityMessage parseattackUpdateMessage(CircularByteBuffer byteBuffer){
EntityMessage rVal = new EntityMessage(EntityMessageType.ATTACKUPDATE); EntityMessage rVal = new EntityMessage(EntityMessageType.ATTACKUPDATE);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream)); rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setrotationX(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setrotationX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setrotationY(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setrotationY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setrotationZ(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setrotationZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setvelocity(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setvelocity(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.settreeState(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.settreeState(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -645,14 +645,14 @@ public class EntityMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static EntityMessage parseMoveMessage(List<Byte> byteStream){ public static EntityMessage parseMoveMessage(CircularByteBuffer byteBuffer){
EntityMessage rVal = new EntityMessage(EntityMessageType.MOVE); EntityMessage rVal = new EntityMessage(EntityMessageType.MOVE);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream)); rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -667,11 +667,11 @@ public class EntityMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static EntityMessage parseKillMessage(List<Byte> byteStream){ public static EntityMessage parseKillMessage(CircularByteBuffer byteBuffer){
EntityMessage rVal = new EntityMessage(EntityMessageType.KILL); EntityMessage rVal = new EntityMessage(EntityMessageType.KILL);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream)); rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -683,10 +683,10 @@ public class EntityMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static EntityMessage parseDestroyMessage(List<Byte> byteStream){ public static EntityMessage parseDestroyMessage(CircularByteBuffer byteBuffer){
EntityMessage rVal = new EntityMessage(EntityMessageType.DESTROY); EntityMessage rVal = new EntityMessage(EntityMessageType.DESTROY);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -697,13 +697,13 @@ public class EntityMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static EntityMessage parseSetBehaviorTreeMessage(List<Byte> byteStream){ public static EntityMessage parseSetBehaviorTreeMessage(CircularByteBuffer byteBuffer){
EntityMessage rVal = new EntityMessage(EntityMessageType.SETBEHAVIORTREE); EntityMessage rVal = new EntityMessage(EntityMessageType.SETBEHAVIORTREE);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream)); rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
rVal.settreeType(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.settreeType(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.settreeStatus(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.settreeStatus(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -717,13 +717,13 @@ public class EntityMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static EntityMessage parsesetPropertyMessage(List<Byte> byteStream){ public static EntityMessage parsesetPropertyMessage(CircularByteBuffer byteBuffer){
EntityMessage rVal = new EntityMessage(EntityMessageType.SETPROPERTY); EntityMessage rVal = new EntityMessage(EntityMessageType.SETPROPERTY);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream)); rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
rVal.setpropertyType(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setpropertyType(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setpropertyValue(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setpropertyValue(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -737,14 +737,14 @@ public class EntityMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static EntityMessage parsesetBTreePropertyIntMessage(List<Byte> byteStream){ public static EntityMessage parsesetBTreePropertyIntMessage(CircularByteBuffer byteBuffer){
EntityMessage rVal = new EntityMessage(EntityMessageType.SETBTREEPROPERTYINT); EntityMessage rVal = new EntityMessage(EntityMessageType.SETBTREEPROPERTYINT);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream)); rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
rVal.setbTreeID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setbTreeID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setpropertyID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setpropertyID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setpropertyValueInt(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setpropertyValueInt(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -759,14 +759,14 @@ public class EntityMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static EntityMessage parsesetBTreePropertyFloatMessage(List<Byte> byteStream){ public static EntityMessage parsesetBTreePropertyFloatMessage(CircularByteBuffer byteBuffer){
EntityMessage rVal = new EntityMessage(EntityMessageType.SETBTREEPROPERTYFLOAT); EntityMessage rVal = new EntityMessage(EntityMessageType.SETBTREEPROPERTYFLOAT);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream)); rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
rVal.setbTreeID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setbTreeID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setpropertyID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setpropertyID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setpropertyValueFloat(ByteStreamUtils.popFloatFromByteQueue(byteStream)); rVal.setpropertyValueFloat(ByteStreamUtils.popFloatFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -781,14 +781,14 @@ public class EntityMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static EntityMessage parsesetBTreePropertyDoubleMessage(List<Byte> byteStream){ public static EntityMessage parsesetBTreePropertyDoubleMessage(CircularByteBuffer byteBuffer){
EntityMessage rVal = new EntityMessage(EntityMessageType.SETBTREEPROPERTYDOUBLE); EntityMessage rVal = new EntityMessage(EntityMessageType.SETBTREEPROPERTYDOUBLE);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream)); rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
rVal.setbTreeID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setbTreeID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setpropertyID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setpropertyID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setpropertyValueDouble(ByteStreamUtils.popDoubleFromByteQueue(byteStream)); rVal.setpropertyValueDouble(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -803,8 +803,8 @@ public class EntityMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static boolean canParsesetBTreePropertyStringMessage(List<Byte> byteStream){ public static boolean canParsesetBTreePropertyStringMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteStream.size(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
@ -822,10 +822,10 @@ public class EntityMessage extends NetworkMessage {
if(currentStreamLength < 26){ if(currentStreamLength < 26){
return false; return false;
} else { } else {
temporaryByteQueue.add(byteStream.get(22 + 0)); temporaryByteQueue.add(byteBuffer.peek(22 + 0));
temporaryByteQueue.add(byteStream.get(22 + 1)); temporaryByteQueue.add(byteBuffer.peek(22 + 1));
temporaryByteQueue.add(byteStream.get(22 + 2)); temporaryByteQueue.add(byteBuffer.peek(22 + 2));
temporaryByteQueue.add(byteStream.get(22 + 3)); temporaryByteQueue.add(byteBuffer.peek(22 + 3));
propertyValueStringSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue); propertyValueStringSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
} }
if(currentStreamLength < 26 + propertyValueStringSize){ if(currentStreamLength < 26 + propertyValueStringSize){
@ -834,14 +834,14 @@ public class EntityMessage extends NetworkMessage {
return true; return true;
} }
public static EntityMessage parsesetBTreePropertyStringMessage(List<Byte> byteStream){ public static EntityMessage parsesetBTreePropertyStringMessage(CircularByteBuffer byteBuffer){
EntityMessage rVal = new EntityMessage(EntityMessageType.SETBTREEPROPERTYSTRING); EntityMessage rVal = new EntityMessage(EntityMessageType.SETBTREEPROPERTYSTRING);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream)); rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
rVal.setbTreeID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setbTreeID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setpropertyID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setpropertyID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setpropertyValueString(ByteStreamUtils.popStringFromByteQueue(byteStream)); rVal.setpropertyValueString(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -856,14 +856,14 @@ public class EntityMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static EntityMessage parsesetBTreePropertyEnumMessage(List<Byte> byteStream){ public static EntityMessage parsesetBTreePropertyEnumMessage(CircularByteBuffer byteBuffer){
EntityMessage rVal = new EntityMessage(EntityMessageType.SETBTREEPROPERTYENUM); EntityMessage rVal = new EntityMessage(EntityMessageType.SETBTREEPROPERTYENUM);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream)); rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
rVal.setbTreeID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setbTreeID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setpropertyID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setpropertyID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setpropertyValueInt(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setpropertyValueInt(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -878,8 +878,8 @@ public class EntityMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static boolean canParseattachEntityToEntityMessage(List<Byte> byteStream){ public static boolean canParseattachEntityToEntityMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteStream.size(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
@ -888,10 +888,10 @@ public class EntityMessage extends NetworkMessage {
if(currentStreamLength < 10){ if(currentStreamLength < 10){
return false; return false;
} else { } else {
temporaryByteQueue.add(byteStream.get(6 + 0)); temporaryByteQueue.add(byteBuffer.peek(6 + 0));
temporaryByteQueue.add(byteStream.get(6 + 1)); temporaryByteQueue.add(byteBuffer.peek(6 + 1));
temporaryByteQueue.add(byteStream.get(6 + 2)); temporaryByteQueue.add(byteBuffer.peek(6 + 2));
temporaryByteQueue.add(byteStream.get(6 + 3)); temporaryByteQueue.add(byteBuffer.peek(6 + 3));
boneSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue); boneSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
} }
if(currentStreamLength < 10 + boneSize){ if(currentStreamLength < 10 + boneSize){
@ -903,12 +903,12 @@ public class EntityMessage extends NetworkMessage {
return true; return true;
} }
public static EntityMessage parseattachEntityToEntityMessage(List<Byte> byteStream){ public static EntityMessage parseattachEntityToEntityMessage(CircularByteBuffer byteBuffer){
EntityMessage rVal = new EntityMessage(EntityMessageType.ATTACHENTITYTOENTITY); EntityMessage rVal = new EntityMessage(EntityMessageType.ATTACHENTITYTOENTITY);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setbone(ByteStreamUtils.popStringFromByteQueue(byteStream)); rVal.setbone(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
rVal.settargetID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.settargetID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
return rVal; return rVal;
} }

View File

@ -1,6 +1,7 @@
package electrosphere.net.parser.net.message; package electrosphere.net.parser.net.message;
import electrosphere.net.parser.util.ByteStreamUtils; import electrosphere.net.parser.util.ByteStreamUtils;
import electrosphere.net.parser.net.raw.CircularByteBuffer;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -72,37 +73,36 @@ public class InventoryMessage extends NetworkMessage {
this.containerType = containerType; this.containerType = containerType;
} }
static void stripPacketHeader(List<Byte> byteStream){ static void stripPacketHeader(CircularByteBuffer byteBuffer){
byteStream.remove(0); byteBuffer.read(2);
byteStream.remove(0);
} }
public static boolean canParseMessage(List<Byte> byteStream, byte secondByte){ public static boolean canParseMessage(CircularByteBuffer byteBuffer, byte secondByte){
switch(secondByte){ switch(secondByte){
case TypeBytes.INVENTORY_MESSAGE_TYPE_ADDITEMTOINVENTORY: case TypeBytes.INVENTORY_MESSAGE_TYPE_ADDITEMTOINVENTORY:
return InventoryMessage.canParseaddItemToInventoryMessage(byteStream); return InventoryMessage.canParseaddItemToInventoryMessage(byteBuffer);
case TypeBytes.INVENTORY_MESSAGE_TYPE_REMOVEITEMFROMINVENTORY: case TypeBytes.INVENTORY_MESSAGE_TYPE_REMOVEITEMFROMINVENTORY:
if(byteStream.size() >= TypeBytes.INVENTORY_MESSAGE_TYPE_REMOVEITEMFROMINVENTORY_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.INVENTORY_MESSAGE_TYPE_REMOVEITEMFROMINVENTORY_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTEQUIPITEM: case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTEQUIPITEM:
return InventoryMessage.canParseclientRequestEquipItemMessage(byteStream); return InventoryMessage.canParseclientRequestEquipItemMessage(byteBuffer);
case TypeBytes.INVENTORY_MESSAGE_TYPE_SERVERCOMMANDMOVEITEMCONTAINER: case TypeBytes.INVENTORY_MESSAGE_TYPE_SERVERCOMMANDMOVEITEMCONTAINER:
return InventoryMessage.canParseserverCommandMoveItemContainerMessage(byteStream); return InventoryMessage.canParseserverCommandMoveItemContainerMessage(byteBuffer);
case TypeBytes.INVENTORY_MESSAGE_TYPE_SERVERCOMMANDEQUIPITEM: case TypeBytes.INVENTORY_MESSAGE_TYPE_SERVERCOMMANDEQUIPITEM:
return InventoryMessage.canParseserverCommandEquipItemMessage(byteStream); return InventoryMessage.canParseserverCommandEquipItemMessage(byteBuffer);
case TypeBytes.INVENTORY_MESSAGE_TYPE_SERVERCOMMANDUNEQUIPITEM: case TypeBytes.INVENTORY_MESSAGE_TYPE_SERVERCOMMANDUNEQUIPITEM:
return InventoryMessage.canParseserverCommandUnequipItemMessage(byteStream); return InventoryMessage.canParseserverCommandUnequipItemMessage(byteBuffer);
case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTUNEQUIPITEM: case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTUNEQUIPITEM:
return InventoryMessage.canParseclientRequestUnequipItemMessage(byteStream); return InventoryMessage.canParseclientRequestUnequipItemMessage(byteBuffer);
} }
return false; return false;
} }
public static boolean canParseaddItemToInventoryMessage(List<Byte> byteStream){ public static boolean canParseaddItemToInventoryMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteStream.size(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
@ -111,10 +111,10 @@ public class InventoryMessage extends NetworkMessage {
if(currentStreamLength < 10){ if(currentStreamLength < 10){
return false; return false;
} else { } else {
temporaryByteQueue.add(byteStream.get(6 + 0)); temporaryByteQueue.add(byteBuffer.peek(6 + 0));
temporaryByteQueue.add(byteStream.get(6 + 1)); temporaryByteQueue.add(byteBuffer.peek(6 + 1));
temporaryByteQueue.add(byteStream.get(6 + 2)); temporaryByteQueue.add(byteBuffer.peek(6 + 2));
temporaryByteQueue.add(byteStream.get(6 + 3)); temporaryByteQueue.add(byteBuffer.peek(6 + 3));
itemTemplateSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue); itemTemplateSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
} }
if(currentStreamLength < 10 + itemTemplateSize){ if(currentStreamLength < 10 + itemTemplateSize){
@ -123,11 +123,11 @@ public class InventoryMessage extends NetworkMessage {
return true; return true;
} }
public static InventoryMessage parseaddItemToInventoryMessage(List<Byte> byteStream){ public static InventoryMessage parseaddItemToInventoryMessage(CircularByteBuffer byteBuffer){
InventoryMessage rVal = new InventoryMessage(InventoryMessageType.ADDITEMTOINVENTORY); InventoryMessage rVal = new InventoryMessage(InventoryMessageType.ADDITEMTOINVENTORY);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setentityId(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityId(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setitemTemplate(ByteStreamUtils.popStringFromByteQueue(byteStream)); rVal.setitemTemplate(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -139,10 +139,10 @@ public class InventoryMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static InventoryMessage parseremoveItemFromInventoryMessage(List<Byte> byteStream){ public static InventoryMessage parseremoveItemFromInventoryMessage(CircularByteBuffer byteBuffer){
InventoryMessage rVal = new InventoryMessage(InventoryMessageType.REMOVEITEMFROMINVENTORY); InventoryMessage rVal = new InventoryMessage(InventoryMessageType.REMOVEITEMFROMINVENTORY);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setentityId(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityId(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -153,17 +153,17 @@ public class InventoryMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static boolean canParseclientRequestEquipItemMessage(List<Byte> byteStream){ public static boolean canParseclientRequestEquipItemMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteStream.size(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList();
int equipPointIdSize = 0; int equipPointIdSize = 0;
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} else { } else {
temporaryByteQueue.add(byteStream.get(2 + 0)); temporaryByteQueue.add(byteBuffer.peek(2 + 0));
temporaryByteQueue.add(byteStream.get(2 + 1)); temporaryByteQueue.add(byteBuffer.peek(2 + 1));
temporaryByteQueue.add(byteStream.get(2 + 2)); temporaryByteQueue.add(byteBuffer.peek(2 + 2));
temporaryByteQueue.add(byteStream.get(2 + 3)); temporaryByteQueue.add(byteBuffer.peek(2 + 3));
equipPointIdSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue); equipPointIdSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
} }
if(currentStreamLength < 6 + equipPointIdSize){ if(currentStreamLength < 6 + equipPointIdSize){
@ -175,11 +175,11 @@ public class InventoryMessage extends NetworkMessage {
return true; return true;
} }
public static InventoryMessage parseclientRequestEquipItemMessage(List<Byte> byteStream){ public static InventoryMessage parseclientRequestEquipItemMessage(CircularByteBuffer byteBuffer){
InventoryMessage rVal = new InventoryMessage(InventoryMessageType.CLIENTREQUESTEQUIPITEM); InventoryMessage rVal = new InventoryMessage(InventoryMessageType.CLIENTREQUESTEQUIPITEM);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setequipPointId(ByteStreamUtils.popStringFromByteQueue(byteStream)); rVal.setequipPointId(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
rVal.setentityId(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityId(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -191,8 +191,8 @@ public class InventoryMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static boolean canParseserverCommandMoveItemContainerMessage(List<Byte> byteStream){ public static boolean canParseserverCommandMoveItemContainerMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteStream.size(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
@ -204,10 +204,10 @@ public class InventoryMessage extends NetworkMessage {
if(currentStreamLength < 14){ if(currentStreamLength < 14){
return false; return false;
} else { } else {
temporaryByteQueue.add(byteStream.get(10 + 0)); temporaryByteQueue.add(byteBuffer.peek(10 + 0));
temporaryByteQueue.add(byteStream.get(10 + 1)); temporaryByteQueue.add(byteBuffer.peek(10 + 1));
temporaryByteQueue.add(byteStream.get(10 + 2)); temporaryByteQueue.add(byteBuffer.peek(10 + 2));
temporaryByteQueue.add(byteStream.get(10 + 3)); temporaryByteQueue.add(byteBuffer.peek(10 + 3));
equipPointIdSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue); equipPointIdSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
} }
if(currentStreamLength < 14 + equipPointIdSize){ if(currentStreamLength < 14 + equipPointIdSize){
@ -216,12 +216,12 @@ public class InventoryMessage extends NetworkMessage {
return true; return true;
} }
public static InventoryMessage parseserverCommandMoveItemContainerMessage(List<Byte> byteStream){ public static InventoryMessage parseserverCommandMoveItemContainerMessage(CircularByteBuffer byteBuffer){
InventoryMessage rVal = new InventoryMessage(InventoryMessageType.SERVERCOMMANDMOVEITEMCONTAINER); InventoryMessage rVal = new InventoryMessage(InventoryMessageType.SERVERCOMMANDMOVEITEMCONTAINER);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setentityId(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityId(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setcontainerType(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setcontainerType(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setequipPointId(ByteStreamUtils.popStringFromByteQueue(byteStream)); rVal.setequipPointId(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -234,8 +234,8 @@ public class InventoryMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static boolean canParseserverCommandEquipItemMessage(List<Byte> byteStream){ public static boolean canParseserverCommandEquipItemMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteStream.size(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
@ -244,10 +244,10 @@ public class InventoryMessage extends NetworkMessage {
if(currentStreamLength < 10){ if(currentStreamLength < 10){
return false; return false;
} else { } else {
temporaryByteQueue.add(byteStream.get(6 + 0)); temporaryByteQueue.add(byteBuffer.peek(6 + 0));
temporaryByteQueue.add(byteStream.get(6 + 1)); temporaryByteQueue.add(byteBuffer.peek(6 + 1));
temporaryByteQueue.add(byteStream.get(6 + 2)); temporaryByteQueue.add(byteBuffer.peek(6 + 2));
temporaryByteQueue.add(byteStream.get(6 + 3)); temporaryByteQueue.add(byteBuffer.peek(6 + 3));
equipPointIdSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue); equipPointIdSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
} }
if(currentStreamLength < 10 + equipPointIdSize){ if(currentStreamLength < 10 + equipPointIdSize){
@ -260,10 +260,10 @@ public class InventoryMessage extends NetworkMessage {
if(currentStreamLength < 18){ if(currentStreamLength < 18){
return false; return false;
} else { } else {
temporaryByteQueue.add(byteStream.get(14 + equipPointIdSize + 0)); temporaryByteQueue.add(byteBuffer.peek(14 + equipPointIdSize + 0));
temporaryByteQueue.add(byteStream.get(14 + equipPointIdSize + 1)); temporaryByteQueue.add(byteBuffer.peek(14 + equipPointIdSize + 1));
temporaryByteQueue.add(byteStream.get(14 + equipPointIdSize + 2)); temporaryByteQueue.add(byteBuffer.peek(14 + equipPointIdSize + 2));
temporaryByteQueue.add(byteStream.get(14 + equipPointIdSize + 3)); temporaryByteQueue.add(byteBuffer.peek(14 + equipPointIdSize + 3));
itemTemplateSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue); itemTemplateSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
} }
if(currentStreamLength < 18 + equipPointIdSize + itemTemplateSize){ if(currentStreamLength < 18 + equipPointIdSize + itemTemplateSize){
@ -272,13 +272,13 @@ public class InventoryMessage extends NetworkMessage {
return true; return true;
} }
public static InventoryMessage parseserverCommandEquipItemMessage(List<Byte> byteStream){ public static InventoryMessage parseserverCommandEquipItemMessage(CircularByteBuffer byteBuffer){
InventoryMessage rVal = new InventoryMessage(InventoryMessageType.SERVERCOMMANDEQUIPITEM); InventoryMessage rVal = new InventoryMessage(InventoryMessageType.SERVERCOMMANDEQUIPITEM);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setequipperId(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setequipperId(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setequipPointId(ByteStreamUtils.popStringFromByteQueue(byteStream)); rVal.setequipPointId(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
rVal.setentityId(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setentityId(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setitemTemplate(ByteStreamUtils.popStringFromByteQueue(byteStream)); rVal.setitemTemplate(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -292,8 +292,8 @@ public class InventoryMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static boolean canParseserverCommandUnequipItemMessage(List<Byte> byteStream){ public static boolean canParseserverCommandUnequipItemMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteStream.size(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList();
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
@ -302,10 +302,10 @@ public class InventoryMessage extends NetworkMessage {
if(currentStreamLength < 10){ if(currentStreamLength < 10){
return false; return false;
} else { } else {
temporaryByteQueue.add(byteStream.get(6 + 0)); temporaryByteQueue.add(byteBuffer.peek(6 + 0));
temporaryByteQueue.add(byteStream.get(6 + 1)); temporaryByteQueue.add(byteBuffer.peek(6 + 1));
temporaryByteQueue.add(byteStream.get(6 + 2)); temporaryByteQueue.add(byteBuffer.peek(6 + 2));
temporaryByteQueue.add(byteStream.get(6 + 3)); temporaryByteQueue.add(byteBuffer.peek(6 + 3));
equipPointIdSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue); equipPointIdSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
} }
if(currentStreamLength < 10 + equipPointIdSize){ if(currentStreamLength < 10 + equipPointIdSize){
@ -314,11 +314,11 @@ public class InventoryMessage extends NetworkMessage {
return true; return true;
} }
public static InventoryMessage parseserverCommandUnequipItemMessage(List<Byte> byteStream){ public static InventoryMessage parseserverCommandUnequipItemMessage(CircularByteBuffer byteBuffer){
InventoryMessage rVal = new InventoryMessage(InventoryMessageType.SERVERCOMMANDUNEQUIPITEM); InventoryMessage rVal = new InventoryMessage(InventoryMessageType.SERVERCOMMANDUNEQUIPITEM);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setequipperId(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setequipperId(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setequipPointId(ByteStreamUtils.popStringFromByteQueue(byteStream)); rVal.setequipPointId(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -330,17 +330,17 @@ public class InventoryMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static boolean canParseclientRequestUnequipItemMessage(List<Byte> byteStream){ public static boolean canParseclientRequestUnequipItemMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteStream.size(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList();
int equipPointIdSize = 0; int equipPointIdSize = 0;
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} else { } else {
temporaryByteQueue.add(byteStream.get(2 + 0)); temporaryByteQueue.add(byteBuffer.peek(2 + 0));
temporaryByteQueue.add(byteStream.get(2 + 1)); temporaryByteQueue.add(byteBuffer.peek(2 + 1));
temporaryByteQueue.add(byteStream.get(2 + 2)); temporaryByteQueue.add(byteBuffer.peek(2 + 2));
temporaryByteQueue.add(byteStream.get(2 + 3)); temporaryByteQueue.add(byteBuffer.peek(2 + 3));
equipPointIdSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue); equipPointIdSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
} }
if(currentStreamLength < 6 + equipPointIdSize){ if(currentStreamLength < 6 + equipPointIdSize){
@ -349,10 +349,10 @@ public class InventoryMessage extends NetworkMessage {
return true; return true;
} }
public static InventoryMessage parseclientRequestUnequipItemMessage(List<Byte> byteStream){ public static InventoryMessage parseclientRequestUnequipItemMessage(CircularByteBuffer byteBuffer){
InventoryMessage rVal = new InventoryMessage(InventoryMessageType.CLIENTREQUESTUNEQUIPITEM); InventoryMessage rVal = new InventoryMessage(InventoryMessageType.CLIENTREQUESTUNEQUIPITEM);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setequipPointId(ByteStreamUtils.popStringFromByteQueue(byteStream)); rVal.setequipPointId(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
return rVal; return rVal;
} }

View File

@ -1,6 +1,7 @@
package electrosphere.net.parser.net.message; package electrosphere.net.parser.net.message;
import electrosphere.net.parser.util.ByteStreamUtils; import electrosphere.net.parser.util.ByteStreamUtils;
import electrosphere.net.parser.net.raw.CircularByteBuffer;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -35,40 +36,39 @@ public class LoreMessage extends NetworkMessage {
this.data = data; this.data = data;
} }
static void stripPacketHeader(List<Byte> byteStream){ static void stripPacketHeader(CircularByteBuffer byteBuffer){
byteStream.remove(0); byteBuffer.read(2);
byteStream.remove(0);
} }
public static boolean canParseMessage(List<Byte> byteStream, byte secondByte){ public static boolean canParseMessage(CircularByteBuffer byteBuffer, byte secondByte){
switch(secondByte){ switch(secondByte){
case TypeBytes.LORE_MESSAGE_TYPE_REQUESTRACES: case TypeBytes.LORE_MESSAGE_TYPE_REQUESTRACES:
if(byteStream.size() >= TypeBytes.LORE_MESSAGE_TYPE_REQUESTRACES_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.LORE_MESSAGE_TYPE_REQUESTRACES_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.LORE_MESSAGE_TYPE_RESPONSERACES: case TypeBytes.LORE_MESSAGE_TYPE_RESPONSERACES:
return LoreMessage.canParseResponseRacesMessage(byteStream); return LoreMessage.canParseResponseRacesMessage(byteBuffer);
case TypeBytes.LORE_MESSAGE_TYPE_REQUESTRACEDATA: case TypeBytes.LORE_MESSAGE_TYPE_REQUESTRACEDATA:
if(byteStream.size() >= TypeBytes.LORE_MESSAGE_TYPE_REQUESTRACEDATA_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.LORE_MESSAGE_TYPE_REQUESTRACEDATA_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.LORE_MESSAGE_TYPE_RESPONSERACEDATA: case TypeBytes.LORE_MESSAGE_TYPE_RESPONSERACEDATA:
return LoreMessage.canParseResponseRaceDataMessage(byteStream); return LoreMessage.canParseResponseRaceDataMessage(byteBuffer);
case TypeBytes.LORE_MESSAGE_TYPE_REQUESTDATA: case TypeBytes.LORE_MESSAGE_TYPE_REQUESTDATA:
return LoreMessage.canParseRequestDataMessage(byteStream); return LoreMessage.canParseRequestDataMessage(byteBuffer);
case TypeBytes.LORE_MESSAGE_TYPE_RESPONSEDATA: case TypeBytes.LORE_MESSAGE_TYPE_RESPONSEDATA:
return LoreMessage.canParseResponseDataMessage(byteStream); return LoreMessage.canParseResponseDataMessage(byteBuffer);
} }
return false; return false;
} }
public static LoreMessage parseRequestRacesMessage(List<Byte> byteStream){ public static LoreMessage parseRequestRacesMessage(CircularByteBuffer byteBuffer){
LoreMessage rVal = new LoreMessage(LoreMessageType.REQUESTRACES); LoreMessage rVal = new LoreMessage(LoreMessageType.REQUESTRACES);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
return rVal; return rVal;
} }
@ -78,17 +78,17 @@ public class LoreMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static boolean canParseResponseRacesMessage(List<Byte> byteStream){ public static boolean canParseResponseRacesMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteStream.size(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList();
int dataSize = 0; int dataSize = 0;
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} else { } else {
temporaryByteQueue.add(byteStream.get(2 + 0)); temporaryByteQueue.add(byteBuffer.peek(2 + 0));
temporaryByteQueue.add(byteStream.get(2 + 1)); temporaryByteQueue.add(byteBuffer.peek(2 + 1));
temporaryByteQueue.add(byteStream.get(2 + 2)); temporaryByteQueue.add(byteBuffer.peek(2 + 2));
temporaryByteQueue.add(byteStream.get(2 + 3)); temporaryByteQueue.add(byteBuffer.peek(2 + 3));
dataSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue); dataSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
} }
if(currentStreamLength < 6 + dataSize){ if(currentStreamLength < 6 + dataSize){
@ -97,10 +97,10 @@ public class LoreMessage extends NetworkMessage {
return true; return true;
} }
public static LoreMessage parseResponseRacesMessage(List<Byte> byteStream){ public static LoreMessage parseResponseRacesMessage(CircularByteBuffer byteBuffer){
LoreMessage rVal = new LoreMessage(LoreMessageType.RESPONSERACES); LoreMessage rVal = new LoreMessage(LoreMessageType.RESPONSERACES);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setdata(ByteStreamUtils.popStringFromByteQueue(byteStream)); rVal.setdata(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -111,9 +111,9 @@ public class LoreMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static LoreMessage parseRequestRaceDataMessage(List<Byte> byteStream){ public static LoreMessage parseRequestRaceDataMessage(CircularByteBuffer byteBuffer){
LoreMessage rVal = new LoreMessage(LoreMessageType.REQUESTRACEDATA); LoreMessage rVal = new LoreMessage(LoreMessageType.REQUESTRACEDATA);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
return rVal; return rVal;
} }
@ -123,17 +123,17 @@ public class LoreMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static boolean canParseResponseRaceDataMessage(List<Byte> byteStream){ public static boolean canParseResponseRaceDataMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteStream.size(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList();
int dataSize = 0; int dataSize = 0;
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} else { } else {
temporaryByteQueue.add(byteStream.get(2 + 0)); temporaryByteQueue.add(byteBuffer.peek(2 + 0));
temporaryByteQueue.add(byteStream.get(2 + 1)); temporaryByteQueue.add(byteBuffer.peek(2 + 1));
temporaryByteQueue.add(byteStream.get(2 + 2)); temporaryByteQueue.add(byteBuffer.peek(2 + 2));
temporaryByteQueue.add(byteStream.get(2 + 3)); temporaryByteQueue.add(byteBuffer.peek(2 + 3));
dataSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue); dataSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
} }
if(currentStreamLength < 6 + dataSize){ if(currentStreamLength < 6 + dataSize){
@ -142,10 +142,10 @@ public class LoreMessage extends NetworkMessage {
return true; return true;
} }
public static LoreMessage parseResponseRaceDataMessage(List<Byte> byteStream){ public static LoreMessage parseResponseRaceDataMessage(CircularByteBuffer byteBuffer){
LoreMessage rVal = new LoreMessage(LoreMessageType.RESPONSERACEDATA); LoreMessage rVal = new LoreMessage(LoreMessageType.RESPONSERACEDATA);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setdata(ByteStreamUtils.popStringFromByteQueue(byteStream)); rVal.setdata(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -156,17 +156,17 @@ public class LoreMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static boolean canParseRequestDataMessage(List<Byte> byteStream){ public static boolean canParseRequestDataMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteStream.size(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList();
int dataSize = 0; int dataSize = 0;
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} else { } else {
temporaryByteQueue.add(byteStream.get(2 + 0)); temporaryByteQueue.add(byteBuffer.peek(2 + 0));
temporaryByteQueue.add(byteStream.get(2 + 1)); temporaryByteQueue.add(byteBuffer.peek(2 + 1));
temporaryByteQueue.add(byteStream.get(2 + 2)); temporaryByteQueue.add(byteBuffer.peek(2 + 2));
temporaryByteQueue.add(byteStream.get(2 + 3)); temporaryByteQueue.add(byteBuffer.peek(2 + 3));
dataSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue); dataSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
} }
if(currentStreamLength < 6 + dataSize){ if(currentStreamLength < 6 + dataSize){
@ -175,10 +175,10 @@ public class LoreMessage extends NetworkMessage {
return true; return true;
} }
public static LoreMessage parseRequestDataMessage(List<Byte> byteStream){ public static LoreMessage parseRequestDataMessage(CircularByteBuffer byteBuffer){
LoreMessage rVal = new LoreMessage(LoreMessageType.REQUESTDATA); LoreMessage rVal = new LoreMessage(LoreMessageType.REQUESTDATA);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setdata(ByteStreamUtils.popStringFromByteQueue(byteStream)); rVal.setdata(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -189,17 +189,17 @@ public class LoreMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static boolean canParseResponseDataMessage(List<Byte> byteStream){ public static boolean canParseResponseDataMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteStream.size(); int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList(); List<Byte> temporaryByteQueue = new LinkedList();
int dataSize = 0; int dataSize = 0;
if(currentStreamLength < 6){ if(currentStreamLength < 6){
return false; return false;
} else { } else {
temporaryByteQueue.add(byteStream.get(2 + 0)); temporaryByteQueue.add(byteBuffer.peek(2 + 0));
temporaryByteQueue.add(byteStream.get(2 + 1)); temporaryByteQueue.add(byteBuffer.peek(2 + 1));
temporaryByteQueue.add(byteStream.get(2 + 2)); temporaryByteQueue.add(byteBuffer.peek(2 + 2));
temporaryByteQueue.add(byteStream.get(2 + 3)); temporaryByteQueue.add(byteBuffer.peek(2 + 3));
dataSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue); dataSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
} }
if(currentStreamLength < 6 + dataSize){ if(currentStreamLength < 6 + dataSize){
@ -208,10 +208,10 @@ public class LoreMessage extends NetworkMessage {
return true; return true;
} }
public static LoreMessage parseResponseDataMessage(List<Byte> byteStream){ public static LoreMessage parseResponseDataMessage(CircularByteBuffer byteBuffer){
LoreMessage rVal = new LoreMessage(LoreMessageType.RESPONSEDATA); LoreMessage rVal = new LoreMessage(LoreMessageType.RESPONSEDATA);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setdata(ByteStreamUtils.popStringFromByteQueue(byteStream)); rVal.setdata(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
return rVal; return rVal;
} }

View File

@ -1,6 +1,8 @@
package electrosphere.net.parser.net.message; package electrosphere.net.parser.net.message;
import electrosphere.net.parser.util.ByteStreamUtils; import electrosphere.net.parser.util.ByteStreamUtils;
import electrosphere.net.parser.net.raw.CircularByteBuffer;
import java.util.List; import java.util.List;
public abstract class NetworkMessage { public abstract class NetworkMessage {
@ -28,329 +30,314 @@ INVENTORY_MESSAGE,
return rawBytes; return rawBytes;
} }
public static NetworkMessage parseBytestreamForMessage(List<Byte> byteStream){ public static NetworkMessage parseBytestreamForMessage(CircularByteBuffer byteBuffer){
NetworkMessage rVal = null; NetworkMessage rVal = null;
byte firstByte; byte firstByte;
byte secondByte; byte secondByte;
if(byteStream.size() > 1){ if(byteBuffer.getRemaining() > 1){
firstByte = byteStream.get(0); firstByte = byteBuffer.peek();
switch(firstByte){ switch(firstByte){
case TypeBytes.MESSAGE_TYPE_ENTITY: case TypeBytes.MESSAGE_TYPE_ENTITY:
secondByte = byteStream.get(1); secondByte = byteBuffer.peek(1);
switch(secondByte){ switch(secondByte){
case TypeBytes.ENTITY_MESSAGE_TYPE_CREATE: case TypeBytes.ENTITY_MESSAGE_TYPE_CREATE:
if(EntityMessage.canParseMessage(byteStream,secondByte)){ if(EntityMessage.canParseMessage(byteBuffer,secondByte)){
rVal = EntityMessage.parseCreateMessage(byteStream); rVal = EntityMessage.parseCreateMessage(byteBuffer);
} }
break; break;
case TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNCREATURE: case TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNCREATURE:
if(EntityMessage.canParseMessage(byteStream,secondByte)){ if(EntityMessage.canParseMessage(byteBuffer,secondByte)){
rVal = EntityMessage.parseSpawnCreatureMessage(byteStream); rVal = EntityMessage.parseSpawnCreatureMessage(byteBuffer);
} }
break; break;
case TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNITEM: case TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNITEM:
if(EntityMessage.canParseMessage(byteStream,secondByte)){ if(EntityMessage.canParseMessage(byteBuffer,secondByte)){
rVal = EntityMessage.parseSpawnItemMessage(byteStream); rVal = EntityMessage.parseSpawnItemMessage(byteBuffer);
} }
break; break;
case TypeBytes.ENTITY_MESSAGE_TYPE_SETPOSITION: case TypeBytes.ENTITY_MESSAGE_TYPE_SETPOSITION:
if(EntityMessage.canParseMessage(byteStream,secondByte)){ if(EntityMessage.canParseMessage(byteBuffer,secondByte)){
rVal = EntityMessage.parseSetPositionMessage(byteStream); rVal = EntityMessage.parseSetPositionMessage(byteBuffer);
} }
break; break;
case TypeBytes.ENTITY_MESSAGE_TYPE_SETFACING: case TypeBytes.ENTITY_MESSAGE_TYPE_SETFACING:
if(EntityMessage.canParseMessage(byteStream,secondByte)){ if(EntityMessage.canParseMessage(byteBuffer,secondByte)){
rVal = EntityMessage.parsesetFacingMessage(byteStream); rVal = EntityMessage.parsesetFacingMessage(byteBuffer);
} }
break; break;
case TypeBytes.ENTITY_MESSAGE_TYPE_MOVEUPDATE: case TypeBytes.ENTITY_MESSAGE_TYPE_MOVEUPDATE:
if(EntityMessage.canParseMessage(byteStream,secondByte)){ if(EntityMessage.canParseMessage(byteBuffer,secondByte)){
rVal = EntityMessage.parsemoveUpdateMessage(byteStream); rVal = EntityMessage.parsemoveUpdateMessage(byteBuffer);
} }
break; break;
case TypeBytes.ENTITY_MESSAGE_TYPE_ATTACKUPDATE: case TypeBytes.ENTITY_MESSAGE_TYPE_ATTACKUPDATE:
if(EntityMessage.canParseMessage(byteStream,secondByte)){ if(EntityMessage.canParseMessage(byteBuffer,secondByte)){
rVal = EntityMessage.parseattackUpdateMessage(byteStream); rVal = EntityMessage.parseattackUpdateMessage(byteBuffer);
} }
break; break;
case TypeBytes.ENTITY_MESSAGE_TYPE_MOVE: case TypeBytes.ENTITY_MESSAGE_TYPE_MOVE:
if(EntityMessage.canParseMessage(byteStream,secondByte)){ if(EntityMessage.canParseMessage(byteBuffer,secondByte)){
rVal = EntityMessage.parseMoveMessage(byteStream); rVal = EntityMessage.parseMoveMessage(byteBuffer);
} }
break; break;
case TypeBytes.ENTITY_MESSAGE_TYPE_KILL: case TypeBytes.ENTITY_MESSAGE_TYPE_KILL:
if(EntityMessage.canParseMessage(byteStream,secondByte)){ if(EntityMessage.canParseMessage(byteBuffer,secondByte)){
rVal = EntityMessage.parseKillMessage(byteStream); rVal = EntityMessage.parseKillMessage(byteBuffer);
} }
break; break;
case TypeBytes.ENTITY_MESSAGE_TYPE_DESTROY: case TypeBytes.ENTITY_MESSAGE_TYPE_DESTROY:
if(EntityMessage.canParseMessage(byteStream,secondByte)){ if(EntityMessage.canParseMessage(byteBuffer,secondByte)){
rVal = EntityMessage.parseDestroyMessage(byteStream); rVal = EntityMessage.parseDestroyMessage(byteBuffer);
} }
break; break;
case TypeBytes.ENTITY_MESSAGE_TYPE_SETBEHAVIORTREE: case TypeBytes.ENTITY_MESSAGE_TYPE_SETBEHAVIORTREE:
if(EntityMessage.canParseMessage(byteStream,secondByte)){ if(EntityMessage.canParseMessage(byteBuffer,secondByte)){
rVal = EntityMessage.parseSetBehaviorTreeMessage(byteStream); rVal = EntityMessage.parseSetBehaviorTreeMessage(byteBuffer);
} }
break; break;
case TypeBytes.ENTITY_MESSAGE_TYPE_SETPROPERTY: case TypeBytes.ENTITY_MESSAGE_TYPE_SETPROPERTY:
if(EntityMessage.canParseMessage(byteStream,secondByte)){ if(EntityMessage.canParseMessage(byteBuffer,secondByte)){
rVal = EntityMessage.parsesetPropertyMessage(byteStream); rVal = EntityMessage.parsesetPropertyMessage(byteBuffer);
} }
break; break;
case TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYINT: case TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYINT:
if(EntityMessage.canParseMessage(byteStream,secondByte)){ if(EntityMessage.canParseMessage(byteBuffer,secondByte)){
rVal = EntityMessage.parsesetBTreePropertyIntMessage(byteStream); rVal = EntityMessage.parsesetBTreePropertyIntMessage(byteBuffer);
} }
break; break;
case TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYFLOAT: case TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYFLOAT:
if(EntityMessage.canParseMessage(byteStream,secondByte)){ if(EntityMessage.canParseMessage(byteBuffer,secondByte)){
rVal = EntityMessage.parsesetBTreePropertyFloatMessage(byteStream); rVal = EntityMessage.parsesetBTreePropertyFloatMessage(byteBuffer);
} }
break; break;
case TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYDOUBLE: case TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYDOUBLE:
if(EntityMessage.canParseMessage(byteStream,secondByte)){ if(EntityMessage.canParseMessage(byteBuffer,secondByte)){
rVal = EntityMessage.parsesetBTreePropertyDoubleMessage(byteStream); rVal = EntityMessage.parsesetBTreePropertyDoubleMessage(byteBuffer);
} }
break; break;
case TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYSTRING: case TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYSTRING:
if(EntityMessage.canParseMessage(byteStream,secondByte)){ if(EntityMessage.canParseMessage(byteBuffer,secondByte)){
rVal = EntityMessage.parsesetBTreePropertyStringMessage(byteStream); rVal = EntityMessage.parsesetBTreePropertyStringMessage(byteBuffer);
} }
break; break;
case TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYENUM: case TypeBytes.ENTITY_MESSAGE_TYPE_SETBTREEPROPERTYENUM:
if(EntityMessage.canParseMessage(byteStream,secondByte)){ if(EntityMessage.canParseMessage(byteBuffer,secondByte)){
rVal = EntityMessage.parsesetBTreePropertyEnumMessage(byteStream); rVal = EntityMessage.parsesetBTreePropertyEnumMessage(byteBuffer);
} }
break; break;
case TypeBytes.ENTITY_MESSAGE_TYPE_ATTACHENTITYTOENTITY: case TypeBytes.ENTITY_MESSAGE_TYPE_ATTACHENTITYTOENTITY:
if(EntityMessage.canParseMessage(byteStream,secondByte)){ if(EntityMessage.canParseMessage(byteBuffer,secondByte)){
rVal = EntityMessage.parseattachEntityToEntityMessage(byteStream); rVal = EntityMessage.parseattachEntityToEntityMessage(byteBuffer);
} }
break; break;
} }
break; break;
case TypeBytes.MESSAGE_TYPE_LORE: case TypeBytes.MESSAGE_TYPE_LORE:
secondByte = byteStream.get(1); secondByte = byteBuffer.peek(1);
switch(secondByte){ switch(secondByte){
case TypeBytes.LORE_MESSAGE_TYPE_REQUESTRACES: case TypeBytes.LORE_MESSAGE_TYPE_REQUESTRACES:
if(LoreMessage.canParseMessage(byteStream,secondByte)){ if(LoreMessage.canParseMessage(byteBuffer,secondByte)){
rVal = LoreMessage.parseRequestRacesMessage(byteStream); rVal = LoreMessage.parseRequestRacesMessage(byteBuffer);
} }
break; break;
case TypeBytes.LORE_MESSAGE_TYPE_RESPONSERACES: case TypeBytes.LORE_MESSAGE_TYPE_RESPONSERACES:
if(LoreMessage.canParseMessage(byteStream,secondByte)){ if(LoreMessage.canParseMessage(byteBuffer,secondByte)){
rVal = LoreMessage.parseResponseRacesMessage(byteStream); rVal = LoreMessage.parseResponseRacesMessage(byteBuffer);
} }
break; break;
case TypeBytes.LORE_MESSAGE_TYPE_REQUESTRACEDATA: case TypeBytes.LORE_MESSAGE_TYPE_REQUESTRACEDATA:
if(LoreMessage.canParseMessage(byteStream,secondByte)){ if(LoreMessage.canParseMessage(byteBuffer,secondByte)){
rVal = LoreMessage.parseRequestRaceDataMessage(byteStream); rVal = LoreMessage.parseRequestRaceDataMessage(byteBuffer);
} }
break; break;
case TypeBytes.LORE_MESSAGE_TYPE_RESPONSERACEDATA: case TypeBytes.LORE_MESSAGE_TYPE_RESPONSERACEDATA:
if(LoreMessage.canParseMessage(byteStream,secondByte)){ if(LoreMessage.canParseMessage(byteBuffer,secondByte)){
rVal = LoreMessage.parseResponseRaceDataMessage(byteStream); rVal = LoreMessage.parseResponseRaceDataMessage(byteBuffer);
} }
break; break;
case TypeBytes.LORE_MESSAGE_TYPE_REQUESTDATA: case TypeBytes.LORE_MESSAGE_TYPE_REQUESTDATA:
if(LoreMessage.canParseMessage(byteStream,secondByte)){ if(LoreMessage.canParseMessage(byteBuffer,secondByte)){
rVal = LoreMessage.parseRequestDataMessage(byteStream); rVal = LoreMessage.parseRequestDataMessage(byteBuffer);
} }
break; break;
case TypeBytes.LORE_MESSAGE_TYPE_RESPONSEDATA: case TypeBytes.LORE_MESSAGE_TYPE_RESPONSEDATA:
if(LoreMessage.canParseMessage(byteStream,secondByte)){ if(LoreMessage.canParseMessage(byteBuffer,secondByte)){
rVal = LoreMessage.parseResponseDataMessage(byteStream); rVal = LoreMessage.parseResponseDataMessage(byteBuffer);
} }
break; break;
} }
break; break;
case TypeBytes.MESSAGE_TYPE_PLAYER: case TypeBytes.MESSAGE_TYPE_PLAYER:
secondByte = byteStream.get(1); secondByte = byteBuffer.peek(1);
switch(secondByte){ switch(secondByte){
case TypeBytes.PLAYER_MESSAGE_TYPE_SET_ID: case TypeBytes.PLAYER_MESSAGE_TYPE_SET_ID:
if(PlayerMessage.canParseMessage(byteStream,secondByte)){ if(PlayerMessage.canParseMessage(byteBuffer,secondByte)){
rVal = PlayerMessage.parseSet_IDMessage(byteStream); rVal = PlayerMessage.parseSet_IDMessage(byteBuffer);
} }
break; break;
case TypeBytes.PLAYER_MESSAGE_TYPE_SETINITIALDISCRETEPOSITION: case TypeBytes.PLAYER_MESSAGE_TYPE_SETINITIALDISCRETEPOSITION:
if(PlayerMessage.canParseMessage(byteStream,secondByte)){ if(PlayerMessage.canParseMessage(byteBuffer,secondByte)){
rVal = PlayerMessage.parseSetInitialDiscretePositionMessage(byteStream); rVal = PlayerMessage.parseSetInitialDiscretePositionMessage(byteBuffer);
} }
break; break;
} }
break; break;
case TypeBytes.MESSAGE_TYPE_TERRAIN: case TypeBytes.MESSAGE_TYPE_TERRAIN:
secondByte = byteStream.get(1); secondByte = byteBuffer.peek(1);
switch(secondByte){ switch(secondByte){
case TypeBytes.TERRAIN_MESSAGE_TYPE_REQUESTMETADATA: case TypeBytes.TERRAIN_MESSAGE_TYPE_REQUESTMETADATA:
if(TerrainMessage.canParseMessage(byteStream,secondByte)){ if(TerrainMessage.canParseMessage(byteBuffer,secondByte)){
rVal = TerrainMessage.parseRequestMetadataMessage(byteStream); rVal = TerrainMessage.parseRequestMetadataMessage(byteBuffer);
} }
break; break;
case TypeBytes.TERRAIN_MESSAGE_TYPE_RESPONSEMETADATA: case TypeBytes.TERRAIN_MESSAGE_TYPE_RESPONSEMETADATA:
if(TerrainMessage.canParseMessage(byteStream,secondByte)){ if(TerrainMessage.canParseMessage(byteBuffer,secondByte)){
rVal = TerrainMessage.parseResponseMetadataMessage(byteStream); rVal = TerrainMessage.parseResponseMetadataMessage(byteBuffer);
} }
break; break;
case TypeBytes.TERRAIN_MESSAGE_TYPE_REQUESTCHUNK: case TypeBytes.TERRAIN_MESSAGE_TYPE_REQUESTCHUNK:
if(TerrainMessage.canParseMessage(byteStream,secondByte)){ if(TerrainMessage.canParseMessage(byteBuffer,secondByte)){
rVal = TerrainMessage.parseRequestChunkMessage(byteStream); rVal = TerrainMessage.parseRequestChunkMessage(byteBuffer);
} }
break; break;
case TypeBytes.TERRAIN_MESSAGE_TYPE_UPDATE: case TypeBytes.TERRAIN_MESSAGE_TYPE_UPDATE:
if(TerrainMessage.canParseMessage(byteStream,secondByte)){ if(TerrainMessage.canParseMessage(byteBuffer,secondByte)){
rVal = TerrainMessage.parseUpdateMessage(byteStream); rVal = TerrainMessage.parseUpdateMessage(byteBuffer);
}
break;
case TypeBytes.TERRAIN_MESSAGE_TYPE_CHUNKLOADSTART:
if(TerrainMessage.canParseMessage(byteStream,secondByte)){
rVal = TerrainMessage.parsechunkLoadStartMessage(byteStream);
}
break;
case TypeBytes.TERRAIN_MESSAGE_TYPE_MACROVALUE:
if(TerrainMessage.canParseMessage(byteStream,secondByte)){
rVal = TerrainMessage.parseMacroValueMessage(byteStream);
}
break;
case TypeBytes.TERRAIN_MESSAGE_TYPE_HEIGHTMAPMODIFICATION:
if(TerrainMessage.canParseMessage(byteStream,secondByte)){
rVal = TerrainMessage.parseheightMapModificationMessage(byteStream);
} }
break; break;
case TypeBytes.TERRAIN_MESSAGE_TYPE_SPAWNPOSITION: case TypeBytes.TERRAIN_MESSAGE_TYPE_SPAWNPOSITION:
if(TerrainMessage.canParseMessage(byteStream,secondByte)){ if(TerrainMessage.canParseMessage(byteBuffer,secondByte)){
rVal = TerrainMessage.parseSpawnPositionMessage(byteStream); rVal = TerrainMessage.parseSpawnPositionMessage(byteBuffer);
} }
break; break;
case TypeBytes.TERRAIN_MESSAGE_TYPE_REQUESTCHUNKDATA: case TypeBytes.TERRAIN_MESSAGE_TYPE_REQUESTCHUNKDATA:
if(TerrainMessage.canParseMessage(byteStream,secondByte)){ if(TerrainMessage.canParseMessage(byteBuffer,secondByte)){
rVal = TerrainMessage.parseRequestChunkDataMessage(byteStream); rVal = TerrainMessage.parseRequestChunkDataMessage(byteBuffer);
} }
break; break;
case TypeBytes.TERRAIN_MESSAGE_TYPE_SENDCHUNKDATA: case TypeBytes.TERRAIN_MESSAGE_TYPE_SENDCHUNKDATA:
if(TerrainMessage.canParseMessage(byteStream,secondByte)){ if(TerrainMessage.canParseMessage(byteBuffer,secondByte)){
rVal = TerrainMessage.parsesendChunkDataMessage(byteStream); rVal = TerrainMessage.parsesendChunkDataMessage(byteBuffer);
} }
break; break;
} }
break; break;
case TypeBytes.MESSAGE_TYPE_SERVER: case TypeBytes.MESSAGE_TYPE_SERVER:
secondByte = byteStream.get(1); secondByte = byteBuffer.peek(1);
switch(secondByte){ switch(secondByte){
case TypeBytes.SERVER_MESSAGE_TYPE_PING: case TypeBytes.SERVER_MESSAGE_TYPE_PING:
if(ServerMessage.canParseMessage(byteStream,secondByte)){ if(ServerMessage.canParseMessage(byteBuffer,secondByte)){
rVal = ServerMessage.parsePingMessage(byteStream); rVal = ServerMessage.parsePingMessage(byteBuffer);
} }
break; break;
case TypeBytes.SERVER_MESSAGE_TYPE_PONG: case TypeBytes.SERVER_MESSAGE_TYPE_PONG:
if(ServerMessage.canParseMessage(byteStream,secondByte)){ if(ServerMessage.canParseMessage(byteBuffer,secondByte)){
rVal = ServerMessage.parsePongMessage(byteStream); rVal = ServerMessage.parsePongMessage(byteBuffer);
} }
break; break;
} }
break; break;
case TypeBytes.MESSAGE_TYPE_AUTH: case TypeBytes.MESSAGE_TYPE_AUTH:
secondByte = byteStream.get(1); secondByte = byteBuffer.peek(1);
switch(secondByte){ switch(secondByte){
case TypeBytes.AUTH_MESSAGE_TYPE_AUTHREQUEST: case TypeBytes.AUTH_MESSAGE_TYPE_AUTHREQUEST:
if(AuthMessage.canParseMessage(byteStream,secondByte)){ if(AuthMessage.canParseMessage(byteBuffer,secondByte)){
rVal = AuthMessage.parseAuthRequestMessage(byteStream); rVal = AuthMessage.parseAuthRequestMessage(byteBuffer);
} }
break; break;
case TypeBytes.AUTH_MESSAGE_TYPE_AUTHDETAILS: case TypeBytes.AUTH_MESSAGE_TYPE_AUTHDETAILS:
if(AuthMessage.canParseMessage(byteStream,secondByte)){ if(AuthMessage.canParseMessage(byteBuffer,secondByte)){
rVal = AuthMessage.parseAuthDetailsMessage(byteStream); rVal = AuthMessage.parseAuthDetailsMessage(byteBuffer);
} }
break; break;
case TypeBytes.AUTH_MESSAGE_TYPE_AUTHSUCCESS: case TypeBytes.AUTH_MESSAGE_TYPE_AUTHSUCCESS:
if(AuthMessage.canParseMessage(byteStream,secondByte)){ if(AuthMessage.canParseMessage(byteBuffer,secondByte)){
rVal = AuthMessage.parseAuthSuccessMessage(byteStream); rVal = AuthMessage.parseAuthSuccessMessage(byteBuffer);
} }
break; break;
case TypeBytes.AUTH_MESSAGE_TYPE_AUTHFAILURE: case TypeBytes.AUTH_MESSAGE_TYPE_AUTHFAILURE:
if(AuthMessage.canParseMessage(byteStream,secondByte)){ if(AuthMessage.canParseMessage(byteBuffer,secondByte)){
rVal = AuthMessage.parseAuthFailureMessage(byteStream); rVal = AuthMessage.parseAuthFailureMessage(byteBuffer);
} }
break; break;
} }
break; break;
case TypeBytes.MESSAGE_TYPE_CHARACTER: case TypeBytes.MESSAGE_TYPE_CHARACTER:
secondByte = byteStream.get(1); secondByte = byteBuffer.peek(1);
switch(secondByte){ switch(secondByte){
case TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTCHARACTERLIST: case TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTCHARACTERLIST:
if(CharacterMessage.canParseMessage(byteStream,secondByte)){ if(CharacterMessage.canParseMessage(byteBuffer,secondByte)){
rVal = CharacterMessage.parseRequestCharacterListMessage(byteStream); rVal = CharacterMessage.parseRequestCharacterListMessage(byteBuffer);
} }
break; break;
case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECHARACTERLIST: case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECHARACTERLIST:
if(CharacterMessage.canParseMessage(byteStream,secondByte)){ if(CharacterMessage.canParseMessage(byteBuffer,secondByte)){
rVal = CharacterMessage.parseResponseCharacterListMessage(byteStream); rVal = CharacterMessage.parseResponseCharacterListMessage(byteBuffer);
} }
break; break;
case TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTCREATECHARACTER: case TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTCREATECHARACTER:
if(CharacterMessage.canParseMessage(byteStream,secondByte)){ if(CharacterMessage.canParseMessage(byteBuffer,secondByte)){
rVal = CharacterMessage.parseRequestCreateCharacterMessage(byteStream); rVal = CharacterMessage.parseRequestCreateCharacterMessage(byteBuffer);
} }
break; break;
case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERSUCCESS: case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERSUCCESS:
if(CharacterMessage.canParseMessage(byteStream,secondByte)){ if(CharacterMessage.canParseMessage(byteBuffer,secondByte)){
rVal = CharacterMessage.parseResponseCreateCharacterSuccessMessage(byteStream); rVal = CharacterMessage.parseResponseCreateCharacterSuccessMessage(byteBuffer);
} }
break; break;
case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERFAILURE: case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSECREATECHARACTERFAILURE:
if(CharacterMessage.canParseMessage(byteStream,secondByte)){ if(CharacterMessage.canParseMessage(byteBuffer,secondByte)){
rVal = CharacterMessage.parseResponseCreateCharacterFailureMessage(byteStream); rVal = CharacterMessage.parseResponseCreateCharacterFailureMessage(byteBuffer);
} }
break; break;
case TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTSPAWNCHARACTER: case TypeBytes.CHARACTER_MESSAGE_TYPE_REQUESTSPAWNCHARACTER:
if(CharacterMessage.canParseMessage(byteStream,secondByte)){ if(CharacterMessage.canParseMessage(byteBuffer,secondByte)){
rVal = CharacterMessage.parseRequestSpawnCharacterMessage(byteStream); rVal = CharacterMessage.parseRequestSpawnCharacterMessage(byteBuffer);
} }
break; break;
case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSESPAWNCHARACTER: case TypeBytes.CHARACTER_MESSAGE_TYPE_RESPONSESPAWNCHARACTER:
if(CharacterMessage.canParseMessage(byteStream,secondByte)){ if(CharacterMessage.canParseMessage(byteBuffer,secondByte)){
rVal = CharacterMessage.parseResponseSpawnCharacterMessage(byteStream); rVal = CharacterMessage.parseResponseSpawnCharacterMessage(byteBuffer);
} }
break; break;
} }
break; break;
case TypeBytes.MESSAGE_TYPE_INVENTORY: case TypeBytes.MESSAGE_TYPE_INVENTORY:
secondByte = byteStream.get(1); secondByte = byteBuffer.peek(1);
switch(secondByte){ switch(secondByte){
case TypeBytes.INVENTORY_MESSAGE_TYPE_ADDITEMTOINVENTORY: case TypeBytes.INVENTORY_MESSAGE_TYPE_ADDITEMTOINVENTORY:
if(InventoryMessage.canParseMessage(byteStream,secondByte)){ if(InventoryMessage.canParseMessage(byteBuffer,secondByte)){
rVal = InventoryMessage.parseaddItemToInventoryMessage(byteStream); rVal = InventoryMessage.parseaddItemToInventoryMessage(byteBuffer);
} }
break; break;
case TypeBytes.INVENTORY_MESSAGE_TYPE_REMOVEITEMFROMINVENTORY: case TypeBytes.INVENTORY_MESSAGE_TYPE_REMOVEITEMFROMINVENTORY:
if(InventoryMessage.canParseMessage(byteStream,secondByte)){ if(InventoryMessage.canParseMessage(byteBuffer,secondByte)){
rVal = InventoryMessage.parseremoveItemFromInventoryMessage(byteStream); rVal = InventoryMessage.parseremoveItemFromInventoryMessage(byteBuffer);
} }
break; break;
case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTEQUIPITEM: case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTEQUIPITEM:
if(InventoryMessage.canParseMessage(byteStream,secondByte)){ if(InventoryMessage.canParseMessage(byteBuffer,secondByte)){
rVal = InventoryMessage.parseclientRequestEquipItemMessage(byteStream); rVal = InventoryMessage.parseclientRequestEquipItemMessage(byteBuffer);
} }
break; break;
case TypeBytes.INVENTORY_MESSAGE_TYPE_SERVERCOMMANDMOVEITEMCONTAINER: case TypeBytes.INVENTORY_MESSAGE_TYPE_SERVERCOMMANDMOVEITEMCONTAINER:
if(InventoryMessage.canParseMessage(byteStream,secondByte)){ if(InventoryMessage.canParseMessage(byteBuffer,secondByte)){
rVal = InventoryMessage.parseserverCommandMoveItemContainerMessage(byteStream); rVal = InventoryMessage.parseserverCommandMoveItemContainerMessage(byteBuffer);
} }
break; break;
case TypeBytes.INVENTORY_MESSAGE_TYPE_SERVERCOMMANDEQUIPITEM: case TypeBytes.INVENTORY_MESSAGE_TYPE_SERVERCOMMANDEQUIPITEM:
if(InventoryMessage.canParseMessage(byteStream,secondByte)){ if(InventoryMessage.canParseMessage(byteBuffer,secondByte)){
rVal = InventoryMessage.parseserverCommandEquipItemMessage(byteStream); rVal = InventoryMessage.parseserverCommandEquipItemMessage(byteBuffer);
} }
break; break;
case TypeBytes.INVENTORY_MESSAGE_TYPE_SERVERCOMMANDUNEQUIPITEM: case TypeBytes.INVENTORY_MESSAGE_TYPE_SERVERCOMMANDUNEQUIPITEM:
if(InventoryMessage.canParseMessage(byteStream,secondByte)){ if(InventoryMessage.canParseMessage(byteBuffer,secondByte)){
rVal = InventoryMessage.parseserverCommandUnequipItemMessage(byteStream); rVal = InventoryMessage.parseserverCommandUnequipItemMessage(byteBuffer);
} }
break; break;
case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTUNEQUIPITEM: case TypeBytes.INVENTORY_MESSAGE_TYPE_CLIENTREQUESTUNEQUIPITEM:
if(InventoryMessage.canParseMessage(byteStream,secondByte)){ if(InventoryMessage.canParseMessage(byteBuffer,secondByte)){
rVal = InventoryMessage.parseclientRequestUnequipItemMessage(byteStream); rVal = InventoryMessage.parseclientRequestUnequipItemMessage(byteBuffer);
} }
break; break;
} }

View File

@ -1,6 +1,7 @@
package electrosphere.net.parser.net.message; package electrosphere.net.parser.net.message;
import electrosphere.net.parser.util.ByteStreamUtils; import electrosphere.net.parser.util.ByteStreamUtils;
import electrosphere.net.parser.net.raw.CircularByteBuffer;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -58,21 +59,20 @@ public class PlayerMessage extends NetworkMessage {
this.initialDiscretePositionZ = initialDiscretePositionZ; this.initialDiscretePositionZ = initialDiscretePositionZ;
} }
static void stripPacketHeader(List<Byte> byteStream){ static void stripPacketHeader(CircularByteBuffer byteBuffer){
byteStream.remove(0); byteBuffer.read(2);
byteStream.remove(0);
} }
public static boolean canParseMessage(List<Byte> byteStream, byte secondByte){ public static boolean canParseMessage(CircularByteBuffer byteBuffer, byte secondByte){
switch(secondByte){ switch(secondByte){
case TypeBytes.PLAYER_MESSAGE_TYPE_SET_ID: case TypeBytes.PLAYER_MESSAGE_TYPE_SET_ID:
if(byteStream.size() >= TypeBytes.PLAYER_MESSAGE_TYPE_SET_ID_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.PLAYER_MESSAGE_TYPE_SET_ID_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.PLAYER_MESSAGE_TYPE_SETINITIALDISCRETEPOSITION: case TypeBytes.PLAYER_MESSAGE_TYPE_SETINITIALDISCRETEPOSITION:
if(byteStream.size() >= TypeBytes.PLAYER_MESSAGE_TYPE_SETINITIALDISCRETEPOSITION_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.PLAYER_MESSAGE_TYPE_SETINITIALDISCRETEPOSITION_SIZE){
return true; return true;
} else { } else {
return false; return false;
@ -81,10 +81,10 @@ public class PlayerMessage extends NetworkMessage {
return false; return false;
} }
public static PlayerMessage parseSet_IDMessage(List<Byte> byteStream){ public static PlayerMessage parseSet_IDMessage(CircularByteBuffer byteBuffer){
PlayerMessage rVal = new PlayerMessage(PlayerMessageType.SET_ID); PlayerMessage rVal = new PlayerMessage(PlayerMessageType.SET_ID);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setplayerID(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setplayerID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
return rVal; return rVal;
} }
@ -95,12 +95,12 @@ public class PlayerMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static PlayerMessage parseSetInitialDiscretePositionMessage(List<Byte> byteStream){ public static PlayerMessage parseSetInitialDiscretePositionMessage(CircularByteBuffer byteBuffer){
PlayerMessage rVal = new PlayerMessage(PlayerMessageType.SETINITIALDISCRETEPOSITION); PlayerMessage rVal = new PlayerMessage(PlayerMessageType.SETINITIALDISCRETEPOSITION);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
rVal.setinitialDiscretePositionX(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setinitialDiscretePositionX(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setinitialDiscretePositionY(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setinitialDiscretePositionY(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
rVal.setinitialDiscretePositionZ(ByteStreamUtils.popIntFromByteQueue(byteStream)); rVal.setinitialDiscretePositionZ(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
return rVal; return rVal;
} }

View File

@ -1,6 +1,7 @@
package electrosphere.net.parser.net.message; package electrosphere.net.parser.net.message;
import electrosphere.net.parser.util.ByteStreamUtils; import electrosphere.net.parser.util.ByteStreamUtils;
import electrosphere.net.parser.net.raw.CircularByteBuffer;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -22,21 +23,20 @@ public class ServerMessage extends NetworkMessage {
return this.messageType; return this.messageType;
} }
static void stripPacketHeader(List<Byte> byteStream){ static void stripPacketHeader(CircularByteBuffer byteBuffer){
byteStream.remove(0); byteBuffer.read(2);
byteStream.remove(0);
} }
public static boolean canParseMessage(List<Byte> byteStream, byte secondByte){ public static boolean canParseMessage(CircularByteBuffer byteBuffer, byte secondByte){
switch(secondByte){ switch(secondByte){
case TypeBytes.SERVER_MESSAGE_TYPE_PING: case TypeBytes.SERVER_MESSAGE_TYPE_PING:
if(byteStream.size() >= TypeBytes.SERVER_MESSAGE_TYPE_PING_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.SERVER_MESSAGE_TYPE_PING_SIZE){
return true; return true;
} else { } else {
return false; return false;
} }
case TypeBytes.SERVER_MESSAGE_TYPE_PONG: case TypeBytes.SERVER_MESSAGE_TYPE_PONG:
if(byteStream.size() >= TypeBytes.SERVER_MESSAGE_TYPE_PONG_SIZE){ if(byteBuffer.getRemaining() >= TypeBytes.SERVER_MESSAGE_TYPE_PONG_SIZE){
return true; return true;
} else { } else {
return false; return false;
@ -45,9 +45,9 @@ public class ServerMessage extends NetworkMessage {
return false; return false;
} }
public static ServerMessage parsePingMessage(List<Byte> byteStream){ public static ServerMessage parsePingMessage(CircularByteBuffer byteBuffer){
ServerMessage rVal = new ServerMessage(ServerMessageType.PING); ServerMessage rVal = new ServerMessage(ServerMessageType.PING);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
return rVal; return rVal;
} }
@ -57,9 +57,9 @@ public class ServerMessage extends NetworkMessage {
return rVal; return rVal;
} }
public static ServerMessage parsePongMessage(List<Byte> byteStream){ public static ServerMessage parsePongMessage(CircularByteBuffer byteBuffer){
ServerMessage rVal = new ServerMessage(ServerMessageType.PONG); ServerMessage rVal = new ServerMessage(ServerMessageType.PONG);
stripPacketHeader(byteStream); stripPacketHeader(byteBuffer);
return rVal; return rVal;
} }

View File

@ -81,12 +81,9 @@ Message categories
public static final byte TERRAIN_MESSAGE_TYPE_RESPONSEMETADATA = 1; public static final byte TERRAIN_MESSAGE_TYPE_RESPONSEMETADATA = 1;
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTCHUNK = 2; public static final byte TERRAIN_MESSAGE_TYPE_REQUESTCHUNK = 2;
public static final byte TERRAIN_MESSAGE_TYPE_UPDATE = 3; public static final byte TERRAIN_MESSAGE_TYPE_UPDATE = 3;
public static final byte TERRAIN_MESSAGE_TYPE_CHUNKLOADSTART = 4; public static final byte TERRAIN_MESSAGE_TYPE_SPAWNPOSITION = 4;
public static final byte TERRAIN_MESSAGE_TYPE_MACROVALUE = 5; public static final byte TERRAIN_MESSAGE_TYPE_REQUESTCHUNKDATA = 5;
public static final byte TERRAIN_MESSAGE_TYPE_HEIGHTMAPMODIFICATION = 6; public static final byte TERRAIN_MESSAGE_TYPE_SENDCHUNKDATA = 6;
public static final byte TERRAIN_MESSAGE_TYPE_SPAWNPOSITION = 7;
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTCHUNKDATA = 8;
public static final byte TERRAIN_MESSAGE_TYPE_SENDCHUNKDATA = 9;
/* /*
Terrain packet sizes Terrain packet sizes
*/ */
@ -94,9 +91,6 @@ Message categories
public static final byte TERRAIN_MESSAGE_TYPE_RESPONSEMETADATA_SIZE = 30; public static final byte TERRAIN_MESSAGE_TYPE_RESPONSEMETADATA_SIZE = 30;
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTCHUNK_SIZE = 10; public static final byte TERRAIN_MESSAGE_TYPE_REQUESTCHUNK_SIZE = 10;
public static final byte TERRAIN_MESSAGE_TYPE_UPDATE_SIZE = 14; public static final byte TERRAIN_MESSAGE_TYPE_UPDATE_SIZE = 14;
public static final byte TERRAIN_MESSAGE_TYPE_CHUNKLOADSTART_SIZE = 14;
public static final short TERRAIN_MESSAGE_TYPE_MACROVALUE_SIZE = 310;
public static final byte TERRAIN_MESSAGE_TYPE_HEIGHTMAPMODIFICATION_SIZE = 30;
public static final byte TERRAIN_MESSAGE_TYPE_SPAWNPOSITION_SIZE = 26; public static final byte TERRAIN_MESSAGE_TYPE_SPAWNPOSITION_SIZE = 26;
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTCHUNKDATA_SIZE = 14; public static final byte TERRAIN_MESSAGE_TYPE_REQUESTCHUNKDATA_SIZE = 14;
/* /*

View File

@ -0,0 +1,120 @@
package electrosphere.net.parser.net.raw;
import java.util.concurrent.Semaphore;
/**
* A circular byte buffer optimized for high throughput (relative to a list) and peaking at early elements of the current position.
*/
public class CircularByteBuffer {
//The array backing this circular byte buffer
byte[] backingArray;
//the current read position of the buffer in the backing array
int position;
//the remaining bytes to read before the read position equals the write position
int remaining;
//the capacity of the backing array
int capacity;
//Lock to make the structure threadsafe
Semaphore lock = new Semaphore(1);
/**
* Constructs a CircularByteBuffer
* @param capacity The capacity of the backing array in bytes
*/
public CircularByteBuffer(int capacity){
backingArray = new byte[capacity];
position = 0;
remaining = 0;
this.capacity = capacity;
}
/**
* Adds an array of bytes to the circular buffer
* @param bytes The bytes
* @param len The number of bytes to pull from the array bytes
*/
public void add(byte[] bytes, int len){
lock.acquireUninterruptibly();
// System.out.println("Add start");
int writePosition = (position + remaining) % capacity;
//amount possible to write before wrapping
int writeBeforeWrap = capacity - writePosition;
//only run wrapping logic if necessary
if(len > writeBeforeWrap){
System.arraycopy(bytes, 0, backingArray, writePosition, writeBeforeWrap);
System.arraycopy(bytes, writeBeforeWrap, backingArray, 0, len - writeBeforeWrap);
} else {
System.arraycopy(bytes, 0, backingArray, writePosition, len);
}
remaining = remaining + len;
lock.release();
}
/**
* Peeks at the next element in the buffer
* @return The value of the byte next in the buffer
*/
public byte peek(){
byte rVal = peek(0);
return rVal;
}
/**
* Peeks at an element @param offset elements further along the buffer from the current position
* @param offset The offset, in bytes, to look forward in the buffer
* @return The value of the byte at the current position + @param offset
*/
public byte peek(int offset){
lock.acquireUninterruptibly();
byte rVal = backingArray[(position + offset) % capacity];
lock.release();
return rVal;
}
/**
* Gets the remaining number of bytes in the buffer
* @return The remaining number of bytes
*/
public int getRemaining(){
lock.acquireUninterruptibly();
int rVal = remaining;
lock.release();
return rVal;
}
/**
* Gets the capacity of the buffer
* @return The capacity
*/
public int getCapacity(){
lock.acquireUninterruptibly();
int rVal = capacity;
lock.release();
return rVal;
}
/**
* Reads a given number of bytes from the buffer
* @param len The number of bytes to read
* @return The bytes in an array
*/
public byte[] read(int len){
lock.acquireUninterruptibly();
byte[] rVal = new byte[len];
//amount possible to read before loop
int toReadBeforeLoop = capacity - position;
if(len > capacity - position){
System.arraycopy(backingArray, position, rVal, 0, toReadBeforeLoop);
System.arraycopy(backingArray, 0, rVal, toReadBeforeLoop, len - toReadBeforeLoop);
} else {
System.arraycopy(backingArray, position, rVal, 0, len);
}
position = (position + len) % capacity;
remaining = remaining - len;
lock.release();
return rVal;
}
}

View File

@ -15,7 +15,7 @@ public class NetworkParser {
CopyOnWriteArrayList<NetworkMessage> incomingMessageQueue = new CopyOnWriteArrayList<NetworkMessage>(); CopyOnWriteArrayList<NetworkMessage> incomingMessageQueue = new CopyOnWriteArrayList<NetworkMessage>();
CopyOnWriteArrayList<NetworkMessage> outgoingMessageQueue = new CopyOnWriteArrayList<NetworkMessage>(); CopyOnWriteArrayList<NetworkMessage> outgoingMessageQueue = new CopyOnWriteArrayList<NetworkMessage>();
CopyOnWriteArrayList<Byte> incomingByteQueue = new CopyOnWriteArrayList<Byte>(); CircularByteBuffer incomingByteBuffer = new CircularByteBuffer(64 * 1024 * 124);
CopyOnWriteArrayList<Byte> outgoingByteQueue = new CopyOnWriteArrayList<Byte>(); CopyOnWriteArrayList<Byte> outgoingByteQueue = new CopyOnWriteArrayList<Byte>();
@ -29,24 +29,24 @@ public class NetworkParser {
} }
static final int READ_BUFFER_SIZE = 64 * 1024 * 1024;
byte[] readBuffer = new byte[READ_BUFFER_SIZE];
public void readMessagesIn(){ public void readMessagesIn(){
try { try {
//read in bytes //read in bytes
int nextValue = 0; int bytesRead = 0;
byte currentByte = -1; byte currentByte = -1;
while(incomingStream.available() > 0){ while(incomingStream.available() > 0){
nextValue = incomingStream.read(); // nextValue = incomingStream.read();
if(nextValue != -1){ bytesRead = incomingStream.read(readBuffer, 0, READ_BUFFER_SIZE);
currentByte = (byte)nextValue; if(bytesRead > 0){
incomingByteQueue.add(currentByte); incomingByteBuffer.add(readBuffer, bytesRead);
// System.out.println(currentByte);
} }
//add bytes to some kind of queue
} }
//parse byte queue for messages //parse byte queue for messages
//for each message, append to clientIncomingMessageQueue //for each message, append to clientIncomingMessageQueue
NetworkMessage newMessage; NetworkMessage newMessage;
while((newMessage = NetworkMessage.parseBytestreamForMessage(incomingByteQueue))!=null){ while((newMessage = NetworkMessage.parseBytestreamForMessage(incomingByteBuffer))!=null){
incomingMessageQueue.add(newMessage); incomingMessageQueue.add(newMessage);
} }
} catch (IOException ex) { } catch (IOException ex) {

View File

@ -1,5 +1,7 @@
package electrosphere.net.parser.util; package electrosphere.net.parser.util;
import electrosphere.net.parser.net.raw.CircularByteBuffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.List; import java.util.List;
import java.util.concurrent.Semaphore; import java.util.concurrent.Semaphore;
@ -107,6 +109,96 @@ public class ByteStreamUtils {
bufferLock.release(); bufferLock.release();
return rVal; return rVal;
} }
public static int popIntFromByteQueue(CircularByteBuffer byteBuffer){
int rVal = -1;
bufferLock.acquireUninterruptibly();
integerCompactor.clear();
integerCompactor.position(0);
integerCompactor.limit(4);
integerCompactor.put(0,byteBuffer.peek(0));
integerCompactor.put(1,byteBuffer.peek(1));
integerCompactor.put(2,byteBuffer.peek(2));
integerCompactor.put(3,byteBuffer.peek(3));
byteBuffer.read(4);
integerCompactor.position(0);
integerCompactor.limit(4);
rVal = integerCompactor.getInt();
bufferLock.release();
return rVal;
}
public static float popFloatFromByteQueue(CircularByteBuffer byteBuffer){
float rVal = -1;
bufferLock.acquireUninterruptibly();
integerCompactor.clear();
integerCompactor.position(0);
integerCompactor.limit(4);
integerCompactor.put(0,byteBuffer.read(1));
integerCompactor.put(1,byteBuffer.read(1));
integerCompactor.put(2,byteBuffer.read(1));
integerCompactor.put(3,byteBuffer.read(1));
integerCompactor.position(0);
integerCompactor.limit(4);
rVal = integerCompactor.getFloat();
bufferLock.release();
return rVal;
}
public static long popLongFromByteQueue(CircularByteBuffer byteBuffer){
long rVal = -1;
bufferLock.acquireUninterruptibly();
integerCompactor.clear();
integerCompactor.position(0);
integerCompactor.limit(8);
integerCompactor.put(0,byteBuffer.read(1));
integerCompactor.put(1,byteBuffer.read(1));
integerCompactor.put(2,byteBuffer.read(1));
integerCompactor.put(3,byteBuffer.read(1));
integerCompactor.put(4,byteBuffer.read(1));
integerCompactor.put(5,byteBuffer.read(1));
integerCompactor.put(6,byteBuffer.read(1));
integerCompactor.put(7,byteBuffer.read(1));
integerCompactor.position(0);
integerCompactor.limit(8);
rVal = integerCompactor.getLong();
bufferLock.release();
return rVal;
}
public static String popStringFromByteQueue(CircularByteBuffer byteBuffer){
int length = popIntFromByteQueue(byteBuffer);
byte[] stringBytes = byteBuffer.read(length);
String rVal = new String(stringBytes);
return rVal;
}
public static byte[] popByteArrayFromByteQueue(CircularByteBuffer byteBuffer){
int length = popIntFromByteQueue(byteBuffer);
byte[] bytes = byteBuffer.read(length);
return bytes;
}
public static double popDoubleFromByteQueue(CircularByteBuffer byteBuffer){
double rVal = -1;
bufferLock.acquireUninterruptibly();
integerCompactor.clear();
integerCompactor.position(0);
integerCompactor.limit(8);
integerCompactor.put(0,byteBuffer.read(1));
integerCompactor.put(1,byteBuffer.read(1));
integerCompactor.put(2,byteBuffer.read(1));
integerCompactor.put(3,byteBuffer.read(1));
integerCompactor.put(4,byteBuffer.read(1));
integerCompactor.put(5,byteBuffer.read(1));
integerCompactor.put(6,byteBuffer.read(1));
integerCompactor.put(7,byteBuffer.read(1));
integerCompactor.position(0);
integerCompactor.limit(8);
rVal = integerCompactor.getDouble();
bufferLock.release();
return rVal;
}
public static byte[] serializeIntToBytes(int i){ public static byte[] serializeIntToBytes(int i){
byte[] rVal = new byte[4]; byte[] rVal = new byte[4];

View File

@ -1,5 +1,10 @@
package electrosphere.net.server.protocol; package electrosphere.net.server.protocol;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import electrosphere.client.terrain.cache.ChunkData;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.net.parser.net.message.TerrainMessage; import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.net.server.Server; import electrosphere.net.server.Server;
@ -12,25 +17,27 @@ public class TerrainProtocol {
protected static void handleTerrainMessage(ServerConnectionHandler connectionHandler, TerrainMessage message){ protected static void handleTerrainMessage(ServerConnectionHandler connectionHandler, TerrainMessage message){
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case REQUESTCHUNK: case REQUESTCHUNK:
sendWorldChunk(connectionHandler, message.getworldX(), message.getworldY()); // sendWorldChunk(connectionHandler, message.getworldX(), message.getworldY());
break; break;
case REQUESTMETADATA: case REQUESTMETADATA:
sendWorldMetadata(connectionHandler); sendWorldMetadata(connectionHandler);
break; break;
case REQUESTCHUNKDATA:
sendWorldSubChunk(connectionHandler,
message.getworldX(), message.getworldY(), message.getworldZ()
);
break;
//all ignored message types //all ignored message types
case CHUNKLOADSTART:
case HEIGHTMAPMODIFICATION:
case MACROVALUE:
case RESPONSEMETADATA: case RESPONSEMETADATA:
case SPAWNPOSITION: case SPAWNPOSITION:
case UPDATE: case UPDATE:
case SENDCHUNKDATA:
//silently ignore //silently ignore
break; break;
} }
} }
static void sendWorldChunk(ServerConnectionHandler connectionHandler, int worldX, int worldY){ static void sendWorldSubChunk(ServerConnectionHandler connectionHandler, int worldX, int worldY, int worldZ){
/* /*
int locationX, int locationX,
int locationY, int locationY,
@ -56,92 +63,117 @@ public class TerrainProtocol {
// System.out.println("Received request for chunk " + message.getworldX() + " " + message.getworldY()); // System.out.println("Received request for chunk " + message.getworldX() + " " + message.getworldY());
ServerTerrainChunk chunk = Globals.serverTerrainManager.getChunk(worldX, worldY); ServerTerrainChunk chunk = Globals.serverTerrainManager.getChunk(worldX, worldY, worldZ);
float[][] macroValues = chunk.getMacroValues();//Globals.serverTerrainManager.getRad5MacroValues(message.getworldX(), message.getworldY()); // float[][] macroValues = chunk.getMacroValues();//Globals.serverTerrainManager.getRad5MacroValues(message.getworldX(), message.getworldY());
long[][] randomizer = chunk.getRandomizer();//Globals.serverTerrainManager.getRandomizer(message.getworldX(), message.getworldY()); // long[][] randomizer = chunk.getRandomizer();//Globals.serverTerrainManager.getRandomizer(message.getworldX(), message.getworldY());
int numMessages = 2 + chunk.getModifications().size(); ByteBuffer buffer = ByteBuffer.allocate(ServerTerrainChunk.CHUNK_DIMENSION*ServerTerrainChunk.CHUNK_DIMENSION*ServerTerrainChunk.CHUNK_DIMENSION*(4+4));
FloatBuffer floatView = buffer.asFloatBuffer();
connectionHandler.addMessagetoOutgoingQueue( for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){
TerrainMessage.constructchunkLoadStartMessage(worldX, worldY, numMessages) for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){
); for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){
floatView.put(chunk.getWeights()[x][y][z]);
connectionHandler.addMessagetoOutgoingQueue( }
TerrainMessage.constructMacroValueMessage( }
worldX,
worldY,
macroValues[0][0],
macroValues[0][1],
macroValues[0][2],
macroValues[0][3],
macroValues[0][4],
macroValues[1][0],
macroValues[1][1],
macroValues[1][2],
macroValues[1][3],
macroValues[1][4],
macroValues[2][0],
macroValues[2][1],
macroValues[2][2],
macroValues[2][3],
macroValues[2][4],
macroValues[3][0],
macroValues[3][1],
macroValues[3][2],
macroValues[3][3],
macroValues[3][4],
macroValues[4][0],
macroValues[4][1],
macroValues[4][2],
macroValues[4][3],
macroValues[4][4],
randomizer[0][0],
randomizer[0][1],
randomizer[0][2],
randomizer[0][3],
randomizer[0][4],
randomizer[1][0],
randomizer[1][1],
randomizer[1][2],
randomizer[1][3],
randomizer[1][4],
randomizer[2][0],
randomizer[2][1],
randomizer[2][2],
randomizer[2][3],
randomizer[2][4],
randomizer[3][0],
randomizer[3][1],
randomizer[3][2],
randomizer[3][3],
randomizer[3][4],
randomizer[4][0],
randomizer[4][1],
randomizer[4][2],
randomizer[4][3],
randomizer[4][4]
)
);
for(TerrainModification modification : chunk.getModifications()){
connectionHandler.addMessagetoOutgoingQueue(
TerrainMessage.constructheightMapModificationMessage(
modification.getValue(),
modification.getWorldX(),
0,
modification.getWorldY(),
modification.getLocationX(),
0,
modification.getLocationY()
)
);
} }
IntBuffer intView = buffer.asIntBuffer();
intView.position(floatView.position());
for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){
for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){
for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){
intView.put(chunk.getValues()[x][y][z]);
}
}
}
connectionHandler.addMessagetoOutgoingQueue(TerrainMessage.constructsendChunkDataMessage(worldX, worldY, worldZ, buffer.array()));
// int numMessages = 2 + chunk.getModifications().size();
// connectionHandler.addMessagetoOutgoingQueue(
// TerrainMessage.constructchunkLoadStartMessage(worldX, worldY, numMessages)
// );
// connectionHandler.addMessagetoOutgoingQueue(
// TerrainMessage.constructMacroValueMessage(
// worldX,
// worldY,
// macroValues[0][0],
// macroValues[0][1],
// macroValues[0][2],
// macroValues[0][3],
// macroValues[0][4],
// macroValues[1][0],
// macroValues[1][1],
// macroValues[1][2],
// macroValues[1][3],
// macroValues[1][4],
// macroValues[2][0],
// macroValues[2][1],
// macroValues[2][2],
// macroValues[2][3],
// macroValues[2][4],
// macroValues[3][0],
// macroValues[3][1],
// macroValues[3][2],
// macroValues[3][3],
// macroValues[3][4],
// macroValues[4][0],
// macroValues[4][1],
// macroValues[4][2],
// macroValues[4][3],
// macroValues[4][4],
// randomizer[0][0],
// randomizer[0][1],
// randomizer[0][2],
// randomizer[0][3],
// randomizer[0][4],
// randomizer[1][0],
// randomizer[1][1],
// randomizer[1][2],
// randomizer[1][3],
// randomizer[1][4],
// randomizer[2][0],
// randomizer[2][1],
// randomizer[2][2],
// randomizer[2][3],
// randomizer[2][4],
// randomizer[3][0],
// randomizer[3][1],
// randomizer[3][2],
// randomizer[3][3],
// randomizer[3][4],
// randomizer[4][0],
// randomizer[4][1],
// randomizer[4][2],
// randomizer[4][3],
// randomizer[4][4]
// )
// );
// for(TerrainModification modification : chunk.getModifications()){
// connectionHandler.addMessagetoOutgoingQueue(
// TerrainMessage.constructheightMapModificationMessage(
// modification.getValue(),
// modification.getWorldX(),
// 0,
// modification.getWorldY(),
// modification.getLocationX(),
// 0,
// modification.getLocationY()
// )
// );
// }
} }
static void sendWorldMetadata(ServerConnectionHandler connectionHandler){ static void sendWorldMetadata(ServerConnectionHandler connectionHandler){

View File

@ -1,15 +1,8 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package electrosphere.renderer; package electrosphere.renderer;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.renderer.texture.Texture; import electrosphere.renderer.texture.Texture;
import org.lwjgl.PointerBuffer;
import org.lwjgl.assimp.AIMaterial; import org.lwjgl.assimp.AIMaterial;
import org.lwjgl.assimp.AIMaterialProperty;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D; import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.glBindTexture; import static org.lwjgl.opengl.GL11.glBindTexture;
import static org.lwjgl.opengl.GL13.GL_TEXTURE0; import static org.lwjgl.opengl.GL13.GL_TEXTURE0;
@ -27,6 +20,8 @@ public class Material {
String specular; String specular;
boolean hasTransparency = false; boolean hasTransparency = false;
//Sets whether this material should get its texture pointers from the assetManager by looking up diffuse and specular paths
//or whether it should have a manually set texturePointer and not look up while binding
boolean usesFetch = true; boolean usesFetch = true;
int texturePointer; int texturePointer;
@ -70,8 +65,11 @@ public class Material {
usesFetch = false; usesFetch = false;
} }
/**
* Applies the material
*/
public void apply_material(){ public void apply_material(){
//basically a switch for the case where we want to manually set texture pointer //Controls whether the texturePointer should be resolved by looking up the diffuse in asset manager or using the texture pointer already set in this material
if(usesFetch){ if(usesFetch){
Texture diffuseTexture = Globals.assetManager.fetchTexture(diffuse); Texture diffuseTexture = Globals.assetManager.fetchTexture(diffuse);
if(diffuseTexture != null){ if(diffuseTexture != null){

View File

@ -132,40 +132,41 @@ public class InstanceData {
*/ */
protected void fillBuffers(){ protected void fillBuffers(){
int i = 0; int i = 0;
//reset all buffers //for some reason the limit is not being set correctly. This explicitly forces it for each buffer
for(ShaderAttribute attribute : attributeIndices){ for(ShaderAttribute attribute : attributeIndices){
switch(attributeGlBufferMap.get(attribute).getType()){ switch(attributeGlBufferMap.get(attribute).getType()){
case VEC3F: { case VEC3F: {
FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute)); FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute));
buffer.position(0); buffer.limit(buffer.capacity());
} break; } break;
case VEC3D: { case VEC3D: {
DoubleBuffer buffer = ((DoubleBuffer)attributeCpuBufferMap.get(attribute)); DoubleBuffer buffer = ((DoubleBuffer)attributeCpuBufferMap.get(attribute));
buffer.position(0); buffer.limit(buffer.capacity());
} break; } break;
case VEC4F: { case VEC4F: {
FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute)); FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute));
buffer.position(0); buffer.limit(buffer.capacity());
} break; } break;
case VEC4D: { case VEC4D: {
DoubleBuffer buffer = ((DoubleBuffer)attributeCpuBufferMap.get(attribute)); DoubleBuffer buffer = ((DoubleBuffer)attributeCpuBufferMap.get(attribute));
buffer.position(0); buffer.limit(buffer.capacity());
} break; } break;
case MAT4F: { case MAT4F: {
FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute)); FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute));
buffer.position(0); buffer.limit(buffer.capacity());
// System.out.println(buffer.position() + " " + buffer.limit());
} break; } break;
case DOUBLE: { case DOUBLE: {
DoubleBuffer buffer = ((DoubleBuffer)attributeCpuBufferMap.get(attribute)); DoubleBuffer buffer = ((DoubleBuffer)attributeCpuBufferMap.get(attribute));
buffer.position(0); buffer.limit(buffer.capacity());
} break; } break;
case FLOAT: { case FLOAT: {
FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute)); FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute));
buffer.position(0); buffer.limit(buffer.capacity());
} break; } break;
case INT: { case INT: {
IntBuffer buffer = ((IntBuffer)attributeCpuBufferMap.get(attribute)); IntBuffer buffer = ((IntBuffer)attributeCpuBufferMap.get(attribute));
buffer.position(0); buffer.limit(buffer.capacity());
} break; } break;
} }
} }
@ -308,6 +309,46 @@ public class InstanceData {
} }
} }
protected void flip(){
//reset all buffers
for(ShaderAttribute attribute : attributeIndices){
switch(attributeGlBufferMap.get(attribute).getType()){
case VEC3F: {
FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute));
buffer.flip();
} break;
case VEC3D: {
DoubleBuffer buffer = ((DoubleBuffer)attributeCpuBufferMap.get(attribute));
buffer.flip();
} break;
case VEC4F: {
FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute));
buffer.flip();
} break;
case VEC4D: {
DoubleBuffer buffer = ((DoubleBuffer)attributeCpuBufferMap.get(attribute));
buffer.flip();
} break;
case MAT4F: {
FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute));
buffer.flip();
} break;
case DOUBLE: {
DoubleBuffer buffer = ((DoubleBuffer)attributeCpuBufferMap.get(attribute));
buffer.flip();
} break;
case FLOAT: {
FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute));
buffer.flip();
} break;
case INT: {
IntBuffer buffer = ((IntBuffer)attributeCpuBufferMap.get(attribute));
buffer.flip();
} break;
}
}
}
/** /**
* Gets a map of all attributes to the buffers of data for that attribute * Gets a map of all attributes to the buffers of data for that attribute
* @return The data buffers * @return The data buffers

View File

@ -85,6 +85,8 @@ public class InstanceManager {
model.draw(renderPipelineState); model.draw(renderPipelineState);
} }
data.flip();
//clear queue //clear queue
data.clearDrawQueue(); data.clearDrawQueue();
} }

View File

@ -790,6 +790,7 @@ public class TerrainChunkModelGeneration {
Material groundMat = new Material(); Material groundMat = new Material();
groundMat.set_diffuse("/Textures/Ground/Dirt1.png"); groundMat.set_diffuse("/Textures/Ground/Dirt1.png");
groundMat.set_specular("/Textures/Ground/Dirt1.png"); groundMat.set_specular("/Textures/Ground/Dirt1.png");
Globals.assetManager.addTexturePathtoQueue("/Textures/Ground/Dirt1.png");
m.setMaterial(groundMat); m.setMaterial(groundMat);
m.setShader(TerrainChunkModelGeneration.terrainChunkShaderProgram); m.setShader(TerrainChunkModelGeneration.terrainChunkShaderProgram);
@ -802,7 +803,7 @@ public class TerrainChunkModelGeneration {
//TODO: more optimal key creation //TODO: more optimal key creation
private static String getVertKeyFromPoints(float x, float y, float z){ private static String getVertKeyFromPoints(float x, float y, float z){
return x + "-" + y + "-" + z; return x + "_" + y + "_" + z;
} }
private static int getVertIndex(Vector3f vert, Map<String,Integer> vertMap, List<Vector3f> verts){ private static int getVertIndex(Vector3f vert, Map<String,Integer> vertMap, List<Vector3f> verts){

View File

@ -64,7 +64,7 @@ public class MillAbout extends AI {
rand.nextFloat() - 0.5, rand.nextFloat() - 0.5,
rand.nextFloat() - 0.5 rand.nextFloat() - 0.5
).normalize().mul(millTargetMaxDist); ).normalize().mul(millTargetMaxDist);
moveVector.y = Globals.commonWorldData.getElevationAtPoint(new Vector3d(position).add(moveVector)); moveVector.y = position.y; //Globals.commonWorldData.getElevationAtPoint(new Vector3d(position).add(moveVector));
//TODO: search in navmeshmanager to make sure navigable, otherwise generate new pos //TODO: search in navmeshmanager to make sure navigable, otherwise generate new pos
// } // }

View File

@ -29,18 +29,18 @@ public class SeekTown extends AI {
@Override @Override
public void simulate() { public void simulate() {
if(target == null){ // if(target == null){
if(Globals.macroData.getTowns().size() > 0){ // if(Globals.macroData.getTowns().size() > 0){
target = Globals.macroData.getTowns().get(0); // target = Globals.macroData.getTowns().get(0);
targetPos = new Vector3d( // targetPos = new Vector3d(
Globals.commonWorldData.convertWorldToReal(target.getPositions().get(0).x), // Globals.commonWorldData.convertWorldToReal(target.getPositions().get(0).x),
0, // 0,
Globals.commonWorldData.convertWorldToReal(target.getPositions().get(0).y) // Globals.commonWorldData.convertWorldToReal(target.getPositions().get(0).y)
); // );
targetPos.y = Globals.commonWorldData.getElevationAtPoint(targetPos); // targetPos.y = Globals.commonWorldData.getElevationAtPoint(targetPos);
System.out.println("Target pos: " + targetPos); // System.out.println("Target pos: " + targetPos);
} // }
} // }
moveToTarget(); moveToTarget();
} }

View File

@ -24,14 +24,14 @@ public class EnvironmentGenerator {
Random rand = new Random(randomizer); Random rand = new Random(randomizer);
int targetNum = (int)(rand.nextFloat() * 10) + 10; int targetNum = (int)(rand.nextFloat() * 10) + 10;
for(int i = 0; i < targetNum; i++){ for(int i = 0; i < targetNum; i++){
Entity newTree = FoliageUtils.spawnBasicFoliage("FallOak1"); // Entity newTree = FoliageUtils.spawnBasicFoliage("FallOak1");
cell.getScene().registerEntity(newTree); // cell.getScene().registerEntity(newTree);
double posX = worldPos.x * Globals.serverWorldData.getDynamicInterpolationRatio() + (float)(rand.nextFloat() * Globals.serverWorldData.getDynamicInterpolationRatio()); // double posX = worldPos.x * Globals.serverWorldData.getDynamicInterpolationRatio() + (float)(rand.nextFloat() * Globals.serverWorldData.getDynamicInterpolationRatio());
double posZ = worldPos.z * Globals.serverWorldData.getDynamicInterpolationRatio() + (float)(rand.nextFloat() * Globals.serverWorldData.getDynamicInterpolationRatio()); // double posZ = worldPos.z * Globals.serverWorldData.getDynamicInterpolationRatio() + (float)(rand.nextFloat() * Globals.serverWorldData.getDynamicInterpolationRatio());
double posY = Globals.serverTerrainManager.getHeightAtPosition(posX, posZ); // double posY = Globals.serverTerrainManager.getHeightAtPosition(posX, posZ);
// System.out.println("Spawning tree at: " + posX + "," + posY + "," + posZ); // // System.out.println("Spawning tree at: " + posX + "," + posY + "," + posZ);
// CollisionObjUtils.positionCharacter(newTree, new Vector3f(posX,posY,posZ)); // // CollisionObjUtils.positionCharacter(newTree, new Vector3f(posX,posY,posZ));
EntityUtils.getPosition(newTree).set(posX,posY,posZ); // EntityUtils.getPosition(newTree).set(posX,posY,posZ);
} }
} }
} }

View File

@ -15,7 +15,14 @@ public class ServerContentManager {
//else create from scratch //else create from scratch
EnvironmentGenerator.generatePlains(cell, worldPos, Globals.serverTerrainManager.getRandomizerAtPoint(worldPos.x, worldPos.z)); EnvironmentGenerator.generatePlains(cell, worldPos, Globals.serverTerrainManager.getRandomizerAtPoint(worldPos.x, worldPos.z));
} }
cell.setNavMesh(NavMeshUtils.createMeshFromChunk(Globals.serverTerrainManager.getChunk(worldPos.x, worldPos.z),Globals.navMeshManager.getBlockerCache().getBlocker(worldPos.x, worldPos.z))); cell.setNavMesh(
NavMeshUtils.createMeshFromChunk(Globals.serverTerrainManager.getChunk(
worldPos.x,
worldPos.y,
worldPos.z
),
Globals.navMeshManager.getBlockerCache().getBlocker(worldPos.x, worldPos.z))
);
} }

View File

@ -1,9 +1,12 @@
package electrosphere.server.datacell; package electrosphere.server.datacell;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Semaphore;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector3i; import org.joml.Vector3i;
@ -16,29 +19,40 @@ import electrosphere.game.server.world.ServerWorldData;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.net.server.player.Player; import electrosphere.net.server.player.Player;
import electrosphere.server.datacell.interfaces.DataCellManager; import electrosphere.server.datacell.interfaces.DataCellManager;
import electrosphere.server.datacell.physics.PhysicsDataCell;
import electrosphere.server.terrain.manager.ServerTerrainManager;
import electrosphere.server.terrain.manager.ServerTerrainChunk;
/** /**
* Implementation of DataCellManager that lays out cells in a logical grid (array). Useful for eg 3d terrain gridded world. * Implementation of DataCellManager that lays out cells in a logical grid (array). Useful for eg 3d terrain gridded world.
*/ */
public class GriddedDataCellManager implements DataCellManager { public class GriddedDataCellManager implements DataCellManager {
//these are going to be the natural ground grid of data cells, but we're going to have more than this //these are going to be the natural ground grid of data cells, but we're going to have more than this
ServerDataCell[][][] groundDataCells; Map<String,ServerDataCell> groundDataCells = new HashMap<String,ServerDataCell>();
//loaded cells
Semaphore loadedCellsLock = new Semaphore(1);
Set<ServerDataCell> loadedCells; Set<ServerDataCell> loadedCells;
int discreteWorldSize; int discreteWorldSize;
//parent realm //parent realm
Realm parent; Realm parent;
//Manager for terrain for this particular cell manager
ServerTerrainManager serverTerrainManager;
/** /**
* Constructor * Constructor
* @param parent The gridded data cell manager's parent realm * @param parent The gridded data cell manager's parent realm
*/ */
public GriddedDataCellManager(Realm parent) { public GriddedDataCellManager(Realm parent, ServerTerrainManager serverTerrainManager) {
this.parent = parent; this.parent = parent;
this.serverTerrainManager = serverTerrainManager;
} }
/**
* Initializes the gridded data cell manager
* @param data The server world data to back the manager with
*/
public void init(ServerWorldData data){ public void init(ServerWorldData data){
discreteWorldSize = data.getWorldSizeDiscrete(); discreteWorldSize = data.getWorldSizeDiscrete();
groundDataCells = new ServerDataCell[discreteWorldSize][discreteWorldSize][discreteWorldSize];
loadedCells = new HashSet<ServerDataCell>(); loadedCells = new HashSet<ServerDataCell>();
} }
@ -57,17 +71,24 @@ public class GriddedDataCellManager implements DataCellManager {
y >= 0 && y < discreteWorldSize && y >= 0 && y < discreteWorldSize &&
z >= 0 && z < discreteWorldSize z >= 0 && z < discreteWorldSize
){ ){
LoggerInterface.loggerEngine.DEBUG("TerrainDataCellManager: Add player to " + x + " " + y); Vector3i targetPos = new Vector3i(x,y,z);
if(groundDataCells[x][y][z] != null){ LoggerInterface.loggerEngine.DEBUG("GriddedDataCellManager: Add player to " + x + " " + y + " " + z);
groundDataCells[x][y][z].addPlayer(player); if(groundDataCells.get(getServerDataCellKey(targetPos)) != null){
groundDataCells.get(getServerDataCellKey(targetPos)).addPlayer(player);
} else { } else {
LoggerInterface.loggerEngine.DEBUG("Creating new cell @ " + x + " " + y + " " + z);
//create data cell //create data cell
groundDataCells[x][y][z] = ServerDataCell.createServerDataCell(new Scene()); createServerDataCell(targetPos);
loadedCells.add(groundDataCells[x][y][z]); ///generates physics for the cell in a dedicated thread then finally registers
runPhysicsGenerationThread(targetPos);
//add to loaded cells
loadedCellsLock.acquireUninterruptibly();
loadedCells.add(groundDataCells.get(getServerDataCellKey(targetPos)));
loadedCellsLock.release();
//generate/handle content for new server data cell //generate/handle content for new server data cell
//add player //add player
groundDataCells[x][y][z].addPlayer(player); groundDataCells.get(getServerDataCellKey(targetPos)).addPlayer(player);
} }
} }
} }
@ -103,10 +124,11 @@ public class GriddedDataCellManager implements DataCellManager {
z > newPosition.z + playerSimulationRadius z > newPosition.z + playerSimulationRadius
) )
){ ){
if(groundDataCells[x][y][z] != null){ Vector3i targetPos = new Vector3i(x,y,z);
if(groundDataCells[x][y][z].containsPlayer(player)){ if(groundDataCells.get(getServerDataCellKey(targetPos)) != null){
if(groundDataCells.get(getServerDataCellKey(targetPos)).containsPlayer(player)){
// removals++; // removals++;
groundDataCells[x][y][z].removePlayer(player); groundDataCells.get(getServerDataCellKey(targetPos)).removePlayer(player);
} }
} }
} }
@ -129,14 +151,21 @@ public class GriddedDataCellManager implements DataCellManager {
z > oldPosition.z + playerSimulationRadius z > oldPosition.z + playerSimulationRadius
) )
){ ){
Vector3i targetPos = new Vector3i(x,y,z);
// System.out.println("Add player to " + x + " " + y); // System.out.println("Add player to " + x + " " + y);
if(groundDataCells[x][y][z] != null){ if(groundDataCells.get(getServerDataCellKey(targetPos)) != null){
groundDataCells[x][y][z].addPlayer(player); groundDataCells.get(getServerDataCellKey(targetPos)).addPlayer(player);
} else { } else {
//create data cell //create data cell
groundDataCells[x][y][z] = parent.createNewCell(); createServerDataCell(targetPos);
//generates physics for the cell in a dedicated thread then finally registers
runPhysicsGenerationThread(targetPos);
//add to loaded cells
loadedCellsLock.acquireUninterruptibly();
loadedCells.add(groundDataCells.get(getServerDataCellKey(targetPos)));
loadedCellsLock.release();
//add player //add player
groundDataCells[x][y][z].addPlayer(player); groundDataCells.get(getServerDataCellKey(targetPos)).addPlayer(player);
} }
// additions++; // additions++;
} else { } else {
@ -148,6 +177,15 @@ public class GriddedDataCellManager implements DataCellManager {
} }
// System.out.println("removals: " + removals + "\tadditions: " + additions); // System.out.println("removals: " + removals + "\tadditions: " + additions);
} }
/**
* Creates physics entities when new data cell being created
*/
private void createTerrainPhysicsEntities(Vector3i worldPos){
ServerTerrainChunk subChunk = serverTerrainManager.getChunk(worldPos.x, worldPos.y, worldPos.z);
PhysicsDataCell cell = PhysicsDataCell.createPhysicsCell(parent, worldPos, subChunk);
cell.generatePhysics();
}
/** /**
* For every player, looks at their entity and determines what data cell they should be considered inside of * For every player, looks at their entity and determines what data cell they should be considered inside of
@ -181,15 +219,16 @@ public class GriddedDataCellManager implements DataCellManager {
int worldX = Globals.serverWorldData.convertRealToChunkSpace(point.x); int worldX = Globals.serverWorldData.convertRealToChunkSpace(point.x);
int worldY = Globals.serverWorldData.convertRealToChunkSpace(point.y); int worldY = Globals.serverWorldData.convertRealToChunkSpace(point.y);
int worldZ = Globals.serverWorldData.convertRealToChunkSpace(point.z); int worldZ = Globals.serverWorldData.convertRealToChunkSpace(point.z);
Vector3i worldPos = new Vector3i(worldX,worldY,worldZ);
if( if(
//in bounds of array //in bounds of array
worldX >= 0 && worldX < groundDataCells.length && worldX >= 0 && worldX < discreteWorldSize &&
worldY >= 0 && worldY < groundDataCells[0].length && worldY >= 0 && worldY < discreteWorldSize &&
worldZ >= 0 && worldZ < groundDataCells[0][0].length && worldZ >= 0 && worldZ < discreteWorldSize &&
//isn't null //isn't null
groundDataCells[worldX][worldY][worldZ] != null groundDataCells.get(getServerDataCellKey(worldPos)) != null
){ ){
rVal = groundDataCells[worldX][worldY][worldZ]; rVal = groundDataCells.get(getServerDataCellKey(worldPos));
} }
return rVal; return rVal;
} }
@ -203,18 +242,25 @@ public class GriddedDataCellManager implements DataCellManager {
int worldX = Globals.serverWorldData.convertRealToChunkSpace(point.x); int worldX = Globals.serverWorldData.convertRealToChunkSpace(point.x);
int worldY = Globals.serverWorldData.convertRealToChunkSpace(point.y); int worldY = Globals.serverWorldData.convertRealToChunkSpace(point.y);
int worldZ = Globals.serverWorldData.convertRealToChunkSpace(point.z); int worldZ = Globals.serverWorldData.convertRealToChunkSpace(point.z);
Vector3i worldPos = new Vector3i(worldX,worldY,worldZ);
if( if(
//in bounds of array //in bounds of array
worldX >= 0 && worldX < groundDataCells.length && worldX >= 0 && worldX < discreteWorldSize &&
worldY >= 0 && worldY < groundDataCells[0].length && worldY >= 0 && worldY < discreteWorldSize &&
worldZ >= 0 && worldZ < groundDataCells[0][0].length && worldZ >= 0 && worldZ < discreteWorldSize &&
//isn't null //isn't null
groundDataCells[worldX][worldY][worldZ] == null groundDataCells.get(getServerDataCellKey(worldPos)) == null
){ ){
groundDataCells[worldX][worldY][worldZ] = ServerDataCell.createServerDataCell(new Scene()); //create data cell
loadedCells.add(groundDataCells[worldX][worldY][worldZ]); createServerDataCell(worldPos);
//generates physics for the cell in a dedicated thread then finally registers
runPhysicsGenerationThread(worldPos);
//add to loaded cells
loadedCellsLock.acquireUninterruptibly();
loadedCells.add(groundDataCells.get(getServerDataCellKey(worldPos)));
loadedCellsLock.release();
} }
return groundDataCells[worldX][worldY][worldZ]; return groundDataCells.get(getServerDataCellKey(worldPos));
} }
/** /**
@ -225,13 +271,13 @@ public class GriddedDataCellManager implements DataCellManager {
public ServerDataCell getCellAtWorldPosition(Vector3i position){ public ServerDataCell getCellAtWorldPosition(Vector3i position){
if( if(
//in bounds of array //in bounds of array
position.x >= 0 && position.x < groundDataCells.length && position.x >= 0 && position.x < discreteWorldSize &&
position.y >= 0 && position.y < groundDataCells[0].length && position.y >= 0 && position.y < discreteWorldSize &&
position.z >= 0 && position.z < groundDataCells[0][0].length && position.z >= 0 && position.z < discreteWorldSize &&
//isn't null //isn't null
groundDataCells[position.x][position.y][position.z] != null groundDataCells.get(getServerDataCellKey(position)) != null
){ ){
return groundDataCells[position.x][position.y][position.z]; return groundDataCells.get(getServerDataCellKey(position));
} }
return null; return null;
} }
@ -241,9 +287,59 @@ public class GriddedDataCellManager implements DataCellManager {
* Calls the simulate function on all loaded cells * Calls the simulate function on all loaded cells
*/ */
public void simulate(){ public void simulate(){
loadedCellsLock.acquireUninterruptibly();
for(ServerDataCell cell : loadedCells){ for(ServerDataCell cell : loadedCells){
Globals.microSimulation.simulate(cell, parent.getHitboxManager()); Globals.microSimulation.simulate(cell, parent.getHitboxManager());
} }
loadedCellsLock.release();
}
/**
* Gets the server terrain manager for this realm if it exists
* @return The server terrain manager if it exists, null otherwise
*/
public ServerTerrainManager getServerTerrainManager(){
return serverTerrainManager;
}
/**
* Runs code to generate physics entities and register cell in a dedicated thread.
* Because cell hasn't been registered yet, no simulation is performed until the physics is created.
* @param worldPos
*/
private void runPhysicsGenerationThread(Vector3i worldPos){
Thread thread = new Thread(new Runnable(){
@Override
public void run() {
//create physics entities
createTerrainPhysicsEntities(worldPos);
//set ready
groundDataCells.get(getServerDataCellKey(worldPos)).setReady(true);
}
});
groundDataCells.get(getServerDataCellKey(worldPos)).setReady(false);
thread.start();
}
/**
* Gets the key in the groundDataCells map for the data cell at the provided world pos
* @param worldPos The position in world coordinates of the server data cell
* @return The server data cell if it exists, otherwise null
*/
private String getServerDataCellKey(Vector3i worldPos){
return worldPos.x + "_" + worldPos.y + "_" + worldPos.z;
}
/**
* Registers a server data cell with the internal datastructure for tracking them
* @param key The key to register the cell at
* @param cell The cell itself
*/
private ServerDataCell createServerDataCell(Vector3i worldPos){
ServerDataCell rVal = parent.createNewCell();
groundDataCells.put(getServerDataCellKey(worldPos),rVal);
return rVal;
} }
} }

View File

@ -7,13 +7,14 @@ import electrosphere.entity.EntityUtils;
import electrosphere.entity.Scene; import electrosphere.entity.Scene;
import electrosphere.entity.types.hitbox.HitboxManager; import electrosphere.entity.types.hitbox.HitboxManager;
import electrosphere.game.collision.CollisionEngine; import electrosphere.game.collision.CollisionEngine;
import electrosphere.game.collision.CommonWorldData; import electrosphere.game.collision.CollisionWorldData;
import electrosphere.game.server.world.ServerWorldData; import electrosphere.game.server.world.ServerWorldData;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.NetworkMessage; import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.server.Server; import electrosphere.net.server.Server;
import electrosphere.net.server.player.Player; import electrosphere.net.server.player.Player;
import electrosphere.server.datacell.interfaces.DataCellManager; import electrosphere.server.datacell.interfaces.DataCellManager;
import electrosphere.server.terrain.manager.ServerTerrainManager;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -30,9 +31,6 @@ public class Realm {
//this is the cell that all players loading into the game (via connection startup, death, etc) reside in //this is the cell that all players loading into the game (via connection startup, death, etc) reside in
ServerDataCell loadingCell = new ServerDataCell(new Scene()); ServerDataCell loadingCell = new ServerDataCell(new Scene());
//resolver for location -> data cell within this realm
// DataCellLocationResolver dataCellLocationResolver;
//resolver for entity -> data cell within this realm //resolver for entity -> data cell within this realm
EntityDataCellMapper entityDataCellMapper; EntityDataCellMapper entityDataCellMapper;

View File

@ -4,10 +4,14 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.types.hitbox.HitboxManager; import electrosphere.entity.types.hitbox.HitboxManager;
import electrosphere.game.collision.CollisionEngine; import electrosphere.game.collision.CollisionEngine;
import electrosphere.game.collision.CollisionWorldData;
import electrosphere.game.server.world.ServerWorldData; import electrosphere.game.server.world.ServerWorldData;
/** /**
@ -16,9 +20,9 @@ import electrosphere.game.server.world.ServerWorldData;
public class RealmManager { public class RealmManager {
//All realms in this manager //All realms in this manager
Set<Realm> realms = new HashSet<Realm>(); Set<Realm> realms = new CopyOnWriteArraySet<Realm>();
//Map of entities to the realm the entity is in //Map of entities to the realm the entity is in
Map<Entity,Realm> entityToRealmMap = new HashMap<Entity,Realm>(); Map<Entity,Realm> entityToRealmMap = new ConcurrentHashMap<Entity,Realm>();
/** /**
@ -42,9 +46,13 @@ public class RealmManager {
* @return The realm * @return The realm
*/ */
public Realm createGriddedRealm(ServerWorldData serverWorldData){ public Realm createGriddedRealm(ServerWorldData serverWorldData){
Realm realm = new Realm(new CollisionEngine(), new HitboxManager()); //create collision engine
CollisionEngine collisionEngine = new CollisionEngine();
collisionEngine.setCollisionWorldData(new CollisionWorldData(serverWorldData));
//create realm
Realm realm = new Realm(collisionEngine, new HitboxManager());
//create function classes //create function classes
GriddedDataCellManager griddedDataCellManager = new GriddedDataCellManager(realm); GriddedDataCellManager griddedDataCellManager = new GriddedDataCellManager(realm,Globals.serverTerrainManager);
EntityDataCellMapper entityDataCellMapper = new EntityDataCellMapper(); EntityDataCellMapper entityDataCellMapper = new EntityDataCellMapper();
//init gridded manager //init gridded manager
griddedDataCellManager.init(serverWorldData); griddedDataCellManager.init(serverWorldData);

View File

@ -31,7 +31,8 @@ public class ServerDataCell {
List<Player> activePlayers = new LinkedList<Player>(); List<Player> activePlayers = new LinkedList<Player>();
NavMesh navMesh; NavMesh navMesh;
Scene scene; Scene scene;
//controls whether the server data cell simulates its entities or not
boolean ready = false;
/** /**
* Constructs a datacell based on a virtual cell. Should be used when a player * Constructs a datacell based on a virtual cell. Should be used when a player
@ -222,5 +223,21 @@ public class ServerDataCell {
public void setNavMesh(NavMesh navMesh){ public void setNavMesh(NavMesh navMesh){
this.navMesh = navMesh; this.navMesh = navMesh;
} }
/**
* Gets the simulation ready status of the server data cell
* @return True if ready, false otherwise
*/
public boolean isReady(){
return ready;
}
/**
* Sets the simulation ready status of the server data cell
* @param ready True if ready, false otherwise
*/
public void setReady(boolean ready){
this.ready = ready;
}
} }

View File

@ -1,5 +1,6 @@
package electrosphere.server.datacell.physics; package electrosphere.server.datacell.physics;
import electrosphere.client.terrain.cache.ChunkData;
import electrosphere.collision.dispatch.CollisionObject; import electrosphere.collision.dispatch.CollisionObject;
import electrosphere.dynamics.RigidBody; import electrosphere.dynamics.RigidBody;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
@ -7,6 +8,8 @@ import electrosphere.entity.Entity;
import electrosphere.entity.EntityCreationUtils; import electrosphere.entity.EntityCreationUtils;
import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
import electrosphere.entity.ServerEntityUtils;
import electrosphere.entity.types.terrain.TerrainChunk;
import electrosphere.game.collision.PhysicsUtils; import electrosphere.game.collision.PhysicsUtils;
import electrosphere.game.collision.collidable.Collidable; import electrosphere.game.collision.collidable.Collidable;
import electrosphere.game.terrain.processing.TerrainInterpolator; import electrosphere.game.terrain.processing.TerrainInterpolator;
@ -19,30 +22,33 @@ import electrosphere.renderer.ShaderProgram;
import electrosphere.renderer.actor.ActorTextureMask; import electrosphere.renderer.actor.ActorTextureMask;
import electrosphere.renderer.texture.Texture; import electrosphere.renderer.texture.Texture;
import electrosphere.server.datacell.Realm; import electrosphere.server.datacell.Realm;
import electrosphere.server.terrain.manager.ServerTerrainManager;
import electrosphere.server.terrain.manager.ServerTerrainChunk;
import electrosphere.util.Utilities; import electrosphere.util.Utilities;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import org.joml.Quaternionf; import org.joml.Quaternionf;
import org.joml.Vector3d;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.joml.Vector3i;
/** /**
* *
* @author satellite * @author satellite
*/ */
public class PhysicsDataCell { public class PhysicsDataCell {
int cellX;
int cellZ; Vector3i worldPos;
float[][] heightmap; ServerTerrainChunk chunkData;
float[][] texturemap;
int dynamicInterpolationRatio;
Entity physicsEntity; Entity physicsEntity;
CollisionObject physicsObject; CollisionObject physicsObject;
Realm realm;
PhysicsDataCell(){ PhysicsDataCell(){
@ -50,18 +56,15 @@ public class PhysicsDataCell {
} }
public static PhysicsDataCell generateTerrainCell( public static PhysicsDataCell createPhysicsCell(
int cellX, Realm realm,
int cellZ, Vector3i worldPos,
float[][] heightmap, ServerTerrainChunk chunkData
float[][] texturemap,
int dynamicInterpolationRatio
){ ){
PhysicsDataCell rVal = new PhysicsDataCell(); PhysicsDataCell rVal = new PhysicsDataCell();
rVal.cellX = cellX; rVal.realm = realm;
rVal.cellZ = cellZ; rVal.worldPos = worldPos;
rVal.dynamicInterpolationRatio = dynamicInterpolationRatio; rVal.chunkData = chunkData;
rVal.heightmap = heightmap;
return rVal; return rVal;
} }
@ -72,17 +75,25 @@ public class PhysicsDataCell {
EntityUtils.cleanUpEntity(physicsEntity); EntityUtils.cleanUpEntity(physicsEntity);
} }
/**
* Generates the physics entity for this chunk
*/
public void generatePhysics(){ public void generatePhysics(){
//if the entity hasn't already been created for some reason, need to create it //if the entity hasn't already been created for some reason, need to create it
if(physicsEntity == null){ if(physicsEntity == null){
physicsEntity = EntityCreationUtils.createClientSpatialEntity(); Vector3d position = new Vector3d(
worldPos.x * ServerTerrainChunk.CHUNK_DIMENSION,
worldPos.y * ServerTerrainChunk.CHUNK_DIMENSION,
worldPos.z * ServerTerrainChunk.CHUNK_DIMENSION
);
physicsEntity = TerrainChunk.serverCreateTerrainChunkEntity(realm, position, chunkData.getWeights(), chunkData.getValues());
physicsEntity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true); physicsEntity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
EntityUtils.getPosition(physicsEntity).set(new Vector3f(cellX * dynamicInterpolationRatio, 0.0f, cellZ * dynamicInterpolationRatio)); ServerEntityUtils.repositionEntity(physicsEntity, position);
} }
//then actually perform the attach // //then actually perform the attach
physicsObject = PhysicsUtils.attachTerrainRigidBody(physicsEntity,heightmap,true); // physicsObject = PhysicsUtils.attachTerrainRigidBody(physicsEntity,heightmap,true);
Realm realm = Globals.realmManager.getEntityRealm(physicsEntity); // Realm realm = Globals.realmManager.getEntityRealm(physicsEntity);
realm.getCollisionEngine().registerPhysicsEntity(physicsEntity); // realm.getCollisionEngine().registerPhysicsEntity(physicsEntity);
} }
public void destroyPhysics(){ public void destroyPhysics(){

View File

@ -23,7 +23,7 @@ public class NavMeshUtils {
static float NAVMESH_PHASE_TWO_DISPARITY_TOLERANCE = 0.5f; static float NAVMESH_PHASE_TWO_DISPARITY_TOLERANCE = 0.5f;
public static NavMesh createMeshFromChunk(ServerTerrainChunk chunk, NavBlocker navBlocker){ public static NavMesh createMeshFromChunk(ServerTerrainChunk chunk, NavBlocker navBlocker){
NavMesh rVal = Globals.navMeshManager.createNavMesh(); NavMesh rVal = Globals.navMeshManager.createNavMesh();
float[][] heightMap = chunk.getHeightMap(); float[][] heightMap = chunk.getWeights()[0];
boolean[][] navMeshGeneratorMask = navBlocker.getHeightfieldBlocker(); boolean[][] navMeshGeneratorMask = navBlocker.getHeightfieldBlocker();
List<FirstPhaseBox> firstPassBoxes = new LinkedList<FirstPhaseBox>(); List<FirstPhaseBox> firstPassBoxes = new LinkedList<FirstPhaseBox>();
int numInCurrent = 0; int numInCurrent = 0;

View File

@ -22,7 +22,7 @@ public class NavTerrainBlockerCache {
public String getKey(int x, int y){ public String getKey(int x, int y){
return x + "-" + y; return x + "_" + y;
} }
public NavBlocker getBlocker(int x, int y){ public NavBlocker getBlocker(int x, int y){

View File

@ -106,7 +106,7 @@ public class SaveUtils {
} }
public static boolean loadTerrainAndCreateWorldData(String currentSaveName){ public static boolean loadTerrainAndCreateWorldData(String currentSaveName){
Globals.serverTerrainManager = new ServerTerrainManager(2000,50,100,0.0f,0); Globals.serverTerrainManager = new ServerTerrainManager(2000,50,ServerTerrainManager.SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO,0.0f,0);
SaveUtils.loadTerrainAndDB(currentSaveName); SaveUtils.loadTerrainAndDB(currentSaveName);
Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager); Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager);
Globals.realmManager.createGriddedRealm(Globals.serverWorldData); Globals.realmManager.createGriddedRealm(Globals.serverWorldData);

View File

@ -105,9 +105,9 @@ public class MacroSimulation {
} }
} }
if(placementPos != null){ if(placementPos != null){
Structure placedStructure = VirtualStructureUtils.placeStructureAtPoint(placementPos.x, placementPos.y, buildingTypeToPlace); // Structure placedStructure = VirtualStructureUtils.placeStructureAtPoint(placementPos.x, placementPos.y, buildingTypeToPlace);
CharacterUtils.addShelter(chara, placedStructure); // CharacterUtils.addShelter(chara, placedStructure);
VirtualStructureUtils.addResident(placedStructure, chara); // VirtualStructureUtils.addResident(placedStructure, chara);
} }
} }
} }

View File

@ -47,62 +47,64 @@ public class MicroSimulation {
} }
public void simulate(ServerDataCell dataCell, HitboxManager hitboxManager){ public void simulate(ServerDataCell dataCell, HitboxManager hitboxManager){
//update dynamic entity positions calculated by bullet if(dataCell.isReady()){
// Globals.collisionEngine.updateDynamicObjectTransforms(); //update dynamic entity positions calculated by bullet
//list dynamic object positions // Globals.collisionEngine.updateDynamicObjectTransforms();
// Globals.collisionEngine.listBodyPositions(); //list dynamic object positions
//simulate ai // Globals.collisionEngine.listBodyPositions();
Globals.aiManager.simulate(); //simulate ai
//update actor animations Globals.aiManager.simulate();
for(Entity currentEntity : dataCell.getScene().getEntitiesWithTag(EntityTags.DRAWABLE)){ //update actor animations
//fetch actor for(Entity currentEntity : dataCell.getScene().getEntitiesWithTag(EntityTags.DRAWABLE)){
Actor currentActor = EntityUtils.getActor(currentEntity); //fetch actor
//increment animations Actor currentActor = EntityUtils.getActor(currentEntity);
if(currentActor.isPlayingAnimation()){ //increment animations
currentActor.incrementAnimationTime(Main.deltaFrames / Main.targetFrameRate); if(currentActor.isPlayingAnimation()){
currentActor.incrementAnimationTime(Main.deltaFrames / Main.targetFrameRate);
}
} }
} //make items play idle animation
//make items play idle animation for(Entity item : dataCell.getScene().getEntitiesWithTag(EntityTags.ITEM)){
for(Entity item : dataCell.getScene().getEntitiesWithTag(EntityTags.ITEM)){ ItemUtils.updateItemActorAnimation(item);
ItemUtils.updateItemActorAnimation(item); }
} //particle state updates
//particle state updates for(Entity particle : dataCell.getScene().getEntitiesWithTag(EntityTags.PARTICLE)){
for(Entity particle : dataCell.getScene().getEntitiesWithTag(EntityTags.PARTICLE)){ // ParticleTree tree = ParticleUtils.getParticleTree(particle);
// ParticleTree tree = ParticleUtils.getParticleTree(particle); // tree.simulate(Main.deltaFrames);
// tree.simulate(Main.deltaFrames); ParticleUtils.makeParticleBillboardFaceCamera(particle);
ParticleUtils.makeParticleBillboardFaceCamera(particle); }
} //update attached entity positions
//update attached entity positions AttachUtils.serverUpdateAttachedEntityPositions(dataCell);
AttachUtils.serverUpdateAttachedEntityPositions(dataCell); //update hitbox positions
//update hitbox positions for(Entity currentHitbox : hitboxManager.getAllHitboxes()){
for(Entity currentHitbox : hitboxManager.getAllHitboxes()){ HitboxUtils.serverUpdatePosition(currentHitbox);
HitboxUtils.serverUpdatePosition(currentHitbox); }
} //collide hitboxes
//collide hitboxes for(Entity currentHitbox : hitboxManager.getAllHitboxes()){
for(Entity currentHitbox : hitboxManager.getAllHitboxes()){ if(isReady){
if(isReady){ HitboxUtils.serverCollideEntities(currentHitbox);
HitboxUtils.serverCollideEntities(currentHitbox); }
}
//tally collidables and offset position accordingly
// for(Entity currentCollidable : Globals.entityManager.getEntitiesWithTag(EntityTags.COLLIDABLE)){
// CollidableTree tree = CollidableTree.getCollidableTree(currentCollidable);
// tree.simulate(Main.deltaFrames);
// }
//targeting crosshair
if(Globals.RUN_CLIENT){
Crosshair.checkTargetable();
Crosshair.updateTargetCrosshairPosition();
}
//simulate behavior trees
dataCell.getScene().simulateBehaviorTrees(Main.deltaFrames);
//sum collidable impulses
for(Entity collidable : dataCell.getScene().getEntitiesWithTag(EntityTags.COLLIDABLE)){
ServerCollidableTree.getServerCollidableTree(collidable).simulate(Main.deltaFrames);
}
//delete all client side entities that aren't in visible chunks
if(Globals.clientEntityCullingManager != null){
Globals.clientEntityCullingManager.clearOutOfBoundsEntities();
} }
}
//tally collidables and offset position accordingly
// for(Entity currentCollidable : Globals.entityManager.getEntitiesWithTag(EntityTags.COLLIDABLE)){
// CollidableTree tree = CollidableTree.getCollidableTree(currentCollidable);
// tree.simulate(Main.deltaFrames);
// }
//targeting crosshair
if(Globals.RUN_CLIENT){
Crosshair.checkTargetable();
Crosshair.updateTargetCrosshairPosition();
}
//simulate behavior trees
dataCell.getScene().simulateBehaviorTrees(Main.deltaFrames);
//sum collidable impulses
for(Entity collidable : dataCell.getScene().getEntitiesWithTag(EntityTags.COLLIDABLE)){
ServerCollidableTree.getServerCollidableTree(collidable).simulate(Main.deltaFrames);
}
//delete all client side entities that aren't in visible chunks
if(Globals.clientEntityCullingManager != null){
Globals.clientEntityCullingManager.clearOutOfBoundsEntities();
} }
} }

View File

@ -6,29 +6,58 @@ import java.util.List;
import electrosphere.server.terrain.models.TerrainModification; import electrosphere.server.terrain.models.TerrainModification;
/** /**
* * Is a single subchunk of terrain on the server
* @author amaterasu
*/ */
public class ServerTerrainChunk { public class ServerTerrainChunk {
int worldX, worldY;
List<TerrainModification> modifications = new LinkedList<TerrainModification>();
float[][] heightMap;
float[][] macroValues;
long[][] randomizer;
public ServerTerrainChunk(int worldX, int worldY, float[][] heightMap, float[][] macroValues, long[][] randomizer) { //all chunks are 16x16x16
public static final int CHUNK_DIMENSION = 16;
int worldX, worldY, worldZ;
List<TerrainModification> modifications = new LinkedList<TerrainModification>();
float[][][] weights;
int[][][] values;
public ServerTerrainChunk(int worldX, int worldY, int worldZ, float[][][] weights, int[][][] values) {
this.worldX = worldX; this.worldX = worldX;
this.worldY = worldY; this.worldY = worldY;
this.heightMap = heightMap; this.worldZ = worldZ;
this.macroValues = macroValues; this.weights = weights;
this.randomizer = randomizer; this.values = values;
} }
public static ServerTerrainChunk getArenaChunk(int width, int x, int y){ public static ServerTerrainChunk getArenaChunk(int worldX, int worldY, int worldZ){
float[][] macroValues = new float[5][5]; float[][][] weights = new float[CHUNK_DIMENSION][CHUNK_DIMENSION][CHUNK_DIMENSION];
long[][] randomizer = new long[5][5]; int[][][] values = new int[CHUNK_DIMENSION][CHUNK_DIMENSION][CHUNK_DIMENSION];
float[][] heightmap = new float[width + 1][width + 1]; for(int inc = 0; inc < CHUNK_DIMENSION; inc++){
ServerTerrainChunk rVal = new ServerTerrainChunk(x, y, heightmap, macroValues, randomizer); for(int weightX = 0; weightX < CHUNK_DIMENSION; weightX++){
for(int weightZ = 0; weightZ < CHUNK_DIMENSION; weightZ++){
weights[weightX][inc][weightZ] = -1;
values[weightX][inc][weightZ] = 0;
}
}
}
if(worldY < 1){
for(int weightX = 0; weightX < CHUNK_DIMENSION; weightX++){
for(int weightZ = 0; weightZ < CHUNK_DIMENSION; weightZ++){
weights[weightX][0][weightZ] = 0.1f;
values[weightX][0][weightZ] = 1;
}
}
}
// for(int weightX = 0; weightX < SUB_CHUNK_DIMENSION; weightX++){
// for(int weightZ = 0; weightZ < SUB_CHUNK_DIMENSION; weightZ++){
// weights[weightX][SUB_CHUNK_DIMENSION-1][weightZ] = 1;
// values[weightX][SUB_CHUNK_DIMENSION-1][weightZ] = 1;
// }
// }
// for(int weightX = 0; weightX < SUB_CHUNK_DIMENSION; weightX++){
// for(int weightZ = 0; weightZ < SUB_CHUNK_DIMENSION; weightZ++){
// weights[SUB_CHUNK_DIMENSION-1][weightX][weightZ] = 1;
// values[SUB_CHUNK_DIMENSION-1][weightX][weightZ] = 1;
// }
// }
ServerTerrainChunk rVal = new ServerTerrainChunk(worldX, worldY, worldZ, weights, values);
// rVal.addModification(new TerrainModification(x, y, 3, 3, 5)); // rVal.addModification(new TerrainModification(x, y, 3, 3, 5));
return rVal; return rVal;
} }
@ -41,24 +70,26 @@ public class ServerTerrainChunk {
return worldY; return worldY;
} }
public int getWorldZ() {
return worldZ;
}
public List<TerrainModification> getModifications() { public List<TerrainModification> getModifications() {
return modifications; return modifications;
} }
public float[][] getHeightMap() { public float[][][] getWeights() {
return heightMap; return weights;
} }
public float[][] getMacroValues() { public int[][][] getValues() {
return macroValues; return values;
} }
public long[][] getRandomizer() {
return randomizer;
}
public void addModification(TerrainModification modification){ public void addModification(TerrainModification modification){
modifications.add(modification); modifications.add(modification);
values[modification.getVoxelPos().x][modification.getVoxelPos().y][modification.getVoxelPos().z] = modification.getValue();
weights[modification.getVoxelPos().x][modification.getVoxelPos().y][modification.getVoxelPos().z] = modification.getWeight();
} }

View File

@ -14,15 +14,21 @@ import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import org.joml.Vector3i;
/** /**
* * Provides an interface for the server to query information about terrain
* @author satellite
*/ */
public class ServerTerrainManager { public class ServerTerrainManager {
//the interpolation width of a server terrain manager is hard coded at the moment to make sure it's divisible by the sub chunk calculations
public static final int SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO = 128;
//The size of the world in discrete units * must be multiple of 200 //The size of the world in discrete units * must be multiple of 200
int worldSizeDiscrete; int worldSizeDiscrete;
@ -42,9 +48,14 @@ public class ServerTerrainManager {
//Basic idea is we associate string that contains chunk x&y with elevation //Basic idea is we associate string that contains chunk x&y with elevation
//While we incur a penalty with converting ints -> string, think this will //While we incur a penalty with converting ints -> string, think this will
//offset regenerating the array every time we want a new one //offset regenerating the array every time we want a new one
int cacheSize = 50; int cacheSize = 500;
Map<String, ServerTerrainChunk> elevationMapCache; Map<String, ServerTerrainChunk> chunkCache;
List<String> elevationMapCacheContents; List<String> chunkCacheContents;
//cache for the bicubic interpolated chunks
//don't need to interpolate each time a new chunk is created
//This should eventually be removed as terrain generation becomes more complicated than a heightmap
Map<String, float[][]> heightmapCache = new ConcurrentHashMap<>();
@ -52,8 +63,8 @@ public class ServerTerrainManager {
this.worldSizeDiscrete = worldSizeDiscrete; this.worldSizeDiscrete = worldSizeDiscrete;
this.verticalInterpolationRatio = verticalInterpolationRatio; this.verticalInterpolationRatio = verticalInterpolationRatio;
this.dynamicInterpolationRatio = dynamicInterpolationRatio; this.dynamicInterpolationRatio = dynamicInterpolationRatio;
this.elevationMapCache = new HashMap<String, ServerTerrainChunk>(); this.chunkCache = new ConcurrentHashMap<String, ServerTerrainChunk>();
this.elevationMapCacheContents = new ArrayList<String>(); this.chunkCacheContents = new CopyOnWriteArrayList<String>();
this.interpolationRandomDampener = interpolationRandomDampener; this.interpolationRandomDampener = interpolationRandomDampener;
this.seed = seed; this.seed = seed;
} }
@ -66,9 +77,9 @@ public class ServerTerrainManager {
ServerTerrainManager rVal = new ServerTerrainManager(); ServerTerrainManager rVal = new ServerTerrainManager();
rVal.worldSizeDiscrete = 2; rVal.worldSizeDiscrete = 2;
rVal.verticalInterpolationRatio = 0; rVal.verticalInterpolationRatio = 0;
rVal.dynamicInterpolationRatio = 100; rVal.dynamicInterpolationRatio = SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO;
rVal.elevationMapCache = new HashMap<String, ServerTerrainChunk>(); rVal.chunkCache = new ConcurrentHashMap<String, ServerTerrainChunk>();
rVal.elevationMapCacheContents = new ArrayList<String>(); rVal.chunkCacheContents = new CopyOnWriteArrayList<String>();
rVal.interpolationRandomDampener = 0.0f; rVal.interpolationRandomDampener = 0.0f;
return rVal; return rVal;
} }
@ -139,41 +150,44 @@ public class ServerTerrainManager {
// } // }
// } // }
public double getHeightAtPosition(double x, double y){ public double getHeightAtPosition(double x, double y, double z){
//get chunk coordinate space of input x,y //get chunk coordinate space of input x,y
int chunkX = (int)Math.floor(x / dynamicInterpolationRatio); // int chunkX = (int)Math.floor(x / dynamicInterpolationRatio);
int chunkY = (int)Math.floor(y / dynamicInterpolationRatio); // int chunkY = (int)Math.floor(y / dynamicInterpolationRatio);
//get local coordinate space of input x,y // int chunkZ = (int)Math.floor(z / dynamicInterpolationRatio);
double localX = x - chunkX * dynamicInterpolationRatio; // //get local coordinate space of input x,y
double localY = y - chunkY * dynamicInterpolationRatio; // double localX = x - chunkX * dynamicInterpolationRatio;
//get chunk elevation map // double localY = y - chunkY * dynamicInterpolationRatio;
float[][] chunkElevationMap = getChunk(chunkX,chunkY).heightMap; // double localZ = z - chunkZ * dynamicInterpolationRatio;
//floored variants of local values // //get chunk elevation map
int localXf = (int)Math.floor(localX); // float[][] chunkElevationMap = getChunk(chunkX,chunkY,chunkZ).heightMap;
int localYf = (int)Math.floor(localY); // //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. // Average some inner value.
01 11 // 01 11
0.3 0.4 0.5 // 0.3 0.4 0.5
0.1 0.2 0.3 // 0.1 0.2 0.3
00 10 // 00 10
*/ // */
//interp elevation from map // //interp elevation from map
float elevation00 = chunkElevationMap[(int)localX+0][(int)localY+0]; // float elevation00 = chunkElevationMap[(int)localX+0][(int)localY+0];
float elevation10 = chunkElevationMap[(int)localX+1][(int)localY+0]; // float elevation10 = chunkElevationMap[(int)localX+1][(int)localY+0];
float elevation01 = chunkElevationMap[(int)localX+0][(int)localY+1]; // float elevation01 = chunkElevationMap[(int)localX+0][(int)localY+1];
float elevation11 = chunkElevationMap[(int)localX+1][(int)localY+1]; // float elevation11 = chunkElevationMap[(int)localX+1][(int)localY+1];
double rVal = // double rVal =
(1-(localX-localXf))*(1-(localY-localYf)) * elevation00 + // (1-(localX-localXf))*(1-(localY-localYf)) * elevation00 +
( (localX-localXf))*(1-(localY-localYf)) * elevation10 + // ( (localX-localXf))*(1-(localY-localYf)) * elevation10 +
(1-(localX-localXf))*( (localY-localYf)) * elevation01 + // (1-(localX-localXf))*( (localY-localYf)) * elevation01 +
( (localX-localXf))*( (localY-localYf)) * elevation11 // ( (localX-localXf))*( (localY-localYf)) * elevation11
; // ;
return rVal; return y;
} }
public int getChunkWidth(){ public int getChunkWidth(){
@ -250,82 +264,100 @@ public class ServerTerrainManager {
return model; return model;
} }
public String getKey(int x, int y){ public String getKey(int worldX, int worldY, int worldZ){
return x + "-" + y; return worldX + "_" + worldY + "_" + worldZ;
} }
public ServerTerrainChunk getChunk(int x, int y){ public ServerTerrainChunk getChunk(int worldX, int worldY, int worldZ){
if(model != null){ if(model != null){
//THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING //THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING
String key = getKey(x,y); String key = getKey(worldX,worldY,worldZ);
ServerTerrainChunk returnedChunk; ServerTerrainChunk returnedChunk;
if(elevationMapCache.containsKey(key)){ if(chunkCache.containsKey(key)){
elevationMapCacheContents.remove(key); chunkCacheContents.remove(key);
elevationMapCacheContents.add(0, key); chunkCacheContents.add(0, key);
returnedChunk = elevationMapCache.get(key); returnedChunk = chunkCache.get(key);
return returnedChunk; return returnedChunk;
} else { } else {
float[][] macroValues = model.getRad5MacroValuesAtPosition(x, y); float[][] heightmap = getHeightmap(worldX, worldZ);
long[][] randomizer = model.getRad5RandomizerValuesAtPosition(x, y); float[][][] weights = new float[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION];
float[][] heightmap = TerrainInterpolator.getBicubicInterpolatedChunk( int[][][] values = new int[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION];
macroValues, for(int weightX = 0; weightX < ServerTerrainChunk.CHUNK_DIMENSION; weightX++){
randomizer, for(int weightY = 0; weightY < ServerTerrainChunk.CHUNK_DIMENSION; weightY++){
model.getDynamicInterpolationRatio(), for(int weightZ = 0; weightZ < ServerTerrainChunk.CHUNK_DIMENSION; weightZ++){
model.getRandomDampener() if(weightY < heightmap[ServerTerrainChunk.CHUNK_DIMENSION * worldX + weightX][ServerTerrainChunk.CHUNK_DIMENSION * worldZ + weightZ]){
); weights[weightX][weightY][weightZ] = 1;
ModificationList modificationList = model.getModifications(x, y); values[weightX][weightY][weightZ] = 1;
if(modificationList != null){ } else {
for(TerrainModification modification : modificationList.getModifications()){ weights[weightX][weightY][weightZ] = -1;
heightmap = modification.applyToHeightfield(heightmap); values[weightX][weightY][weightZ] = 0;
}
}
} }
} }
if(elevationMapCacheContents.size() > cacheSize){ // ModificationList modificationList = model.getModifications(x, y);
String oldChunk = elevationMapCacheContents.remove(elevationMapCacheContents.size() - 1); // if(modificationList != null){
elevationMapCache.remove(oldChunk); // for(TerrainModification modification : modificationList.getModifications()){
// heightmap = modification.applyToHeightfield(heightmap);
// }
// }
if(chunkCacheContents.size() > cacheSize){
String oldChunk = chunkCacheContents.remove(chunkCacheContents.size() - 1);
chunkCache.remove(oldChunk);
} }
returnedChunk = new ServerTerrainChunk(x, y, heightmap, macroValues, randomizer); returnedChunk = new ServerTerrainChunk(worldX, worldY, worldZ, weights, values);
elevationMapCache.put(key, returnedChunk); chunkCache.put(key, returnedChunk);
elevationMapCacheContents.add(key); chunkCacheContents.add(key);
return returnedChunk; return returnedChunk;
} }
} else { } else {
//THIS FIRES IF THERE IS AN ARENA WORLD RUNNING //THIS FIRES IF THERE IS AN ARENA WORLD RUNNING
String key = getKey(x,y); String key = getKey(worldX, worldY, worldZ);
ServerTerrainChunk returnedChunk; ServerTerrainChunk returnedChunk;
if(elevationMapCache.containsKey(key)){ if(chunkCache.containsKey(key)){
elevationMapCacheContents.remove(key); chunkCacheContents.remove("" + key);
elevationMapCacheContents.add(0, key); chunkCacheContents.add(0, key);
returnedChunk = elevationMapCache.get(key); returnedChunk = chunkCache.get(key);
return returnedChunk; return returnedChunk;
} else { } else {
returnedChunk = ServerTerrainChunk.getArenaChunk(dynamicInterpolationRatio + 1, x, y); returnedChunk = ServerTerrainChunk.getArenaChunk(worldX, worldY, worldZ);
elevationMapCache.put(key, returnedChunk); chunkCache.put(key, returnedChunk);
elevationMapCacheContents.add(key); chunkCacheContents.add(key);
return returnedChunk; return returnedChunk;
} }
} }
} }
public void deformTerrainAtLocationToValue(int worldX, int worldY, int locationX, int locationY, float value){ private float[][] getHeightmap(int worldX, int worldZ){
System.out.println("Add modification at " + worldX + "," + worldY + " subloc " + locationX + "," + locationY); String key = worldX + "_" + worldZ;
TerrainModification modification = new TerrainModification(worldX,worldY,locationX,locationY,value); if(heightmapCache.containsKey(key)){
model.addModification(modification); return heightmapCache.get(key);
String key = getKey(worldX,worldY); } else {
if(elevationMapCache.containsKey(key)){ float[][] macroValues = model.getRad5MacroValuesAtPosition(worldX, worldZ);
ServerTerrainChunk chunk = elevationMapCache.get(key); long[][] randomizer = model.getRad5RandomizerValuesAtPosition(worldX, worldZ);
chunk.addModification(modification); float[][] heightmap = TerrainInterpolator.getBicubicInterpolatedChunk(
chunk.heightMap = modification.applyToHeightfield(chunk.heightMap); macroValues,
randomizer,
model.getDynamicInterpolationRatio(),
model.getRandomDampener()
);
heightmapCache.put(key,heightmap);
return heightmap;
} }
if(locationX == 0){ }
if(locationY == 0){
deformTerrainAtLocationToValue(worldX - 1, worldY - 1, Globals.serverTerrainManager.dynamicInterpolationRatio, Globals.serverTerrainManager.dynamicInterpolationRatio, value); public void deformTerrainAtLocationToValue(
deformTerrainAtLocationToValue(worldX - 1, worldY, Globals.serverTerrainManager.dynamicInterpolationRatio, locationY, value); Vector3i worldPos,
deformTerrainAtLocationToValue(worldX, worldY - 1, locationX, Globals.serverTerrainManager.dynamicInterpolationRatio, value); Vector3i subChunkPos,
} else { Vector3i voxelPos,
deformTerrainAtLocationToValue(worldX - 1, worldY, Globals.serverTerrainManager.dynamicInterpolationRatio, locationY, value); float weight, int value){
} System.out.println("Add modification at " + worldPos.x + "," + worldPos.z + " subloc " + voxelPos.x + "," + voxelPos.z);
} else if(locationY == 0){ TerrainModification modification = new TerrainModification(worldPos,subChunkPos,voxelPos,weight,value);
deformTerrainAtLocationToValue(worldX, worldY - 1, locationX, Globals.serverTerrainManager.dynamicInterpolationRatio, value); model.addModification(modification);
String key = getKey(worldPos.x,worldPos.y,worldPos.z);
if(chunkCache.containsKey(key)){
ServerTerrainChunk chunk = chunkCache.get(key);
chunk.addModification(modification);
} }
} }

View File

@ -372,12 +372,12 @@ public class TerrainModel {
return realOceanThreshold; return realOceanThreshold;
} }
public String getModificationKey(int x, int y){ public String getModificationKey(int x, int y, int z){
return x + "-" + y; return x + "_" + y + "_" + z;
} }
public void addModification(TerrainModification modification){ public void addModification(TerrainModification modification){
String key = getModificationKey(modification.worldX,modification.worldY); String key = getModificationKey(modification.getWorldPos().x,modification.getWorldPos().y,modification.getWorldPos().z);
ModificationList list; ModificationList list;
if(!modifications.containsKey(key)){ if(!modifications.containsKey(key)){
list = new ModificationList(); list = new ModificationList();
@ -388,13 +388,13 @@ public class TerrainModel {
list.addModification(modification); list.addModification(modification);
} }
public boolean containsModificationsAtCoord(int worldX, int worldY){ public boolean containsModificationsAtCoord(int worldX, int worldY, int worldZ){
return modifications.containsKey(getModificationKey(worldX, worldY)); return modifications.containsKey(getModificationKey(worldX, worldY, worldZ));
} }
public ModificationList getModifications(int worldX, int worldY){ public ModificationList getModifications(int worldX, int worldY, int worldZ){
// System.out.println("Got modifications at " + worldX + " " + worldY); // System.out.println("Got modifications at " + worldX + " " + worldY);
return modifications.get(getModificationKey(worldX, worldY)); return modifications.get(getModificationKey(worldX, worldY, worldZ));
} }
} }

View File

@ -1,48 +1,47 @@
package electrosphere.server.terrain.models; package electrosphere.server.terrain.models;
import org.joml.Vector3i;
import electrosphere.server.terrain.manager.ServerTerrainChunk;
/** /**
* *
* @author amaterasu * @author amaterasu
*/ */
public class TerrainModification { public class TerrainModification {
int worldX; Vector3i worldPos;
int worldY; Vector3i subChunkPos;
int locationX; Vector3i voxelPos;
int locationY; float weight;
float value; int value;
public TerrainModification(int worldX, int worldY, int locationX, int locationY, float value) { public TerrainModification(Vector3i worldPos, Vector3i subChunkPos, Vector3i voxelPos, float weight, int value) {
this.worldX = worldX; this.worldPos = worldPos;
this.worldY = worldY; this.subChunkPos = subChunkPos;
this.locationX = locationX; this.voxelPos = voxelPos;
this.locationY = locationY; this.weight = weight;
this.value = value; this.value = value;
} }
public int getWorldX() { public Vector3i getWorldPos() {
return worldX; return worldPos;
} }
public int getWorldY() { public Vector3i getSubChunkPos() {
return worldY; return subChunkPos;
} }
public int getLocationX() { public Vector3i getVoxelPos() {
return locationX; return voxelPos;
} }
public int getLocationY() { public float getWeight(){
return locationY; return weight;
} }
public float getValue() { public int getValue() {
return value; return value;
} }
public float[][] applyToHeightfield(float[][] heightfield){
heightfield[locationX][locationY] = value;
return heightfield;
}
} }