Terrain Streaming over network

This commit is contained in:
austin 2021-06-14 00:17:37 -04:00
parent 8c4f902652
commit 444bda5394
45 changed files with 2022 additions and 948 deletions

View File

@ -217,6 +217,7 @@ public class ControlHandler {
controlsState.put(DATA_STRING_INPUT_CODE_MOVEMENT_FORWARD, true);
Vector3f position = EntityUtils.getEntityPosition(Globals.playerCharacter);
EntityMessage outgoingMessage = EntityMessage.constructMoveMessage(
System.currentTimeMillis(),
Globals.playerCharacter.getId(),
position.x,
position.y,

View File

@ -6,6 +6,7 @@ package electrosphere.entity;
*/
public class EntityDataStrings {
/*
Drawable Entity
*/

View File

@ -1,9 +0,0 @@
package electrosphere.entity.collision;
/**
*
* @author amaterasu
*/
public class CollisionAnimation {
}

View File

@ -1,9 +0,0 @@
package electrosphere.entity.collision;
/**
*
* @author amaterasu
*/
public class CollisionSphere {
}

View File

@ -29,12 +29,16 @@ public class MovementTree {
IDLE,
}
MovementTreeState state;
Entity parent;
CopyOnWriteArrayList<EntityMessage> networkMessageQueue = new CopyOnWriteArrayList();
public MovementTree(Entity e){
state = MovementTreeState.IDLE;
parent = e;
@ -75,7 +79,15 @@ public class MovementTree {
case MOVE:
position.set(message.getpositionX(), message.getpositionY(), message.getpositionZ());
if(Globals.mainConfig.runServer){
Globals.server.broadcastMessage(EntityMessage.constructMoveMessage(parent.getId(), message.getpositionX(), message.getpositionY(), message.getpositionZ()));
Globals.server.broadcastMessage(
EntityMessage.constructMoveMessage(
System.currentTimeMillis(),
parent.getId(),
message.getpositionX(),
message.getpositionY(),
message.getpositionZ()
)
);
}
break;
}
@ -100,9 +112,11 @@ public class MovementTree {
}
//move the entity
newPosition = new Vector3f(position).add(new Vector3f(movementVector).mul(velocity));
if(!Globals.collisionEngine.checkCanOccupyPosition(Globals.world, parent, newPosition)){
newPosition = Globals.collisionEngine.suggestMovementPosition(Globals.world, parent, newPosition);
//check/update if collision
if(!Globals.collisionEngine.checkCanOccupyPosition(Globals.commonWorldData, parent, newPosition)){
newPosition = Globals.collisionEngine.suggestMovementPosition(Globals.commonWorldData, parent, newPosition);
}
//actually update
EntityUtils.getEntityPosition(parent).set(newPosition);
EntityUtils.getEntityRotation(parent).rotationTo(new Vector3f(0,0,1), movementVector);
break;
@ -118,8 +132,8 @@ public class MovementTree {
//check if can move forward (collision engine)
//if can, move forward by entity movement stats
newPosition = new Vector3f(position).add(new Vector3f(movementVector).mul(velocity));
if(!Globals.collisionEngine.checkCanOccupyPosition(Globals.world, parent, newPosition)){
newPosition = Globals.collisionEngine.suggestMovementPosition(Globals.world, parent, newPosition);
if(!Globals.collisionEngine.checkCanOccupyPosition(Globals.commonWorldData, parent, newPosition)){
newPosition = Globals.collisionEngine.suggestMovementPosition(Globals.commonWorldData, parent, newPosition);
}
EntityUtils.getEntityPosition(parent).set(newPosition);
EntityUtils.getEntityRotation(parent).rotationTo(new Vector3f(0,0,1), movementVector);
@ -141,8 +155,8 @@ public class MovementTree {
}
//move the entity
newPosition = new Vector3f(position).add(new Vector3f(movementVector).mul(velocity));
if(!Globals.collisionEngine.checkCanOccupyPosition(Globals.world, parent, newPosition)){
newPosition = Globals.collisionEngine.suggestMovementPosition(Globals.world, parent, newPosition);
if(!Globals.collisionEngine.checkCanOccupyPosition(Globals.commonWorldData, parent, newPosition)){
newPosition = Globals.collisionEngine.suggestMovementPosition(Globals.commonWorldData, parent, newPosition);
}
EntityUtils.getEntityPosition(parent).set(newPosition);
EntityUtils.getEntityRotation(parent).rotationTo(new Vector3f(0,0,1), movementVector);

View File

@ -1,7 +1,8 @@
package electrosphere.game.cell;
package electrosphere.game.client.drawcell;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.game.terrain.processing.TerrainInterpolator;
import electrosphere.main.Globals;
import electrosphere.renderer.Model;
import electrosphere.renderer.ModelUtils;
@ -14,21 +15,33 @@ import org.joml.Vector3f;
* @author satellite
*/
public class DrawCell {
float[][] drawArray;
int drawWidth;
int cellX;
int cellY;
int cellWidth;
float[][] heightmap;
int dynamicInterpolationRatio;
Entity modelEntity;
ShaderProgram program;
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
* 6/3/2021
* 06/03/2021
*
*
* ITS NOT EVEN UP TO DATE!
* 06/13/2021
*
* @param drawArray
* @param drawWidth
* @param cellX
@ -36,13 +49,20 @@ public class DrawCell {
* @param cellWidth
* @param program
*/
public DrawCell(float[][] drawArray, int drawWidth, int cellX, int cellY, int cellWidth, ShaderProgram program){
this.drawArray = drawArray;
this.drawWidth = drawWidth;
this.cellX = cellX;
this.cellY = cellY;
this.cellWidth = cellWidth;
this.program = program;
public static DrawCell generateTerrainCell(
int cellX,
int cellY,
float[][] heightmap,
int dynamicInterpolationRatio,
ShaderProgram program
){
DrawCell rVal = new DrawCell();
rVal.cellX = cellX;
rVal.cellY = cellY;
rVal.program = program;
rVal.dynamicInterpolationRatio = dynamicInterpolationRatio;
rVal.heightmap = heightmap;
return rVal;
}
/**
@ -53,11 +73,11 @@ public class DrawCell {
if(modelEntity != null){
Globals.entityManager.deregisterEntity(modelEntity);
}
Model terrainModel = ModelUtils.createTerrainModelPrecomputedShader(drawArray, program, stride);
Model terrainModel = ModelUtils.createTerrainModelPrecomputedShader(heightmap, program, stride);
String terrainModelPath = Globals.assetManager.registerModel(terrainModel);
modelEntity = EntityUtils.spawnDrawableEntity(terrainModelPath);
// System.out.println("New cell @ " + cellX * cellWidth + "," + cellY * cellWidth);
EntityUtils.getEntityPosition(modelEntity).set(new Vector3f(cellX * cellWidth, 0.01f, cellY * cellWidth));
EntityUtils.getEntityPosition(modelEntity).set(new Vector3f(cellX * dynamicInterpolationRatio, 0.01f, cellY * dynamicInterpolationRatio));
}
public void retireCell(){

View File

@ -1,9 +1,13 @@
package electrosphere.game.cell;
package electrosphere.game.client.drawcell;
import electrosphere.game.terrain.TerrainManager;
import electrosphere.game.client.terrain.manager.ClientTerrainManager;
import electrosphere.game.server.terrain.manager.ServerTerrainManager;
import electrosphere.game.client.world.ClientWorldData;
import electrosphere.main.Globals;
import electrosphere.net.parser.net.message.WorldMessage;
import electrosphere.renderer.ShaderProgram;
import java.util.Arrays;
import java.util.HashMap;
import org.joml.Vector3f;
/**
@ -12,8 +16,6 @@ import org.joml.Vector3f;
*/
public class DrawCellManager {
//the terrain manager this cell manager constructs off of
TerrainManager terrainManager;
//the center of this cell manager's array in cell space
int cellX;
@ -32,59 +34,59 @@ public class DrawCellManager {
boolean[][] valid;
boolean[][] drawable;
boolean[][] updateable;
boolean[][] hasRequested;
ShaderProgram program;
int drawRadius = 6;
int drawRadius = 1;
int drawStepdownInterval = 3;
int drawStepdownValue = 5;
//signals the update function to handle dynamic cell generation from terrainmodel
boolean DRAW_CELL_MANAGER_FLAG_UPDATE_DYNAMIC_TERRAIN = true;
//signals the drawcell manager to generate an arena instead of dynamic terrain
boolean DRAW_CELL_MANAGER_FLAG_GENERATE_ARENA = false;
//metadata about the game world
ClientWorldData clientWorldData;
//client terrain manager
ClientTerrainManager clientTerrainManager;
//ready to start updating?
boolean update = false;
public DrawCellManager(TerrainManager terrainManager, float realX, float realY){
this.terrainManager = terrainManager;
public DrawCellManager(ClientWorldData clientWorldData, ClientTerrainManager clientTerrainManager, float realX, float realY){
this.clientWorldData = clientWorldData;
this.clientTerrainManager = clientTerrainManager;
this.miniCellWidth = miniCellWidth;
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];
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;
}
}
cellX = transformRealSpaceToCellSpace(realX);
cellY = transformRealSpaceToCellSpace(realY);
program = Globals.defaultMeshShader;
update = true;
}
DrawCellManager(){
}
public static DrawCellManager createArenaDrawCellManager(){
DrawCellManager rVal = new DrawCellManager();
rVal.cells = new DrawCell[2][2];
rVal.DRAW_CELL_MANAGER_FLAG_UPDATE_DYNAMIC_TERRAIN = false;
rVal.DRAW_CELL_MANAGER_FLAG_GENERATE_ARENA = true;
rVal.cellWidth = 2;
rVal.cellHeight = 2;
rVal.program = Globals.defaultMeshShader;
return rVal;
}
public int getCellX(){
return cellX;
}
@ -122,24 +124,39 @@ public class DrawCellManager {
if(found){
int currentCellX = cellX - drawRadius + targetX;
int currentCellY = cellY - drawRadius + targetY;
if(
currentCellX >= 0 &&
currentCellX < terrainManager.getWorldDiscreteSize() &&
currentCellX < clientWorldData.getWorldDiscreteSize() &&
currentCellY >= 0 &&
currentCellY < terrainManager.getWorldDiscreteSize()
currentCellY < clientWorldData.getWorldDiscreteSize()
){
cells[targetX][targetY] = new DrawCell(
terrainManager.getAugmentedTerrainAtChunk(currentCellX, currentCellY),
terrainManager.getAugmentedChunkWidth(),
currentCellX,
currentCellY,
terrainManager.getChunkWidth(),
program
);
if(clientTerrainManager.containsHeightmapAtDiscretePoint(currentCellX, currentCellY)){
cells[targetX][targetY] = DrawCell.generateTerrainCell(
currentCellX,
currentCellY,
clientTerrainManager.getHeightmapAtPoint(currentCellX, currentCellY),
clientWorldData.getDynamicInterpolationRatio(),
program
);
valid[targetX][targetY] = true;
drawable[targetX][targetY] = false;
updateable[targetX][targetY] = false;
hasRequested[targetX][targetY] = false;
} else {
if(hasRequested[targetX][targetY] == false){
//client should request macro values from server
Globals.clientConnection.queueOutgoingMessage(WorldMessage.constructRequestMacroValuesMessage(currentCellX, currentCellY));
hasRequested[targetX][targetY] = true;
}
}
} else {
valid[targetX][targetY] = true;
drawable[targetX][targetY] = false;
updateable[targetX][targetY] = false;
hasRequested[targetX][targetY] = false;
}
valid[targetX][targetY] = true;
drawable[targetX][targetY] = false;
updateable[targetX][targetY] = false;
}
}
@ -166,13 +183,13 @@ public class DrawCellManager {
int currentCellY = cellY - drawRadius + targetY;
if(
currentCellX >= 0 &&
currentCellX < terrainManager.getWorldDiscreteSize() &&
currentCellX < clientWorldData.getWorldDiscreteSize() &&
currentCellY >= 0 &&
currentCellY < terrainManager.getWorldDiscreteSize()
currentCellY < clientWorldData.getWorldDiscreteSize()
){
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(terrainManager.getChunkWidth()/2, Math.max(1, dist / drawStepdownInterval * drawStepdownValue));
while(terrainManager.getChunkWidth() % stride != 0){
int stride = Math.min(clientWorldData.getDynamicInterpolationRatio()/2, Math.max(1, dist / drawStepdownInterval * drawStepdownValue));
while(clientWorldData.getDynamicInterpolationRatio() % stride != 0){
stride = stride + 1;
}
cells[targetX][targetY].generateDrawableEntity(stride);
@ -204,13 +221,13 @@ public class DrawCellManager {
int currentCellY = cellY - drawRadius + targetY;
if(
currentCellX >= 0 &&
currentCellX < terrainManager.getWorldDiscreteSize() &&
currentCellX < clientWorldData.getWorldDiscreteSize() &&
currentCellY >= 0 &&
currentCellY < terrainManager.getWorldDiscreteSize()
currentCellY < clientWorldData.getWorldDiscreteSize()
){
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(terrainManager.getChunkWidth()/2, Math.max(1, dist / drawStepdownInterval * drawStepdownValue));
while(terrainManager.getChunkWidth() % stride != 0){
int stride = Math.min(clientWorldData.getDynamicInterpolationRatio()/2, Math.max(1, dist / drawStepdownInterval * drawStepdownValue));
while(clientWorldData.getDynamicInterpolationRatio() % stride != 0){
stride = stride + 1;
}
cells[targetX][targetY].generateDrawableEntity(stride);
@ -222,7 +239,7 @@ public class DrawCellManager {
public boolean containsInvalidCell(){
if(DRAW_CELL_MANAGER_FLAG_UPDATE_DYNAMIC_TERRAIN){
// 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]){
@ -230,9 +247,9 @@ public class DrawCellManager {
}
}
}
} 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;
}
// } 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;
}
@ -267,10 +284,12 @@ public class DrawCellManager {
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];
}
}
for(int y = 0; y < drawRadius * 2 + 1; y++){
valid[0][y] = false;
hasRequested[0][y] = false;
}
}
@ -282,10 +301,12 @@ public class DrawCellManager {
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];
}
}
for(int y = 0; y < drawRadius * 2 + 1; y++){
valid[drawRadius * 2][y] = false;
hasRequested[drawRadius * 2][y] = false;
}
}
@ -297,10 +318,12 @@ public class DrawCellManager {
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];
}
}
for(int x = 0; x < drawRadius * 2 + 1; x++){
valid[x][0] = false;
hasRequested[x][0] = false;
}
}
@ -312,16 +335,18 @@ public class DrawCellManager {
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];
}
}
for(int x = 0; x < drawRadius * 2 + 1; x++){
valid[x][drawRadius * 2] = false;
hasRequested[x][drawRadius * 2] = false;
}
}
public int transformRealSpaceToCellSpace(float input){
return (int)(input / terrainManager.getChunkWidth());
return (int)(input / clientWorldData.getDynamicInterpolationRatio());
}
@ -334,7 +359,7 @@ public class DrawCellManager {
}
public void calculateDeltas(Vector3f oldPosition, Vector3f newPosition){
if(DRAW_CELL_MANAGER_FLAG_UPDATE_DYNAMIC_TERRAIN){
// if(DRAW_CELL_MANAGER_FLAG_UPDATE_DYNAMIC_TERRAIN){
if(transformRealSpaceToCellSpace(newPosition.x()) < transformRealSpaceToCellSpace(oldPosition.x())){
shiftChunksNegX();
setCellX(transformRealSpaceToCellSpace(newPosition.x()));
@ -354,11 +379,12 @@ public class DrawCellManager {
setCellX(transformRealSpaceToCellSpace(newPosition.x()));
setCellY(transformRealSpaceToCellSpace(newPosition.z()));
}
}
// }
}
public void update(){
if(DRAW_CELL_MANAGER_FLAG_UPDATE_DYNAMIC_TERRAIN){
if(update){
// if(DRAW_CELL_MANAGER_FLAG_UPDATE_DYNAMIC_TERRAIN){
if(containsInvalidCell()){
updateInvalidCell();
} else if(containsUndrawableCell()){
@ -366,63 +392,72 @@ public class DrawCellManager {
} else if(containsUpdateableCell()){
updateCellModel();
}
} 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);
}
}
// } 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 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;
}
// public
}

View File

@ -0,0 +1,85 @@
package electrosphere.game.client.terrain.cache;
import electrosphere.game.client.world.ClientWorldData;
import electrosphere.game.server.terrain.models.TerrainModel;
import electrosphere.game.terrain.processing.TerrainInterpolator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.concurrent.CopyOnWriteArrayList;
public class ClientTerrainCache {
/*
Acts as a cache in front of terrain model to streamline receiving heightmaps
on both client and server
*/
ClientWorldData clientWorldData;
int cacheSize;
HashMap<String,float[][]> cacheMap = new HashMap();
CopyOnWriteArrayList<String> cacheList = new CopyOnWriteArrayList();
public ClientTerrainCache(int cacheSize, ClientWorldData clientWorldData){
this.cacheSize = cacheSize;
this.clientWorldData = clientWorldData;
}
// 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);
float[][] heightmap = TerrainInterpolator.getAugmentedElevationForChunk(
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 String getKey(int x, int y){
return x + "-" + y;
}
public boolean containsHeightmapAtChunkPoint(int x, int y){
return cacheMap.containsKey(getKey(x,y));
}
//ALL RETRIEVE
public float[][] getHeightmapAtChunkPoint(int x, int y){
return cacheMap.get(getKey(x,y));
}
}

View File

@ -0,0 +1,118 @@
package electrosphere.game.client.terrain.manager;
import electrosphere.game.client.terrain.cache.ClientTerrainCache;
import electrosphere.game.client.world.ClientWorldData;
import electrosphere.net.parser.net.message.WorldMessage;
import java.util.concurrent.CopyOnWriteArrayList;
public class ClientTerrainManager {
//queues messages from server
CopyOnWriteArrayList<WorldMessage> messageQueue = new CopyOnWriteArrayList();
//caches chunks from server
static final int CACHE_SIZE = 50;
//used for caching the macro values
ClientTerrainCache terrainCache;
ClientWorldData clientWorldData;
public ClientTerrainManager(ClientWorldData clientWorldData){
this.clientWorldData = clientWorldData;
terrainCache = new ClientTerrainCache(CACHE_SIZE,clientWorldData);
}
public void handleMessages(){
for(WorldMessage message : messageQueue){
messageQueue.remove(message);
switch(message.getMessageSubtype()){
case MACROVALUE:
float[][] macroValues = new float[3][3];
long[][] randomizer = new long[3][3];
//macro values
macroValues[0][0] = message.getmacroValue00();
macroValues[0][1] = message.getmacroValue01();
macroValues[0][2] = message.getmacroValue02();
macroValues[1][0] = message.getmacroValue10();
macroValues[1][1] = message.getmacroValue11();
macroValues[1][2] = message.getmacroValue12();
macroValues[2][0] = message.getmacroValue20();
macroValues[2][1] = message.getmacroValue21();
macroValues[2][2] = message.getmacroValue22();
//randomizer
randomizer[0][0] = message.getrandomizerValue00();
randomizer[0][1] = message.getrandomizerValue01();
randomizer[0][2] = message.getrandomizerValue02();
randomizer[1][0] = message.getrandomizerValue10();
randomizer[1][1] = message.getrandomizerValue11();
randomizer[1][2] = message.getrandomizerValue12();
randomizer[2][0] = message.getrandomizerValue20();
randomizer[2][1] = message.getrandomizerValue21();
randomizer[2][2] = message.getrandomizerValue22();
terrainCache.addChunkValuesToCache(message.getlocationX(), message.getlocationY(), macroValues, randomizer);
break;
}
}
}
public void attachWorldMessage(WorldMessage message){
messageQueue.add(message);
}
public boolean containsHeightmapAtDiscretePoint(int x, int y){
return terrainCache.containsHeightmapAtChunkPoint(x, y);
}
public boolean containsHeightmapAtRealPoint(float x, float z){
return terrainCache.containsHeightmapAtChunkPoint(clientWorldData.convertRealToChunkSpace(x), clientWorldData.convertRealToChunkSpace(z));
}
public float[][] getHeightmapAtPoint(int x, int y){
return terrainCache.getHeightmapAtChunkPoint(x, y);
}
public float getHeightAtPosition(float x, float y){
//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
float localX = x - chunkX * clientWorldData.getDynamicInterpolationRatio();
float 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];
float 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;
}
}

View File

@ -0,0 +1,81 @@
package electrosphere.game.client.world;
import electrosphere.game.server.world.*;
import electrosphere.game.server.terrain.manager.ServerTerrainManager;
import electrosphere.game.server.world.datacell.DataCell;
import java.util.List;
import org.joml.Vector3f;
/**
*
* @author amaterasu
*/
public class ClientWorldData {
/*
world max
+---------------------+
| |
| |
| |
| |
| |
+---------------------+
world min
basically we're saying what the maximum and minimum x and z something can occupy are
FOR THE TIME BEING DOES NOT ACCOUNT FOR Y
*/
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;
this.randomDampener = randomDampener;
this.worldDiscreteSize = worldDiscreteSize;
}
public Vector3f getWorldBoundMin(){
return worldMinPoint;
}
public Vector3f getWorldBoundMax(){
return worldMaxPoint;
}
public int getDynamicInterpolationRatio() {
return dynamicInterpolationRatio;
}
public float getRandomDampener() {
return randomDampener;
}
public int getWorldDiscreteSize() {
return worldDiscreteSize;
}
public int convertRealToChunkSpace(float real){
return (int)Math.floor(real / dynamicInterpolationRatio);
}
}

View File

@ -1,9 +1,9 @@
package electrosphere.entity.collision;
package electrosphere.game.collision;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.game.world.World;
import electrosphere.game.server.world.ServerWorldData;
import java.util.ArrayList;
import java.util.List;
import org.joml.Vector3f;
@ -27,7 +27,7 @@ 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(World w, Entity e, Vector3f positionToCheck){
public boolean checkCanOccupyPosition(CommonWorldData w, Entity e, Vector3f positionToCheck){
boolean rVal = true;
//
// are we below the terrain?
@ -56,7 +56,7 @@ public class CollisionEngine {
* @return the position the engine recommends it move to instead (this is
* guaranteed to be a valid position)
*/
public Vector3f suggestMovementPosition(World w, Entity e, Vector3f positionToCheck){
public Vector3f suggestMovementPosition(CommonWorldData w, Entity e, Vector3f positionToCheck){
Vector3f suggestedPosition = new Vector3f(positionToCheck);
//
// adjust for minimum height (Terrain)

View File

@ -0,0 +1,73 @@
package electrosphere.game.collision;
import electrosphere.game.client.terrain.manager.ClientTerrainManager;
import electrosphere.game.client.world.ClientWorldData;
import electrosphere.game.server.terrain.manager.ServerTerrainManager;
import electrosphere.game.server.world.ServerWorldData;
import org.joml.Vector3f;
public class CommonWorldData {
ClientWorldData clientWorldData;
ClientTerrainManager clientTerrainManager;
ServerWorldData serverWorldData;
ServerTerrainManager serverTerrainManager;
public CommonWorldData(ClientWorldData clientWorldData, ClientTerrainManager clientTerrainManager){
this.clientWorldData = clientWorldData;
this.clientTerrainManager = clientTerrainManager;
}
public CommonWorldData(ServerWorldData serverWorldData, ServerTerrainManager serverTerrainManager){
this.serverWorldData = serverWorldData;
this.serverTerrainManager = serverTerrainManager;
}
/**
* IF SERVER, RETURN HEIGHT
* IF CLIENT:
* IF HAS DATA,
* RETURN HEIGHT
* IF DOES NOT HAVE DATA,
* RETURN 0
* @param position
* @return
*/
public float getElevationAtPoint(Vector3f 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(){
if(clientWorldData != null){
return clientWorldData.getWorldBoundMin();
} else {
return serverWorldData.getWorldBoundMin();
}
}
public Vector3f getWorldBoundMax(){
if(clientWorldData != null){
return clientWorldData.getWorldBoundMax();
} else {
return serverWorldData.getWorldBoundMax();
}
}
}

View File

@ -1,4 +1,4 @@
package electrosphere.game.terrain.generation;
package electrosphere.game.server.terrain.generation;
/**
*

View File

@ -1,4 +1,4 @@
package electrosphere.game.terrain.generation;
package electrosphere.game.server.terrain.generation;
/**
*

View File

@ -1,4 +1,4 @@
package electrosphere.game.terrain.generation;
package electrosphere.game.server.terrain.generation;
import java.awt.Color;
import java.awt.Graphics;

View File

@ -1,4 +1,4 @@
package electrosphere.game.terrain.generation;
package electrosphere.game.server.terrain.generation;
/**
*

View File

@ -1,4 +1,4 @@
package electrosphere.game.terrain.generation;
package electrosphere.game.server.terrain.generation;
/**
*

View File

@ -1,6 +1,6 @@
package electrosphere.game.terrain.generation;
package electrosphere.game.server.terrain.generation;
import electrosphere.game.terrain.generation.models.TerrainModel;
import electrosphere.game.server.terrain.models.TerrainModel;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.BufferedReader;

View File

@ -1,4 +1,4 @@
package electrosphere.game.terrain.generation;
package electrosphere.game.server.terrain.generation;
import java.util.ArrayList;
import java.util.Iterator;
@ -76,7 +76,7 @@ class TerrainGenerator {
}
}
if(spots.size() < 5){
spots.add(new Hotspot(electrosphere.game.terrain.generation.Utilities.random_Integer(0, DIMENSION - 1),electrosphere.game.terrain.generation.Utilities.random_Integer(0, DIMENSION - 1),electrosphere.game.terrain.generation.Utilities.random_Integer(6000, 10000), electrosphere.game.terrain.generation.Utilities.random_Integer(3, 5), this));
spots.add(new Hotspot(electrosphere.game.server.terrain.generation.Utilities.random_Integer(0, DIMENSION - 1),electrosphere.game.server.terrain.generation.Utilities.random_Integer(0, DIMENSION - 1),electrosphere.game.server.terrain.generation.Utilities.random_Integer(6000, 10000), electrosphere.game.server.terrain.generation.Utilities.random_Integer(3, 5), this));
}
for(int x = 0; x < DIMENSION; x++){
for(int y = 0; y < DIMENSION; y++){
@ -122,7 +122,7 @@ class TerrainGenerator {
for(int x = 0; x < DIMENSION; x++){
for(int y = 0; y < DIMENSION; y++){
if(asthenosphere_Heat[x][y] > 25){
if(electrosphere.game.terrain.generation.Utilities.random_Integer(1, 10) == 10){
if(electrosphere.game.server.terrain.generation.Utilities.random_Integer(1, 10) == 10){
elevation[x][y] = elevation[x][y] + 1;
if(elevation[x][y] > 100){
elevation[x][y] = 100;
@ -203,16 +203,16 @@ class TerrainGenerator {
for(int x = 0; x < DIMENSION; x++){
for(int y = 0; y < DIMENSION; y++){
boolean transfer = false;
if (electrosphere.game.terrain.generation.Utilities.random_Integer(1, 50) == 1) {
if (electrosphere.game.server.terrain.generation.Utilities.random_Integer(1, 50) == 1) {
transfer = true;
}
int transfer_goal;
if(electrosphere.game.terrain.generation.Utilities.random_Integer(1, 2)==1){
transfer_goal = electrosphere.game.terrain.generation.Utilities.random_Integer(20, 60);
if(electrosphere.game.server.terrain.generation.Utilities.random_Integer(1, 2)==1){
transfer_goal = electrosphere.game.server.terrain.generation.Utilities.random_Integer(20, 60);
} else {
transfer_goal = electrosphere.game.terrain.generation.Utilities.random_Integer(0, 60);
transfer_goal = electrosphere.game.server.terrain.generation.Utilities.random_Integer(0, 60);
}
if(electrosphere.game.terrain.generation.Utilities.random_Integer(1, 2)==1){
if(electrosphere.game.server.terrain.generation.Utilities.random_Integer(1, 2)==1){
if (currents[x][y].x >= 0) {
if (transfer) {
if (x + 1 < DIMENSION) {

View File

@ -1,4 +1,4 @@
package electrosphere.game.terrain.generation;
package electrosphere.game.server.terrain.generation;
import java.awt.Point;
import java.io.BufferedReader;

View File

@ -1,4 +1,4 @@
package electrosphere.game.terrain.generation;
package electrosphere.game.server.terrain.generation;
/**
*

View File

@ -1,9 +1,10 @@
package electrosphere.game.terrain;
package electrosphere.game.server.terrain.manager;
import com.google.gson.Gson;
import electrosphere.game.terrain.processing.TerrainInterpolator;
import electrosphere.main.Globals;
import electrosphere.game.terrain.generation.TerrainGen;
import electrosphere.game.terrain.generation.models.TerrainModel;
import electrosphere.game.server.terrain.generation.TerrainGen;
import electrosphere.game.server.terrain.models.TerrainModel;
import electrosphere.util.Utilities;
import java.io.File;
import java.io.IOException;
@ -15,7 +16,7 @@ import java.util.HashMap;
*
* @author satellite
*/
public class TerrainManager {
public class ServerTerrainManager {
//The size of the world in discrete units * must be multiple of 200
@ -40,7 +41,7 @@ public class TerrainManager {
public TerrainManager(int worldSizeDiscrete, int verticalInterpolationRatio, int dynamicInterpolationRatio, float randomDampener){
public ServerTerrainManager(int worldSizeDiscrete, int verticalInterpolationRatio, int dynamicInterpolationRatio, float randomDampener){
this.worldSizeDiscrete = worldSizeDiscrete;
this.verticalInterpolationRatio = verticalInterpolationRatio;
this.dynamicInterpolationRatio = dynamicInterpolationRatio;
@ -49,6 +50,21 @@ public class TerrainManager {
this.randomDampener = randomDampener;
}
ServerTerrainManager(){
}
public static ServerTerrainManager constructArenaTerrainManager(){
ServerTerrainManager rVal = new ServerTerrainManager();
rVal.worldSizeDiscrete = 2;
rVal.verticalInterpolationRatio = 0;
rVal.dynamicInterpolationRatio = 100;
rVal.elevationMapCache = new HashMap();
rVal.elevationMapCacheContents = new ArrayList();
rVal.randomDampener = 0.0f;
return rVal;
}
public void generate(){
TerrainGen terrainGen = new TerrainGen();
terrainGen.setInterpolationRatio(worldSizeDiscrete/200);
@ -79,20 +95,31 @@ public class TerrainManager {
}
public float[][] getAugmentedTerrainAtChunk(int x, int y){
String targetChunkName = x + "-" + y;
if(elevationMapCache.containsKey(targetChunkName)){
elevationMapCacheContents.remove(targetChunkName);
elevationMapCacheContents.add(0, targetChunkName);
return elevationMapCache.get(targetChunkName);
} else {
float[][] targetChunk = model.getAugmentedElevationForChunk(model.getMacroValuesAtPosition(x, y), model.getRandomizerValuesAtPosition(x, y));
if(elevationMapCacheContents.size() > cacheSize){
String oldChunk = elevationMapCacheContents.remove(elevationMapCacheContents.size() - 1);
elevationMapCache.remove(oldChunk);
//THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING
if(model != null){
String targetChunkName = x + "-" + y;
if(elevationMapCache.containsKey(targetChunkName)){
elevationMapCacheContents.remove(targetChunkName);
elevationMapCacheContents.add(0, targetChunkName);
return elevationMapCache.get(targetChunkName);
} else {
float[][] targetChunk = TerrainInterpolator.getAugmentedElevationForChunk(
model.getMacroValuesAtPosition(x, y),
model.getRandomizerValuesAtPosition(x, y),
model.getDynamicInterpolationRatio(),
model.getRandomDampener()
);
if(elevationMapCacheContents.size() > cacheSize){
String oldChunk = elevationMapCacheContents.remove(elevationMapCacheContents.size() - 1);
elevationMapCache.remove(oldChunk);
}
elevationMapCache.put(targetChunkName, targetChunk);
elevationMapCacheContents.add(targetChunkName);
return targetChunk;
}
elevationMapCache.put(targetChunkName, targetChunk);
elevationMapCacheContents.add(targetChunkName);
return targetChunk;
} else {
//THIS FIRES IF THERE IS AN ARENA WORLD RUNNING
return new float[dynamicInterpolationRatio + 1][dynamicInterpolationRatio + 1];
}
}
@ -146,7 +173,51 @@ public class TerrainManager {
}
public float getDiscreteValue(int x, int y){
return model.getElevation()[x][y];
if(model != null){
return model.getElevation()[x][y];
} else {
return 0;
}
}
public int getDynamicInterpolationRatio(){
//THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING
if(model != null){
return model.getDynamicInterpolationRatio();
} else {
//THIS FIRES IF THERE IS AN ARENA WORLD RUNNING
return 0;
}
}
public float getRandomDampener(){
//THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING
if(model != null){
return model.getRandomDampener();
} else {
//THIS FIRES IF THERE IS AN ARENA WORLD RUNNING
return 0.0f;
}
}
public float[][] getMacroValues(int x, int y){
//THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING
if(model != null){
return model.getMacroValuesAtPosition(x, y);
} else {
//THIS FIRES IF THERE IS AN ARENA WORLD RUNNING
return new float[3][3];
}
}
public long[][] getRandomizer(int x, int y){
//THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING
if(model != null){
return model.getRandomizerValuesAtPosition(x, y);
} else {
//THIS FIRES IF THERE IS AN ARENA WORLD RUNNING
return new long[3][3];
}
}
}

View File

@ -0,0 +1,316 @@
package electrosphere.game.server.terrain.models;
import java.util.Random;
public class TerrainModel {
int dynamicInterpolationRatio;
int discreteArrayDimension;
float[][] elevation;
long[][] chunkRandomizer;
float randomDampener = 0.4f;
TerrainModel() {
}
public TerrainModel(int dimension, float[][] elevation, long[][] chunkRandomizer, int dynamicInterpolationRatio){
this.dynamicInterpolationRatio = dynamicInterpolationRatio;
this.discreteArrayDimension = dimension;
this.elevation = elevation;
this.chunkRandomizer = chunkRandomizer;
}
public static TerrainModel constructTerrainModel(int dimension, int dynamicInterpolationRatio){
TerrainModel rVal = new TerrainModel();
rVal.discreteArrayDimension = dimension;
rVal.dynamicInterpolationRatio = dynamicInterpolationRatio;
return rVal;
}
public float[][] getElevation(){
return elevation;
}
public void setRandomDampener(float f){
randomDampener = f;
}
/**
* Dynamically interpolates a chunk of a specific size from the pre-existing elevation map
* @param x The x position on the elevation map to get a chunk from
* @param y The y position on the elevation map to get a chunk from
* @return Dynamically interpolated float array of elevations of chunk
*/
public float[][] getElevationForChunk(int x, int y){
Random rand = new Random(chunkRandomizer[x][y]);
//this is what we intend to return from the function
float[][] rVal = new float[dynamicInterpolationRatio][dynamicInterpolationRatio];
/*
So we're looking at chunk x,y
if this is our grid:
4 0.1 0.2 0.3 0.4
^
| 3 0.1 0.2 0.3 0.4
|
| 2 0.1 0.2 0.3 0.4
x 1 0.1 0.2 0.3 0.4
0 1 2 3
y ---- >
say we're looking at x=2,y=1
"macroValues" should contain the values for bounds x = [1,3] and y = [0,2]
the goal is to have the "center" of the output chunk have the value the
elevation grid at x=2,y=1
*/
//set macroValues
float[][] macroValues = getMacroValuesAtPosition(x,y);
int halfLength = dynamicInterpolationRatio/2;
/*
Four quadrants we're generating
_____________________
|1 |2 |
| | |
| | |
| | |
|__________|__________|
|3 |4 |
| | |
| | |
|__________|__________|
First set of loops is quadrant 1
then quadrant 2
then quadrant 3
then quadrant 4
*/
int outXOffset = 0;
int outYOffset = 0;
for(int i = 0; i < halfLength; i++){
for(int j = 0; j < halfLength; j++){
rVal[i+outXOffset][j+outYOffset] =
(1.0f * (halfLength - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[0][0] +
(1.0f * (0 - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[1][0] +
(1.0f * (halfLength - i) * (0 - j))/(halfLength * halfLength) * macroValues[0][1] +
(1.0f * (0 - i) * (0 - j))/(halfLength * halfLength) * macroValues[1][1]
;
}
}
outXOffset = halfLength;
for(int i = 0; i < halfLength; i++){
for(int j = 0; j < halfLength; j++){
rVal[i+outXOffset][j+outYOffset] =
(1.0f * (halfLength - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[1][0] +
(1.0f * (0 - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[2][0] +
(1.0f * (halfLength - i) * (0 - j))/(halfLength * halfLength) * macroValues[1][1] +
(1.0f * (0 - i) * (0 - j))/(halfLength * halfLength) * macroValues[2][1]
;
}
}
outXOffset = 0;
outYOffset = halfLength;
for(int i = 0; i < halfLength; i++){
for(int j = 0; j < halfLength; j++){
rVal[i+outXOffset][j+outYOffset] =
(1.0f * (halfLength - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[0][1] +
(1.0f * (0 - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[1][1] +
(1.0f * (halfLength - i) * (0 - j))/(halfLength * halfLength) * macroValues[0][2] +
(1.0f * (0 - i) * (0 - j))/(halfLength * halfLength) * macroValues[1][2]
;
}
}
outXOffset = halfLength;
for(int i = 0; i < halfLength; i++){
for(int j = 0; j < halfLength; j++){
rVal[i+outXOffset][j+outYOffset] =
(1.0f * (halfLength - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[1][1] +
(1.0f * (0 - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[2][1] +
(1.0f * (halfLength - i) * (0 - j))/(halfLength * halfLength) * macroValues[1][2] +
(1.0f * (0 - i) * (0 - j))/(halfLength * halfLength) * macroValues[2][2]
;
}
}
return rVal;
}
/*
So we're looking at chunk x,y
if this is our grid:
4 0.1 0.2 0.3 0.4
^
| 3 0.1 0.2 0.3 0.4
|
| 2 0.1 0.2 0.3 0.4
x 1 0.1 0.2 0.3 0.4
0 1 2 3
y ---- >
say we're looking at x=2,y=1
"macroValues" should contain the values for x = [1,3] and y = [0,2]
the goal is to have the "center" of the output chunk have the value the
elevation grid at x=2,y=1
*/
public float[][] getMacroValuesAtPosition(int x, int y){
float[][] rVal = new float[3][3];
rVal[1][1] = elevation[x][y];
if(x - 1 >= 0){
rVal[0][1] = elevation[x-1][y];
if(y - 1 >= 0){
rVal[0][0] = elevation[x-1][y-1];
} else {
rVal[0][0] = 0;
}
if(y + 1 < discreteArrayDimension){
rVal[0][2] = elevation[x-1][y+1];
} else {
rVal[0][2] = 0;
}
} else {
rVal[0][0] = 0;
rVal[0][1] = 0;
rVal[0][2] = 0;
}
if(x + 1 < discreteArrayDimension){
rVal[2][1] = elevation[x+1][y];
if(y - 1 >= 0){
rVal[2][0] = elevation[x+1][y-1];
} else {
rVal[2][0] = 0;
}
if(y + 1 < discreteArrayDimension){
rVal[2][2] = elevation[x+1][y+1];
} else {
rVal[2][2] = 0;
}
} else {
rVal[2][0] = 0;
rVal[2][1] = 0;
rVal[2][2] = 0;
}
if(y - 1 >= 0){
rVal[1][0] = elevation[x][y-1];
} else {
rVal[1][0] = 0;
}
if(y + 1 < discreteArrayDimension){
rVal[1][2] = elevation[x][y+1];
} else {
rVal[1][2] = 0;
}
return rVal;
}
/*
So we're looking at chunk x,y
if this is our grid:
4 0.1 0.2 0.3 0.4
^
| 3 0.1 0.2 0.3 0.4
|
| 2 0.1 0.2 0.3 0.4
x 1 0.1 0.2 0.3 0.4
0 1 2 3
y ---- >
say we're looking at x=2,y=1
"macroValues" should contain the values for x = [1,3] and y = [0,2]
the goal is to have the "center" of the output chunk have the value the
elevation grid at x=2,y=1
*/
public long[][] getRandomizerValuesAtPosition(int x, int y){
long[][] rVal = new long[3][3];
rVal[1][1] = chunkRandomizer[x][y];
if(x - 1 >= 0){
rVal[0][1] = chunkRandomizer[x-1][y];
if(y - 1 >= 0){
rVal[0][0] = chunkRandomizer[x-1][y-1];
}
if(y + 1 < discreteArrayDimension){
rVal[0][2] = chunkRandomizer[x-1][y+1];
}
}
if(x + 1 < discreteArrayDimension){
rVal[2][1] = chunkRandomizer[x+1][y];
if(y - 1 >= 0){
rVal[2][0] = chunkRandomizer[x+1][y-1];
}
if(y + 1 < discreteArrayDimension){
rVal[2][2] = chunkRandomizer[x+1][y+1];
}
}
if(y - 1 >= 0){
rVal[1][0] = chunkRandomizer[x][y-1];
}
if(y + 1 < discreteArrayDimension){
rVal[1][2] = chunkRandomizer[x][y+1];
}
return rVal;
}
public float getRandomDampener(){
return randomDampener;
}
public int getDynamicInterpolationRatio(){
return dynamicInterpolationRatio;
}
}

View File

@ -0,0 +1,99 @@
package electrosphere.game.server.world;
import electrosphere.game.server.terrain.manager.ServerTerrainManager;
import electrosphere.game.server.world.datacell.DataCell;
import java.util.List;
import org.joml.Vector3f;
/**
*
* @author amaterasu
*/
public class ServerWorldData {
public static enum WorldType {
GAME_WORLD,
ARENA_WORLD,
}
WorldType type;
/*
world max
+---------------------+
| |
| |
| |
| |
| |
+---------------------+
world min
basically we're saying what the maximum and minimum x and z something can occupy are
FOR THE TIME BEING DOES NOT ACCOUNT FOR Y
*/
Vector3f worldMinPoint;
Vector3f worldMaxPoint;
int worldSizeDiscrete;
int dynamicInterpolationRatio;
float randomDampener;
public static ServerWorldData createArenaWorld(){
ServerWorldData rVal = new ServerWorldData();
rVal.type = WorldType.ARENA_WORLD;
rVal.worldMinPoint = new Vector3f(0,0,0);
rVal.worldMaxPoint = new Vector3f(200,0,200);
rVal.dynamicInterpolationRatio = 100;
rVal.worldSizeDiscrete = 2;
rVal.randomDampener = 0.0f;
return rVal;
}
public static ServerWorldData createGameWorld(ServerTerrainManager terrainManager){
ServerWorldData rVal = new ServerWorldData();
rVal.type = WorldType.GAME_WORLD;
rVal.worldMinPoint = new Vector3f(0,0,0);
int worldDim = terrainManager.getWorldDiscreteSize() * terrainManager.getChunkWidth();
rVal.worldMaxPoint = new Vector3f(worldDim,0,worldDim);
rVal.dynamicInterpolationRatio = terrainManager.getDynamicInterpolationRatio();
rVal.worldSizeDiscrete = terrainManager.getWorldDiscreteSize();
rVal.randomDampener = terrainManager.getRandomDampener();
return rVal;
}
public Vector3f getWorldBoundMin(){
return worldMinPoint;
}
public Vector3f getWorldBoundMax(){
return worldMaxPoint;
}
public int getWorldSizeDiscrete() {
return worldSizeDiscrete;
}
public int getDynamicInterpolationRatio() {
return dynamicInterpolationRatio;
}
public float getRandomDampener() {
return randomDampener;
}
public int convertRealToChunkSpace(float real){
return (int)Math.floor(real / dynamicInterpolationRatio);
}
}

View File

@ -1,4 +1,4 @@
package electrosphere.game.world.datacell;
package electrosphere.game.server.world.datacell;
/**
*

View File

@ -1,40 +0,0 @@
package electrosphere.game.simcell.entity;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import java.util.concurrent.CopyOnWriteArrayList;
import org.joml.Vector3f;
/**
*
* @author satellite
*/
public class EntityCell {
int realWorldXStart;
int realWorldYStart;
int width;
CopyOnWriteArrayList<Entity> residentEntities = new CopyOnWriteArrayList();
public boolean containsPoint(Vector3f position){
float x = position.x;
float z = position.z;
return x >=realWorldXStart &&
x < realWorldXStart + width &&
z >=realWorldYStart &&
z < realWorldYStart + width;
}
public CopyOnWriteArrayList<Entity> getResidentEntities(){
return residentEntities;
}
public void simulate(){
for(Entity entity : residentEntities){
if(!containsPoint(EntityUtils.getEntityPosition(entity))){
residentEntities.remove(entity);
}
}
}
}

View File

@ -4,13 +4,16 @@ import electrosphere.controls.ControlHandler;
import electrosphere.entity.CameraEntityUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.collision.CollisionEngine;
import electrosphere.game.collision.CollisionEngine;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.types.item.ItemUtils;
import electrosphere.game.cell.DrawCellManager;
import electrosphere.game.client.drawcell.DrawCellManager;
import electrosphere.game.client.terrain.manager.ClientTerrainManager;
import electrosphere.game.client.world.ClientWorldData;
import electrosphere.game.collision.CommonWorldData;
import electrosphere.game.state.SimulationState.SimulationStateMachine;
import electrosphere.game.terrain.TerrainManager;
import electrosphere.game.world.World;
import electrosphere.game.server.terrain.manager.ServerTerrainManager;
import electrosphere.game.server.world.ServerWorldData;
import electrosphere.main.Globals;
import static electrosphere.main.Globals.loadingBox;
import electrosphere.menu.MenuUtils;
@ -85,10 +88,11 @@ public class LoadingThread extends Thread {
loadingBox.setDraw(true);
//initialize the terrain manager (server only)
initTerrainManager();
initServerGameTerrainManager();
//init the data of the world
initGameWorld();
initServerGameWorldData();
//initialize the server thread (server only)
if(FLAG_INIT_SERVER){
@ -100,6 +104,9 @@ public class LoadingThread extends Thread {
initClientThread();
}
//init client terrain manager
initClientTerrainManager();
//initialize the cell manager (client)
initDynamicCellManager();
@ -109,6 +116,14 @@ public class LoadingThread extends Thread {
//initialize the basic graphical entities of the world (skybox, camera)
initWorldBaseGraphicalEntities();
while(Globals.clientConnection.getClientProtocol().isLoading()){
try {
TimeUnit.MILLISECONDS.sleep(5);
} catch (InterruptedException ex) {
}
}
loadingBox.setDraw(false);
Globals.RENDER_FLAG_RENDER_SHADOW_MAP = true;
@ -134,8 +149,12 @@ public class LoadingThread extends Thread {
case LOAD_ARENA:
loadingBox.setDraw(true);
//init the data of the world
initArenaWorld();
initServerArenaWorldData();
//init server arena terrain manager separately
initServerArenaTerrainManager();
//initialize the server thread (server only)
if(FLAG_INIT_SERVER){
@ -147,8 +166,11 @@ public class LoadingThread extends Thread {
initClientThread();
}
//init client terrain manager
initClientTerrainManager();
//initialize the cell manager (client)
initArenaCellManager();
initDynamicCellManager();
//collision engine
initCollisionEngine();
@ -158,6 +180,13 @@ public class LoadingThread extends Thread {
creatingRandomEntities();
while(Globals.clientConnection.getClientProtocol().isLoading()){
try {
TimeUnit.MILLISECONDS.sleep(5);
} catch (InterruptedException ex) {
}
}
loadingBox.setDraw(false);
Globals.RENDER_FLAG_RENDER_SHADOW_MAP = true;
@ -194,19 +223,19 @@ public class LoadingThread extends Thread {
static void initTerrainManager(){
static void initServerGameTerrainManager(){
/*
Actually initialize the terrain manager
*/
float[][] elevation;
Globals.terrainManager = new TerrainManager(2000,200,100,0.25f);
Globals.serverTerrainManager = new ServerTerrainManager(2000,200,100,0.25f);
if(Globals.mainConfig.runServer){
if(Globals.mainConfig.loadTerrain){
Globals.terrainManager.load();
Globals.serverTerrainManager.load();
} else {
Globals.terrainManager.generate();
Globals.terrainManager.save();
Globals.serverTerrainManager.generate();
Globals.serverTerrainManager.save();
}
}
@ -215,12 +244,12 @@ public class LoadingThread extends Thread {
*/
int playerStartX = 0;
int playerStartY = 0;
int discreteSize = Globals.terrainManager.getWorldDiscreteSize();
int chunkSize = Globals.terrainManager.getChunkWidth();
int discreteSize = Globals.serverTerrainManager.getWorldDiscreteSize();
int chunkSize = Globals.serverTerrainManager.getChunkWidth();
boolean found = false;
for(int x = 0; x < discreteSize; x++){
for(int y = 0; y < discreteSize; y++){
if(Globals.terrainManager.getDiscreteValue(x, y)>0){
if(Globals.serverTerrainManager.getDiscreteValue(x, y)>0){
playerStartX = x;
playerStartY = y;
found = true;
@ -240,16 +269,36 @@ public class LoadingThread extends Thread {
}
static void initArenaWorld(){
Globals.world = World.createArenaWorld();
static void initServerArenaTerrainManager(){
Globals.serverTerrainManager = ServerTerrainManager.constructArenaTerrainManager();
Globals.spawnPoint = new Vector3f(1,0,1);
}
static void initClientTerrainManager(){
while(!Globals.clientConnection.getClientProtocol().hasReceivedWorld()){
try {
TimeUnit.MILLISECONDS.sleep(5);
} catch (InterruptedException ex) {
}
}
Globals.clientTerrainManager = new ClientTerrainManager(Globals.clientWorldData);
}
static void initServerArenaWorldData(){
Globals.serverWorldData = ServerWorldData.createArenaWorld();
Globals.spawnPoint = new Vector3f(0,0,0);
}
static void initGameWorld(){
Globals.world = World.createGameWorld(Globals.terrainManager);
static void initServerGameWorldData(){
Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager);
}
static void initCollisionEngine(){
if(Globals.mainConfig.runServer){
Globals.commonWorldData = new CommonWorldData(Globals.serverWorldData, Globals.serverTerrainManager);
} else {
Globals.commonWorldData = new CommonWorldData(Globals.clientWorldData, Globals.clientTerrainManager);
}
Globals.collisionEngine = new CollisionEngine();
}
@ -282,7 +331,14 @@ public class LoadingThread extends Thread {
static void initDynamicCellManager(){
Globals.drawCellManager = new DrawCellManager(Globals.terrainManager, Globals.spawnPoint.x, Globals.spawnPoint.z);
Globals.drawCellManager = new DrawCellManager(
Globals.clientWorldData,
Globals.clientTerrainManager,
Globals.spawnPoint.x,
Globals.spawnPoint.z
// Globals.terrainManager.getDynamicInterpolationRatio(),
// Globals.terrainManager.getRandomDampener()
);
while(Globals.drawCellManager.containsInvalidCell()){
// Globals.drawCellManager.updateInvalidCell();
@ -303,15 +359,6 @@ public class LoadingThread extends Thread {
}
}
static void initArenaCellManager(){
Globals.drawCellManager = DrawCellManager.createArenaDrawCellManager();
while(Globals.drawCellManager.containsInvalidCell()){
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException ex) {
}
}
}
static void initWorldBaseGraphicalEntities(){
@ -382,13 +429,13 @@ public class LoadingThread extends Thread {
// }
for(int i = 0; i < 10; i++){
Random rand = new Random();
String treePath = "Models/tree1.fbx";
Entity tree = EntityUtils.spawnDrawableEntity(treePath);
EntityUtils.getEntityPosition(tree).set(rand.nextFloat() * 150 + 10, 0, rand.nextFloat() * 150 + 10);
// EntityUtils.getEntityRotation(tree).rotateAxis((float)-Math.PI/2.0f, new Vector3f(1,0,0));
}
// for(int i = 0; i < 10; i++){
// Random rand = new Random();
// String treePath = "Models/tree1.fbx";
// Entity tree = EntityUtils.spawnDrawableEntity(treePath);
// EntityUtils.getEntityPosition(tree).set(rand.nextFloat() * 150 + 10, 0, rand.nextFloat() * 150 + 10);
//// EntityUtils.getEntityRotation(tree).rotateAxis((float)-Math.PI/2.0f, new Vector3f(1,0,0));
// }
Entity sword = ItemUtils.spawnBasicItem(2);
Entity testHomie = CreatureUtils.spawnBasicCreature(0, 0.1f, 0.5f);

View File

@ -1,170 +1,9 @@
package electrosphere.game.terrain.generation.models;
package electrosphere.game.terrain.processing;
import java.util.Random;
public class TerrainModel {
public class TerrainInterpolator {
int dynamicInterpolationRatio;
int discreteArrayDimension;
float[][] elevation;
long[][] chunkRandomizer;
float randomDampener = 0.4f;
TerrainModel() {
}
public TerrainModel(int dimension, float[][] elevation, long[][] chunkRandomizer, int dynamicInterpolationRatio){
this.dynamicInterpolationRatio = dynamicInterpolationRatio;
this.discreteArrayDimension = dimension;
this.elevation = elevation;
this.chunkRandomizer = chunkRandomizer;
}
public static TerrainModel constructTerrainModel(int dimension, int dynamicInterpolationRatio){
TerrainModel rVal = new TerrainModel();
rVal.discreteArrayDimension = dimension;
rVal.dynamicInterpolationRatio = dynamicInterpolationRatio;
return rVal;
}
public float[][] getElevation(){
return elevation;
}
public void setRandomDampener(float f){
randomDampener = f;
}
/**
* Dynamically interpolates a chunk of a specific size from the pre-existing elevation map
* @param x The x position on the elevation map to get a chunk from
* @param y The y position on the elevation map to get a chunk from
* @return Dynamically interpolated float array of elevations of chunk
*/
public float[][] getElevationForChunk(int x, int y){
Random rand = new Random(chunkRandomizer[x][y]);
//this is what we intend to return from the function
float[][] rVal = new float[dynamicInterpolationRatio][dynamicInterpolationRatio];
/*
So we're looking at chunk x,y
if this is our grid:
4 0.1 0.2 0.3 0.4
^
| 3 0.1 0.2 0.3 0.4
|
| 2 0.1 0.2 0.3 0.4
x 1 0.1 0.2 0.3 0.4
0 1 2 3
y ---- >
say we're looking at x=2,y=1
"macroValues" should contain the values for bounds x = [1,3] and y = [0,2]
the goal is to have the "center" of the output chunk have the value the
elevation grid at x=2,y=1
*/
//set macroValues
float[][] macroValues = getMacroValuesAtPosition(x,y);
int halfLength = dynamicInterpolationRatio/2;
/*
Four quadrants we're generating
_____________________
|1 |2 |
| | |
| | |
| | |
|__________|__________|
|3 |4 |
| | |
| | |
|__________|__________|
First set of loops is quadrant 1
then quadrant 2
then quadrant 3
then quadrant 4
*/
int outXOffset = 0;
int outYOffset = 0;
for(int i = 0; i < halfLength; i++){
for(int j = 0; j < halfLength; j++){
rVal[i+outXOffset][j+outYOffset] =
(1.0f * (halfLength - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[0][0] +
(1.0f * (0 - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[1][0] +
(1.0f * (halfLength - i) * (0 - j))/(halfLength * halfLength) * macroValues[0][1] +
(1.0f * (0 - i) * (0 - j))/(halfLength * halfLength) * macroValues[1][1]
;
}
}
outXOffset = halfLength;
for(int i = 0; i < halfLength; i++){
for(int j = 0; j < halfLength; j++){
rVal[i+outXOffset][j+outYOffset] =
(1.0f * (halfLength - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[1][0] +
(1.0f * (0 - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[2][0] +
(1.0f * (halfLength - i) * (0 - j))/(halfLength * halfLength) * macroValues[1][1] +
(1.0f * (0 - i) * (0 - j))/(halfLength * halfLength) * macroValues[2][1]
;
}
}
outXOffset = 0;
outYOffset = halfLength;
for(int i = 0; i < halfLength; i++){
for(int j = 0; j < halfLength; j++){
rVal[i+outXOffset][j+outYOffset] =
(1.0f * (halfLength - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[0][1] +
(1.0f * (0 - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[1][1] +
(1.0f * (halfLength - i) * (0 - j))/(halfLength * halfLength) * macroValues[0][2] +
(1.0f * (0 - i) * (0 - j))/(halfLength * halfLength) * macroValues[1][2]
;
}
}
outXOffset = halfLength;
for(int i = 0; i < halfLength; i++){
for(int j = 0; j < halfLength; j++){
rVal[i+outXOffset][j+outYOffset] =
(1.0f * (halfLength - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[1][1] +
(1.0f * (0 - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[2][1] +
(1.0f * (halfLength - i) * (0 - j))/(halfLength * halfLength) * macroValues[1][2] +
(1.0f * (0 - i) * (0 - j))/(halfLength * halfLength) * macroValues[2][2]
;
}
}
return rVal;
}
/*
@ -181,7 +20,7 @@ public class TerrainModel {
* @param y The y position on the elevation map to get a chunk from
* @return Dynamically interpolated float array of elevations of chunk
*/
public float[][] getAugmentedElevationForChunk(float[][] macroValues, long[][] randomizerValues){
public static float[][] getAugmentedElevationForChunk(float[][] macroValues, long[][] randomizerValues, int dynamicInterpolationRatio, float randomDampener){
//this is what we intend to return from the function
float[][] rVal = new float[dynamicInterpolationRatio+1][dynamicInterpolationRatio+1];
@ -573,8 +412,6 @@ public class TerrainModel {
return rVal;
}
/*
So we're looking at chunk x,y
@ -601,94 +438,4 @@ public class TerrainModel {
*/
public float[][] getMacroValuesAtPosition(int x, int y){
float[][] rVal = new float[3][3];
rVal[1][1] = elevation[x][y];
if(x - 1 >= 0){
rVal[0][1] = elevation[x-1][y];
if(y - 1 >= 0){
rVal[0][0] = elevation[x-1][y-1];
}
if(y + 1 < discreteArrayDimension){
rVal[0][2] = elevation[x-1][y+1];
}
}
if(x + 1 < discreteArrayDimension){
rVal[2][1] = elevation[x+1][y];
if(y - 1 >= 0){
rVal[2][0] = elevation[x+1][y-1];
}
if(y + 1 < discreteArrayDimension){
rVal[2][2] = elevation[x+1][y+1];
}
}
if(y - 1 >= 0){
rVal[1][0] = elevation[x][y-1];
}
if(y + 1 < discreteArrayDimension){
rVal[1][2] = elevation[x][y+1];
}
return rVal;
}
/*
So we're looking at chunk x,y
if this is our grid:
4 0.1 0.2 0.3 0.4
^
| 3 0.1 0.2 0.3 0.4
|
| 2 0.1 0.2 0.3 0.4
x 1 0.1 0.2 0.3 0.4
0 1 2 3
y ---- >
say we're looking at x=2,y=1
"macroValues" should contain the values for x = [1,3] and y = [0,2]
the goal is to have the "center" of the output chunk have the value the
elevation grid at x=2,y=1
*/
public long[][] getRandomizerValuesAtPosition(int x, int y){
long[][] rVal = new long[3][3];
rVal[1][1] = chunkRandomizer[x][y];
if(x - 1 >= 0){
rVal[0][1] = chunkRandomizer[x-1][y];
if(y - 1 >= 0){
rVal[0][0] = chunkRandomizer[x-1][y-1];
}
if(y + 1 < discreteArrayDimension){
rVal[0][2] = chunkRandomizer[x-1][y+1];
}
}
if(x + 1 < discreteArrayDimension){
rVal[2][1] = chunkRandomizer[x+1][y];
if(y - 1 >= 0){
rVal[2][0] = chunkRandomizer[x+1][y-1];
}
if(y + 1 < discreteArrayDimension){
rVal[2][2] = chunkRandomizer[x+1][y+1];
}
}
if(y - 1 >= 0){
rVal[1][0] = chunkRandomizer[x][y-1];
}
if(y + 1 < discreteArrayDimension){
rVal[1][2] = chunkRandomizer[x][y+1];
}
return rVal;
}
}

View File

@ -1,89 +0,0 @@
package electrosphere.game.world;
import electrosphere.game.terrain.TerrainManager;
import electrosphere.game.world.datacell.DataCell;
import java.util.List;
import org.joml.Vector3f;
/**
*
* @author amaterasu
*/
public class World {
public static enum WorldType {
GAME_WORLD,
ARENA_WORLD,
}
WorldType type;
List<DataCell> cellsLoadedIntoMemory;
TerrainManager terrainManager;
/*
world max
+---------------------+
| |
| |
| |
| |
| |
+---------------------+
world min
basically we're saying what the maximum and minimum x and z something can occupy are
FOR THE TIME BEING DOES NOT ACCOUNT FOR Y
*/
Vector3f worldMinPoint;
Vector3f worldMaxPoint;
public static World createArenaWorld(){
World rVal = new World();
rVal.type = WorldType.ARENA_WORLD;
rVal.worldMinPoint = new Vector3f(0,0,0);
rVal.worldMaxPoint = new Vector3f(200,0,200);
return rVal;
}
public static World createGameWorld(TerrainManager terrainManager){
World rVal = new World();
rVal.type = WorldType.GAME_WORLD;
rVal.terrainManager = terrainManager;
rVal.worldMinPoint = new Vector3f(0,0,0);
int worldDim = rVal.terrainManager.getWorldDiscreteSize() * rVal.terrainManager.getChunkWidth();
rVal.worldMaxPoint = new Vector3f(worldDim,0,worldDim);
return rVal;
}
public float getElevationAtPoint(Vector3f point){
float rVal = 0.0f;
switch(type){
case GAME_WORLD:
rVal = terrainManager.getHeightAtPosition(point.x, point.z);
break;
case ARENA_WORLD:
break;
}
return rVal;
}
public Vector3f getWorldBoundMin(){
return worldMinPoint;
}
public Vector3f getWorldBoundMax(){
return worldMaxPoint;
}
public TerrainManager getTerrainManager(){
return terrainManager;
}
}

View File

@ -13,15 +13,18 @@ import electrosphere.cfg.MainConfig;
import electrosphere.controls.ControlHandler;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityManager;
import electrosphere.entity.collision.CollisionEngine;
import electrosphere.game.collision.CollisionEngine;
import electrosphere.entity.types.creature.creaturemap.CreatureType;
import electrosphere.entity.types.creature.creaturemap.CreatureTypeList;
import electrosphere.entity.types.hitbox.HitboxManager;
import electrosphere.game.cell.DrawCellManager;
import electrosphere.game.client.drawcell.DrawCellManager;
import electrosphere.game.client.terrain.manager.ClientTerrainManager;
import electrosphere.game.client.world.ClientWorldData;
import electrosphere.game.collision.CommonWorldData;
import electrosphere.game.state.AliveManager;
import electrosphere.game.state.LoadingThread;
import electrosphere.game.terrain.TerrainManager;
import electrosphere.game.world.World;
import electrosphere.game.server.terrain.manager.ServerTerrainManager;
import electrosphere.game.server.world.ServerWorldData;
import electrosphere.menu.Menu;
import electrosphere.net.client.ClientNetworking;
import electrosphere.net.server.Server;
@ -94,7 +97,7 @@ public class Globals {
//
//current world
//
public static World world;
public static ServerWorldData serverWorldData;
//
@ -163,7 +166,7 @@ public class Globals {
public static EntityManager entityManager;
//terrain manager
public static TerrainManager terrainManager;
public static ServerTerrainManager serverTerrainManager;
public static Vector3f spawnPoint = new Vector3f(1000,0,1000);
//manages all models loaded into memory
@ -173,6 +176,12 @@ public class Globals {
//manages hitboxes
public static HitboxManager hitboxManager;
//client world data
public static ClientWorldData clientWorldData;
//client terrain manager
public static ClientTerrainManager clientTerrainManager;
//chunk stuff
//constant for how far in game units you have to move to load chunks
public static DrawCellManager drawCellManager;
@ -195,6 +204,9 @@ public class Globals {
//life status entity manager
public static AliveManager aliveManager;
//collision world data
public static CommonWorldData commonWorldData;
//the player camera entity
public static Entity playerCamera;

View File

@ -13,7 +13,6 @@ import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.MovementTree;
import electrosphere.entity.types.hitbox.HitboxUtils;
import electrosphere.entity.types.item.ItemUtils;
import electrosphere.game.cell.DrawCellManager;
import electrosphere.game.state.AttachUtils;
import electrosphere.game.state.LoadingThread;
import electrosphere.game.state.SimulationState;
@ -210,7 +209,6 @@ public class Main {
}
///
/// C L I E N T C E L L M A N A G E R
///

View File

@ -22,7 +22,7 @@ public class NetUtils {
public static EntityMessage createSetCreatureControllerIdEntityMessage(Entity e){
System.out.println("Controller id: " + CreatureUtils.getControllerPlayerId(e));
EntityMessage rVal = EntityMessage.constructsetPropertyMessage(e.getId(), 0, CreatureUtils.getControllerPlayerId(e));
EntityMessage rVal = EntityMessage.constructsetPropertyMessage(System.currentTimeMillis(), e.getId(), 0, CreatureUtils.getControllerPlayerId(e));
return rVal;
}

View File

@ -41,6 +41,8 @@ public class ClientNetworking implements Runnable{
boolean initialized;
NetworkParser parser;
ClientProtocol clientProtocol = new ClientProtocol();
public ClientNetworking(String address, int port){
try {
this.socket = new Socket(address,port);
@ -78,6 +80,7 @@ public class ClientNetworking implements Runnable{
} catch (IOException ex) {
Logger.getLogger(ClientNetworking.class.getName()).log(Level.SEVERE, null, ex);
}
initialized = true;
while(Main.isRunning()){
//attempt poll incoming messages
@ -94,69 +97,18 @@ public class ClientNetworking implements Runnable{
NetworkMessage message = parser.popIncomingMessage();
System.out.println("New message " + message.getType());
//do something
handleMessage(message);
clientProtocol.handleMessage(message);
}
}
}
void handleMessage(NetworkMessage message){
switch(message.getType()){
case ENTITY_MESSAGE:
handleEntityMessage((EntityMessage)message);
break;
case PLAYER_MESSAGE:
handlePlayerMessage((PlayerMessage)message);
break;
}
}
void handleEntityMessage(EntityMessage message){
System.out.println(message.getMessageSubtype());
switch(message.getMessageSubtype()){
case CREATE:
System.out.println("Spawn ID " + message.getentityID());
Entity newlySpawnedEntity = CreatureUtils.spawnBasicCreature(message.getcreatureType(), 0.005f, 0.025f);
EntityUtils.getEntityScale(newlySpawnedEntity).set(0.005f);
EntityUtils.getEntityPosition(newlySpawnedEntity).set(10 - 0.5f,Globals.terrainManager.getHeightAtPosition(10, 10),10 - 0.5f);
EntityUtils.setEntityID(newlySpawnedEntity, message.getentityID());
break;
case DESTROY:
break;
case MOVE:
//literally just adding this to scope so I can use `` Entity target; `` again
if(message.getentityID() != -1){
Entity target = Globals.entityManager.getEntityFromId(message.getentityID());
EntityUtils.getEntityPosition(target).set(message.getpositionX(),message.getpositionY(),message.getpositionZ());
}
// CreatureUtils.attachEntityMessageToMovementTree(Globals.entityManager.getEntityFromId(message.getId()),message);
break;
case SETBEHAVIORTREE:
break;
case SETPROPERTY:
if(message.getpropertyType()== 0){
Entity target = Globals.entityManager.getEntityFromId(message.getentityID());
if(target != null){
CreatureUtils.setControllerPlayerId(target, message.getpropertyValue());
if(message.getpropertyValue() == Main.playerId){
Globals.playerCharacter = target;
}
}
}
break;
}
}
void handlePlayerMessage(PlayerMessage message){
switch(message.getMessageSubtype()){
case SET_ID:
Main.playerId = message.getplayerID();
System.out.println("Player ID is " + Main.playerId);
break;
}
}
public void queueOutgoingMessage(NetworkMessage message){
parser.addOutgoingMessage(message);
}
public ClientProtocol getClientProtocol(){
return clientProtocol;
}
}

View File

@ -0,0 +1,119 @@
package electrosphere.net.client;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.game.client.world.ClientWorldData;
import electrosphere.main.Globals;
import electrosphere.main.Main;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.parser.net.message.PlayerMessage;
import electrosphere.net.parser.net.message.StatusMessage;
import electrosphere.net.parser.net.message.WorldMessage;
import org.joml.Vector3f;
public class ClientProtocol {
boolean isLoading = true;
boolean hasReceivedWorld = false;
public void handleMessage(NetworkMessage message){
switch(message.getType()){
case STATUS_MESSAGE:
handleStatusMessage((StatusMessage)message);
break;
case ENTITY_MESSAGE:
handleEntityMessage((EntityMessage)message);
break;
case PLAYER_MESSAGE:
handlePlayerMessage((PlayerMessage)message);
break;
case WORLD_MESSAGE:
handleWorldMessage((WorldMessage)message);
break;
}
}
void handleStatusMessage(StatusMessage message){
switch(message.getMessageSubtype()){
case READY:
isLoading = false;
break;
}
}
void handleEntityMessage(EntityMessage message){
System.out.println(message.getMessageSubtype());
switch(message.getMessageSubtype()){
case CREATE:
System.out.println("Spawn ID " + message.getentityID());
Entity newlySpawnedEntity = CreatureUtils.spawnBasicCreature(message.getcreatureType(), 0.005f, 0.025f);
EntityUtils.getEntityScale(newlySpawnedEntity).set(0.005f);
EntityUtils.getEntityPosition(newlySpawnedEntity).set(10 - 0.5f,Globals.serverTerrainManager.getHeightAtPosition(10, 10),10 - 0.5f);
EntityUtils.setEntityID(newlySpawnedEntity, message.getentityID());
break;
case DESTROY:
break;
case MOVE:
//literally just adding this to scope so I can use `` Entity target; `` again
if(message.getentityID() != -1){
Entity target = Globals.entityManager.getEntityFromId(message.getentityID());
EntityUtils.getEntityPosition(target).set(message.getpositionX(),message.getpositionY(),message.getpositionZ());
}
// CreatureUtils.attachEntityMessageToMovementTree(Globals.entityManager.getEntityFromId(message.getId()),message);
break;
case SETBEHAVIORTREE:
break;
case SETPROPERTY:
if(message.getpropertyType()== 0){
Entity target = Globals.entityManager.getEntityFromId(message.getentityID());
if(target != null){
CreatureUtils.setControllerPlayerId(target, message.getpropertyValue());
if(message.getpropertyValue() == Main.playerId){
Globals.playerCharacter = target;
}
}
}
break;
}
}
void handlePlayerMessage(PlayerMessage message){
switch(message.getMessageSubtype()){
case SET_ID:
Main.playerId = message.getplayerID();
System.out.println("Player ID is " + Main.playerId);
break;
}
}
void handleWorldMessage(WorldMessage message){
switch(message.getMessageSubtype()){
case METADATA:
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(),
message.getrandomDampener(),
message.getworldSizeDiscrete()
);
hasReceivedWorld = true;
break;
case MACROVALUE:
Globals.clientTerrainManager.attachWorldMessage(message);
Globals.clientTerrainManager.handleMessages();
break;
}
}
public boolean isLoading(){
return isLoading;
}
public boolean hasReceivedWorld(){
return hasReceivedWorld;
}
}

View File

@ -1,7 +1,7 @@
package electrosphere.net.parser.net.message;
import electrosphere.net.parser.util.ByteStreamUtils;
import java.util.LinkedList;
import java.util.List;
public class EntityMessage extends NetworkMessage {
@ -24,6 +24,7 @@ public class EntityMessage extends NetworkMessage {
int propertyValue;
int treeType;
int treeStatus;
long time;
EntityMessage(EntityMessageType messageType){
this.type = MessageType.ENTITY_MESSAGE;
@ -106,12 +107,20 @@ public class EntityMessage extends NetworkMessage {
this.treeStatus = treeStatus;
}
static void stripPacketHeader(LinkedList<Byte> byteStream){
public long gettime() {
return time;
}
public void settime(long time) {
this.time = time;
}
static void stripPacketHeader(List<Byte> byteStream){
byteStream.remove(0);
byteStream.remove(0);
}
public static boolean canParseMessage(LinkedList<Byte> byteStream, byte secondByte){
public static boolean canParseMessage(List<Byte> byteStream, byte secondByte){
switch(secondByte){
case TypeBytes.ENTITY_MESSAGE_TYPE_CREATE:
if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_CREATE_SIZE){
@ -153,7 +162,7 @@ public class EntityMessage extends NetworkMessage {
return false;
}
public static EntityMessage parseCreateMessage(LinkedList<Byte> byteStream){
public static EntityMessage parseCreateMessage(List<Byte> byteStream){
EntityMessage rVal = new EntityMessage(EntityMessageType.CREATE);
stripPacketHeader(byteStream);
rVal.setcreatureType(ByteStreamUtils.popIntFromByteQueue(byteStream));
@ -175,9 +184,10 @@ public class EntityMessage extends NetworkMessage {
return rVal;
}
public static EntityMessage parseSetPositionMessage(LinkedList<Byte> byteStream){
public static EntityMessage parseSetPositionMessage(List<Byte> byteStream){
EntityMessage rVal = new EntityMessage(EntityMessageType.SETPOSITION);
stripPacketHeader(byteStream);
rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream));
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream));
rVal.setpositionX(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setpositionY(ByteStreamUtils.popFloatFromByteQueue(byteStream));
@ -185,8 +195,9 @@ public class EntityMessage extends NetworkMessage {
return rVal;
}
public static EntityMessage constructSetPositionMessage(int entityID,float positionX,float positionY,float positionZ){
public static EntityMessage constructSetPositionMessage(long time,int entityID,float positionX,float positionY,float positionZ){
EntityMessage rVal = new EntityMessage(EntityMessageType.SETPOSITION);
rVal.settime(time);
rVal.setentityID(entityID);
rVal.setpositionX(positionX);
rVal.setpositionY(positionY);
@ -195,9 +206,10 @@ public class EntityMessage extends NetworkMessage {
return rVal;
}
public static EntityMessage parseMoveMessage(LinkedList<Byte> byteStream){
public static EntityMessage parseMoveMessage(List<Byte> byteStream){
EntityMessage rVal = new EntityMessage(EntityMessageType.MOVE);
stripPacketHeader(byteStream);
rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream));
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream));
rVal.setpositionX(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setpositionY(ByteStreamUtils.popFloatFromByteQueue(byteStream));
@ -205,8 +217,9 @@ public class EntityMessage extends NetworkMessage {
return rVal;
}
public static EntityMessage constructMoveMessage(int entityID,float positionX,float positionY,float positionZ){
public static EntityMessage constructMoveMessage(long time,int entityID,float positionX,float positionY,float positionZ){
EntityMessage rVal = new EntityMessage(EntityMessageType.MOVE);
rVal.settime(time);
rVal.setentityID(entityID);
rVal.setpositionX(positionX);
rVal.setpositionY(positionY);
@ -215,7 +228,7 @@ public class EntityMessage extends NetworkMessage {
return rVal;
}
public static EntityMessage parseDestroyMessage(LinkedList<Byte> byteStream){
public static EntityMessage parseDestroyMessage(List<Byte> byteStream){
EntityMessage rVal = new EntityMessage(EntityMessageType.DESTROY);
stripPacketHeader(byteStream);
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream));
@ -229,17 +242,19 @@ public class EntityMessage extends NetworkMessage {
return rVal;
}
public static EntityMessage parseSetBehaviorTreeMessage(LinkedList<Byte> byteStream){
public static EntityMessage parseSetBehaviorTreeMessage(List<Byte> byteStream){
EntityMessage rVal = new EntityMessage(EntityMessageType.SETBEHAVIORTREE);
stripPacketHeader(byteStream);
rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream));
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream));
rVal.settreeType(ByteStreamUtils.popIntFromByteQueue(byteStream));
rVal.settreeStatus(ByteStreamUtils.popIntFromByteQueue(byteStream));
return rVal;
}
public static EntityMessage constructSetBehaviorTreeMessage(int entityID,int treeType,int treeStatus){
public static EntityMessage constructSetBehaviorTreeMessage(long time,int entityID,int treeType,int treeStatus){
EntityMessage rVal = new EntityMessage(EntityMessageType.SETBEHAVIORTREE);
rVal.settime(time);
rVal.setentityID(entityID);
rVal.settreeType(treeType);
rVal.settreeStatus(treeStatus);
@ -247,17 +262,19 @@ public class EntityMessage extends NetworkMessage {
return rVal;
}
public static EntityMessage parsesetPropertyMessage(LinkedList<Byte> byteStream){
public static EntityMessage parsesetPropertyMessage(List<Byte> byteStream){
EntityMessage rVal = new EntityMessage(EntityMessageType.SETPROPERTY);
stripPacketHeader(byteStream);
rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream));
rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream));
rVal.setpropertyType(ByteStreamUtils.popIntFromByteQueue(byteStream));
rVal.setpropertyValue(ByteStreamUtils.popIntFromByteQueue(byteStream));
return rVal;
}
public static EntityMessage constructsetPropertyMessage(int entityID,int propertyType,int propertyValue){
public static EntityMessage constructsetPropertyMessage(long time,int entityID,int propertyType,int propertyValue){
EntityMessage rVal = new EntityMessage(EntityMessageType.SETPROPERTY);
rVal.settime(time);
rVal.setentityID(entityID);
rVal.setpropertyType(propertyType);
rVal.setpropertyValue(propertyValue);
@ -299,19 +316,23 @@ public class EntityMessage extends NetworkMessage {
rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
//entity messaage header
rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_SETPOSITION;
intValues = ByteStreamUtils.serializeLongToBytes(time);
for(int i = 0; i < 8; i++){
rawBytes[2+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(entityID);
for(int i = 0; i < 4; i++){
rawBytes[2+i] = intValues[i];
rawBytes[10+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeFloatToBytes(positionX);
for(int i = 0; i < 4; i++){
rawBytes[6+i] = intValues[i];
rawBytes[14+i] = intValues[i];
} intValues = ByteStreamUtils.serializeFloatToBytes(positionY);
for(int i = 0; i < 4; i++){
rawBytes[10+i] = intValues[i];
rawBytes[18+i] = intValues[i];
} intValues = ByteStreamUtils.serializeFloatToBytes(positionZ);
for(int i = 0; i < 4; i++){
rawBytes[14+i] = intValues[i];
rawBytes[22+i] = intValues[i];
} break;
case MOVE:
rawBytes = new byte[TypeBytes.ENTITY_MESSAGE_TYPE_MOVE_SIZE];
@ -319,19 +340,23 @@ public class EntityMessage extends NetworkMessage {
rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
//entity messaage header
rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_MOVE;
intValues = ByteStreamUtils.serializeLongToBytes(time);
for(int i = 0; i < 8; i++){
rawBytes[2+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(entityID);
for(int i = 0; i < 4; i++){
rawBytes[2+i] = intValues[i];
rawBytes[10+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeFloatToBytes(positionX);
for(int i = 0; i < 4; i++){
rawBytes[6+i] = intValues[i];
rawBytes[14+i] = intValues[i];
} intValues = ByteStreamUtils.serializeFloatToBytes(positionY);
for(int i = 0; i < 4; i++){
rawBytes[10+i] = intValues[i];
rawBytes[18+i] = intValues[i];
} intValues = ByteStreamUtils.serializeFloatToBytes(positionZ);
for(int i = 0; i < 4; i++){
rawBytes[14+i] = intValues[i];
rawBytes[22+i] = intValues[i];
} break;
case DESTROY:
rawBytes = new byte[TypeBytes.ENTITY_MESSAGE_TYPE_DESTROY_SIZE];
@ -350,17 +375,21 @@ public class EntityMessage extends NetworkMessage {
rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
//entity messaage header
rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_SETBEHAVIORTREE;
intValues = ByteStreamUtils.serializeLongToBytes(time);
for(int i = 0; i < 8; i++){
rawBytes[2+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(entityID);
for(int i = 0; i < 4; i++){
rawBytes[2+i] = intValues[i];
rawBytes[10+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(treeType);
for(int i = 0; i < 4; i++){
rawBytes[6+i] = intValues[i];
rawBytes[14+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(treeStatus);
for(int i = 0; i < 4; i++){
rawBytes[10+i] = intValues[i];
rawBytes[18+i] = intValues[i];
}
break;
case SETPROPERTY:
@ -369,17 +398,21 @@ public class EntityMessage extends NetworkMessage {
rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
//entity messaage header
rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_SETPROPERTY;
intValues = ByteStreamUtils.serializeLongToBytes(time);
for(int i = 0; i < 8; i++){
rawBytes[2+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(entityID);
for(int i = 0; i < 4; i++){
rawBytes[2+i] = intValues[i];
rawBytes[10+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(propertyType);
for(int i = 0; i < 4; i++){
rawBytes[6+i] = intValues[i];
rawBytes[14+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(propertyValue);
for(int i = 0; i < 4; i++){
rawBytes[10+i] = intValues[i];
rawBytes[18+i] = intValues[i];
}
break;
}

View File

@ -1,11 +1,12 @@
package electrosphere.net.parser.net.message;
import electrosphere.net.parser.util.ByteStreamUtils;
import java.util.LinkedList;
import java.util.List;
public abstract class NetworkMessage {
public enum MessageType {
STATUS_MESSAGE,
WORLD_MESSAGE,
PLAYER_MESSAGE,
ENTITY_MESSAGE,
@ -23,19 +24,34 @@ ENTITY_MESSAGE,
return rawBytes;
}
public static NetworkMessage parseBytestreamForMessage(LinkedList<Byte> byteStream){
public static NetworkMessage parseBytestreamForMessage(List<Byte> byteStream){
NetworkMessage rVal = null;
byte firstByte;
byte secondByte;
if(byteStream.size() > 1){
firstByte = byteStream.get(0);
switch(firstByte){
case TypeBytes.MESSAGE_TYPE_STATUS:
secondByte = byteStream.get(1);
switch(secondByte){
case TypeBytes.STATUS_MESSAGE_TYPE_READY:
if(StatusMessage.canParseMessage(byteStream,secondByte)){
rVal = StatusMessage.parseReadyMessage(byteStream);
}
break;
}
break;
case TypeBytes.MESSAGE_TYPE_WORLD:
secondByte = byteStream.get(1);
switch(secondByte){
case TypeBytes.WORLD_MESSAGE_TYPE_INFO:
case TypeBytes.WORLD_MESSAGE_TYPE_METADATA:
if(WorldMessage.canParseMessage(byteStream,secondByte)){
rVal = WorldMessage.parseInfoMessage(byteStream);
rVal = WorldMessage.parseMetadataMessage(byteStream);
}
break;
case TypeBytes.WORLD_MESSAGE_TYPE_REQUESTMACROVALUES:
if(WorldMessage.canParseMessage(byteStream,secondByte)){
rVal = WorldMessage.parseRequestMacroValuesMessage(byteStream);
}
break;
case TypeBytes.WORLD_MESSAGE_TYPE_UPDATE:
@ -48,11 +64,6 @@ ENTITY_MESSAGE,
rVal = WorldMessage.parseMacroValueMessage(byteStream);
}
break;
case TypeBytes.WORLD_MESSAGE_TYPE_RANDOMIZERVALUE:
if(WorldMessage.canParseMessage(byteStream,secondByte)){
rVal = WorldMessage.parseRandomizerValueMessage(byteStream);
}
break;
}
break;
case TypeBytes.MESSAGE_TYPE_PLAYER:

View File

@ -1,7 +1,7 @@
package electrosphere.net.parser.net.message;
import electrosphere.net.parser.util.ByteStreamUtils;
import java.util.LinkedList;
import java.util.List;
public class PlayerMessage extends NetworkMessage {
@ -29,12 +29,12 @@ public class PlayerMessage extends NetworkMessage {
this.playerID = playerID;
}
static void stripPacketHeader(LinkedList<Byte> byteStream){
static void stripPacketHeader(List<Byte> byteStream){
byteStream.remove(0);
byteStream.remove(0);
}
public static boolean canParseMessage(LinkedList<Byte> byteStream, byte secondByte){
public static boolean canParseMessage(List<Byte> byteStream, byte secondByte){
switch(secondByte){
case TypeBytes.PLAYER_MESSAGE_TYPE_SET_ID:
if(byteStream.size() >= TypeBytes.PLAYER_MESSAGE_TYPE_SET_ID_SIZE){
@ -46,7 +46,7 @@ public class PlayerMessage extends NetworkMessage {
return false;
}
public static PlayerMessage parseSet_IDMessage(LinkedList<Byte> byteStream){
public static PlayerMessage parseSet_IDMessage(List<Byte> byteStream){
PlayerMessage rVal = new PlayerMessage(PlayerMessageType.SET_ID);
stripPacketHeader(byteStream);
rVal.setplayerID(ByteStreamUtils.popIntFromByteQueue(byteStream));

View File

@ -0,0 +1,82 @@
package electrosphere.net.parser.net.message;
import electrosphere.net.parser.util.ByteStreamUtils;
import java.util.List;
public class StatusMessage extends NetworkMessage {
public enum StatusMessageType {
READY,
}
StatusMessageType messageType;
int ready;
StatusMessage(StatusMessageType messageType){
this.type = MessageType.STATUS_MESSAGE;
this.messageType = messageType;
}
public StatusMessageType getMessageSubtype(){
return this.messageType;
}
public int getready() {
return ready;
}
public void setready(int ready) {
this.ready = ready;
}
static void stripPacketHeader(List<Byte> byteStream){
byteStream.remove(0);
byteStream.remove(0);
}
public static boolean canParseMessage(List<Byte> byteStream, byte secondByte){
switch(secondByte){
case TypeBytes.STATUS_MESSAGE_TYPE_READY:
if(byteStream.size() >= TypeBytes.STATUS_MESSAGE_TYPE_READY_SIZE){
return true;
} else {
return false;
}
}
return false;
}
public static StatusMessage parseReadyMessage(List<Byte> byteStream){
StatusMessage rVal = new StatusMessage(StatusMessageType.READY);
stripPacketHeader(byteStream);
rVal.setready(ByteStreamUtils.popIntFromByteQueue(byteStream));
return rVal;
}
public static StatusMessage constructReadyMessage(int ready){
StatusMessage rVal = new StatusMessage(StatusMessageType.READY);
rVal.setready(ready);
rVal.serialize();
return rVal;
}
@Override
void serialize(){
byte[] intValues = new byte[8];
switch(this.messageType){
case READY:
rawBytes = new byte[TypeBytes.STATUS_MESSAGE_TYPE_READY_SIZE];
//message header
rawBytes[0] = TypeBytes.MESSAGE_TYPE_STATUS;
//entity messaage header
rawBytes[1] = TypeBytes.STATUS_MESSAGE_TYPE_READY;
intValues = ByteStreamUtils.serializeIntToBytes(ready);
for(int i = 0; i < 4; i++){
rawBytes[2+i] = intValues[i];
}
break;
}
serialized = true;
}
}

View File

@ -5,23 +5,32 @@ public class TypeBytes {
/*
Message categories
*/
public static final byte MESSAGE_TYPE_WORLD = 0;
public static final byte MESSAGE_TYPE_PLAYER = 1;
public static final byte MESSAGE_TYPE_ENTITY = 2;
public static final byte MESSAGE_TYPE_STATUS = 0;
public static final byte MESSAGE_TYPE_WORLD = 1;
public static final byte MESSAGE_TYPE_PLAYER = 2;
public static final byte MESSAGE_TYPE_ENTITY = 3;
/*
Status subcategories
*/
public static final byte STATUS_MESSAGE_TYPE_READY = 0;
/*
Status packet sizes
*/
public static final byte STATUS_MESSAGE_TYPE_READY_SIZE = 6;
/*
World subcategories
*/
public static final byte WORLD_MESSAGE_TYPE_INFO = 0;
public static final byte WORLD_MESSAGE_TYPE_UPDATE = 1;
public static final byte WORLD_MESSAGE_TYPE_MACROVALUE = 2;
public static final byte WORLD_MESSAGE_TYPE_RANDOMIZERVALUE = 3;
public static final byte WORLD_MESSAGE_TYPE_METADATA = 0;
public static final byte WORLD_MESSAGE_TYPE_REQUESTMACROVALUES = 1;
public static final byte WORLD_MESSAGE_TYPE_UPDATE = 2;
public static final byte WORLD_MESSAGE_TYPE_MACROVALUE = 3;
/*
World packet sizes
*/
public static final byte WORLD_MESSAGE_TYPE_INFO_SIZE = 6;
public static final byte WORLD_MESSAGE_TYPE_METADATA_SIZE = 30;
public static final byte WORLD_MESSAGE_TYPE_REQUESTMACROVALUES_SIZE = 10;
public static final byte WORLD_MESSAGE_TYPE_UPDATE_SIZE = 10;
public static final byte WORLD_MESSAGE_TYPE_MACROVALUE_SIZE = 74;
public static final byte WORLD_MESSAGE_TYPE_RANDOMIZERVALUE_SIZE = 38;
public static final byte WORLD_MESSAGE_TYPE_MACROVALUE_SIZE = 118;
/*
Player subcategories
*/
@ -43,10 +52,10 @@ Message categories
Entity packet sizes
*/
public static final byte ENTITY_MESSAGE_TYPE_CREATE_SIZE = 22;
public static final byte ENTITY_MESSAGE_TYPE_SETPOSITION_SIZE = 18;
public static final byte ENTITY_MESSAGE_TYPE_MOVE_SIZE = 18;
public static final byte ENTITY_MESSAGE_TYPE_SETPOSITION_SIZE = 26;
public static final byte ENTITY_MESSAGE_TYPE_MOVE_SIZE = 26;
public static final byte ENTITY_MESSAGE_TYPE_DESTROY_SIZE = 6;
public static final byte ENTITY_MESSAGE_TYPE_SETBEHAVIORTREE_SIZE = 14;
public static final byte ENTITY_MESSAGE_TYPE_SETPROPERTY_SIZE = 14;
public static final byte ENTITY_MESSAGE_TYPE_SETBEHAVIORTREE_SIZE = 22;
public static final byte ENTITY_MESSAGE_TYPE_SETPROPERTY_SIZE = 22;
}

View File

@ -1,39 +1,45 @@
package electrosphere.net.parser.net.message;
import electrosphere.net.parser.util.ByteStreamUtils;
import java.util.LinkedList;
import java.util.List;
public class WorldMessage extends NetworkMessage {
public enum WorldMessageType {
INFO,
METADATA,
REQUESTMACROVALUES,
UPDATE,
MACROVALUE,
RANDOMIZERVALUE,
}
WorldMessageType messageType;
int worldSize;
int worldSizeDiscrete;
int dynamicInterpolationRatio;
float randomDampener;
int worldMinX;
int worldMinY;
int worldMaxX;
int worldMaxY;
int locationX;
int locationY;
long macroValue00;
long macroValue01;
long macroValue02;
long macroValue10;
long macroValue11;
long macroValue12;
long macroValue20;
long macroValue21;
long macroValue22;
float randomizerValue00;
float randomizerValue01;
float randomizerValue02;
float randomizerValue10;
float randomizerValue11;
float randomizerValue12;
float randomizerValue20;
float randomizerValue21;
float randomizerValue22;
float macroValue00;
float macroValue01;
float macroValue02;
float macroValue10;
float macroValue11;
float macroValue12;
float macroValue20;
float macroValue21;
float macroValue22;
long randomizerValue00;
long randomizerValue01;
long randomizerValue02;
long randomizerValue10;
long randomizerValue11;
long randomizerValue12;
long randomizerValue20;
long randomizerValue21;
long randomizerValue22;
WorldMessage(WorldMessageType messageType){
this.type = MessageType.WORLD_MESSAGE;
@ -44,12 +50,60 @@ public class WorldMessage extends NetworkMessage {
return this.messageType;
}
public int getworldSize() {
return worldSize;
public int getworldSizeDiscrete() {
return worldSizeDiscrete;
}
public void setworldSize(int worldSize) {
this.worldSize = worldSize;
public void setworldSizeDiscrete(int worldSizeDiscrete) {
this.worldSizeDiscrete = worldSizeDiscrete;
}
public int getdynamicInterpolationRatio() {
return dynamicInterpolationRatio;
}
public void setdynamicInterpolationRatio(int dynamicInterpolationRatio) {
this.dynamicInterpolationRatio = dynamicInterpolationRatio;
}
public float getrandomDampener() {
return randomDampener;
}
public void setrandomDampener(float randomDampener) {
this.randomDampener = randomDampener;
}
public int getworldMinX() {
return worldMinX;
}
public void setworldMinX(int worldMinX) {
this.worldMinX = worldMinX;
}
public int getworldMinY() {
return worldMinY;
}
public void setworldMinY(int worldMinY) {
this.worldMinY = worldMinY;
}
public int getworldMaxX() {
return worldMaxX;
}
public void setworldMaxX(int worldMaxX) {
this.worldMaxX = worldMaxX;
}
public int getworldMaxY() {
return worldMaxY;
}
public void setworldMaxY(int worldMaxY) {
this.worldMaxY = worldMaxY;
}
public int getlocationX() {
@ -68,159 +122,165 @@ public class WorldMessage extends NetworkMessage {
this.locationY = locationY;
}
public long getmacroValue00() {
public float getmacroValue00() {
return macroValue00;
}
public void setmacroValue00(long macroValue00) {
public void setmacroValue00(float macroValue00) {
this.macroValue00 = macroValue00;
}
public long getmacroValue01() {
public float getmacroValue01() {
return macroValue01;
}
public void setmacroValue01(long macroValue01) {
public void setmacroValue01(float macroValue01) {
this.macroValue01 = macroValue01;
}
public long getmacroValue02() {
public float getmacroValue02() {
return macroValue02;
}
public void setmacroValue02(long macroValue02) {
public void setmacroValue02(float macroValue02) {
this.macroValue02 = macroValue02;
}
public long getmacroValue10() {
public float getmacroValue10() {
return macroValue10;
}
public void setmacroValue10(long macroValue10) {
public void setmacroValue10(float macroValue10) {
this.macroValue10 = macroValue10;
}
public long getmacroValue11() {
public float getmacroValue11() {
return macroValue11;
}
public void setmacroValue11(long macroValue11) {
public void setmacroValue11(float macroValue11) {
this.macroValue11 = macroValue11;
}
public long getmacroValue12() {
public float getmacroValue12() {
return macroValue12;
}
public void setmacroValue12(long macroValue12) {
public void setmacroValue12(float macroValue12) {
this.macroValue12 = macroValue12;
}
public long getmacroValue20() {
public float getmacroValue20() {
return macroValue20;
}
public void setmacroValue20(long macroValue20) {
public void setmacroValue20(float macroValue20) {
this.macroValue20 = macroValue20;
}
public long getmacroValue21() {
public float getmacroValue21() {
return macroValue21;
}
public void setmacroValue21(long macroValue21) {
public void setmacroValue21(float macroValue21) {
this.macroValue21 = macroValue21;
}
public long getmacroValue22() {
public float getmacroValue22() {
return macroValue22;
}
public void setmacroValue22(long macroValue22) {
public void setmacroValue22(float macroValue22) {
this.macroValue22 = macroValue22;
}
public float getrandomizerValue00() {
public long getrandomizerValue00() {
return randomizerValue00;
}
public void setrandomizerValue00(float randomizerValue00) {
public void setrandomizerValue00(long randomizerValue00) {
this.randomizerValue00 = randomizerValue00;
}
public float getrandomizerValue01() {
public long getrandomizerValue01() {
return randomizerValue01;
}
public void setrandomizerValue01(float randomizerValue01) {
public void setrandomizerValue01(long randomizerValue01) {
this.randomizerValue01 = randomizerValue01;
}
public float getrandomizerValue02() {
public long getrandomizerValue02() {
return randomizerValue02;
}
public void setrandomizerValue02(float randomizerValue02) {
public void setrandomizerValue02(long randomizerValue02) {
this.randomizerValue02 = randomizerValue02;
}
public float getrandomizerValue10() {
public long getrandomizerValue10() {
return randomizerValue10;
}
public void setrandomizerValue10(float randomizerValue10) {
public void setrandomizerValue10(long randomizerValue10) {
this.randomizerValue10 = randomizerValue10;
}
public float getrandomizerValue11() {
public long getrandomizerValue11() {
return randomizerValue11;
}
public void setrandomizerValue11(float randomizerValue11) {
public void setrandomizerValue11(long randomizerValue11) {
this.randomizerValue11 = randomizerValue11;
}
public float getrandomizerValue12() {
public long getrandomizerValue12() {
return randomizerValue12;
}
public void setrandomizerValue12(float randomizerValue12) {
public void setrandomizerValue12(long randomizerValue12) {
this.randomizerValue12 = randomizerValue12;
}
public float getrandomizerValue20() {
public long getrandomizerValue20() {
return randomizerValue20;
}
public void setrandomizerValue20(float randomizerValue20) {
public void setrandomizerValue20(long randomizerValue20) {
this.randomizerValue20 = randomizerValue20;
}
public float getrandomizerValue21() {
public long getrandomizerValue21() {
return randomizerValue21;
}
public void setrandomizerValue21(float randomizerValue21) {
public void setrandomizerValue21(long randomizerValue21) {
this.randomizerValue21 = randomizerValue21;
}
public float getrandomizerValue22() {
public long getrandomizerValue22() {
return randomizerValue22;
}
public void setrandomizerValue22(float randomizerValue22) {
public void setrandomizerValue22(long randomizerValue22) {
this.randomizerValue22 = randomizerValue22;
}
static void stripPacketHeader(LinkedList<Byte> byteStream){
static void stripPacketHeader(List<Byte> byteStream){
byteStream.remove(0);
byteStream.remove(0);
}
public static boolean canParseMessage(LinkedList<Byte> byteStream, byte secondByte){
public static boolean canParseMessage(List<Byte> byteStream, byte secondByte){
switch(secondByte){
case TypeBytes.WORLD_MESSAGE_TYPE_INFO:
if(byteStream.size() >= TypeBytes.WORLD_MESSAGE_TYPE_INFO_SIZE){
case TypeBytes.WORLD_MESSAGE_TYPE_METADATA:
if(byteStream.size() >= TypeBytes.WORLD_MESSAGE_TYPE_METADATA_SIZE){
return true;
} else {
return false;
}
case TypeBytes.WORLD_MESSAGE_TYPE_REQUESTMACROVALUES:
if(byteStream.size() >= TypeBytes.WORLD_MESSAGE_TYPE_REQUESTMACROVALUES_SIZE){
return true;
} else {
return false;
@ -237,31 +297,53 @@ public class WorldMessage extends NetworkMessage {
} else {
return false;
}
case TypeBytes.WORLD_MESSAGE_TYPE_RANDOMIZERVALUE:
if(byteStream.size() >= TypeBytes.WORLD_MESSAGE_TYPE_RANDOMIZERVALUE_SIZE){
return true;
} else {
return false;
}
}
return false;
}
public static WorldMessage parseInfoMessage(LinkedList<Byte> byteStream){
WorldMessage rVal = new WorldMessage(WorldMessageType.INFO);
public static WorldMessage parseMetadataMessage(List<Byte> byteStream){
WorldMessage rVal = new WorldMessage(WorldMessageType.METADATA);
stripPacketHeader(byteStream);
rVal.setworldSize(ByteStreamUtils.popIntFromByteQueue(byteStream));
rVal.setworldSizeDiscrete(ByteStreamUtils.popIntFromByteQueue(byteStream));
rVal.setdynamicInterpolationRatio(ByteStreamUtils.popIntFromByteQueue(byteStream));
rVal.setrandomDampener(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setworldMinX(ByteStreamUtils.popIntFromByteQueue(byteStream));
rVal.setworldMinY(ByteStreamUtils.popIntFromByteQueue(byteStream));
rVal.setworldMaxX(ByteStreamUtils.popIntFromByteQueue(byteStream));
rVal.setworldMaxY(ByteStreamUtils.popIntFromByteQueue(byteStream));
return rVal;
}
public static WorldMessage constructInfoMessage(int worldSize){
WorldMessage rVal = new WorldMessage(WorldMessageType.INFO);
rVal.setworldSize(worldSize);
public static WorldMessage constructMetadataMessage(int worldSizeDiscrete,int dynamicInterpolationRatio,float randomDampener,int worldMinX,int worldMinY,int worldMaxX,int worldMaxY){
WorldMessage rVal = new WorldMessage(WorldMessageType.METADATA);
rVal.setworldSizeDiscrete(worldSizeDiscrete);
rVal.setdynamicInterpolationRatio(dynamicInterpolationRatio);
rVal.setrandomDampener(randomDampener);
rVal.setworldMinX(worldMinX);
rVal.setworldMinY(worldMinY);
rVal.setworldMaxX(worldMaxX);
rVal.setworldMaxY(worldMaxY);
rVal.serialize();
return rVal;
}
public static WorldMessage parseUpdateMessage(LinkedList<Byte> byteStream){
public static WorldMessage parseRequestMacroValuesMessage(List<Byte> byteStream){
WorldMessage rVal = new WorldMessage(WorldMessageType.REQUESTMACROVALUES);
stripPacketHeader(byteStream);
rVal.setlocationX(ByteStreamUtils.popIntFromByteQueue(byteStream));
rVal.setlocationY(ByteStreamUtils.popIntFromByteQueue(byteStream));
return rVal;
}
public static WorldMessage constructRequestMacroValuesMessage(int locationX,int locationY){
WorldMessage rVal = new WorldMessage(WorldMessageType.REQUESTMACROVALUES);
rVal.setlocationX(locationX);
rVal.setlocationY(locationY);
rVal.serialize();
return rVal;
}
public static WorldMessage parseUpdateMessage(List<Byte> byteStream){
WorldMessage rVal = new WorldMessage(WorldMessageType.UPDATE);
stripPacketHeader(byteStream);
rVal.setlocationX(ByteStreamUtils.popIntFromByteQueue(byteStream));
@ -277,23 +359,36 @@ public class WorldMessage extends NetworkMessage {
return rVal;
}
public static WorldMessage parseMacroValueMessage(LinkedList<Byte> byteStream){
public static WorldMessage parseMacroValueMessage(List<Byte> byteStream){
WorldMessage rVal = new WorldMessage(WorldMessageType.MACROVALUE);
stripPacketHeader(byteStream);
rVal.setmacroValue00(ByteStreamUtils.popLongFromByteQueue(byteStream));
rVal.setmacroValue01(ByteStreamUtils.popLongFromByteQueue(byteStream));
rVal.setmacroValue02(ByteStreamUtils.popLongFromByteQueue(byteStream));
rVal.setmacroValue10(ByteStreamUtils.popLongFromByteQueue(byteStream));
rVal.setmacroValue11(ByteStreamUtils.popLongFromByteQueue(byteStream));
rVal.setmacroValue12(ByteStreamUtils.popLongFromByteQueue(byteStream));
rVal.setmacroValue20(ByteStreamUtils.popLongFromByteQueue(byteStream));
rVal.setmacroValue21(ByteStreamUtils.popLongFromByteQueue(byteStream));
rVal.setmacroValue22(ByteStreamUtils.popLongFromByteQueue(byteStream));
rVal.setlocationX(ByteStreamUtils.popIntFromByteQueue(byteStream));
rVal.setlocationY(ByteStreamUtils.popIntFromByteQueue(byteStream));
rVal.setmacroValue00(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setmacroValue01(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setmacroValue02(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setmacroValue10(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setmacroValue11(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setmacroValue12(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setmacroValue20(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setmacroValue21(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setmacroValue22(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setrandomizerValue00(ByteStreamUtils.popLongFromByteQueue(byteStream));
rVal.setrandomizerValue01(ByteStreamUtils.popLongFromByteQueue(byteStream));
rVal.setrandomizerValue02(ByteStreamUtils.popLongFromByteQueue(byteStream));
rVal.setrandomizerValue10(ByteStreamUtils.popLongFromByteQueue(byteStream));
rVal.setrandomizerValue11(ByteStreamUtils.popLongFromByteQueue(byteStream));
rVal.setrandomizerValue12(ByteStreamUtils.popLongFromByteQueue(byteStream));
rVal.setrandomizerValue20(ByteStreamUtils.popLongFromByteQueue(byteStream));
rVal.setrandomizerValue21(ByteStreamUtils.popLongFromByteQueue(byteStream));
rVal.setrandomizerValue22(ByteStreamUtils.popLongFromByteQueue(byteStream));
return rVal;
}
public static WorldMessage constructMacroValueMessage(long macroValue00,long macroValue01,long macroValue02,long macroValue10,long macroValue11,long macroValue12,long macroValue20,long macroValue21,long macroValue22){
public static WorldMessage constructMacroValueMessage(int locationX,int locationY,float macroValue00,float macroValue01,float macroValue02,float macroValue10,float macroValue11,float macroValue12,float macroValue20,float macroValue21,float macroValue22,long randomizerValue00,long randomizerValue01,long randomizerValue02,long randomizerValue10,long randomizerValue11,long randomizerValue12,long randomizerValue20,long randomizerValue21,long randomizerValue22){
WorldMessage rVal = new WorldMessage(WorldMessageType.MACROVALUE);
rVal.setlocationX(locationX);
rVal.setlocationY(locationY);
rVal.setmacroValue00(macroValue00);
rVal.setmacroValue01(macroValue01);
rVal.setmacroValue02(macroValue02);
@ -303,27 +398,6 @@ public class WorldMessage extends NetworkMessage {
rVal.setmacroValue20(macroValue20);
rVal.setmacroValue21(macroValue21);
rVal.setmacroValue22(macroValue22);
rVal.serialize();
return rVal;
}
public static WorldMessage parseRandomizerValueMessage(LinkedList<Byte> byteStream){
WorldMessage rVal = new WorldMessage(WorldMessageType.RANDOMIZERVALUE);
stripPacketHeader(byteStream);
rVal.setrandomizerValue00(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setrandomizerValue01(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setrandomizerValue02(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setrandomizerValue10(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setrandomizerValue11(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setrandomizerValue12(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setrandomizerValue20(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setrandomizerValue21(ByteStreamUtils.popFloatFromByteQueue(byteStream));
rVal.setrandomizerValue22(ByteStreamUtils.popFloatFromByteQueue(byteStream));
return rVal;
}
public static WorldMessage constructRandomizerValueMessage(float randomizerValue00,float randomizerValue01,float randomizerValue02,float randomizerValue10,float randomizerValue11,float randomizerValue12,float randomizerValue20,float randomizerValue21,float randomizerValue22){
WorldMessage rVal = new WorldMessage(WorldMessageType.RANDOMIZERVALUE);
rVal.setrandomizerValue00(randomizerValue00);
rVal.setrandomizerValue01(randomizerValue01);
rVal.setrandomizerValue02(randomizerValue02);
@ -341,16 +415,54 @@ public class WorldMessage extends NetworkMessage {
void serialize(){
byte[] intValues = new byte[8];
switch(this.messageType){
case INFO:
rawBytes = new byte[TypeBytes.WORLD_MESSAGE_TYPE_INFO_SIZE];
case METADATA:
rawBytes = new byte[TypeBytes.WORLD_MESSAGE_TYPE_METADATA_SIZE];
//message header
rawBytes[0] = TypeBytes.MESSAGE_TYPE_WORLD;
//entity messaage header
rawBytes[1] = TypeBytes.WORLD_MESSAGE_TYPE_INFO;
intValues = ByteStreamUtils.serializeIntToBytes(worldSize);
rawBytes[1] = TypeBytes.WORLD_MESSAGE_TYPE_METADATA;
intValues = ByteStreamUtils.serializeIntToBytes(worldSizeDiscrete);
for(int i = 0; i < 4; i++){
rawBytes[2+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(dynamicInterpolationRatio);
for(int i = 0; i < 4; i++){
rawBytes[6+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeFloatToBytes(randomDampener);
for(int i = 0; i < 4; i++){
rawBytes[10+i] = intValues[i];
} intValues = ByteStreamUtils.serializeIntToBytes(worldMinX);
for(int i = 0; i < 4; i++){
rawBytes[14+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(worldMinY);
for(int i = 0; i < 4; i++){
rawBytes[18+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(worldMaxX);
for(int i = 0; i < 4; i++){
rawBytes[22+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(worldMaxY);
for(int i = 0; i < 4; i++){
rawBytes[26+i] = intValues[i];
}
break;
case REQUESTMACROVALUES:
rawBytes = new byte[TypeBytes.WORLD_MESSAGE_TYPE_REQUESTMACROVALUES_SIZE];
//message header
rawBytes[0] = TypeBytes.MESSAGE_TYPE_WORLD;
//entity messaage header
rawBytes[1] = TypeBytes.WORLD_MESSAGE_TYPE_REQUESTMACROVALUES;
intValues = ByteStreamUtils.serializeIntToBytes(locationX);
for(int i = 0; i < 4; i++){
rawBytes[2+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeIntToBytes(locationY);
for(int i = 0; i < 4; i++){
rawBytes[6+i] = intValues[i];
}
break;
case UPDATE:
rawBytes = new byte[TypeBytes.WORLD_MESSAGE_TYPE_UPDATE_SIZE];
@ -373,68 +485,78 @@ public class WorldMessage extends NetworkMessage {
rawBytes[0] = TypeBytes.MESSAGE_TYPE_WORLD;
//entity messaage header
rawBytes[1] = TypeBytes.WORLD_MESSAGE_TYPE_MACROVALUE;
intValues = ByteStreamUtils.serializeLongToBytes(macroValue00);
for(int i = 0; i < 8; i++){
rawBytes[2+i] = intValues[i];
} intValues = ByteStreamUtils.serializeLongToBytes(macroValue01);
for(int i = 0; i < 8; i++){
rawBytes[6+i] = intValues[i];
} intValues = ByteStreamUtils.serializeLongToBytes(macroValue02);
for(int i = 0; i < 8; i++){
rawBytes[10+i] = intValues[i];
} intValues = ByteStreamUtils.serializeLongToBytes(macroValue10);
for(int i = 0; i < 8; i++){
rawBytes[14+i] = intValues[i];
} intValues = ByteStreamUtils.serializeLongToBytes(macroValue11);
for(int i = 0; i < 8; i++){
rawBytes[18+i] = intValues[i];
} intValues = ByteStreamUtils.serializeLongToBytes(macroValue12);
for(int i = 0; i < 8; i++){
rawBytes[22+i] = intValues[i];
} intValues = ByteStreamUtils.serializeLongToBytes(macroValue20);
for(int i = 0; i < 8; i++){
rawBytes[26+i] = intValues[i];
} intValues = ByteStreamUtils.serializeLongToBytes(macroValue21);
for(int i = 0; i < 8; i++){
rawBytes[30+i] = intValues[i];
} intValues = ByteStreamUtils.serializeLongToBytes(macroValue22);
for(int i = 0; i < 8; i++){
rawBytes[34+i] = intValues[i];
} break;
case RANDOMIZERVALUE:
rawBytes = new byte[TypeBytes.WORLD_MESSAGE_TYPE_RANDOMIZERVALUE_SIZE];
//message header
rawBytes[0] = TypeBytes.MESSAGE_TYPE_WORLD;
//entity messaage header
rawBytes[1] = TypeBytes.WORLD_MESSAGE_TYPE_RANDOMIZERVALUE;
intValues = ByteStreamUtils.serializeFloatToBytes(randomizerValue00);
intValues = ByteStreamUtils.serializeIntToBytes(locationX);
for(int i = 0; i < 4; i++){
rawBytes[2+i] = intValues[i];
} intValues = ByteStreamUtils.serializeFloatToBytes(randomizerValue01);
}
intValues = ByteStreamUtils.serializeIntToBytes(locationY);
for(int i = 0; i < 4; i++){
rawBytes[6+i] = intValues[i];
} intValues = ByteStreamUtils.serializeFloatToBytes(randomizerValue02);
}
intValues = ByteStreamUtils.serializeFloatToBytes(macroValue00);
for(int i = 0; i < 4; i++){
rawBytes[10+i] = intValues[i];
} intValues = ByteStreamUtils.serializeFloatToBytes(randomizerValue10);
} intValues = ByteStreamUtils.serializeFloatToBytes(macroValue01);
for(int i = 0; i < 4; i++){
rawBytes[14+i] = intValues[i];
} intValues = ByteStreamUtils.serializeFloatToBytes(randomizerValue11);
} intValues = ByteStreamUtils.serializeFloatToBytes(macroValue02);
for(int i = 0; i < 4; i++){
rawBytes[18+i] = intValues[i];
} intValues = ByteStreamUtils.serializeFloatToBytes(randomizerValue12);
} intValues = ByteStreamUtils.serializeFloatToBytes(macroValue10);
for(int i = 0; i < 4; i++){
rawBytes[22+i] = intValues[i];
} intValues = ByteStreamUtils.serializeFloatToBytes(randomizerValue20);
} intValues = ByteStreamUtils.serializeFloatToBytes(macroValue11);
for(int i = 0; i < 4; i++){
rawBytes[26+i] = intValues[i];
} intValues = ByteStreamUtils.serializeFloatToBytes(randomizerValue21);
} intValues = ByteStreamUtils.serializeFloatToBytes(macroValue12);
for(int i = 0; i < 4; i++){
rawBytes[30+i] = intValues[i];
} intValues = ByteStreamUtils.serializeFloatToBytes(randomizerValue22);
} intValues = ByteStreamUtils.serializeFloatToBytes(macroValue20);
for(int i = 0; i < 4; i++){
rawBytes[34+i] = intValues[i];
} break;
} intValues = ByteStreamUtils.serializeFloatToBytes(macroValue21);
for(int i = 0; i < 4; i++){
rawBytes[38+i] = intValues[i];
} intValues = ByteStreamUtils.serializeFloatToBytes(macroValue22);
for(int i = 0; i < 4; i++){
rawBytes[42+i] = intValues[i];
} intValues = ByteStreamUtils.serializeLongToBytes(randomizerValue00);
for(int i = 0; i < 8; i++){
rawBytes[46+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeLongToBytes(randomizerValue01);
for(int i = 0; i < 8; i++){
rawBytes[54+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeLongToBytes(randomizerValue02);
for(int i = 0; i < 8; i++){
rawBytes[62+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeLongToBytes(randomizerValue10);
for(int i = 0; i < 8; i++){
rawBytes[70+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeLongToBytes(randomizerValue11);
for(int i = 0; i < 8; i++){
rawBytes[78+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeLongToBytes(randomizerValue12);
for(int i = 0; i < 8; i++){
rawBytes[86+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeLongToBytes(randomizerValue20);
for(int i = 0; i < 8; i++){
rawBytes[94+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeLongToBytes(randomizerValue21);
for(int i = 0; i < 8; i++){
rawBytes[102+i] = intValues[i];
}
intValues = ByteStreamUtils.serializeLongToBytes(randomizerValue22);
for(int i = 0; i < 8; i++){
rawBytes[110+i] = intValues[i];
}
break;
}
serialized = true;
}

View File

@ -4,18 +4,18 @@ import electrosphere.net.parser.net.message.NetworkMessage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.LinkedList;
import java.util.concurrent.CopyOnWriteArrayList;
public class NetworkParser {
InputStream incomingStream;
OutputStream outgoingStream;
LinkedList<NetworkMessage> incomingMessageQueue = new LinkedList();
LinkedList<NetworkMessage> outgoingMessageQueue = new LinkedList();
CopyOnWriteArrayList<NetworkMessage> incomingMessageQueue = new CopyOnWriteArrayList();
CopyOnWriteArrayList<NetworkMessage> outgoingMessageQueue = new CopyOnWriteArrayList();
LinkedList<Byte> incomingByteQueue = new LinkedList();
LinkedList<Byte> outgoingByteQueue = new LinkedList();
CopyOnWriteArrayList<Byte> incomingByteQueue = new CopyOnWriteArrayList();
CopyOnWriteArrayList<Byte> outgoingByteQueue = new CopyOnWriteArrayList();

View File

@ -1,7 +1,7 @@
package electrosphere.net.parser.util;
import java.nio.ByteBuffer;
import java.util.LinkedList;
import java.util.List;
public class ByteStreamUtils {
@ -11,7 +11,7 @@ public class ByteStreamUtils {
integerCompactor = ByteBuffer.allocate(8);
}
public static int popIntFromByteQueue(LinkedList<Byte> queue){
public static int popIntFromByteQueue(List<Byte> queue){
int rVal = -1;
integerCompactor.clear();
integerCompactor.put(queue.remove(0));
@ -23,7 +23,7 @@ public class ByteStreamUtils {
return rVal;
}
public static float popFloatFromByteQueue(LinkedList<Byte> queue){
public static float popFloatFromByteQueue(List<Byte> queue){
float rVal = -1;
integerCompactor.clear();
integerCompactor.put(queue.remove(0));
@ -35,7 +35,7 @@ public class ByteStreamUtils {
return rVal;
}
public static long popLongFromByteQueue(LinkedList<Byte> queue){
public static long popLongFromByteQueue(List<Byte> queue){
long rVal = -1;
integerCompactor.clear();
integerCompactor.put(queue.remove(0));

View File

@ -11,6 +11,8 @@ import electrosphere.net.NetUtils;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.parser.net.message.PlayerMessage;
import electrosphere.net.parser.net.message.StatusMessage;
import electrosphere.net.parser.net.message.WorldMessage;
import electrosphere.net.parser.net.raw.NetworkParser;
import java.io.IOException;
import java.io.InputStream;
@ -47,6 +49,8 @@ public class ServerConnectionHandler implements Runnable {
NetworkParser networkParser;
int playerID;
ServerProtocol serverProtocol;
public ServerConnectionHandler(Socket socket) {
this.socket = socket;
playerID = getPlayerID();
@ -81,6 +85,7 @@ public class ServerConnectionHandler implements Runnable {
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
networkParser = new NetworkParser(inputStream,outputStream);
serverProtocol = new ServerProtocol(this);
} catch (IOException ex) {
ex.printStackTrace();
System.exit(1);
@ -88,7 +93,7 @@ public class ServerConnectionHandler implements Runnable {
//spawn player in world
Entity newPlayerCharacter = CreatureUtils.spawnBasicCreature(0, 0.001f, 0.05f);
EntityUtils.getEntityScale(newPlayerCharacter).set(0.005f);
EntityUtils.getEntityPosition(newPlayerCharacter).set(Globals.spawnPoint.x,Globals.drawCellManager.getElevationAtRealPoint(Globals.spawnPoint.x, Globals.spawnPoint.z),Globals.spawnPoint.z);
EntityUtils.getEntityPosition(newPlayerCharacter).set(Globals.spawnPoint.x,0,Globals.spawnPoint.z);
//spawn player sword
Entity sword = ItemUtils.spawnBasicItem(2);
AttachUtils.attachEntityToEntityAtBone(newPlayerCharacter, sword, "Bone.020");
@ -97,6 +102,18 @@ public class ServerConnectionHandler implements Runnable {
if(Globals.mainConfig.runServer && Main.playerId == -1){
Globals.playerCharacter = newPlayerCharacter;
}
//world metadata
networkParser.addOutgoingMessage(
WorldMessage.constructMetadataMessage(
Globals.serverWorldData.getWorldSizeDiscrete(),
Globals.serverWorldData.getDynamicInterpolationRatio(),
Globals.serverWorldData.getRandomDampener(),
(int)Globals.serverWorldData.getWorldBoundMin().x,
(int)Globals.serverWorldData.getWorldBoundMin().z,
(int)Globals.serverWorldData.getWorldBoundMax().x,
(int)Globals.serverWorldData.getWorldBoundMax().z
)
);
//tell them what player stats they are
networkParser.addOutgoingMessage(PlayerMessage.constructSet_IDMessage(playerID));
//figure out what chunk they're in
@ -115,6 +132,9 @@ public class ServerConnectionHandler implements Runnable {
}
}
}
//let client know it's ready
networkParser.addOutgoingMessage(StatusMessage.constructReadyMessage(1));
initialized = true;
while(Main.isRunning()){
@ -123,7 +143,7 @@ public class ServerConnectionHandler implements Runnable {
//ponder incoming messages
while(networkParser.hasIncomingMessaage()){
NetworkMessage message = networkParser.popIncomingMessage();
handleMessage(message);
serverProtocol.handleMessage(message);
}
//push outgoing message
networkParser.pushMessagesOut();
@ -137,30 +157,7 @@ public class ServerConnectionHandler implements Runnable {
}
void handleMessage(NetworkMessage message){
switch(message.getType()){
case ENTITY_MESSAGE:
handleEntityMessage((EntityMessage)message);
break;
}
}
void handleEntityMessage(EntityMessage message){
switch(message.getMessageSubtype()){
case CREATE:
break;
case DESTROY:
break;
case MOVE:
Entity targetEntity = Globals.entityManager.getEntityFromId(message.getentityID());
if(targetEntity != null){
CreatureUtils.attachEntityMessageToMovementTree(targetEntity,message);
}
break;
case SETBEHAVIORTREE:
break;
}
}
static int getPlayerID(){

View File

@ -0,0 +1,105 @@
package electrosphere.net.server;
import electrosphere.entity.Entity;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.main.Globals;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.parser.net.message.WorldMessage;
public class ServerProtocol {
ServerConnectionHandler connectionHandler;
public ServerProtocol(ServerConnectionHandler connectionHandler){
this.connectionHandler = connectionHandler;
}
void handleMessage(NetworkMessage message){
switch(message.getType()){
case ENTITY_MESSAGE:
handleEntityMessage((EntityMessage)message);
break;
case WORLD_MESSAGE:
handleWorldMessage((WorldMessage)message);
break;
}
}
void handleEntityMessage(EntityMessage message){
switch(message.getMessageSubtype()){
case CREATE:
break;
case DESTROY:
break;
case MOVE:
Entity targetEntity = Globals.entityManager.getEntityFromId(message.getentityID());
if(targetEntity != null){
CreatureUtils.attachEntityMessageToMovementTree(targetEntity,message);
}
break;
case SETBEHAVIORTREE:
break;
}
}
void handleWorldMessage(WorldMessage message){
switch(message.getMessageSubtype()){
case REQUESTMACROVALUES:
/*
int locationX,
int locationY,
float macroValue00,
float macroValue01,
float macroValue02,
float macroValue10,
float macroValue11,
float macroValue12,
float macroValue20,
float macroValue21,
float macroValue22,
long randomizerValue00,
long randomizerValue01,
long randomizerValue02,
long randomizerValue10,
long randomizerValue11,
long randomizerValue12,
long randomizerValue20,
long randomizerValue21,
long randomizerValue22
*/
float[][] macroValues = Globals.serverTerrainManager.getMacroValues(message.getlocationX(), message.getlocationY());
long[][] randomizer = Globals.serverTerrainManager.getRandomizer(message.getlocationX(), message.getlocationY());
connectionHandler.addMessagetoOutgoingQueue(
WorldMessage.constructMacroValueMessage(
message.getlocationX(),
message.getlocationY(),
macroValues[0][0],
macroValues[0][1],
macroValues[0][2],
macroValues[1][0],
macroValues[1][1],
macroValues[1][2],
macroValues[2][0],
macroValues[2][1],
macroValues[2][2],
randomizer[0][0],
randomizer[0][1],
randomizer[0][2],
randomizer[1][0],
randomizer[1][1],
randomizer[1][2],
randomizer[2][0],
randomizer[2][1],
randomizer[2][2]
)
);
break;
}
}
}

View File

@ -4,13 +4,62 @@
"categories":[
{
"categoryName" : "Status",
"data" : [
{
"name" : "ready",
"type" : "FIXED_INT"
}
],
"messageTypes" : [
{
"messageName" : "Ready",
"data" : [
"ready"
]
}
]
},
{
"categoryName" : "World",
"data" : [
{
"name" : "worldSize",
"name" : "worldSizeDiscrete",
"type" : "FIXED_INT"
},
{
"name" : "dynamicInterpolationRatio",
"type" : "FIXED_INT"
},
{
"name" : "randomDampener",
"type" : "FIXED_FLOAT"
},
{
"name" : "worldMinX",
"type" : "FIXED_INT"
},
{
"name" : "worldMinY",
"type" : "FIXED_INT"
},
{
"name" : "worldMaxX",
"type" : "FIXED_INT"
},
{
"name" : "worldMaxY",
"type" : "FIXED_INT"
},
{
"name" : "locationX",
"type" : "FIXED_INT"
@ -19,87 +68,106 @@
"name" : "locationY",
"type" : "FIXED_INT"
},
{
"name" : "macroValue00",
"type" : "FIXED_LONG"
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue01",
"type" : "FIXED_LONG"
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue02",
"type" : "FIXED_LONG"
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue10",
"type" : "FIXED_LONG"
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue11",
"type" : "FIXED_LONG"
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue12",
"type" : "FIXED_LONG"
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue20",
"type" : "FIXED_LONG"
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue21",
"type" : "FIXED_LONG"
"type" : "FIXED_FLOAT"
},
{
"name" : "macroValue22",
"type" : "FIXED_LONG"
"type" : "FIXED_FLOAT"
},
{
"name" : "randomizerValue00",
"type" : "FIXED_FLOAT"
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue01",
"type" : "FIXED_FLOAT"
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue02",
"type" : "FIXED_FLOAT"
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue10",
"type" : "FIXED_FLOAT"
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue11",
"type" : "FIXED_FLOAT"
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue12",
"type" : "FIXED_FLOAT"
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue20",
"type" : "FIXED_FLOAT"
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue21",
"type" : "FIXED_FLOAT"
"type" : "FIXED_LONG"
},
{
"name" : "randomizerValue22",
"type" : "FIXED_FLOAT"
"type" : "FIXED_LONG"
}
],
"messageTypes" : [
{
"messageName" : "Info",
"messageName" : "Metadata",
"data" : [
"worldSize"
"worldSizeDiscrete",
"dynamicInterpolationRatio",
"randomDampener",
"worldMinX",
"worldMinY",
"worldMaxX",
"worldMaxY"
]
},
{
"messageName" : "RequestMacroValues",
"data" : [
"locationX",
"locationY"
]
},
{
@ -112,6 +180,8 @@
{
"messageName" : "MacroValue",
"data" : [
"locationX",
"locationY",
"macroValue00",
"macroValue01",
"macroValue02",
@ -120,12 +190,7 @@
"macroValue12",
"macroValue20",
"macroValue21",
"macroValue22"
]
},
{
"messageName" : "RandomizerValue",
"data" : [
"macroValue22",
"randomizerValue00",
"randomizerValue01",
"randomizerValue02",
@ -214,6 +279,10 @@
{
"name" : "treeStatus",
"type" : "FIXED_INT"
},
{
"name" : "time",
"type" : "FIXED_LONG"
}
],
"messageTypes" : [
@ -230,6 +299,7 @@
{
"messageName" : "SetPosition",
"data" : [
"time",
"entityID",
"positionX",
"positionY",
@ -239,6 +309,7 @@
{
"messageName" : "Move",
"data" : [
"time",
"entityID",
"positionX",
"positionY",
@ -254,6 +325,7 @@
{
"messageName" : "SetBehaviorTree",
"data" : [
"time",
"entityID",
"treeType",
"treeStatus"
@ -262,6 +334,7 @@
{
"messageName" : "setProperty",
"data" : [
"time",
"entityID",
"propertyType",
"propertyValue"