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",
"type" : "FIXED_INT"
},
{
"name" : "value",
"type" : "FIXED_FLOAT"
},
{
"name" : "worldX",
"type" : "FIXED_INT"
@ -45,26 +53,8 @@
"name" : "worldZ",
"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",
"type" : "BYTE_ARRAY"
},
{
"name" : "terrainWeight",
"type" : "FIXED_FLOAT"
},
{
"name" : "terrainValue",
"type" : "FIXED_INT"
}
],
"messageTypes" : [
@ -319,87 +112,10 @@
},
{
"messageName" : "Update",
"data" : [
"locationX",
"locationY",
"locationZ"
]
},
{
"messageName" : "chunkLoadStart",
"data" : [
"worldX",
"worldY",
"value"
]
},
{
"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"
"worldZ"
]
},
{

View File

@ -143,6 +143,15 @@
<version>0.1</version>
</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-->
<!--License: Apache-->
<!-- https://mvnrepository.com/artifact/org.xerial/sqlite-jdbc -->

View File

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

View File

@ -1,7 +1,9 @@
package electrosphere.client.foliagemanager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
@ -42,6 +44,15 @@ public class ClientFoliageManager {
//Used to prevent concurrent usage of grassEntities set
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);
attributes.put(modelMatrixAttribute,HomogenousBufferTypes.MAT4F);
//set grass generating voxel ids
grassGeneratingVoxelIds.add(2);
}
//shader paths
@ -119,14 +133,6 @@ public class ClientFoliageManager {
grassPosition.set(getNewPosition(playerPosition));
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();
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);
//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
* @param entity The entity
@ -188,6 +187,19 @@ public class ClientFoliageManager {
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.concurrent.ConcurrentHashMap;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.Scene;
import electrosphere.game.collision.CollisionEngine;

View File

@ -1,11 +1,5 @@
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;
/**
@ -44,7 +38,13 @@ public class ClientWorldData {
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.worldMaxPoint = worldMaxPoint;
this.dynamicInterpolationRatio = dynamicInterpolationRatio;
@ -84,4 +84,12 @@ public class ClientWorldData {
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.engine.Globals;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.types.camera.CameraEntityUtils;
import org.joml.Vector3d;
import org.joml.Vector3f;
/**
*
@ -45,7 +43,6 @@ public class ClientFunctions {
public static void loadTerrain(){
if(Globals.clientTerrainManager != null){
Globals.clientTerrainManager.handleMessages();
Globals.clientTerrainManager.ejectLoadedChunks();
updateCellManager();
}
}
@ -59,7 +56,7 @@ public class ClientFunctions {
newPlayerCharacterPosition = EntityUtils.getPosition(Globals.playerEntity);
}
//Cell manager do your things
Globals.drawCellManager.calculateDeltas(oldPlayerCharacterPosition, newPlayerCharacterPosition);
Globals.drawCellManager.calculateDeltas(newPlayerCharacterPosition);
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;
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.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Acts as a cache in front of terrain model to streamline receiving chunks
*/
public class ClientTerrainCache {
/*
Acts as a cache in front of terrain model to streamline receiving heightmaps
on both client and server
*/
ClientWorldData clientWorldData;
//cache capacity
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>();
/**
* Constructor
* @param cacheSize The capacity of the cache
*/
public ClientTerrainCache(int cacheSize){
this.cacheSize = cacheSize;
}
// TerrainChunkValues getChunkValuesAtPoint(int x, int y){
// if(terrainModel != null){
// return new TerrainChunkValues(
// terrainModel.getMacroValuesAtPosition(x, y),
// terrainModel.getRandomizerValuesAtPosition(x, y)
// );
// } else {
// return new TerrainChunkValues(
// new float[3][3],
// 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);
/**
* Adds a chunk data to the terrain cache
* @param worldX The x world position
* @param worldY The y world position
* @param worldZ The z world position
* @param chunkData The chunk data to add at the specified positions
*/
public void addChunkDataToCache(int worldX, int worldY, int worldZ, ChunkData chunkData){
cacheMap.put(getKey(worldX,worldY,worldZ),chunkData);
while(cacheList.size() > cacheSize){
String currentChunk = cacheList.remove(0);
cacheMap.remove(currentChunk);
@ -75,29 +42,41 @@ public class ClientTerrainCache {
}
public String getKey(int x, int y){
return x + "-" + y;
/**
* Generates a key for the cache based on the position provided
* @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){
return cacheMap.containsKey(getKey(x,y));
/**
* Checks whether the cache contains chunk data at a given world point
* @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){
return cacheMap.get(getKey(x,y));
}
public void setClientWorldData(ClientWorldData clientWorldData){
this.clientWorldData = clientWorldData;
/**
* Gets chunk data at the given world point
* @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){
return cacheMap.get(getKey(worldX,worldY,worldZ));
}
}

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;
import electrosphere.client.terrain.cache.ChunkData;
import electrosphere.client.terrain.manager.ClientTerrainManager;
import electrosphere.collision.dispatch.CollisionObject;
import electrosphere.dynamics.RigidBody;
import electrosphere.engine.Globals;
import electrosphere.entity.ClientEntityUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityCreationUtils;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.types.terrain.TerrainChunk;
import electrosphere.game.collision.PhysicsUtils;
import electrosphere.game.collision.collidable.Collidable;
import electrosphere.game.terrain.processing.TerrainInterpolator;
@ -24,20 +28,19 @@ import java.util.LinkedList;
import java.util.List;
import org.joml.Quaternionf;
import org.joml.Vector3d;
import org.joml.Vector3f;
import org.joml.Vector3i;
/**
*
* @author satellite
*/
public class DrawCell {
int cellX;
int cellY;
//the position of the draw cell in world coordinates
Vector3i worldPos;
float[][] heightmap;
float[][] texturemap;
int dynamicInterpolationRatio;
ChunkData data;
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
* because the model creation code for terrain heightmaps sucks :D
* 06/03/2021
*
*
* ITS NOT EVEN UP TO DATE!
* 06/13/2021
*
* //@param drawArray
* Constructs a drawcell object
*/
public static DrawCell generateTerrainCell(
int cellX,
int cellY,
float[][] heightmap,
float[][] texturemap,
int dynamicInterpolationRatio,
Vector3i worldPos,
ChunkData data,
ShaderProgram program
){
DrawCell rVal = new DrawCell();
rVal.cellX = cellX;
rVal.cellY = cellY;
rVal.worldPos = worldPos;
rVal.program = program;
rVal.dynamicInterpolationRatio = dynamicInterpolationRatio;
rVal.heightmap = heightmap;
rVal.texturemap = texturemap;
rVal.data = data;
return rVal;
}
@ -96,52 +85,63 @@ public class DrawCell {
* Generates a drawable entity based on this chunk
* @param stride The stride between indices used to generate "sparse" meshes
*/
public void generateDrawableEntity(int stride){
public void generateDrawableEntity(){
if(modelEntity != null){
Globals.clientScene.deregisterEntity(modelEntity);
}
Model terrainModel = RenderUtils.createMinimizedTerrainModelPrecomputedShader(heightmap, texturemap, program, stride);
Mesh terrainMesh = terrainModel.meshes.get(0);
List<Texture> textureList = new LinkedList<Texture>();
textureList.add(groundTextureOne);
textureList.add(groundTextureTwo);
textureList.add(groundTextureThree);
textureList.add(groundTextureFour);
List<String> uniformList = new LinkedList<String>();
uniformList.add("groundTextures[0]");
uniformList.add("groundTextures[1]");
uniformList.add("groundTextures[2]");
uniformList.add("groundTextures[3]");
String terrainModelPath = Globals.assetManager.registerModel(terrainModel);
modelEntity = EntityCreationUtils.createClientSpatialEntity();
EntityCreationUtils.makeEntityDrawable(modelEntity, terrainModelPath);
EntityUtils.getActor(modelEntity).addTextureMask(new ActorTextureMask("terrain",textureList,uniformList));
modelEntity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
modelEntity.putData(EntityDataStrings.DRAW_CAST_SHADOW, true);
LoggerInterface.loggerRenderer.INFO("New cell @ " + cellX * dynamicInterpolationRatio + "," + cellY * dynamicInterpolationRatio);
EntityUtils.getPosition(modelEntity).set(new Vector3f(cellX * dynamicInterpolationRatio, 0.0f, cellY * dynamicInterpolationRatio));
modelEntity = TerrainChunk.clientCreateTerrainChunkEntity(data.getVoxelWeight(), data.getVoxelType());
// TerrainChunk.createTerrainChunkEntity();
// Model terrainModel = RenderUtils.createMinimizedTerrainModelPrecomputedShader(heightmap, texturemap, program, stride);
// Mesh terrainMesh = terrainModel.meshes.get(0);
// List<Texture> textureList = new LinkedList<Texture>();
// textureList.add(groundTextureOne);
// textureList.add(groundTextureTwo);
// textureList.add(groundTextureThree);
// textureList.add(groundTextureFour);
// List<String> uniformList = new LinkedList<String>();
// uniformList.add("groundTextures[0]");
// uniformList.add("groundTextures[1]");
// uniformList.add("groundTextures[2]");
// uniformList.add("groundTextures[3]");
// String terrainModelPath = Globals.assetManager.registerModel(terrainModel);
// modelEntity = EntityCreationUtils.createClientSpatialEntity();
// EntityCreationUtils.makeEntityDrawable(modelEntity, terrainModelPath);
// EntityUtils.getActor(modelEntity).addTextureMask(new ActorTextureMask("terrain",textureList,uniformList));
// modelEntity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
// 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(){
EntityUtils.cleanUpEntity(modelEntity);
}
public void generatePhysics(){
//if we're in no-graphics mode, need to generate the entity
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");
protected Vector3d getRealPos(){
return new Vector3d(
worldPos.x * ChunkData.CHUNK_SIZE,
worldPos.y * ChunkData.CHUNK_SIZE,
worldPos.z * ChunkData.CHUNK_SIZE
);
}
public void destroyPhysics(){
Globals.clientSceneWrapper.getCollisionEngine().deregisterCollidableEntity(modelEntity);
Globals.clientSceneWrapper.getCollisionEngine().deregisterRigidBody((RigidBody)physicsObject);
}
// public void generatePhysics(){
// //if we're in no-graphics mode, need to generate the entity
// 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;
import electrosphere.client.scene.ClientWorldData;
import electrosphere.client.terrain.cache.ChunkData;
import electrosphere.client.terrain.manager.ClientTerrainManager;
import electrosphere.engine.Globals;
import electrosphere.entity.EntityUtils;
import electrosphere.game.terrain.processing.TerrainInterpolator;
import electrosphere.game.collision.CommonWorldData;
import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.renderer.ShaderProgram;
import electrosphere.server.terrain.manager.ServerTerrainManager;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.joml.Vector2i;
import org.joml.Vector3d;
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
int cellX;
int cellY;
int cellZ;
//the dimensions of the world that this cell manager can handles
int cellWidth;
int cellHeight;
//the width of a minicell in this manager
int miniCellWidth;
//all currently displaying mini cells
DrawCell[][] cells;
boolean[][] valid;
boolean[][] drawable;
boolean[][] updateable;
boolean[][] hasRequested;
boolean[][] needsPhysics;
boolean[][] hasPhysics;
Set<DrawCell> cells;
Map<String,DrawCell> keyCellMap = new HashMap<String,DrawCell>();
Set<String> hasNotRequested;
Set<String> hasRequested;
Set<String> drawable;
Set<String> undrawable;
Set<String> updateable;
ShaderProgram program;
int drawRadius = 5;
// int drawRadius = 5;
int drawStepdownInterval = 3;
int drawStepdownValue = 25;
double drawRadius = 200;
int physicsRadius = 3;
int worldBoundDiscreteMin = 0;
int worldBoundDiscreteMax = 0;
//metadata about the game world
CommonWorldData commonWorldData;
//client terrain manager
// ClientTerrainManager clientTerrainManager;
@ -80,600 +84,273 @@ public class DrawCellManager {
* @param discreteX The initial discrete position X coordinate
* @param discreteY The initial discrete position Y coordinate
*/
public DrawCellManager(CommonWorldData commonWorldData, ClientTerrainManager clientTerrainManager, int discreteX, int discreteY){
this.commonWorldData = commonWorldData;
worldBoundDiscreteMax = (int)(commonWorldData.getWorldBoundMin().x / commonWorldData.getDynamicInterpolationRatio() * 1.0f);
// this.clientTerrainManager = clientTerrainManager;
cells = new DrawCell[drawRadius * 2 + 1][drawRadius * 2 + 1];
valid = new boolean[drawRadius * 2 + 1][drawRadius * 2 + 1];
drawable = new boolean[drawRadius * 2 + 1][drawRadius * 2 + 1];
updateable = new boolean[drawRadius * 2 + 1][drawRadius * 2 + 1];
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;
}
}
public DrawCellManager(ClientTerrainManager clientTerrainManager, int discreteX, int discreteY, int discreteZ){
worldBoundDiscreteMax = (int)(Globals.clientWorldData.getWorldBoundMin().x / Globals.clientWorldData.getDynamicInterpolationRatio() * 1.0f);
cells = new HashSet<DrawCell>();
hasNotRequested = new HashSet<String>();
drawable = new HashSet<String>();
undrawable = new HashSet<String>();
updateable = new HashSet<String>();
hasRequested = new HashSet<String>();
cellX = discreteX;
cellY = discreteY;
cellZ = discreteZ;
program = Globals.terrainShaderProgram;
drawRadius = Globals.userSettings.getGraphicsPerformanceLODChunkRadius();
// drawRadius = Globals.userSettings.getGraphicsPerformanceLODChunkRadius();
drawStepdownInterval = Globals.userSettings.getGameplayPhysicsCellRadius();
physicsRadius = Globals.userSettings.getGameplayPhysicsCellRadius();
invalidateAllCells();
update = true;
}
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;
cellY = cellPos.y;
cellZ = cellPos.z;
}
void updateInvalidCell(){
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]){
found = true;
break;
}
}
if(found){
break;
}
}
if(found){
int currentCellX = cellX - drawRadius + targetX;
int currentCellY = cellY - drawRadius + targetY;
void updateUnrequestedCell(){
if(hasNotRequested.size() > 0){
String targetKey = hasNotRequested.iterator().next();
hasNotRequested.remove(targetKey);
Vector3i worldPos = getVectorFromKey(targetKey);
// Vector3i vector = getVectorFromKey(targetKey);
// int currentCellX = cellX - drawRadius + vector.x;
// int currentCellY = cellY - drawRadius + vector.y;
// int currentCellZ = cellZ - drawRadius + vector.z;
if(
currentCellX >= 0 &&
currentCellX < commonWorldData.getWorldDiscreteSize() &&
currentCellY >= 0 &&
currentCellY < commonWorldData.getWorldDiscreteSize()
){
if(containsHeightmapAtDiscretePoint(currentCellX, currentCellY)){
cells[targetX][targetY] = DrawCell.generateTerrainCell(
currentCellX,
currentCellY,
getHeightmapAtPoint(currentCellX, currentCellY),
getTextureMapAtPoint(currentCellX, currentCellY),
commonWorldData.getDynamicInterpolationRatio(),
program
);
valid[targetX][targetY] = true;
drawable[targetX][targetY] = false;
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;
worldPos.x >= 0 &&
worldPos.x < Globals.clientWorldData.getWorldDiscreteSize() &&
worldPos.y >= 0 &&
worldPos.y < Globals.clientWorldData.getWorldDiscreteSize() &&
worldPos.z >= 0 &&
worldPos.z < Globals.clientWorldData.getWorldDiscreteSize()
){
// if(!hasRequested.contains(targetKey)){
//client should request chunk data from server
Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestChunkDataMessage(
worldPos.x,
worldPos.y,
worldPos.z
));
undrawable.add(targetKey);
hasRequested.add(targetKey);
// }
}
}
}
/**
* Makes one of the undrawable cells drawable
*/
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){
int currentCellX = cellX - drawRadius + targetX;
int currentCellY = cellY - drawRadius + targetY;
if(undrawable.size() > 0){
String targetKey = undrawable.iterator().next();
Vector3i worldPos = getVectorFromKey(targetKey);
if(
currentCellX >= 0 &&
currentCellX < commonWorldData.getWorldDiscreteSize() &&
currentCellY >= 0 &&
currentCellY < commonWorldData.getWorldDiscreteSize()
){
//physics radius calculation
// if(Math.abs(physicsRadius + 1 - targetX) < physicsRadius && Math.abs(physicsRadius + 1 - targetY) < physicsRadius){
// needsPhysics[targetX][targetY] = true;
// }
//calculation for stride
int dist = (int)Math.sqrt((targetX - drawRadius)*(targetX - drawRadius) + (targetY - drawRadius) * (targetY - drawRadius));//Math.abs(targetX - drawRadius) * Math.abs(targetY - drawRadius);
int stride = Math.min(commonWorldData.getDynamicInterpolationRatio()/2, Math.max(1, dist / drawStepdownInterval * drawStepdownValue));
while(commonWorldData.getDynamicInterpolationRatio() % stride != 0){
stride = stride + 1;
worldPos.x >= 0 &&
worldPos.x < Globals.clientWorldData.getWorldDiscreteSize() &&
worldPos.y >= 0 &&
worldPos.y < Globals.clientWorldData.getWorldDiscreteSize() &&
worldPos.z >= 0 &&
worldPos.z < Globals.clientWorldData.getWorldDiscreteSize()
){
if(containsChunkDataAtWorldPoint(worldPos.x, worldPos.y, worldPos.z)){
DrawCell cell = DrawCell.generateTerrainCell(
worldPos,
Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldPos.x, worldPos.y, worldPos.z),
program
);
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(){
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(updateable[x][y]){
found = true;
break;
}
}
if(found){
break;
}
}
if(found){
int currentCellX = cellX - drawRadius + targetX;
int currentCellY = cellY - drawRadius + targetY;
if(updateable.size() > 0){
String targetKey = updateable.iterator().next();
updateable.remove(targetKey);
Vector3i worldPos = getVectorFromKey(targetKey);
if(
currentCellX >= 0 &&
currentCellX < commonWorldData.getWorldDiscreteSize() &&
currentCellY >= 0 &&
currentCellY < commonWorldData.getWorldDiscreteSize()
worldPos.x >= 0 &&
worldPos.x < Globals.clientWorldData.getWorldDiscreteSize() &&
worldPos.y >= 0 &&
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){
// 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(commonWorldData.getDynamicInterpolationRatio()/2, Math.max(1, dist / drawStepdownInterval * drawStepdownValue));
while(commonWorldData.getDynamicInterpolationRatio() % stride != 0){
stride = stride + 1;
}
cells[targetX][targetY].generateDrawableEntity(stride);
// int dist = (int)Math.sqrt((targetX - drawRadius)*(targetX - drawRadius) + (targetY - drawRadius) * (targetY - drawRadius)); //Math.abs(targetX - drawRadius) * Math.abs(targetY - drawRadius);
// int stride = Math.min(commonWorldData.getDynamicInterpolationRatio()/2, Math.max(1, dist / drawStepdownInterval * drawStepdownValue));
// while(commonWorldData.getDynamicInterpolationRatio() % stride != 0){
// stride = stride + 1;
// }
keyCellMap.get(targetKey).generateDrawableEntity();
}
updateable[targetX][targetY] = false;
drawable[targetX][targetY] = true;
drawable.add(targetKey);
}
}
public boolean containsInvalidCell(){
// if(DRAW_CELL_MANAGER_FLAG_UPDATE_DYNAMIC_TERRAIN){
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 containsUnrequestedCell(){
return hasNotRequested.size() > 0;
}
public boolean containsUndrawableCell(){
for(int x = 0;x < drawRadius * 2 + 1; x++){
for(int y = 0; y < drawRadius * 2 + 1; y++){
if(!drawable[x][y] && this.generateDrawables){
return true;
}
}
}
return false;
return undrawable.size() > 0;
}
public boolean containsUpdateableCell(){
for(int x = 0;x < drawRadius * 2 + 1; x++){
for(int y = 0; y < drawRadius * 2 + 1; y++){
if(updateable[x][y] && 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;
}
return updateable.size() > 0;
}
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){
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(){
for(int x = 0; x < drawRadius * 2 + 1; x++){
for(int y = 0; y < drawRadius * 2 + 1; y++){
valid[x][y] = false;
drawable.clear();
hasNotRequested.clear();
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){
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()));
}
// }
}
/**
* Updates cells that need updating in this manager
*/
public void update(){
if(update){
// if(DRAW_CELL_MANAGER_FLAG_UPDATE_DYNAMIC_TERRAIN){
if(containsInvalidCell()){
updateInvalidCell();
if(containsUnrequestedCell() && !containsUndrawableCell()){
updateUnrequestedCell();
} else if(containsUndrawableCell()){
makeCellDrawable();
} else if(containsUpdateableCell()){
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){
return worldX <= cellX + physicsRadius && worldX >= cellX - physicsRadius && worldY <= cellY + physicsRadius && worldY >= cellY - physicsRadius;
@ -683,38 +360,44 @@ public class DrawCellManager {
this.generateDrawables = generate;
}
boolean containsHeightmapAtDiscretePoint(int currentCellX, int currentCellY){
boolean containsChunkDataAtWorldPoint(int worldX, int worldY, int worldZ){
if(Globals.clientTerrainManager != null){
return Globals.clientTerrainManager.containsHeightmapAtDiscretePoint(currentCellX, currentCellY);
return Globals.clientTerrainManager.containsChunkDataAtWorldPoint(worldX,worldY,worldZ);
}
return true;
}
float[][] getHeightmapAtPoint(int currentCellX, int currentCellY){
if(Globals.clientTerrainManager != null){
return Globals.clientTerrainManager.getHeightmapAtPoint(currentCellX, currentCellY);
}
return Globals.serverTerrainManager.getChunk(currentCellX, currentCellY).getHeightMap();
/**
* Gets the chunk data at a given point
* @param worldX The world position x component of the cell
* @param worldY The world position y component of the cell
* @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);
} else {
//hacky fix to +2 to this, I think the interpolation ratio was different for server/client data
//now that we're merging/ambiguous within this class, it's out of bounds-ing unless I +2
//TODO: investigate
float[][] rVal = new float[commonWorldData.getDynamicInterpolationRatio() + 2][commonWorldData.getDynamicInterpolationRatio() + 2];
rVal[1][1] = 1;
rVal[2][1] = 1;
rVal[3][1] = 1;
rVal[4][1] = 1;
rVal[5][1] = 1;
rVal[5][2] = 1;
rVal[6][1] = 1;
rVal[6][2] = 1;
return rVal;
}
/**
* Gets a unique key for the cell
* @param worldX The world position x component of the cell
* @param worldY The world position y component of the cell
* @param worldZ The world position z component of the cell
* @return The key
*/
private String getCellKey(int worldX, int worldY, int worldZ){
return worldX + "_" + worldY + "_" + worldZ;
}
/**
* Parses a vector3i from the cell key
* @param key The cell key
* @return The vector3i containing the components of the cell key
*/
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;
import electrosphere.client.scene.ClientWorldData;
import electrosphere.client.terrain.cache.ChunkData;
import electrosphere.client.terrain.cache.ClientTerrainCache;
import electrosphere.client.terrain.cache.LoadingChunk;
import electrosphere.client.terrain.cache.LoadingChunkCache;
import electrosphere.engine.Globals;
import electrosphere.entity.types.terrain.TerrainChunkData;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.renderer.Model;
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.List;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Manages terrain storage and access on the client
*/
public class ClientTerrainManager {
//queues messages from server
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
static final int CACHE_SIZE = 50;
@ -29,18 +36,17 @@ public class ClientTerrainManager {
//used for caching the macro values
ClientTerrainCache terrainCache;
//used for caching loading chunks that are still streaming over the net
LoadingChunkCache loadingChunkCache;
//The world data for the client
ClientWorldData clientWorldData;
//The queue of terrain chunk data to be buffered to gpu
static List<TerrainChunkGenQueueItem> terrainChunkGenerationQueue = new CopyOnWriteArrayList<TerrainChunkGenQueueItem>();
/**
* Constructor
*/
public ClientTerrainManager(){
terrainCache = new ClientTerrainCache(CACHE_SIZE);
loadingChunkCache = new LoadingChunkCache();
}
@ -49,89 +55,35 @@ public class ClientTerrainManager {
for(TerrainMessage message : messageQueue){
messageQueue.remove(message);
switch(message.getMessageSubtype()){
case MACROVALUE:
// terrainCache.addChunkValuesToCache(message.getlocationX(), message.getlocationY(), macroValues, randomizer);
if(loadingChunkCache.containsKey(loadingChunkCache.getKey(message.getworldX(), message.getworldY()))){
float[][] macroValues = new float[5][5];
long[][] randomizer = new long[5][5];
//macro values
macroValues[0][0] = message.getmacroValue00();
macroValues[0][1] = message.getmacroValue01();
macroValues[0][2] = message.getmacroValue02();
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);
case SENDCHUNKDATA: {
int[][][] values = new int[ChunkData.CHUNK_SIZE][ChunkData.CHUNK_SIZE][ChunkData.CHUNK_SIZE];
float[][][] weights = new float[ChunkData.CHUNK_SIZE][ChunkData.CHUNK_SIZE][ChunkData.CHUNK_SIZE];
ByteBuffer buffer = ByteBuffer.wrap(message.getchunkData());
FloatBuffer floatBuffer = buffer.asFloatBuffer();
for(int x = 0; x < ChunkData.CHUNK_SIZE; x++){
for(int y = 0; y < ChunkData.CHUNK_SIZE; y++){
for(int z = 0; z < ChunkData.CHUNK_SIZE; z++){
weights[x][y][z] = floatBuffer.get();
}
}
}
break;
case CHUNKLOADSTART:
if(clientWorldData != null){
LoadingChunk newChunk = new LoadingChunk(message.getworldX(),message.getworldY(),(int)message.getvalue(),clientWorldData);
loadingChunkCache.addLoadingChunkToCache(newChunk);
newChunk.incrementMessageCount();
} else {
bouncedMessages.add(message);
IntBuffer intView = buffer.asIntBuffer();
intView.position(floatBuffer.position());
for(int x = 0; x < ChunkData.CHUNK_SIZE; x++){
for(int y = 0; y < ChunkData.CHUNK_SIZE; y++){
for(int z = 0; z < ChunkData.CHUNK_SIZE; z++){
values[x][y][z] = intView.get();
}
}
}
break;
case HEIGHTMAPMODIFICATION:
if(loadingChunkCache.containsKey(loadingChunkCache.getKey(message.getworldX(), message.getworldY()))){
LoadingChunk inProgressChunk = loadingChunkCache.fetch(loadingChunkCache.getKey(message.getworldX(), message.getworldY()));
inProgressChunk.addModification(message.getworldX(), message.getworldZ(), message.getlocationX(), message.getlocationZ(), message.getvalue());
inProgressChunk.incrementMessageCount();
} else {
bouncedMessages.add(message);
}
break;
ChunkData data = new ChunkData();
data.setVoxelType(values);
data.setVoxelWeight(weights);
terrainCache.addChunkDataToCache(
message.getworldX(), message.getworldY(), message.getworldZ(),
data
);
} break;
default:
LoggerInterface.loggerEngine.WARNING("ClientTerrainManager: unhandled network message of type" + message.getMessageSubtype());
break;
@ -146,88 +98,30 @@ public class ClientTerrainManager {
messageQueue.add(message);
}
public boolean containsHeightmapAtDiscretePoint(int x, int y){
return terrainCache.containsHeightmapAtChunkPoint(x, y);
public boolean containsChunkDataAtWorldPoint(int worldX, int worldY, int worldZ){
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;
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){
return terrainCache.getHeightmapAtChunkPoint(x, y);
public ChunkData getChunkDataAtWorldPoint(int worldX, int worldY, int worldZ){
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){
String promisedHash = "";
UUID newUUID = UUID.randomUUID();
@ -237,6 +131,9 @@ public class ClientTerrainManager {
return promisedHash;
}
/**
* Pushes all terrain data in queue to the gpu and registers the resulting models
*/
public static void generateTerrainChunkGeometry(){
for(TerrainChunkGenQueueItem queueItem : terrainChunkGenerationQueue){
Model terrainModel = TerrainChunkModelGeneration.generateTerrainModel(queueItem.getData());
@ -244,14 +141,5 @@ public class ClientTerrainManager {
}
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.types.hitbox.HitboxManager;
import electrosphere.game.collision.CollisionEngine;
import electrosphere.game.collision.CommonWorldData;
import electrosphere.game.collision.CollisionWorldData;
import electrosphere.game.config.UserSettings;
import electrosphere.game.server.structure.virtual.StructureManager;
import electrosphere.game.server.world.MacroData;
@ -64,7 +64,6 @@ import electrosphere.server.ai.AIManager;
import electrosphere.server.datacell.EntityDataCellMapper;
import electrosphere.server.datacell.GriddedDataCellManager;
import electrosphere.server.datacell.RealmManager;
import electrosphere.server.datacell.physics.DataCellPhysicsManager;
import electrosphere.server.db.DatabaseController;
import electrosphere.server.pathfinding.NavMeshManager;
import electrosphere.server.simulation.MacroSimulation;
@ -157,7 +156,6 @@ public class Globals {
public static ServerWorldData serverWorldData;
public static RealmManager realmManager;
public static EntityDataCellMapper entityDataCellMapper;
public static DataCellPhysicsManager dataCellPhysicsManager;
//
//Player manager
@ -299,7 +297,7 @@ public class Globals {
public static int openInventoriesCount = 0;
//collision world data
public static CommonWorldData commonWorldData;
public static CollisionWorldData commonWorldData;
//structure manager
public static StructureManager structureManager;

View File

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

View File

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

View File

@ -29,7 +29,7 @@ public class DebugSPWorldLoading {
WindowUtils.replaceMainMenuContents(MenuGenerators.createEmptyMainMenu());
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")){
//
//the juicy server GENERATION part
@ -63,8 +63,6 @@ public class DebugSPWorldLoading {
LoadingUtils.initLocalConnection();
//initialize the "real" objects simulation
LoadingUtils.initMicroSimulation();
//collision engine
LoadingUtils.initCommonWorldData(Globals.RUN_SERVER);
//init game specific stuff (ie different skybox colors)
LoadingUtils.initGameGraphicalEntities();
//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.types.creature.CreatureTemplate;
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.visualattribute.VisualAttribute;
import electrosphere.game.server.town.Town;
@ -54,7 +54,7 @@ public class LoadingUtils {
Actually initialize the terrain manager
*/
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.userSettings.gameplayGenerateWorld()){
Globals.serverTerrainManager.generate();
@ -108,32 +108,32 @@ public class LoadingUtils {
Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager);
}
static void initCommonWorldData(boolean FLAG_INIT_SERVER){
if(Globals.commonWorldData == null){
if(FLAG_INIT_SERVER){
Globals.commonWorldData = new CommonWorldData(Globals.serverWorldData, Globals.serverTerrainManager);
if(Globals.macroSimulation != null){
Town startTown = Globals.macroData.getTowns().get(0);
Vector2i firstPos = startTown.getPositions().get(0);
// double startX = firstPos.x * Globals.serverTerrainManager.getChunkWidth();
// double startZ = firstPos.y * Globals.serverTerrainManager.getChunkWidth();
double startX = Globals.commonWorldData.convertWorldToReal(firstPos.x);
double startZ = Globals.commonWorldData.convertWorldToReal(firstPos.y);
Globals.spawnPoint.set((float)startX,(float)Globals.commonWorldData.getElevationAtPoint(new Vector3d(startX,0,startZ)),(float)startZ);
}
} else {
//basically wait for the client to receive the world metadata
while(!Globals.clientConnection.getClientProtocol().hasReceivedWorld()){
try {
TimeUnit.MILLISECONDS.sleep(5);
} catch (InterruptedException ex) {
}
}
//then create common world data
Globals.commonWorldData = new CommonWorldData(Globals.clientWorldData, Globals.clientTerrainManager);
}
}
}
// static void initCommonWorldData(boolean FLAG_INIT_SERVER){
// if(Globals.commonWorldData == null){
// if(FLAG_INIT_SERVER){
// Globals.commonWorldData = new CommonWorldData(Globals.serverWorldData, Globals.serverTerrainManager);
// if(Globals.macroSimulation != null){
// Town startTown = Globals.macroData.getTowns().get(0);
// Vector2i firstPos = startTown.getPositions().get(0);
// // double startX = firstPos.x * Globals.serverTerrainManager.getChunkWidth();
// // double startZ = firstPos.y * Globals.serverTerrainManager.getChunkWidth();
// double startX = Globals.commonWorldData.convertWorldToReal(firstPos.x);
// double startZ = Globals.commonWorldData.convertWorldToReal(firstPos.y);
// Globals.spawnPoint.set((float)startX,(float)Globals.commonWorldData.getElevationAtPoint(new Vector3d(startX,0,startZ)),(float)startZ);
// }
// } else {
// //basically wait for the client to receive the world metadata
// while(!Globals.clientConnection.getClientProtocol().hasReceivedWorld()){
// try {
// TimeUnit.MILLISECONDS.sleep(5);
// } catch (InterruptedException ex) {
// }
// }
// //then create common world data
// 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);
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);
// LoadingUtils.initTerrainDataCellManager();
//TODO: set spawnpoint
@ -32,8 +32,6 @@ public class ServerLoading {
LoadingUtils.initMacroSimulation();
//initialize the "real" objects simulation
LoadingUtils.initMicroSimulation();
//collision engine
LoadingUtils.initCommonWorldData(Globals.RUN_SERVER);
//init game specific stuff (ie different skybox colors)
LoadingUtils.initGameGraphicalEntities();
//set simulations to ready if they exist

View File

@ -103,4 +103,20 @@ public class EntityCreationUtils {
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){
Realm realm = Globals.realmManager.getEntityRealm(e);
if(realm != null){
//get data cell
ServerDataCell dataCell = realm.getEntityDataCellMapper().getEntityDataCell(e);
if(dataCell != null){
dataCell.getScene().deregisterEntity(e);
}
realm.getEntityDataCellMapper().ejectEntity(e);
}
Globals.realmManager.removeEntity(e);

View File

@ -44,9 +44,9 @@ public class ServerEntityUtils {
public static void repositionEntity(Entity entity, Vector3d position){
Realm realm = Globals.realmManager.getEntityRealm(entity);
//if server, get current server data cell
if(Globals.RUN_SERVER){
ServerDataCell oldDataCell = realm.getDataCellManager().getDataCellAtPoint(EntityUtils.getPosition(entity));
ServerDataCell newDataCell = realm.getDataCellManager().getDataCellAtPoint(position);
ServerDataCell oldDataCell = realm.getDataCellManager().getDataCellAtPoint(EntityUtils.getPosition(entity));
ServerDataCell newDataCell = realm.getDataCellManager().getDataCellAtPoint(position);
if(oldDataCell != newDataCell){
if(newDataCell != null){
ServerDataCell.moveEntityFromCellToCell(entity, oldDataCell, newDataCell);
ServerBehaviorTreeUtils.updateCell(entity, oldDataCell);
@ -58,13 +58,13 @@ public class ServerEntityUtils {
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
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());
if(impulse.type.matches(Collidable.TYPE_TERRAIN)){
hitTerrain = true;
// System.out.println("Impulse force: " + impulseForce);
// System.out.println("Impulse force: " + impulseForce);
// System.out.println("Position: " + position);
}
if(impulse.type.matches(Collidable.TYPE_ITEM)){

View File

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

View File

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

View File

@ -285,46 +285,49 @@ public class HitboxUtils {
Entity generatorParent = (Entity)generatorHitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT);
Realm generatorRealm = Globals.realmManager.getEntityRealm(generatorParent);
HitboxManager realmHitboxManager = generatorRealm.getHitboxManager();
if(generatorRealm != null){
HitboxManager realmHitboxManager = generatorRealm.getHitboxManager();
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();
for(Entity receiverHitbox : realmHitboxManager.getAllHitboxes()){
if(generatorType.equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT) && receiverType.equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT)){
serverDamageHitboxColision(generatorHitbox, receiverHitbox);
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(generatorType.equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT) && receiverType.equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT)){
serverDamageHitboxColision(receiverHitbox, generatorHitbox);
//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)){
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;
import org.joml.Vector3d;
import org.joml.Vector3f;
import electrosphere.client.terrain.manager.ClientTerrainManager;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityCreationUtils;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.ServerEntityUtils;
import electrosphere.game.collision.PhysicsUtils;
import electrosphere.renderer.Model;
import electrosphere.renderer.meshgen.TerrainChunkModelGeneration;
import electrosphere.server.datacell.Realm;
/**
* Utilities for creating terrain chunk entities
*/
public class TerrainChunk {
public static Entity createTerrainChunkEntity(){
float[][][] terrainGrid = new float[][][]{
//plane 1
{
//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,},
},
//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},
},
};
/**
* Creates a client terrain chunk based on weights and values provided
* @param weights The terrain weights
* @param values The values (block types)
* @return The terrain chunk entity
*/
public static Entity clientCreateTerrainChunkEntity(float[][][] weights, int[][][] values){
TerrainChunkData data = TerrainChunkModelGeneration.generateTerrainChunkData(terrainGrid, textureGrid);
TerrainChunkData data = TerrainChunkModelGeneration.generateTerrainChunkData(weights, values);
String modelPath = ClientTerrainManager.queueTerrainGridGeneration(data);
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
EntityCreationUtils.makeEntityDrawable(rVal, modelPath);
// Entity rVal = EntityUtils.spawnDrawableEntityWithPreexistingModel(modelPath);
PhysicsUtils.clientAttachTerrainChunkRigidBody(rVal, data);
EntityCreationUtils.makeEntityDrawablePreexistingModel(rVal, modelPath);
if(data.vertices.size() > 0){
PhysicsUtils.clientAttachTerrainChunkRigidBody(rVal, data);
}
rVal.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, 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;
}

View File

@ -1,6 +1,7 @@
package electrosphere.game.collision;
import electrosphere.collision.dispatch.CollisionWorld.ClosestConvexResultCallback;
import electrosphere.collision.dispatch.CollisionWorld.ConvexResultCallback;
import electrosphere.collision.dispatch.CollisionWorld.LocalConvexResult;
import electrosphere.collision.broadphase.BroadphaseInterface;
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 {
//world data that the collision engine leverages for position correction and the like
CollisionWorldData collisionWorldData;
DiscreteDynamicsWorld world;
SequentialImpulseConstraintSolver solver;
BroadphaseInterface broadphase;
@ -211,16 +215,16 @@ public class CollisionEngine {
* @param positionToCheck the position that it wants to move to
* @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;
//
// check world bounds
//
if(
positionToCheck.x < w.getWorldBoundMin().x ||
positionToCheck.z < w.getWorldBoundMin().z ||
positionToCheck.x > w.getWorldBoundMax().x ||
positionToCheck.z > w.getWorldBoundMax().z
positionToCheck.x < collisionWorldData.getWorldBoundMin().x ||
positionToCheck.z < collisionWorldData.getWorldBoundMin().z ||
positionToCheck.x > collisionWorldData.getWorldBoundMax().x ||
positionToCheck.z > collisionWorldData.getWorldBoundMax().z
){
return false;
}
@ -246,7 +250,7 @@ public class CollisionEngine {
* @return the position the engine recommends it move to instead (this is
* 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);
//
// adjust for minimum height (Terrain)
@ -258,17 +262,17 @@ public class CollisionEngine {
//
// adjust for world bounds
//
if(suggestedPosition.x < w.getWorldBoundMin().x){
suggestedPosition.x = w.getWorldBoundMin().x;
if(suggestedPosition.x < collisionWorldData.getWorldBoundMin().x){
suggestedPosition.x = collisionWorldData.getWorldBoundMin().x;
}
if(suggestedPosition.z < w.getWorldBoundMin().z){
suggestedPosition.z = w.getWorldBoundMin().z;
if(suggestedPosition.z < collisionWorldData.getWorldBoundMin().z){
suggestedPosition.z = collisionWorldData.getWorldBoundMin().z;
}
if(suggestedPosition.x > w.getWorldBoundMax().x){
suggestedPosition.x = w.getWorldBoundMax().x;
if(suggestedPosition.x > collisionWorldData.getWorldBoundMax().x){
suggestedPosition.x = collisionWorldData.getWorldBoundMax().x;
}
if(suggestedPosition.z > w.getWorldBoundMax().z){
suggestedPosition.z = w.getWorldBoundMax().z;
if(suggestedPosition.z > collisionWorldData.getWorldBoundMax().z){
suggestedPosition.z = collisionWorldData.getWorldBoundMax().z;
}
return suggestedPosition;
}
@ -282,6 +286,13 @@ public class CollisionEngine {
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){
@ -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 {
CollisionObject me;

View File

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

View File

@ -15,6 +15,7 @@ import electrosphere.server.datacell.Realm;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.ServerEntityUtils;
import electrosphere.entity.types.terrain.TerrainChunkData;
import electrosphere.game.collision.collidable.Collidable;
@ -380,7 +381,6 @@ public class PhysicsUtils {
Realm terrainRealm = Globals.realmManager.getEntityRealm(terrain);
terrainRealm.getCollisionEngine().registerCollisionObject(terrainRigidBody, new Collidable(terrain,Collidable.TYPE_TERRAIN));
// terrainRigidBody.getAabb(aabbMin, aabbMax);
//
// System.out.println("aabbMin: " + aabbMin + " aabbMax: " + aabbMax);
@ -598,6 +598,18 @@ public class PhysicsUtils {
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){
electrosphere.linearmath.Transform transform = new electrosphere.linearmath.Transform();

View File

@ -20,28 +20,28 @@ import org.joml.Vector3f;
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 worldY = Globals.serverWorldData.convertRealToChunkSpace(posY);
Structure rVal = new Structure(worldX,worldY,posX,posY,type);
Globals.macroData.addStructure(rVal);
double centerHeight = Globals.serverTerrainManager.getHeightAtPosition(posX, posY);
StructureType currentTypeObject = Globals.gameConfigCurrent.getStructureTypeMap().getType(type);
float radius = currentTypeObject.getRadius();
for(int x = -(int)radius; x < radius; x++){
for(int y = -(int)radius; y < radius; y++){
int newWorldX = Globals.serverWorldData.convertRealToChunkSpace(posX + x);
int newWorldY = Globals.serverWorldData.convertRealToChunkSpace(posY + y);
double newLocationX = Globals.serverWorldData.getRelativeLocation(posX + x, newWorldX);
double newLocationY = Globals.serverWorldData.getRelativeLocation(posY + y, newWorldY);
// System.out.println("Set height: " + centerHeight);
// System.out.println("Deform in chunk: " + newWorldX + "," + newWorldY);
Globals.serverTerrainManager.deformTerrainAtLocationToValue(newWorldX, newWorldY, (int)(newLocationX), (int)(newLocationY), (float)centerHeight);
}
}
// double centerHeight = Globals.serverTerrainManager.getHeightAtPosition(posX, posY, posZ);
// StructureType currentTypeObject = Globals.gameConfigCurrent.getStructureTypeMap().getType(type);
// float radius = currentTypeObject.getRadius();
// for(int x = -(int)radius; x < radius; x++){
// for(int y = -(int)radius; y < radius; y++){
// int newWorldX = Globals.serverWorldData.convertRealToChunkSpace(posX + x);
// int newWorldY = Globals.serverWorldData.convertRealToChunkSpace(posY + y);
// double newLocationX = Globals.serverWorldData.getRelativeLocation(posX + x, newWorldX);
// double newLocationY = Globals.serverWorldData.getRelativeLocation(posY + y, newWorldY);
// // System.out.println("Set height: " + centerHeight);
// // System.out.println("Deform in chunk: " + newWorldX + "," + newWorldY);
// Globals.serverTerrainManager.deformTerrainAtLocationToValue(newWorldX, newWorldY, (int)(newLocationX), (int)(newLocationY), (float)centerHeight);
// }
// }
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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,7 @@
package electrosphere.net.parser.net.message;
import electrosphere.net.parser.util.ByteStreamUtils;
import electrosphere.net.parser.net.raw.CircularByteBuffer;
import java.util.LinkedList;
import java.util.List;
@ -22,21 +23,20 @@ public class ServerMessage extends NetworkMessage {
return this.messageType;
}
static void stripPacketHeader(List<Byte> byteStream){
byteStream.remove(0);
byteStream.remove(0);
static void stripPacketHeader(CircularByteBuffer byteBuffer){
byteBuffer.read(2);
}
public static boolean canParseMessage(List<Byte> byteStream, byte secondByte){
public static boolean canParseMessage(CircularByteBuffer byteBuffer, byte secondByte){
switch(secondByte){
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;
} else {
return false;
}
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;
} else {
return false;
@ -45,9 +45,9 @@ public class ServerMessage extends NetworkMessage {
return false;
}
public static ServerMessage parsePingMessage(List<Byte> byteStream){
public static ServerMessage parsePingMessage(CircularByteBuffer byteBuffer){
ServerMessage rVal = new ServerMessage(ServerMessageType.PING);
stripPacketHeader(byteStream);
stripPacketHeader(byteBuffer);
return rVal;
}
@ -57,9 +57,9 @@ public class ServerMessage extends NetworkMessage {
return rVal;
}
public static ServerMessage parsePongMessage(List<Byte> byteStream){
public static ServerMessage parsePongMessage(CircularByteBuffer byteBuffer){
ServerMessage rVal = new ServerMessage(ServerMessageType.PONG);
stripPacketHeader(byteStream);
stripPacketHeader(byteBuffer);
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_REQUESTCHUNK = 2;
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_MACROVALUE = 5;
public static final byte TERRAIN_MESSAGE_TYPE_HEIGHTMAPMODIFICATION = 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;
public static final byte TERRAIN_MESSAGE_TYPE_SPAWNPOSITION = 4;
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTCHUNKDATA = 5;
public static final byte TERRAIN_MESSAGE_TYPE_SENDCHUNKDATA = 6;
/*
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_REQUESTCHUNK_SIZE = 10;
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_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> outgoingMessageQueue = new CopyOnWriteArrayList<NetworkMessage>();
CopyOnWriteArrayList<Byte> incomingByteQueue = new CopyOnWriteArrayList<Byte>();
CircularByteBuffer incomingByteBuffer = new CircularByteBuffer(64 * 1024 * 124);
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(){
try {
//read in bytes
int nextValue = 0;
int bytesRead = 0;
byte currentByte = -1;
while(incomingStream.available() > 0){
nextValue = incomingStream.read();
if(nextValue != -1){
currentByte = (byte)nextValue;
incomingByteQueue.add(currentByte);
// System.out.println(currentByte);
// nextValue = incomingStream.read();
bytesRead = incomingStream.read(readBuffer, 0, READ_BUFFER_SIZE);
if(bytesRead > 0){
incomingByteBuffer.add(readBuffer, bytesRead);
}
//add bytes to some kind of queue
}
//parse byte queue for messages
//for each message, append to clientIncomingMessageQueue
NetworkMessage newMessage;
while((newMessage = NetworkMessage.parseBytestreamForMessage(incomingByteQueue))!=null){
while((newMessage = NetworkMessage.parseBytestreamForMessage(incomingByteBuffer))!=null){
incomingMessageQueue.add(newMessage);
}
} catch (IOException ex) {

View File

@ -1,5 +1,7 @@
package electrosphere.net.parser.util;
import electrosphere.net.parser.net.raw.CircularByteBuffer;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.concurrent.Semaphore;
@ -107,6 +109,96 @@ public class ByteStreamUtils {
bufferLock.release();
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){
byte[] rVal = new byte[4];

View File

@ -1,5 +1,10 @@
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.net.parser.net.message.TerrainMessage;
import electrosphere.net.server.Server;
@ -12,25 +17,27 @@ public class TerrainProtocol {
protected static void handleTerrainMessage(ServerConnectionHandler connectionHandler, TerrainMessage message){
switch(message.getMessageSubtype()){
case REQUESTCHUNK:
sendWorldChunk(connectionHandler, message.getworldX(), message.getworldY());
// sendWorldChunk(connectionHandler, message.getworldX(), message.getworldY());
break;
case REQUESTMETADATA:
sendWorldMetadata(connectionHandler);
break;
case REQUESTCHUNKDATA:
sendWorldSubChunk(connectionHandler,
message.getworldX(), message.getworldY(), message.getworldZ()
);
break;
//all ignored message types
case CHUNKLOADSTART:
case HEIGHTMAPMODIFICATION:
case MACROVALUE:
case RESPONSEMETADATA:
case SPAWNPOSITION:
case UPDATE:
case SENDCHUNKDATA:
//silently ignore
break;
}
}
static void sendWorldChunk(ServerConnectionHandler connectionHandler, int worldX, int worldY){
static void sendWorldSubChunk(ServerConnectionHandler connectionHandler, int worldX, int worldY, int worldZ){
/*
int locationX,
int locationY,
@ -56,92 +63,117 @@ public class TerrainProtocol {
// 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(
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()
)
);
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++){
floatView.put(chunk.getWeights()[x][y][z]);
}
}
}
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){

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;
import electrosphere.engine.Globals;
import electrosphere.renderer.texture.Texture;
import org.lwjgl.PointerBuffer;
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.glBindTexture;
import static org.lwjgl.opengl.GL13.GL_TEXTURE0;
@ -27,6 +20,8 @@ public class Material {
String specular;
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;
int texturePointer;
@ -70,8 +65,11 @@ public class Material {
usesFetch = false;
}
/**
* Applies the 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){
Texture diffuseTexture = Globals.assetManager.fetchTexture(diffuse);
if(diffuseTexture != null){

View File

@ -132,40 +132,41 @@ public class InstanceData {
*/
protected void fillBuffers(){
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){
switch(attributeGlBufferMap.get(attribute).getType()){
case VEC3F: {
FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute));
buffer.position(0);
buffer.limit(buffer.capacity());
} break;
case VEC3D: {
DoubleBuffer buffer = ((DoubleBuffer)attributeCpuBufferMap.get(attribute));
buffer.position(0);
buffer.limit(buffer.capacity());
} break;
case VEC4F: {
FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute));
buffer.position(0);
buffer.limit(buffer.capacity());
} break;
case VEC4D: {
DoubleBuffer buffer = ((DoubleBuffer)attributeCpuBufferMap.get(attribute));
buffer.position(0);
buffer.limit(buffer.capacity());
} break;
case MAT4F: {
FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute));
buffer.position(0);
buffer.limit(buffer.capacity());
// System.out.println(buffer.position() + " " + buffer.limit());
} break;
case DOUBLE: {
DoubleBuffer buffer = ((DoubleBuffer)attributeCpuBufferMap.get(attribute));
buffer.position(0);
buffer.limit(buffer.capacity());
} break;
case FLOAT: {
FloatBuffer buffer = ((FloatBuffer)attributeCpuBufferMap.get(attribute));
buffer.position(0);
buffer.limit(buffer.capacity());
} break;
case INT: {
IntBuffer buffer = ((IntBuffer)attributeCpuBufferMap.get(attribute));
buffer.position(0);
buffer.limit(buffer.capacity());
} 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
* @return The data buffers

View File

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

View File

@ -790,6 +790,7 @@ public class TerrainChunkModelGeneration {
Material groundMat = new Material();
groundMat.set_diffuse("/Textures/Ground/Dirt1.png");
groundMat.set_specular("/Textures/Ground/Dirt1.png");
Globals.assetManager.addTexturePathtoQueue("/Textures/Ground/Dirt1.png");
m.setMaterial(groundMat);
m.setShader(TerrainChunkModelGeneration.terrainChunkShaderProgram);
@ -802,7 +803,7 @@ public class TerrainChunkModelGeneration {
//TODO: more optimal key creation
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){

View File

@ -64,7 +64,7 @@ public class MillAbout extends AI {
rand.nextFloat() - 0.5,
rand.nextFloat() - 0.5
).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
// }

View File

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

View File

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

View File

@ -15,7 +15,14 @@ public class ServerContentManager {
//else create from scratch
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;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Semaphore;
import org.joml.Vector3d;
import org.joml.Vector3i;
@ -16,29 +19,40 @@ import electrosphere.game.server.world.ServerWorldData;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.server.player.Player;
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.
*/
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
ServerDataCell[][][] groundDataCells;
Map<String,ServerDataCell> groundDataCells = new HashMap<String,ServerDataCell>();
//loaded cells
Semaphore loadedCellsLock = new Semaphore(1);
Set<ServerDataCell> loadedCells;
int discreteWorldSize;
//parent realm
Realm parent;
//Manager for terrain for this particular cell manager
ServerTerrainManager serverTerrainManager;
/**
* Constructor
* @param parent The gridded data cell manager's parent realm
*/
public GriddedDataCellManager(Realm parent) {
public GriddedDataCellManager(Realm parent, ServerTerrainManager serverTerrainManager) {
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){
discreteWorldSize = data.getWorldSizeDiscrete();
groundDataCells = new ServerDataCell[discreteWorldSize][discreteWorldSize][discreteWorldSize];
loadedCells = new HashSet<ServerDataCell>();
}
@ -57,17 +71,24 @@ public class GriddedDataCellManager implements DataCellManager {
y >= 0 && y < discreteWorldSize &&
z >= 0 && z < discreteWorldSize
){
LoggerInterface.loggerEngine.DEBUG("TerrainDataCellManager: Add player to " + x + " " + y);
if(groundDataCells[x][y][z] != null){
groundDataCells[x][y][z].addPlayer(player);
Vector3i targetPos = new Vector3i(x,y,z);
LoggerInterface.loggerEngine.DEBUG("GriddedDataCellManager: Add player to " + x + " " + y + " " + z);
if(groundDataCells.get(getServerDataCellKey(targetPos)) != null){
groundDataCells.get(getServerDataCellKey(targetPos)).addPlayer(player);
} else {
LoggerInterface.loggerEngine.DEBUG("Creating new cell @ " + x + " " + y + " " + z);
//create data cell
groundDataCells[x][y][z] = ServerDataCell.createServerDataCell(new Scene());
loadedCells.add(groundDataCells[x][y][z]);
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();
//generate/handle content for new server data cell
//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
)
){
if(groundDataCells[x][y][z] != null){
if(groundDataCells[x][y][z].containsPlayer(player)){
Vector3i targetPos = new Vector3i(x,y,z);
if(groundDataCells.get(getServerDataCellKey(targetPos)) != null){
if(groundDataCells.get(getServerDataCellKey(targetPos)).containsPlayer(player)){
// 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
)
){
Vector3i targetPos = new Vector3i(x,y,z);
// System.out.println("Add player to " + x + " " + y);
if(groundDataCells[x][y][z] != null){
groundDataCells[x][y][z].addPlayer(player);
if(groundDataCells.get(getServerDataCellKey(targetPos)) != null){
groundDataCells.get(getServerDataCellKey(targetPos)).addPlayer(player);
} else {
//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
groundDataCells[x][y][z].addPlayer(player);
groundDataCells.get(getServerDataCellKey(targetPos)).addPlayer(player);
}
// additions++;
} else {
@ -148,6 +177,15 @@ public class GriddedDataCellManager implements DataCellManager {
}
// 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
@ -181,15 +219,16 @@ public class GriddedDataCellManager implements DataCellManager {
int worldX = Globals.serverWorldData.convertRealToChunkSpace(point.x);
int worldY = Globals.serverWorldData.convertRealToChunkSpace(point.y);
int worldZ = Globals.serverWorldData.convertRealToChunkSpace(point.z);
Vector3i worldPos = new Vector3i(worldX,worldY,worldZ);
if(
//in bounds of array
worldX >= 0 && worldX < groundDataCells.length &&
worldY >= 0 && worldY < groundDataCells[0].length &&
worldZ >= 0 && worldZ < groundDataCells[0][0].length &&
worldX >= 0 && worldX < discreteWorldSize &&
worldY >= 0 && worldY < discreteWorldSize &&
worldZ >= 0 && worldZ < discreteWorldSize &&
//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;
}
@ -203,18 +242,25 @@ public class GriddedDataCellManager implements DataCellManager {
int worldX = Globals.serverWorldData.convertRealToChunkSpace(point.x);
int worldY = Globals.serverWorldData.convertRealToChunkSpace(point.y);
int worldZ = Globals.serverWorldData.convertRealToChunkSpace(point.z);
Vector3i worldPos = new Vector3i(worldX,worldY,worldZ);
if(
//in bounds of array
worldX >= 0 && worldX < groundDataCells.length &&
worldY >= 0 && worldY < groundDataCells[0].length &&
worldZ >= 0 && worldZ < groundDataCells[0][0].length &&
worldX >= 0 && worldX < discreteWorldSize &&
worldY >= 0 && worldY < discreteWorldSize &&
worldZ >= 0 && worldZ < discreteWorldSize &&
//isn't null
groundDataCells[worldX][worldY][worldZ] == null
groundDataCells.get(getServerDataCellKey(worldPos)) == null
){
groundDataCells[worldX][worldY][worldZ] = ServerDataCell.createServerDataCell(new Scene());
loadedCells.add(groundDataCells[worldX][worldY][worldZ]);
//create data cell
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){
if(
//in bounds of array
position.x >= 0 && position.x < groundDataCells.length &&
position.y >= 0 && position.y < groundDataCells[0].length &&
position.z >= 0 && position.z < groundDataCells[0][0].length &&
position.x >= 0 && position.x < discreteWorldSize &&
position.y >= 0 && position.y < discreteWorldSize &&
position.z >= 0 && position.z < discreteWorldSize &&
//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;
}
@ -241,9 +287,59 @@ public class GriddedDataCellManager implements DataCellManager {
* Calls the simulate function on all loaded cells
*/
public void simulate(){
loadedCellsLock.acquireUninterruptibly();
for(ServerDataCell cell : loadedCells){
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.types.hitbox.HitboxManager;
import electrosphere.game.collision.CollisionEngine;
import electrosphere.game.collision.CommonWorldData;
import electrosphere.game.collision.CollisionWorldData;
import electrosphere.game.server.world.ServerWorldData;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.server.Server;
import electrosphere.net.server.player.Player;
import electrosphere.server.datacell.interfaces.DataCellManager;
import electrosphere.server.terrain.manager.ServerTerrainManager;
import java.util.LinkedList;
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
ServerDataCell loadingCell = new ServerDataCell(new Scene());
//resolver for location -> data cell within this realm
// DataCellLocationResolver dataCellLocationResolver;
//resolver for entity -> data cell within this realm
EntityDataCellMapper entityDataCellMapper;

View File

@ -4,10 +4,14 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
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.types.hitbox.HitboxManager;
import electrosphere.game.collision.CollisionEngine;
import electrosphere.game.collision.CollisionWorldData;
import electrosphere.game.server.world.ServerWorldData;
/**
@ -16,9 +20,9 @@ import electrosphere.game.server.world.ServerWorldData;
public class RealmManager {
//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<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
*/
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
GriddedDataCellManager griddedDataCellManager = new GriddedDataCellManager(realm);
GriddedDataCellManager griddedDataCellManager = new GriddedDataCellManager(realm,Globals.serverTerrainManager);
EntityDataCellMapper entityDataCellMapper = new EntityDataCellMapper();
//init gridded manager
griddedDataCellManager.init(serverWorldData);

View File

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

View File

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

View File

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

View File

@ -106,7 +106,7 @@ public class SaveUtils {
}
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);
Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager);
Globals.realmManager.createGriddedRealm(Globals.serverWorldData);

View File

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

View File

@ -47,62 +47,64 @@ public class MicroSimulation {
}
public void simulate(ServerDataCell dataCell, HitboxManager hitboxManager){
//update dynamic entity positions calculated by bullet
// Globals.collisionEngine.updateDynamicObjectTransforms();
//list dynamic object positions
// Globals.collisionEngine.listBodyPositions();
//simulate ai
Globals.aiManager.simulate();
//update actor animations
for(Entity currentEntity : dataCell.getScene().getEntitiesWithTag(EntityTags.DRAWABLE)){
//fetch actor
Actor currentActor = EntityUtils.getActor(currentEntity);
//increment animations
if(currentActor.isPlayingAnimation()){
currentActor.incrementAnimationTime(Main.deltaFrames / Main.targetFrameRate);
if(dataCell.isReady()){
//update dynamic entity positions calculated by bullet
// Globals.collisionEngine.updateDynamicObjectTransforms();
//list dynamic object positions
// Globals.collisionEngine.listBodyPositions();
//simulate ai
Globals.aiManager.simulate();
//update actor animations
for(Entity currentEntity : dataCell.getScene().getEntitiesWithTag(EntityTags.DRAWABLE)){
//fetch actor
Actor currentActor = EntityUtils.getActor(currentEntity);
//increment animations
if(currentActor.isPlayingAnimation()){
currentActor.incrementAnimationTime(Main.deltaFrames / Main.targetFrameRate);
}
}
}
//make items play idle animation
for(Entity item : dataCell.getScene().getEntitiesWithTag(EntityTags.ITEM)){
ItemUtils.updateItemActorAnimation(item);
}
//particle state updates
for(Entity particle : dataCell.getScene().getEntitiesWithTag(EntityTags.PARTICLE)){
// ParticleTree tree = ParticleUtils.getParticleTree(particle);
// tree.simulate(Main.deltaFrames);
ParticleUtils.makeParticleBillboardFaceCamera(particle);
}
//update attached entity positions
AttachUtils.serverUpdateAttachedEntityPositions(dataCell);
//update hitbox positions
for(Entity currentHitbox : hitboxManager.getAllHitboxes()){
HitboxUtils.serverUpdatePosition(currentHitbox);
}
//collide hitboxes
for(Entity currentHitbox : hitboxManager.getAllHitboxes()){
if(isReady){
HitboxUtils.serverCollideEntities(currentHitbox);
//make items play idle animation
for(Entity item : dataCell.getScene().getEntitiesWithTag(EntityTags.ITEM)){
ItemUtils.updateItemActorAnimation(item);
}
//particle state updates
for(Entity particle : dataCell.getScene().getEntitiesWithTag(EntityTags.PARTICLE)){
// ParticleTree tree = ParticleUtils.getParticleTree(particle);
// tree.simulate(Main.deltaFrames);
ParticleUtils.makeParticleBillboardFaceCamera(particle);
}
//update attached entity positions
AttachUtils.serverUpdateAttachedEntityPositions(dataCell);
//update hitbox positions
for(Entity currentHitbox : hitboxManager.getAllHitboxes()){
HitboxUtils.serverUpdatePosition(currentHitbox);
}
//collide hitboxes
for(Entity currentHitbox : hitboxManager.getAllHitboxes()){
if(isReady){
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;
/**
*
* @author amaterasu
* Is a single subchunk of terrain on the server
*/
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.worldY = worldY;
this.heightMap = heightMap;
this.macroValues = macroValues;
this.randomizer = randomizer;
this.worldZ = worldZ;
this.weights = weights;
this.values = values;
}
public static ServerTerrainChunk getArenaChunk(int width, int x, int y){
float[][] macroValues = new float[5][5];
long[][] randomizer = new long[5][5];
float[][] heightmap = new float[width + 1][width + 1];
ServerTerrainChunk rVal = new ServerTerrainChunk(x, y, heightmap, macroValues, randomizer);
public static ServerTerrainChunk getArenaChunk(int worldX, int worldY, int worldZ){
float[][][] weights = new float[CHUNK_DIMENSION][CHUNK_DIMENSION][CHUNK_DIMENSION];
int[][][] values = new int[CHUNK_DIMENSION][CHUNK_DIMENSION][CHUNK_DIMENSION];
for(int inc = 0; inc < CHUNK_DIMENSION; inc++){
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));
return rVal;
}
@ -41,24 +70,26 @@ public class ServerTerrainChunk {
return worldY;
}
public int getWorldZ() {
return worldZ;
}
public List<TerrainModification> getModifications() {
return modifications;
}
public float[][] getHeightMap() {
return heightMap;
public float[][][] getWeights() {
return weights;
}
public float[][] getMacroValues() {
return macroValues;
public int[][][] getValues() {
return values;
}
public long[][] getRandomizer() {
return randomizer;
}
public void addModification(TerrainModification 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.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import org.joml.Vector3i;
/**
*
* @author satellite
* Provides an interface for the server to query information about terrain
*/
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
int worldSizeDiscrete;
@ -42,9 +48,14 @@ public class ServerTerrainManager {
//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
//offset regenerating the array every time we want a new one
int cacheSize = 50;
Map<String, ServerTerrainChunk> elevationMapCache;
List<String> elevationMapCacheContents;
int cacheSize = 500;
Map<String, ServerTerrainChunk> chunkCache;
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.verticalInterpolationRatio = verticalInterpolationRatio;
this.dynamicInterpolationRatio = dynamicInterpolationRatio;
this.elevationMapCache = new HashMap<String, ServerTerrainChunk>();
this.elevationMapCacheContents = new ArrayList<String>();
this.chunkCache = new ConcurrentHashMap<String, ServerTerrainChunk>();
this.chunkCacheContents = new CopyOnWriteArrayList<String>();
this.interpolationRandomDampener = interpolationRandomDampener;
this.seed = seed;
}
@ -66,9 +77,9 @@ public class ServerTerrainManager {
ServerTerrainManager rVal = new ServerTerrainManager();
rVal.worldSizeDiscrete = 2;
rVal.verticalInterpolationRatio = 0;
rVal.dynamicInterpolationRatio = 100;
rVal.elevationMapCache = new HashMap<String, ServerTerrainChunk>();
rVal.elevationMapCacheContents = new ArrayList<String>();
rVal.dynamicInterpolationRatio = SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO;
rVal.chunkCache = new ConcurrentHashMap<String, ServerTerrainChunk>();
rVal.chunkCacheContents = new CopyOnWriteArrayList<String>();
rVal.interpolationRandomDampener = 0.0f;
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
int chunkX = (int)Math.floor(x / dynamicInterpolationRatio);
int chunkY = (int)Math.floor(y / dynamicInterpolationRatio);
//get local coordinate space of input x,y
double localX = x - chunkX * dynamicInterpolationRatio;
double localY = y - chunkY * dynamicInterpolationRatio;
//get chunk elevation map
float[][] chunkElevationMap = getChunk(chunkX,chunkY).heightMap;
//floored variants of local values
int localXf = (int)Math.floor(localX);
int localYf = (int)Math.floor(localY);
// int chunkX = (int)Math.floor(x / dynamicInterpolationRatio);
// int chunkY = (int)Math.floor(y / dynamicInterpolationRatio);
// int chunkZ = (int)Math.floor(z / dynamicInterpolationRatio);
// //get local coordinate space of input x,y
// double localX = x - chunkX * dynamicInterpolationRatio;
// double localY = y - chunkY * dynamicInterpolationRatio;
// double localZ = z - chunkZ * dynamicInterpolationRatio;
// //get chunk elevation map
// float[][] chunkElevationMap = getChunk(chunkX,chunkY,chunkZ).heightMap;
// //floored variants of local values
// int localXf = (int)Math.floor(localX);
// int localYf = (int)Math.floor(localY);
// int localZf = (int)Math.floor(localZ);
/*
Average some inner value.
// /*
// 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];
// 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
;
// 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;
return y;
}
public int getChunkWidth(){
@ -250,82 +264,100 @@ public class ServerTerrainManager {
return model;
}
public String getKey(int x, int y){
return x + "-" + y;
public String getKey(int worldX, int worldY, int worldZ){
return worldX + "_" + worldY + "_" + worldZ;
}
public ServerTerrainChunk getChunk(int x, int y){
public ServerTerrainChunk getChunk(int worldX, int worldY, int worldZ){
if(model != null){
//THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING
String key = getKey(x,y);
String key = getKey(worldX,worldY,worldZ);
ServerTerrainChunk returnedChunk;
if(elevationMapCache.containsKey(key)){
elevationMapCacheContents.remove(key);
elevationMapCacheContents.add(0, key);
returnedChunk = elevationMapCache.get(key);
if(chunkCache.containsKey(key)){
chunkCacheContents.remove(key);
chunkCacheContents.add(0, key);
returnedChunk = chunkCache.get(key);
return returnedChunk;
} else {
float[][] macroValues = model.getRad5MacroValuesAtPosition(x, y);
long[][] randomizer = model.getRad5RandomizerValuesAtPosition(x, y);
float[][] heightmap = TerrainInterpolator.getBicubicInterpolatedChunk(
macroValues,
randomizer,
model.getDynamicInterpolationRatio(),
model.getRandomDampener()
);
ModificationList modificationList = model.getModifications(x, y);
if(modificationList != null){
for(TerrainModification modification : modificationList.getModifications()){
heightmap = modification.applyToHeightfield(heightmap);
float[][] heightmap = getHeightmap(worldX, worldZ);
float[][][] weights = new float[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION];
int[][][] values = new int[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION];
for(int weightX = 0; weightX < ServerTerrainChunk.CHUNK_DIMENSION; weightX++){
for(int weightY = 0; weightY < ServerTerrainChunk.CHUNK_DIMENSION; weightY++){
for(int weightZ = 0; weightZ < ServerTerrainChunk.CHUNK_DIMENSION; weightZ++){
if(weightY < heightmap[ServerTerrainChunk.CHUNK_DIMENSION * worldX + weightX][ServerTerrainChunk.CHUNK_DIMENSION * worldZ + weightZ]){
weights[weightX][weightY][weightZ] = 1;
values[weightX][weightY][weightZ] = 1;
} else {
weights[weightX][weightY][weightZ] = -1;
values[weightX][weightY][weightZ] = 0;
}
}
}
}
if(elevationMapCacheContents.size() > cacheSize){
String oldChunk = elevationMapCacheContents.remove(elevationMapCacheContents.size() - 1);
elevationMapCache.remove(oldChunk);
// ModificationList modificationList = model.getModifications(x, y);
// if(modificationList != null){
// for(TerrainModification modification : modificationList.getModifications()){
// heightmap = modification.applyToHeightfield(heightmap);
// }
// }
if(chunkCacheContents.size() > cacheSize){
String oldChunk = chunkCacheContents.remove(chunkCacheContents.size() - 1);
chunkCache.remove(oldChunk);
}
returnedChunk = new ServerTerrainChunk(x, y, heightmap, macroValues, randomizer);
elevationMapCache.put(key, returnedChunk);
elevationMapCacheContents.add(key);
returnedChunk = new ServerTerrainChunk(worldX, worldY, worldZ, weights, values);
chunkCache.put(key, returnedChunk);
chunkCacheContents.add(key);
return returnedChunk;
}
} else {
//THIS FIRES IF THERE IS AN ARENA WORLD RUNNING
String key = getKey(x,y);
String key = getKey(worldX, worldY, worldZ);
ServerTerrainChunk returnedChunk;
if(elevationMapCache.containsKey(key)){
elevationMapCacheContents.remove(key);
elevationMapCacheContents.add(0, key);
returnedChunk = elevationMapCache.get(key);
if(chunkCache.containsKey(key)){
chunkCacheContents.remove("" + key);
chunkCacheContents.add(0, key);
returnedChunk = chunkCache.get(key);
return returnedChunk;
} else {
returnedChunk = ServerTerrainChunk.getArenaChunk(dynamicInterpolationRatio + 1, x, y);
elevationMapCache.put(key, returnedChunk);
elevationMapCacheContents.add(key);
returnedChunk = ServerTerrainChunk.getArenaChunk(worldX, worldY, worldZ);
chunkCache.put(key, returnedChunk);
chunkCacheContents.add(key);
return returnedChunk;
}
}
}
public void deformTerrainAtLocationToValue(int worldX, int worldY, int locationX, int locationY, float value){
System.out.println("Add modification at " + worldX + "," + worldY + " subloc " + locationX + "," + locationY);
TerrainModification modification = new TerrainModification(worldX,worldY,locationX,locationY,value);
model.addModification(modification);
String key = getKey(worldX,worldY);
if(elevationMapCache.containsKey(key)){
ServerTerrainChunk chunk = elevationMapCache.get(key);
chunk.addModification(modification);
chunk.heightMap = modification.applyToHeightfield(chunk.heightMap);
private float[][] getHeightmap(int worldX, int worldZ){
String key = worldX + "_" + worldZ;
if(heightmapCache.containsKey(key)){
return heightmapCache.get(key);
} else {
float[][] macroValues = model.getRad5MacroValuesAtPosition(worldX, worldZ);
long[][] randomizer = model.getRad5RandomizerValuesAtPosition(worldX, worldZ);
float[][] heightmap = TerrainInterpolator.getBicubicInterpolatedChunk(
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);
deformTerrainAtLocationToValue(worldX - 1, worldY, Globals.serverTerrainManager.dynamicInterpolationRatio, locationY, value);
deformTerrainAtLocationToValue(worldX, worldY - 1, locationX, Globals.serverTerrainManager.dynamicInterpolationRatio, value);
} else {
deformTerrainAtLocationToValue(worldX - 1, worldY, Globals.serverTerrainManager.dynamicInterpolationRatio, locationY, value);
}
} else if(locationY == 0){
deformTerrainAtLocationToValue(worldX, worldY - 1, locationX, Globals.serverTerrainManager.dynamicInterpolationRatio, value);
}
public void deformTerrainAtLocationToValue(
Vector3i worldPos,
Vector3i subChunkPos,
Vector3i voxelPos,
float weight, int value){
System.out.println("Add modification at " + worldPos.x + "," + worldPos.z + " subloc " + voxelPos.x + "," + voxelPos.z);
TerrainModification modification = new TerrainModification(worldPos,subChunkPos,voxelPos,weight,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;
}
public String getModificationKey(int x, int y){
return x + "-" + y;
public String getModificationKey(int x, int y, int z){
return x + "_" + y + "_" + z;
}
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;
if(!modifications.containsKey(key)){
list = new ModificationList();
@ -388,13 +388,13 @@ public class TerrainModel {
list.addModification(modification);
}
public boolean containsModificationsAtCoord(int worldX, int worldY){
return modifications.containsKey(getModificationKey(worldX, worldY));
public boolean containsModificationsAtCoord(int worldX, int worldY, int worldZ){
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);
return modifications.get(getModificationKey(worldX, worldY));
return modifications.get(getModificationKey(worldX, worldY, worldZ));
}
}

View File

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