Server side terrain deformation
This commit is contained in:
parent
b5a0987ea1
commit
b5743b3a1f
Binary file not shown.
BIN
assets/Models/wheat2.fbx
Normal file
BIN
assets/Models/wheat2.fbx
Normal file
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 13 KiB |
@ -12,10 +12,16 @@
|
||||
"/Textures/w1.png"
|
||||
]
|
||||
},
|
||||
"Models/Wheat1.fbx": {
|
||||
"Stalk": [
|
||||
"/Textures/Wheat1stretch.png",
|
||||
"/Textures/Wheat1stretch.png"
|
||||
"Models/wheat1.fbx": {
|
||||
"Cube": [
|
||||
"/Textures/wheat1.png",
|
||||
"/Textures/wheat1.png"
|
||||
]
|
||||
},
|
||||
"Models/wheat2.fbx": {
|
||||
"Wheat": [
|
||||
"/Textures/wheat2.png",
|
||||
"/Textures/wheat2.png"
|
||||
]
|
||||
},
|
||||
"Models/unitsphere.fbx": {
|
||||
|
||||
BIN
assets/Textures/wheat1.png
Normal file
BIN
assets/Textures/wheat1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
BIN
assets/Textures/wheat2.png
Normal file
BIN
assets/Textures/wheat2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 108 KiB |
@ -23,6 +23,7 @@ import electrosphere.entity.types.structure.StructureUtils;
|
||||
import electrosphere.game.collision.PhysicsUtils;
|
||||
import electrosphere.game.collision.collidable.Collidable;
|
||||
import electrosphere.game.server.ai.creature.MindlessAttacker;
|
||||
import electrosphere.game.server.terrain.models.TerrainModification;
|
||||
import electrosphere.game.state.MicroSimulation;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.main.Globals;
|
||||
@ -181,14 +182,13 @@ public class LoadingThread extends Thread {
|
||||
|
||||
//disable menu input
|
||||
Globals.controlHandler.setHandlerState(ControlHandler.ControlsState.NO_INPUT);
|
||||
|
||||
|
||||
//init server arena terrain manager separately
|
||||
initServerArenaTerrainManager();
|
||||
|
||||
//init the data of the world
|
||||
initServerArenaWorldData();
|
||||
|
||||
//init server arena terrain manager separately
|
||||
initServerArenaTerrainManager();
|
||||
|
||||
//initialize the server thread (server only)
|
||||
if(Globals.RUN_SERVER){
|
||||
initServerThread();
|
||||
@ -291,7 +291,7 @@ public class LoadingThread extends Thread {
|
||||
boolean found = false;
|
||||
for(int x = 0; x < discreteSize; x++){
|
||||
for(int y = 0; y < discreteSize; y++){
|
||||
if(Globals.serverTerrainManager.getDiscreteValue(x, y)>1000){
|
||||
if(Globals.serverTerrainManager.getDiscreteValue(x, y)>1800){
|
||||
playerStartX = x;
|
||||
playerStartY = y;
|
||||
found = true;
|
||||
@ -328,6 +328,7 @@ public class LoadingThread extends Thread {
|
||||
static void initServerArenaWorldData(){
|
||||
Globals.serverWorldData = ServerWorldData.createArenaWorld();
|
||||
Globals.spawnPoint = new Vector3f(1,3,1);
|
||||
Globals.serverTerrainManager.getChunk(0, 0).addModification(new TerrainModification(0,0,5,5,5));
|
||||
}
|
||||
|
||||
static void initServerGameWorldData(){
|
||||
@ -491,13 +492,22 @@ public class LoadingThread extends Thread {
|
||||
// }
|
||||
|
||||
//trees \:D/
|
||||
for(int i = 0; i < 10; i++){
|
||||
Random rand = new Random();
|
||||
String treePath = "Models/tree1.fbx";
|
||||
Entity tree = EntityUtils.spawnDrawableEntity(treePath);
|
||||
EntityUtils.getPosition(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.getPosition(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));
|
||||
// }
|
||||
|
||||
// Random rand = new Random();
|
||||
// for(int i = 0; i < 1000; i++){
|
||||
// String wheatPath = "Models/wheat2.fbx";
|
||||
// Entity wheatStalk = EntityUtils.spawnDrawableEntity(wheatPath);
|
||||
// EntityUtils.getPosition(wheatStalk).set(rand.nextFloat() * 20, 0, rand.nextFloat() * 20);
|
||||
// EntityUtils.getRotation(wheatStalk).rotateLocalX(-(float)Math.PI/2.0f);
|
||||
// EntityUtils.getScale(wheatStalk).set(1, 1, 2);
|
||||
// }
|
||||
|
||||
// String buildingPath = "Models/building1.fbx";
|
||||
// Entity building = EntityUtils.spawnDrawableEntity(buildingPath);
|
||||
@ -531,7 +541,7 @@ public class LoadingThread extends Thread {
|
||||
|
||||
// CreatureUtils.positionCharacter(Globals.playerCharacter, new Vector3f(10,3,10));
|
||||
|
||||
StructureUtils.spawnBasicStructure("building1", new Vector3f(10,2.4f,15), new Quaternionf().rotateLocalY((float)Math.PI));
|
||||
// StructureUtils.spawnBasicStructure("building1", new Vector3f(10,2.4f,15), new Quaternionf().rotateLocalY((float)Math.PI));
|
||||
}
|
||||
|
||||
|
||||
|
||||
16
src/main/java/electrosphere/game/client/ClientFunctions.java
Normal file
16
src/main/java/electrosphere/game/client/ClientFunctions.java
Normal file
@ -0,0 +1,16 @@
|
||||
package electrosphere.game.client;
|
||||
|
||||
import electrosphere.main.Globals;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author amaterasu
|
||||
*/
|
||||
public class ClientFunctions {
|
||||
public static void runClientFunctions(){
|
||||
if(Globals.clientTerrainManager != null){
|
||||
Globals.clientTerrainManager.handleMessages();
|
||||
Globals.clientTerrainManager.ejectLoadedChunks();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -45,7 +45,7 @@ public class DrawCellManager {
|
||||
|
||||
int drawRadius = 35;
|
||||
int drawStepdownInterval = 3;
|
||||
int drawStepdownValue = 25;
|
||||
int drawStepdownValue = 9;
|
||||
|
||||
int physicsRadius = 3;
|
||||
|
||||
@ -165,7 +165,7 @@ public class DrawCellManager {
|
||||
} else {
|
||||
if(hasRequested[targetX][targetY] == false){
|
||||
//client should request macro values from server
|
||||
Globals.clientConnection.queueOutgoingMessage(WorldMessage.constructRequestMacroValuesMessage(currentCellX, currentCellY));
|
||||
Globals.clientConnection.queueOutgoingMessage(WorldMessage.constructRequestChunkMessage(currentCellX, currentCellY));
|
||||
hasRequested[targetX][targetY] = true;
|
||||
}
|
||||
}
|
||||
|
||||
48
src/main/java/electrosphere/game/client/terrain/cache/ChunkModification.java
vendored
Normal file
48
src/main/java/electrosphere/game/client/terrain/cache/ChunkModification.java
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
package electrosphere.game.client.terrain.cache;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author amaterasu
|
||||
*/
|
||||
public class ChunkModification {
|
||||
int worldX;
|
||||
int worldY;
|
||||
int locationX;
|
||||
int locationY;
|
||||
float value;
|
||||
|
||||
public ChunkModification(int worldX, int worldY, int locationX, int locationY, float value) {
|
||||
this.worldX = worldX;
|
||||
this.worldY = worldY;
|
||||
this.locationX = locationX;
|
||||
this.locationY = locationY;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getWorldX() {
|
||||
return worldX;
|
||||
}
|
||||
|
||||
public int getLocationX() {
|
||||
return locationX;
|
||||
}
|
||||
|
||||
public int getLocationY() {
|
||||
return locationY;
|
||||
}
|
||||
|
||||
public float getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public int getWorldY() {
|
||||
return worldY;
|
||||
}
|
||||
|
||||
public float[][] applyModification(float[][] heightmap){
|
||||
heightmap[locationX][locationY] = value;
|
||||
return heightmap;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -5,6 +5,7 @@ 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.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public class ClientTerrainCache {
|
||||
@ -20,7 +21,7 @@ public class ClientTerrainCache {
|
||||
|
||||
|
||||
int cacheSize;
|
||||
HashMap<String,float[][]> cacheMap = new HashMap();
|
||||
ConcurrentHashMap<String,float[][]> cacheMap = new ConcurrentHashMap();
|
||||
CopyOnWriteArrayList<String> cacheList = new CopyOnWriteArrayList();
|
||||
|
||||
|
||||
@ -63,6 +64,14 @@ public class ClientTerrainCache {
|
||||
}
|
||||
}
|
||||
|
||||
public void addFloatsToCache(int x, int y, float[][] values){
|
||||
cacheMap.put(getKey(x,y),values);
|
||||
while(cacheList.size() > cacheSize){
|
||||
String currentChunk = cacheList.remove(0);
|
||||
cacheMap.remove(currentChunk);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getKey(int x, int y){
|
||||
|
||||
77
src/main/java/electrosphere/game/client/terrain/cache/LoadingChunk.java
vendored
Normal file
77
src/main/java/electrosphere/game/client/terrain/cache/LoadingChunk.java
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
package electrosphere.game.client.terrain.cache;
|
||||
|
||||
import electrosphere.game.client.world.ClientWorldData;
|
||||
import electrosphere.game.terrain.processing.TerrainInterpolator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author amaterasu
|
||||
*/
|
||||
public class LoadingChunk {
|
||||
|
||||
int worldX, worldY;
|
||||
int totalNumMessages;
|
||||
int numReceivedMessages = 0;
|
||||
|
||||
ClientWorldData clientWorldData;
|
||||
|
||||
float[][] macroValues;
|
||||
long[][] randomizer;
|
||||
List<ChunkModification> modification = new ArrayList();
|
||||
|
||||
public LoadingChunk(int worldX, int worldY, int numMessages, ClientWorldData clientWorldData){
|
||||
this.worldX = worldX;
|
||||
this.worldY = worldY;
|
||||
this.totalNumMessages = numMessages;
|
||||
this.clientWorldData = clientWorldData;
|
||||
}
|
||||
|
||||
public void addMacroValues(float[][] macroValues){
|
||||
this.macroValues = macroValues;
|
||||
}
|
||||
|
||||
public void addRandomizer(long[][] randomizer){
|
||||
this.randomizer = randomizer;
|
||||
}
|
||||
|
||||
public void addModification(int worldX, int worldY, int locationX, int locationY, float value){
|
||||
ChunkModification newModification = new ChunkModification(worldX, worldY, locationX, locationY, value);
|
||||
modification.add(newModification);
|
||||
}
|
||||
|
||||
public void incrementMessageCount(){
|
||||
numReceivedMessages++;
|
||||
}
|
||||
|
||||
public boolean isComplete(){
|
||||
return numReceivedMessages >= totalNumMessages && macroValues != null && randomizer != null;
|
||||
}
|
||||
|
||||
public float[][] exportFloats(){
|
||||
float[][] heightmap = TerrainInterpolator.getBicubicInterpolatedChunk(
|
||||
macroValues,
|
||||
randomizer,
|
||||
clientWorldData.getDynamicInterpolationRatio(),
|
||||
clientWorldData.getRandomDampener()
|
||||
);
|
||||
if(modification != null){
|
||||
for(ChunkModification modification : modification){
|
||||
modification.applyModification(heightmap);
|
||||
}
|
||||
}
|
||||
return heightmap;
|
||||
}
|
||||
|
||||
public int getWorldX() {
|
||||
return worldX;
|
||||
}
|
||||
|
||||
public int getWorldY() {
|
||||
return worldY;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
48
src/main/java/electrosphere/game/client/terrain/cache/LoadingChunkCache.java
vendored
Normal file
48
src/main/java/electrosphere/game/client/terrain/cache/LoadingChunkCache.java
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
package electrosphere.game.client.terrain.cache;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author amaterasu
|
||||
*/
|
||||
public class LoadingChunkCache {
|
||||
ConcurrentHashMap<String,LoadingChunk> cacheMap = new ConcurrentHashMap();
|
||||
CopyOnWriteArrayList<String> cacheList = new CopyOnWriteArrayList();
|
||||
|
||||
|
||||
public LoadingChunkCache(){
|
||||
}
|
||||
|
||||
|
||||
//USED TO ADD macro values
|
||||
public void addLoadingChunkToCache(LoadingChunk chunk){
|
||||
cacheMap.put(getKey(chunk.worldX, chunk.worldY),chunk);
|
||||
}
|
||||
|
||||
public LoadingChunk fetch(String key){
|
||||
return cacheMap.get(key);
|
||||
}
|
||||
|
||||
|
||||
public String getKey(int worldX, int worldY){
|
||||
return worldX + "-" + worldY;
|
||||
}
|
||||
|
||||
public boolean containsKey(String key){
|
||||
return cacheMap.containsKey(key);
|
||||
}
|
||||
|
||||
public Collection<LoadingChunk> getChunks(){
|
||||
return cacheMap.values();
|
||||
}
|
||||
|
||||
public void remove(LoadingChunk chunk){
|
||||
cacheMap.remove(getKey(chunk.worldX,chunk.worldY));
|
||||
cacheList.remove(getKey(chunk.worldX,chunk.worldY));
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,8 +1,13 @@
|
||||
package electrosphere.game.client.terrain.manager;
|
||||
|
||||
import electrosphere.game.client.terrain.cache.ClientTerrainCache;
|
||||
import electrosphere.game.client.terrain.cache.LoadingChunk;
|
||||
import electrosphere.game.client.terrain.cache.LoadingChunkCache;
|
||||
import electrosphere.game.client.world.ClientWorldData;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.net.parser.net.message.WorldMessage;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public class ClientTerrainManager {
|
||||
@ -17,6 +22,9 @@ public class ClientTerrainManager {
|
||||
//used for caching the macro values
|
||||
ClientTerrainCache terrainCache;
|
||||
|
||||
//used for caching loading chunks that are still streaming over the net
|
||||
LoadingChunkCache loadingChunkCache;
|
||||
|
||||
|
||||
ClientWorldData clientWorldData;
|
||||
|
||||
@ -24,72 +32,102 @@ public class ClientTerrainManager {
|
||||
public ClientTerrainManager(ClientWorldData clientWorldData){
|
||||
this.clientWorldData = clientWorldData;
|
||||
terrainCache = new ClientTerrainCache(CACHE_SIZE,clientWorldData);
|
||||
loadingChunkCache = new LoadingChunkCache();
|
||||
}
|
||||
|
||||
|
||||
public void handleMessages(){
|
||||
List<WorldMessage> bouncedMessages = new LinkedList();
|
||||
for(WorldMessage message : messageQueue){
|
||||
messageQueue.remove(message);
|
||||
switch(message.getMessageSubtype()){
|
||||
case MACROVALUE:
|
||||
float[][] macroValues = new float[5][5];
|
||||
long[][] randomizer = new long[5][5];
|
||||
//macro values
|
||||
macroValues[0][0] = message.getmacroValue00();
|
||||
macroValues[0][1] = message.getmacroValue01();
|
||||
macroValues[0][2] = message.getmacroValue02();
|
||||
macroValues[0][3] = message.getmacroValue03();
|
||||
macroValues[0][4] = message.getmacroValue04();
|
||||
macroValues[1][0] = message.getmacroValue10();
|
||||
macroValues[1][1] = message.getmacroValue11();
|
||||
macroValues[1][2] = message.getmacroValue12();
|
||||
macroValues[1][3] = message.getmacroValue13();
|
||||
macroValues[1][4] = message.getmacroValue14();
|
||||
macroValues[2][0] = message.getmacroValue20();
|
||||
macroValues[2][1] = message.getmacroValue21();
|
||||
macroValues[2][2] = message.getmacroValue22();
|
||||
macroValues[2][3] = message.getmacroValue23();
|
||||
macroValues[2][4] = message.getmacroValue24();
|
||||
macroValues[3][0] = message.getmacroValue30();
|
||||
macroValues[3][1] = message.getmacroValue31();
|
||||
macroValues[3][2] = message.getmacroValue32();
|
||||
macroValues[3][3] = message.getmacroValue33();
|
||||
macroValues[3][4] = message.getmacroValue34();
|
||||
macroValues[4][0] = message.getmacroValue40();
|
||||
macroValues[4][1] = message.getmacroValue41();
|
||||
macroValues[4][2] = message.getmacroValue42();
|
||||
macroValues[4][3] = message.getmacroValue43();
|
||||
macroValues[4][4] = message.getmacroValue44();
|
||||
//randomizer
|
||||
randomizer[0][0] = message.getrandomizerValue00();
|
||||
randomizer[0][1] = message.getrandomizerValue01();
|
||||
randomizer[0][2] = message.getrandomizerValue02();
|
||||
randomizer[0][3] = message.getrandomizerValue03();
|
||||
randomizer[0][4] = message.getrandomizerValue04();
|
||||
randomizer[1][0] = message.getrandomizerValue10();
|
||||
randomizer[1][1] = message.getrandomizerValue11();
|
||||
randomizer[1][2] = message.getrandomizerValue12();
|
||||
randomizer[1][3] = message.getrandomizerValue13();
|
||||
randomizer[1][4] = message.getrandomizerValue14();
|
||||
randomizer[2][0] = message.getrandomizerValue20();
|
||||
randomizer[2][1] = message.getrandomizerValue21();
|
||||
randomizer[2][2] = message.getrandomizerValue22();
|
||||
randomizer[2][3] = message.getrandomizerValue23();
|
||||
randomizer[2][4] = message.getrandomizerValue24();
|
||||
randomizer[3][0] = message.getrandomizerValue30();
|
||||
randomizer[3][1] = message.getrandomizerValue31();
|
||||
randomizer[3][2] = message.getrandomizerValue32();
|
||||
randomizer[3][3] = message.getrandomizerValue33();
|
||||
randomizer[3][4] = message.getrandomizerValue34();
|
||||
randomizer[4][0] = message.getrandomizerValue40();
|
||||
randomizer[4][1] = message.getrandomizerValue41();
|
||||
randomizer[4][2] = message.getrandomizerValue42();
|
||||
randomizer[4][3] = message.getrandomizerValue43();
|
||||
randomizer[4][4] = message.getrandomizerValue44();
|
||||
terrainCache.addChunkValuesToCache(message.getlocationX(), message.getlocationY(), macroValues, randomizer);
|
||||
// terrainCache.addChunkValuesToCache(message.getlocationX(), message.getlocationY(), macroValues, randomizer);
|
||||
if(loadingChunkCache.containsKey(loadingChunkCache.getKey(message.getworldX(), message.getworldY()))){
|
||||
float[][] macroValues = new float[5][5];
|
||||
long[][] randomizer = new long[5][5];
|
||||
//macro values
|
||||
macroValues[0][0] = message.getmacroValue00();
|
||||
macroValues[0][1] = message.getmacroValue01();
|
||||
macroValues[0][2] = message.getmacroValue02();
|
||||
macroValues[0][3] = message.getmacroValue03();
|
||||
macroValues[0][4] = message.getmacroValue04();
|
||||
macroValues[1][0] = message.getmacroValue10();
|
||||
macroValues[1][1] = message.getmacroValue11();
|
||||
macroValues[1][2] = message.getmacroValue12();
|
||||
macroValues[1][3] = message.getmacroValue13();
|
||||
macroValues[1][4] = message.getmacroValue14();
|
||||
macroValues[2][0] = message.getmacroValue20();
|
||||
macroValues[2][1] = message.getmacroValue21();
|
||||
macroValues[2][2] = message.getmacroValue22();
|
||||
macroValues[2][3] = message.getmacroValue23();
|
||||
macroValues[2][4] = message.getmacroValue24();
|
||||
macroValues[3][0] = message.getmacroValue30();
|
||||
macroValues[3][1] = message.getmacroValue31();
|
||||
macroValues[3][2] = message.getmacroValue32();
|
||||
macroValues[3][3] = message.getmacroValue33();
|
||||
macroValues[3][4] = message.getmacroValue34();
|
||||
macroValues[4][0] = message.getmacroValue40();
|
||||
macroValues[4][1] = message.getmacroValue41();
|
||||
macroValues[4][2] = message.getmacroValue42();
|
||||
macroValues[4][3] = message.getmacroValue43();
|
||||
macroValues[4][4] = message.getmacroValue44();
|
||||
//randomizer
|
||||
randomizer[0][0] = message.getrandomizerValue00();
|
||||
randomizer[0][1] = message.getrandomizerValue01();
|
||||
randomizer[0][2] = message.getrandomizerValue02();
|
||||
randomizer[0][3] = message.getrandomizerValue03();
|
||||
randomizer[0][4] = message.getrandomizerValue04();
|
||||
randomizer[1][0] = message.getrandomizerValue10();
|
||||
randomizer[1][1] = message.getrandomizerValue11();
|
||||
randomizer[1][2] = message.getrandomizerValue12();
|
||||
randomizer[1][3] = message.getrandomizerValue13();
|
||||
randomizer[1][4] = message.getrandomizerValue14();
|
||||
randomizer[2][0] = message.getrandomizerValue20();
|
||||
randomizer[2][1] = message.getrandomizerValue21();
|
||||
randomizer[2][2] = message.getrandomizerValue22();
|
||||
randomizer[2][3] = message.getrandomizerValue23();
|
||||
randomizer[2][4] = message.getrandomizerValue24();
|
||||
randomizer[3][0] = message.getrandomizerValue30();
|
||||
randomizer[3][1] = message.getrandomizerValue31();
|
||||
randomizer[3][2] = message.getrandomizerValue32();
|
||||
randomizer[3][3] = message.getrandomizerValue33();
|
||||
randomizer[3][4] = message.getrandomizerValue34();
|
||||
randomizer[4][0] = message.getrandomizerValue40();
|
||||
randomizer[4][1] = message.getrandomizerValue41();
|
||||
randomizer[4][2] = message.getrandomizerValue42();
|
||||
randomizer[4][3] = message.getrandomizerValue43();
|
||||
randomizer[4][4] = message.getrandomizerValue44();
|
||||
LoadingChunk inProgressChunk = loadingChunkCache.fetch(loadingChunkCache.getKey(message.getworldX(), message.getworldY()));
|
||||
inProgressChunk.addMacroValues(macroValues);
|
||||
inProgressChunk.addRandomizer(randomizer);
|
||||
inProgressChunk.incrementMessageCount();
|
||||
} else {
|
||||
bouncedMessages.add(message);
|
||||
}
|
||||
break;
|
||||
case CHUNKLOADSTART:
|
||||
LoadingChunk newChunk = new LoadingChunk(message.getworldX(),message.getworldY(),(int)message.getvalue(),clientWorldData);
|
||||
loadingChunkCache.addLoadingChunkToCache(newChunk);
|
||||
newChunk.incrementMessageCount();
|
||||
break;
|
||||
case HEIGHTMAPMODIFICATION:
|
||||
if(loadingChunkCache.containsKey(loadingChunkCache.getKey(message.getworldX(), message.getworldY()))){
|
||||
LoadingChunk inProgressChunk = loadingChunkCache.fetch(loadingChunkCache.getKey(message.getworldX(), message.getworldY()));
|
||||
inProgressChunk.addModification(message.getworldX(), message.getworldY(), message.getlocationX(), message.getlocationY(), message.getvalue());
|
||||
inProgressChunk.incrementMessageCount();
|
||||
} else {
|
||||
bouncedMessages.add(message);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LoggerInterface.loggerEngine.WARNING("ClientTerrainManager: unhandled network message of type" + message.getMessageSubtype());
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(WorldMessage message : bouncedMessages){
|
||||
messageQueue.add(message);
|
||||
}
|
||||
}
|
||||
|
||||
public void attachWorldMessage(WorldMessage message){
|
||||
@ -146,5 +184,18 @@ public class ClientTerrainManager {
|
||||
return rVal;
|
||||
}
|
||||
|
||||
public void ejectLoadedChunks(){
|
||||
List<LoadingChunk> chunksToEject = new LinkedList();
|
||||
for(LoadingChunk chunk : loadingChunkCache.getChunks()){
|
||||
if(chunk.isComplete()){
|
||||
float[][] heightMap = chunk.exportFloats();
|
||||
terrainCache.addFloatsToCache(chunk.getWorldX(), chunk.getWorldY(), heightMap);
|
||||
chunksToEject.add(chunk);
|
||||
}
|
||||
}
|
||||
for(LoadingChunk loadedChunk : chunksToEject){
|
||||
loadingChunkCache.remove(loadedChunk);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,64 @@
|
||||
package electrosphere.game.server.terrain.manager;
|
||||
|
||||
import electrosphere.game.server.terrain.models.TerrainModification;
|
||||
import electrosphere.game.server.terrain.models.TerrainModification;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author amaterasu
|
||||
*/
|
||||
public class ServerTerrainChunk {
|
||||
int worldX, worldY;
|
||||
List<TerrainModification> modifications = new LinkedList();
|
||||
float[][] heightMap;
|
||||
float[][] macroValues;
|
||||
long[][] randomizer;
|
||||
|
||||
public ServerTerrainChunk(int worldX, int worldY, float[][] heightMap, float[][] macroValues, long[][] randomizer) {
|
||||
this.worldX = worldX;
|
||||
this.worldY = worldY;
|
||||
this.heightMap = heightMap;
|
||||
this.macroValues = macroValues;
|
||||
this.randomizer = randomizer;
|
||||
}
|
||||
|
||||
public static ServerTerrainChunk getArenaChunk(int width){
|
||||
float[][] macroValues = new float[5][5];
|
||||
long[][] randomizer = new long[5][5];
|
||||
float[][] heightmap = new float[width + 1][width + 1];
|
||||
ServerTerrainChunk rVal = new ServerTerrainChunk(0, 0, heightmap, macroValues, randomizer);
|
||||
return rVal;
|
||||
}
|
||||
|
||||
public int getWorldX() {
|
||||
return worldX;
|
||||
}
|
||||
|
||||
public int getWorldY() {
|
||||
return worldY;
|
||||
}
|
||||
|
||||
public List<TerrainModification> getModifications() {
|
||||
return modifications;
|
||||
}
|
||||
|
||||
public float[][] getHeightMap() {
|
||||
return heightMap;
|
||||
}
|
||||
|
||||
public float[][] getMacroValues() {
|
||||
return macroValues;
|
||||
}
|
||||
|
||||
public long[][] getRandomizer() {
|
||||
return randomizer;
|
||||
}
|
||||
|
||||
public void addModification(TerrainModification modification){
|
||||
modifications.add(modification);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -4,7 +4,9 @@ import com.google.gson.Gson;
|
||||
import electrosphere.game.terrain.processing.TerrainInterpolator;
|
||||
import electrosphere.main.Globals;
|
||||
import electrosphere.game.server.terrain.generation.TerrainGen;
|
||||
import electrosphere.game.server.terrain.models.ModificationList;
|
||||
import electrosphere.game.server.terrain.models.TerrainModel;
|
||||
import electrosphere.game.server.terrain.models.TerrainModification;
|
||||
import electrosphere.util.FileLoadingUtils;
|
||||
import electrosphere.util.Utilities;
|
||||
import java.io.File;
|
||||
@ -39,7 +41,7 @@ public class ServerTerrainManager {
|
||||
//While we incur a penalty with converting ints -> string, think this will
|
||||
//offset regenerating the array every time we want a new one
|
||||
int cacheSize = 50;
|
||||
HashMap<String, float[][]> elevationMapCache;
|
||||
HashMap<String, ServerTerrainChunk> elevationMapCache;
|
||||
ArrayList<String> elevationMapCacheContents;
|
||||
|
||||
|
||||
@ -98,34 +100,43 @@ public class ServerTerrainManager {
|
||||
return model.getElevationForChunk(x, y);
|
||||
}
|
||||
|
||||
public float[][] getAugmentedTerrainAtChunk(int x, int y){
|
||||
//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.getBicubicInterpolatedChunk(
|
||||
model.getRad5MacroValuesAtPosition(x, y),
|
||||
model.getRad5RandomizerValuesAtPosition(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;
|
||||
}
|
||||
} else {
|
||||
//THIS FIRES IF THERE IS AN ARENA WORLD RUNNING
|
||||
return new float[dynamicInterpolationRatio + 1][dynamicInterpolationRatio + 1];
|
||||
}
|
||||
}
|
||||
// public ServerTerrainChunk getAugmentedTerrainAtChunk(int x, int y){
|
||||
// //THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING
|
||||
// if(model != null){
|
||||
// String key = getKey(x,y);
|
||||
// ServerTerrainChunk returnedChunk;
|
||||
// if(elevationMapCache.containsKey(key)){
|
||||
// elevationMapCacheContents.remove(key);
|
||||
// elevationMapCacheContents.add(0, key);
|
||||
// returnedChunk = elevationMapCache.get(key);
|
||||
// return returnedChunk;
|
||||
// } else {
|
||||
// float[][] macroValues = model.getRad5MacroValuesAtPosition(x, y);
|
||||
// long[][] randomizer = model.getRad5RandomizerValuesAtPosition(x, y);
|
||||
// float[][] heightmap = TerrainInterpolator.getBicubicInterpolatedChunk(
|
||||
// macroValues,
|
||||
// randomizer,
|
||||
// model.getDynamicInterpolationRatio(),
|
||||
// model.getRandomDampener()
|
||||
// );
|
||||
// ModificationList modificationList = model.getModifications(x, y);
|
||||
// for(TerrainModification modification : modificationList.getModifications()){
|
||||
// modification.applyToHeightfield(heightmap);
|
||||
// }
|
||||
// if(elevationMapCacheContents.size() > cacheSize){
|
||||
// String oldChunk = elevationMapCacheContents.remove(elevationMapCacheContents.size() - 1);
|
||||
// elevationMapCache.remove(oldChunk);
|
||||
// }
|
||||
// returnedChunk = new ServerTerrainChunk(x, y, heightmap, macroValues, randomizer);
|
||||
// elevationMapCache.put(key, returnedChunk);
|
||||
// elevationMapCacheContents.add(key);
|
||||
// return returnedChunk;
|
||||
// }
|
||||
// } else {
|
||||
// //THIS FIRES IF THERE IS AN ARENA WORLD RUNNING
|
||||
// return ServerTerrainChunk.getArenaChunk(dynamicInterpolationRatio + 1);
|
||||
// }
|
||||
// }
|
||||
|
||||
public float getHeightAtPosition(float x, float y){
|
||||
//get chunk coordinate space of input x,y
|
||||
@ -135,7 +146,7 @@ public class ServerTerrainManager {
|
||||
float localX = x - chunkX * dynamicInterpolationRatio;
|
||||
float localY = y - chunkY * dynamicInterpolationRatio;
|
||||
//get chunk elevation map
|
||||
float[][] chunkElevationMap = getAugmentedTerrainAtChunk(chunkX,chunkY);
|
||||
float[][] chunkElevationMap = getChunk(chunkX,chunkY).heightMap;
|
||||
//floored variants of local values
|
||||
int localXf = (int)Math.floor(localX);
|
||||
int localYf = (int)Math.floor(localY);
|
||||
@ -214,28 +225,88 @@ public class ServerTerrainManager {
|
||||
// }
|
||||
// }
|
||||
|
||||
public float[][] getRad5MacroValues(int x, int y){
|
||||
//THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING
|
||||
if(model != null){
|
||||
return model.getRad5MacroValuesAtPosition(x, y);
|
||||
} else {
|
||||
//THIS FIRES IF THERE IS AN ARENA WORLD RUNNING
|
||||
return new float[5][5];
|
||||
}
|
||||
}
|
||||
// public float[][] getRad5MacroValues(int x, int y){
|
||||
// //THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING
|
||||
// if(model != null){
|
||||
// return model.getRad5MacroValuesAtPosition(x, y);
|
||||
// } else {
|
||||
// //THIS FIRES IF THERE IS AN ARENA WORLD RUNNING
|
||||
// return new float[5][5];
|
||||
// }
|
||||
// }
|
||||
|
||||
public long[][] getRandomizer(int x, int y){
|
||||
//THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING
|
||||
if(model != null){
|
||||
return model.getRad5RandomizerValuesAtPosition(x, y);
|
||||
} else {
|
||||
//THIS FIRES IF THERE IS AN ARENA WORLD RUNNING
|
||||
return new long[5][5];
|
||||
}
|
||||
}
|
||||
// public long[][] getRandomizer(int x, int y){
|
||||
// //THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING
|
||||
// if(model != null){
|
||||
// return model.getRad5RandomizerValuesAtPosition(x, y);
|
||||
// } else {
|
||||
// //THIS FIRES IF THERE IS AN ARENA WORLD RUNNING
|
||||
// return new long[5][5];
|
||||
// }
|
||||
// }
|
||||
|
||||
public TerrainModel getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
public String getKey(int x, int y){
|
||||
return x + "-" + y;
|
||||
}
|
||||
|
||||
public ServerTerrainChunk getChunk(int x, int y){
|
||||
if(model != null){
|
||||
//THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING
|
||||
String key = getKey(x,y);
|
||||
ServerTerrainChunk returnedChunk;
|
||||
if(elevationMapCache.containsKey(key)){
|
||||
elevationMapCacheContents.remove(key);
|
||||
elevationMapCacheContents.add(0, key);
|
||||
returnedChunk = elevationMapCache.get(key);
|
||||
return returnedChunk;
|
||||
} else {
|
||||
float[][] macroValues = model.getRad5MacroValuesAtPosition(x, y);
|
||||
long[][] randomizer = model.getRad5RandomizerValuesAtPosition(x, y);
|
||||
float[][] heightmap = TerrainInterpolator.getBicubicInterpolatedChunk(
|
||||
macroValues,
|
||||
randomizer,
|
||||
model.getDynamicInterpolationRatio(),
|
||||
model.getRandomDampener()
|
||||
);
|
||||
ModificationList modificationList = model.getModifications(x, y);
|
||||
if(modificationList != null){
|
||||
for(TerrainModification modification : modificationList.getModifications()){
|
||||
modification.applyToHeightfield(heightmap);
|
||||
}
|
||||
}
|
||||
if(elevationMapCacheContents.size() > cacheSize){
|
||||
String oldChunk = elevationMapCacheContents.remove(elevationMapCacheContents.size() - 1);
|
||||
elevationMapCache.remove(oldChunk);
|
||||
}
|
||||
returnedChunk = new ServerTerrainChunk(x, y, heightmap, macroValues, randomizer);
|
||||
elevationMapCache.put(key, returnedChunk);
|
||||
elevationMapCacheContents.add(key);
|
||||
return returnedChunk;
|
||||
}
|
||||
} else {
|
||||
//THIS FIRES IF THERE IS AN ARENA WORLD RUNNING
|
||||
String key = getKey(x,y);
|
||||
ServerTerrainChunk returnedChunk;
|
||||
if(elevationMapCache.containsKey(key)){
|
||||
elevationMapCacheContents.remove(key);
|
||||
elevationMapCacheContents.add(0, key);
|
||||
returnedChunk = elevationMapCache.get(key);
|
||||
return returnedChunk;
|
||||
} else {
|
||||
returnedChunk = ServerTerrainChunk.getArenaChunk(dynamicInterpolationRatio + 1);
|
||||
elevationMapCache.put(key, returnedChunk);
|
||||
elevationMapCacheContents.add(key);
|
||||
return returnedChunk;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void deformTerrainAtLocationToValue(int worldX, int worldY, int locationX, int locationY, float value){
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,22 @@
|
||||
package electrosphere.game.server.terrain.models;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author amaterasu
|
||||
*/
|
||||
public class ModificationList {
|
||||
|
||||
List<TerrainModification> modifications = new ArrayList();
|
||||
|
||||
public List<TerrainModification> getModifications() {
|
||||
return modifications;
|
||||
}
|
||||
|
||||
public void addModification(TerrainModification modification){
|
||||
modifications.add(modification);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,5 +1,8 @@
|
||||
package electrosphere.game.server.terrain.models;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class TerrainModel {
|
||||
@ -14,9 +17,11 @@ public class TerrainModel {
|
||||
float realMountainThreshold;
|
||||
float realOceanThreshold;
|
||||
|
||||
HashMap<String,ModificationList> modifications;
|
||||
|
||||
|
||||
TerrainModel() {
|
||||
|
||||
this.modifications = new HashMap();
|
||||
}
|
||||
|
||||
public TerrainModel(
|
||||
@ -34,7 +39,7 @@ public class TerrainModel {
|
||||
this.chunkRandomizer = chunkRandomizer;
|
||||
this.realMountainThreshold = realMountainThreshold;
|
||||
this.realOceanThreshold = realOceanThreshold;
|
||||
|
||||
this.modifications = new HashMap();
|
||||
}
|
||||
|
||||
public static TerrainModel constructTerrainModel(int dimension, int dynamicInterpolationRatio){
|
||||
@ -366,4 +371,28 @@ public class TerrainModel {
|
||||
return realOceanThreshold;
|
||||
}
|
||||
|
||||
public String getModificationKey(int x, int y){
|
||||
return x + "-" + y;
|
||||
}
|
||||
|
||||
public void addModification(TerrainModification modification){
|
||||
String key = getModificationKey(modification.worldX,modification.worldY);
|
||||
ModificationList list;
|
||||
if(!modifications.containsKey(key)){
|
||||
list = new ModificationList();
|
||||
modifications.put(key, list);
|
||||
} else {
|
||||
list = modifications.get(key);
|
||||
}
|
||||
list.addModification(modification);
|
||||
}
|
||||
|
||||
public boolean containsModificationsAtCoord(int worldX, int worldY){
|
||||
return modifications.containsKey(getModificationKey(worldX, worldY));
|
||||
}
|
||||
|
||||
public ModificationList getModifications(int worldX, int worldY){
|
||||
return modifications.get(getModificationKey(worldX, worldY));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
package electrosphere.game.server.terrain.models;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author amaterasu
|
||||
*/
|
||||
public class TerrainModification {
|
||||
int worldX;
|
||||
int worldY;
|
||||
int locationX;
|
||||
int locationY;
|
||||
float value;
|
||||
|
||||
public TerrainModification(int worldX, int worldY, int locationX, int locationY, float value) {
|
||||
this.worldX = worldX;
|
||||
this.worldY = worldY;
|
||||
this.locationX = locationX;
|
||||
this.locationY = locationY;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getWorldX() {
|
||||
return worldX;
|
||||
}
|
||||
|
||||
public int getWorldY() {
|
||||
return worldY;
|
||||
}
|
||||
|
||||
public int getLocationX() {
|
||||
return locationX;
|
||||
}
|
||||
|
||||
public int getLocationY() {
|
||||
return locationY;
|
||||
}
|
||||
|
||||
public float getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public float[][] applyToHeightfield(float[][] heightfield){
|
||||
heightfield[locationX][locationY] = value;
|
||||
return heightfield;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -14,6 +14,7 @@ import electrosphere.entity.types.hitbox.HitboxUtils;
|
||||
import electrosphere.entity.types.item.ItemUtils;
|
||||
import electrosphere.entity.types.attach.AttachUtils;
|
||||
import electrosphere.engine.LoadingThread;
|
||||
import electrosphere.game.client.ClientFunctions;
|
||||
import electrosphere.game.state.MicroSimulation;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.renderer.RenderingEngine;
|
||||
@ -188,6 +189,7 @@ public class Main {
|
||||
if(Globals.microSimulation != null && Globals.microSimulation.isReady()){
|
||||
Globals.microSimulation.simulate();
|
||||
}
|
||||
ClientFunctions.runClientFunctions();
|
||||
|
||||
|
||||
///
|
||||
|
||||
@ -140,11 +140,19 @@ public class ClientProtocol {
|
||||
break;
|
||||
case MACROVALUE:
|
||||
Globals.clientTerrainManager.attachWorldMessage(message);
|
||||
Globals.clientTerrainManager.handleMessages();
|
||||
break;
|
||||
case SPAWNPOSITION:
|
||||
Globals.spawnPoint.set(new Vector3f(message.getrealLocationX(),0,message.getrealLocationY()));
|
||||
break;
|
||||
case CHUNKLOADSTART:
|
||||
Globals.clientTerrainManager.attachWorldMessage(message);
|
||||
break;
|
||||
case HEIGHTMAPMODIFICATION:
|
||||
Globals.clientTerrainManager.attachWorldMessage(message);
|
||||
break;
|
||||
default:
|
||||
LoggerInterface.loggerNetworking.WARNING("Client networking: Unhandled message of type: " + message.getMessageSubtype());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -49,9 +49,9 @@ ENTITY_MESSAGE,
|
||||
rVal = WorldMessage.parseMetadataMessage(byteStream);
|
||||
}
|
||||
break;
|
||||
case TypeBytes.WORLD_MESSAGE_TYPE_REQUESTMACROVALUES:
|
||||
case TypeBytes.WORLD_MESSAGE_TYPE_REQUESTCHUNK:
|
||||
if(WorldMessage.canParseMessage(byteStream,secondByte)){
|
||||
rVal = WorldMessage.parseRequestMacroValuesMessage(byteStream);
|
||||
rVal = WorldMessage.parseRequestChunkMessage(byteStream);
|
||||
}
|
||||
break;
|
||||
case TypeBytes.WORLD_MESSAGE_TYPE_UPDATE:
|
||||
@ -59,11 +59,21 @@ ENTITY_MESSAGE,
|
||||
rVal = WorldMessage.parseUpdateMessage(byteStream);
|
||||
}
|
||||
break;
|
||||
case TypeBytes.WORLD_MESSAGE_TYPE_CHUNKLOADSTART:
|
||||
if(WorldMessage.canParseMessage(byteStream,secondByte)){
|
||||
rVal = WorldMessage.parsechunkLoadStartMessage(byteStream);
|
||||
}
|
||||
break;
|
||||
case TypeBytes.WORLD_MESSAGE_TYPE_MACROVALUE:
|
||||
if(WorldMessage.canParseMessage(byteStream,secondByte)){
|
||||
rVal = WorldMessage.parseMacroValueMessage(byteStream);
|
||||
}
|
||||
break;
|
||||
case TypeBytes.WORLD_MESSAGE_TYPE_HEIGHTMAPMODIFICATION:
|
||||
if(WorldMessage.canParseMessage(byteStream,secondByte)){
|
||||
rVal = WorldMessage.parseheightMapModificationMessage(byteStream);
|
||||
}
|
||||
break;
|
||||
case TypeBytes.WORLD_MESSAGE_TYPE_SPAWNPOSITION:
|
||||
if(WorldMessage.canParseMessage(byteStream,secondByte)){
|
||||
rVal = WorldMessage.parseSpawnPositionMessage(byteStream);
|
||||
|
||||
@ -21,17 +21,21 @@ Message categories
|
||||
World subcategories
|
||||
*/
|
||||
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_REQUESTCHUNK = 1;
|
||||
public static final byte WORLD_MESSAGE_TYPE_UPDATE = 2;
|
||||
public static final byte WORLD_MESSAGE_TYPE_MACROVALUE = 3;
|
||||
public static final byte WORLD_MESSAGE_TYPE_SPAWNPOSITION = 4;
|
||||
public static final byte WORLD_MESSAGE_TYPE_CHUNKLOADSTART = 3;
|
||||
public static final byte WORLD_MESSAGE_TYPE_MACROVALUE = 4;
|
||||
public static final byte WORLD_MESSAGE_TYPE_HEIGHTMAPMODIFICATION = 5;
|
||||
public static final byte WORLD_MESSAGE_TYPE_SPAWNPOSITION = 6;
|
||||
/*
|
||||
World packet sizes
|
||||
*/
|
||||
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_REQUESTCHUNK_SIZE = 10;
|
||||
public static final byte WORLD_MESSAGE_TYPE_UPDATE_SIZE = 10;
|
||||
public static final byte WORLD_MESSAGE_TYPE_CHUNKLOADSTART_SIZE = 14;
|
||||
public static final int WORLD_MESSAGE_TYPE_MACROVALUE_SIZE = 310;
|
||||
public static final byte WORLD_MESSAGE_TYPE_HEIGHTMAPMODIFICATION_SIZE = 22;
|
||||
public static final byte WORLD_MESSAGE_TYPE_SPAWNPOSITION_SIZE = 10;
|
||||
/*
|
||||
Player subcategories
|
||||
|
||||
@ -8,9 +8,11 @@ public class WorldMessage extends NetworkMessage {
|
||||
|
||||
public enum WorldMessageType {
|
||||
METADATA,
|
||||
REQUESTMACROVALUES,
|
||||
REQUESTCHUNK,
|
||||
UPDATE,
|
||||
CHUNKLOADSTART,
|
||||
MACROVALUE,
|
||||
HEIGHTMAPMODIFICATION,
|
||||
SPAWNPOSITION,
|
||||
}
|
||||
|
||||
@ -22,6 +24,9 @@ public class WorldMessage extends NetworkMessage {
|
||||
int worldMinY;
|
||||
int worldMaxX;
|
||||
int worldMaxY;
|
||||
int worldX;
|
||||
int worldY;
|
||||
float value;
|
||||
int locationX;
|
||||
int locationY;
|
||||
float realLocationX;
|
||||
@ -142,6 +147,30 @@ public class WorldMessage extends NetworkMessage {
|
||||
this.worldMaxY = worldMaxY;
|
||||
}
|
||||
|
||||
public int getworldX() {
|
||||
return worldX;
|
||||
}
|
||||
|
||||
public void setworldX(int worldX) {
|
||||
this.worldX = worldX;
|
||||
}
|
||||
|
||||
public int getworldY() {
|
||||
return worldY;
|
||||
}
|
||||
|
||||
public void setworldY(int worldY) {
|
||||
this.worldY = worldY;
|
||||
}
|
||||
|
||||
public float getvalue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setvalue(float value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getlocationX() {
|
||||
return locationX;
|
||||
}
|
||||
@ -587,8 +616,8 @@ public class WorldMessage extends NetworkMessage {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
case TypeBytes.WORLD_MESSAGE_TYPE_REQUESTMACROVALUES:
|
||||
if(byteStream.size() >= TypeBytes.WORLD_MESSAGE_TYPE_REQUESTMACROVALUES_SIZE){
|
||||
case TypeBytes.WORLD_MESSAGE_TYPE_REQUESTCHUNK:
|
||||
if(byteStream.size() >= TypeBytes.WORLD_MESSAGE_TYPE_REQUESTCHUNK_SIZE){
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -599,12 +628,24 @@ public class WorldMessage extends NetworkMessage {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
case TypeBytes.WORLD_MESSAGE_TYPE_CHUNKLOADSTART:
|
||||
if(byteStream.size() >= TypeBytes.WORLD_MESSAGE_TYPE_CHUNKLOADSTART_SIZE){
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
case TypeBytes.WORLD_MESSAGE_TYPE_MACROVALUE:
|
||||
if(byteStream.size() >= TypeBytes.WORLD_MESSAGE_TYPE_MACROVALUE_SIZE){
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
case TypeBytes.WORLD_MESSAGE_TYPE_HEIGHTMAPMODIFICATION:
|
||||
if(byteStream.size() >= TypeBytes.WORLD_MESSAGE_TYPE_HEIGHTMAPMODIFICATION_SIZE){
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
case TypeBytes.WORLD_MESSAGE_TYPE_SPAWNPOSITION:
|
||||
if(byteStream.size() >= TypeBytes.WORLD_MESSAGE_TYPE_SPAWNPOSITION_SIZE){
|
||||
return true;
|
||||
@ -641,18 +682,18 @@ public class WorldMessage extends NetworkMessage {
|
||||
return rVal;
|
||||
}
|
||||
|
||||
public static WorldMessage parseRequestMacroValuesMessage(List<Byte> byteStream){
|
||||
WorldMessage rVal = new WorldMessage(WorldMessageType.REQUESTMACROVALUES);
|
||||
public static WorldMessage parseRequestChunkMessage(List<Byte> byteStream){
|
||||
WorldMessage rVal = new WorldMessage(WorldMessageType.REQUESTCHUNK);
|
||||
stripPacketHeader(byteStream);
|
||||
rVal.setlocationX(ByteStreamUtils.popIntFromByteQueue(byteStream));
|
||||
rVal.setlocationY(ByteStreamUtils.popIntFromByteQueue(byteStream));
|
||||
rVal.setworldX(ByteStreamUtils.popIntFromByteQueue(byteStream));
|
||||
rVal.setworldY(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);
|
||||
public static WorldMessage constructRequestChunkMessage(int worldX,int worldY){
|
||||
WorldMessage rVal = new WorldMessage(WorldMessageType.REQUESTCHUNK);
|
||||
rVal.setworldX(worldX);
|
||||
rVal.setworldY(worldY);
|
||||
rVal.serialize();
|
||||
return rVal;
|
||||
}
|
||||
@ -673,11 +714,29 @@ public class WorldMessage extends NetworkMessage {
|
||||
return rVal;
|
||||
}
|
||||
|
||||
public static WorldMessage parsechunkLoadStartMessage(List<Byte> byteStream){
|
||||
WorldMessage rVal = new WorldMessage(WorldMessageType.CHUNKLOADSTART);
|
||||
stripPacketHeader(byteStream);
|
||||
rVal.setworldX(ByteStreamUtils.popIntFromByteQueue(byteStream));
|
||||
rVal.setworldY(ByteStreamUtils.popIntFromByteQueue(byteStream));
|
||||
rVal.setvalue(ByteStreamUtils.popFloatFromByteQueue(byteStream));
|
||||
return rVal;
|
||||
}
|
||||
|
||||
public static WorldMessage constructchunkLoadStartMessage(int worldX,int worldY,float value){
|
||||
WorldMessage rVal = new WorldMessage(WorldMessageType.CHUNKLOADSTART);
|
||||
rVal.setworldX(worldX);
|
||||
rVal.setworldY(worldY);
|
||||
rVal.setvalue(value);
|
||||
rVal.serialize();
|
||||
return rVal;
|
||||
}
|
||||
|
||||
public static WorldMessage parseMacroValueMessage(List<Byte> byteStream){
|
||||
WorldMessage rVal = new WorldMessage(WorldMessageType.MACROVALUE);
|
||||
stripPacketHeader(byteStream);
|
||||
rVal.setlocationX(ByteStreamUtils.popIntFromByteQueue(byteStream));
|
||||
rVal.setlocationY(ByteStreamUtils.popIntFromByteQueue(byteStream));
|
||||
rVal.setworldX(ByteStreamUtils.popIntFromByteQueue(byteStream));
|
||||
rVal.setworldY(ByteStreamUtils.popIntFromByteQueue(byteStream));
|
||||
rVal.setmacroValue00(ByteStreamUtils.popFloatFromByteQueue(byteStream));
|
||||
rVal.setmacroValue01(ByteStreamUtils.popFloatFromByteQueue(byteStream));
|
||||
rVal.setmacroValue02(ByteStreamUtils.popFloatFromByteQueue(byteStream));
|
||||
@ -731,10 +790,10 @@ public class WorldMessage extends NetworkMessage {
|
||||
return rVal;
|
||||
}
|
||||
|
||||
public static WorldMessage constructMacroValueMessage(int locationX,int locationY,float macroValue00,float macroValue01,float macroValue02,float macroValue03,float macroValue04,float macroValue10,float macroValue11,float macroValue12,float macroValue13,float macroValue14,float macroValue20,float macroValue21,float macroValue22,float macroValue23,float macroValue24,float macroValue30,float macroValue31,float macroValue32,float macroValue33,float macroValue34,float macroValue40,float macroValue41,float macroValue42,float macroValue43,float macroValue44,long randomizerValue00,long randomizerValue01,long randomizerValue02,long randomizerValue03,long randomizerValue04,long randomizerValue10,long randomizerValue11,long randomizerValue12,long randomizerValue13,long randomizerValue14,long randomizerValue20,long randomizerValue21,long randomizerValue22,long randomizerValue23,long randomizerValue24,long randomizerValue30,long randomizerValue31,long randomizerValue32,long randomizerValue33,long randomizerValue34,long randomizerValue40,long randomizerValue41,long randomizerValue42,long randomizerValue43,long randomizerValue44){
|
||||
public static WorldMessage constructMacroValueMessage(int worldX,int worldY,float macroValue00,float macroValue01,float macroValue02,float macroValue03,float macroValue04,float macroValue10,float macroValue11,float macroValue12,float macroValue13,float macroValue14,float macroValue20,float macroValue21,float macroValue22,float macroValue23,float macroValue24,float macroValue30,float macroValue31,float macroValue32,float macroValue33,float macroValue34,float macroValue40,float macroValue41,float macroValue42,float macroValue43,float macroValue44,long randomizerValue00,long randomizerValue01,long randomizerValue02,long randomizerValue03,long randomizerValue04,long randomizerValue10,long randomizerValue11,long randomizerValue12,long randomizerValue13,long randomizerValue14,long randomizerValue20,long randomizerValue21,long randomizerValue22,long randomizerValue23,long randomizerValue24,long randomizerValue30,long randomizerValue31,long randomizerValue32,long randomizerValue33,long randomizerValue34,long randomizerValue40,long randomizerValue41,long randomizerValue42,long randomizerValue43,long randomizerValue44){
|
||||
WorldMessage rVal = new WorldMessage(WorldMessageType.MACROVALUE);
|
||||
rVal.setlocationX(locationX);
|
||||
rVal.setlocationY(locationY);
|
||||
rVal.setworldX(worldX);
|
||||
rVal.setworldY(worldY);
|
||||
rVal.setmacroValue00(macroValue00);
|
||||
rVal.setmacroValue01(macroValue01);
|
||||
rVal.setmacroValue02(macroValue02);
|
||||
@ -789,6 +848,28 @@ public class WorldMessage extends NetworkMessage {
|
||||
return rVal;
|
||||
}
|
||||
|
||||
public static WorldMessage parseheightMapModificationMessage(List<Byte> byteStream){
|
||||
WorldMessage rVal = new WorldMessage(WorldMessageType.HEIGHTMAPMODIFICATION);
|
||||
stripPacketHeader(byteStream);
|
||||
rVal.setvalue(ByteStreamUtils.popFloatFromByteQueue(byteStream));
|
||||
rVal.setworldX(ByteStreamUtils.popIntFromByteQueue(byteStream));
|
||||
rVal.setworldY(ByteStreamUtils.popIntFromByteQueue(byteStream));
|
||||
rVal.setlocationX(ByteStreamUtils.popIntFromByteQueue(byteStream));
|
||||
rVal.setlocationY(ByteStreamUtils.popIntFromByteQueue(byteStream));
|
||||
return rVal;
|
||||
}
|
||||
|
||||
public static WorldMessage constructheightMapModificationMessage(float value,int worldX,int worldY,int locationX,int locationY){
|
||||
WorldMessage rVal = new WorldMessage(WorldMessageType.HEIGHTMAPMODIFICATION);
|
||||
rVal.setvalue(value);
|
||||
rVal.setworldX(worldX);
|
||||
rVal.setworldY(worldY);
|
||||
rVal.setlocationX(locationX);
|
||||
rVal.setlocationY(locationY);
|
||||
rVal.serialize();
|
||||
return rVal;
|
||||
}
|
||||
|
||||
public static WorldMessage parseSpawnPositionMessage(List<Byte> byteStream){
|
||||
WorldMessage rVal = new WorldMessage(WorldMessageType.SPAWNPOSITION);
|
||||
stripPacketHeader(byteStream);
|
||||
@ -844,17 +925,17 @@ public class WorldMessage extends NetworkMessage {
|
||||
rawBytes[26+i] = intValues[i];
|
||||
}
|
||||
break;
|
||||
case REQUESTMACROVALUES:
|
||||
case REQUESTCHUNK:
|
||||
rawBytes = new byte[2+4+4];
|
||||
//message header
|
||||
rawBytes[0] = TypeBytes.MESSAGE_TYPE_WORLD;
|
||||
//entity messaage header
|
||||
rawBytes[1] = TypeBytes.WORLD_MESSAGE_TYPE_REQUESTMACROVALUES;
|
||||
intValues = ByteStreamUtils.serializeIntToBytes(locationX);
|
||||
rawBytes[1] = TypeBytes.WORLD_MESSAGE_TYPE_REQUESTCHUNK;
|
||||
intValues = ByteStreamUtils.serializeIntToBytes(worldX);
|
||||
for(int i = 0; i < 4; i++){
|
||||
rawBytes[2+i] = intValues[i];
|
||||
}
|
||||
intValues = ByteStreamUtils.serializeIntToBytes(locationY);
|
||||
intValues = ByteStreamUtils.serializeIntToBytes(worldY);
|
||||
for(int i = 0; i < 4; i++){
|
||||
rawBytes[6+i] = intValues[i];
|
||||
}
|
||||
@ -874,17 +955,35 @@ public class WorldMessage extends NetworkMessage {
|
||||
rawBytes[6+i] = intValues[i];
|
||||
}
|
||||
break;
|
||||
case CHUNKLOADSTART:
|
||||
rawBytes = new byte[2+4+4+4];
|
||||
//message header
|
||||
rawBytes[0] = TypeBytes.MESSAGE_TYPE_WORLD;
|
||||
//entity messaage header
|
||||
rawBytes[1] = TypeBytes.WORLD_MESSAGE_TYPE_CHUNKLOADSTART;
|
||||
intValues = ByteStreamUtils.serializeIntToBytes(worldX);
|
||||
for(int i = 0; i < 4; i++){
|
||||
rawBytes[2+i] = intValues[i];
|
||||
}
|
||||
intValues = ByteStreamUtils.serializeIntToBytes(worldY);
|
||||
for(int i = 0; i < 4; i++){
|
||||
rawBytes[6+i] = intValues[i];
|
||||
}
|
||||
intValues = ByteStreamUtils.serializeFloatToBytes(value);
|
||||
for(int i = 0; i < 4; i++){
|
||||
rawBytes[10+i] = intValues[i];
|
||||
} break;
|
||||
case MACROVALUE:
|
||||
rawBytes = new byte[2+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8];
|
||||
//message header
|
||||
rawBytes[0] = TypeBytes.MESSAGE_TYPE_WORLD;
|
||||
//entity messaage header
|
||||
rawBytes[1] = TypeBytes.WORLD_MESSAGE_TYPE_MACROVALUE;
|
||||
intValues = ByteStreamUtils.serializeIntToBytes(locationX);
|
||||
intValues = ByteStreamUtils.serializeIntToBytes(worldX);
|
||||
for(int i = 0; i < 4; i++){
|
||||
rawBytes[2+i] = intValues[i];
|
||||
}
|
||||
intValues = ByteStreamUtils.serializeIntToBytes(locationY);
|
||||
intValues = ByteStreamUtils.serializeIntToBytes(worldY);
|
||||
for(int i = 0; i < 4; i++){
|
||||
rawBytes[6+i] = intValues[i];
|
||||
}
|
||||
@ -1064,6 +1163,32 @@ public class WorldMessage extends NetworkMessage {
|
||||
rawBytes[302+i] = intValues[i];
|
||||
}
|
||||
break;
|
||||
case HEIGHTMAPMODIFICATION:
|
||||
rawBytes = new byte[2+4+4+4+4+4];
|
||||
//message header
|
||||
rawBytes[0] = TypeBytes.MESSAGE_TYPE_WORLD;
|
||||
//entity messaage header
|
||||
rawBytes[1] = TypeBytes.WORLD_MESSAGE_TYPE_HEIGHTMAPMODIFICATION;
|
||||
intValues = ByteStreamUtils.serializeFloatToBytes(value);
|
||||
for(int i = 0; i < 4; i++){
|
||||
rawBytes[2+i] = intValues[i];
|
||||
} intValues = ByteStreamUtils.serializeIntToBytes(worldX);
|
||||
for(int i = 0; i < 4; i++){
|
||||
rawBytes[6+i] = intValues[i];
|
||||
}
|
||||
intValues = ByteStreamUtils.serializeIntToBytes(worldY);
|
||||
for(int i = 0; i < 4; i++){
|
||||
rawBytes[10+i] = intValues[i];
|
||||
}
|
||||
intValues = ByteStreamUtils.serializeIntToBytes(locationX);
|
||||
for(int i = 0; i < 4; i++){
|
||||
rawBytes[14+i] = intValues[i];
|
||||
}
|
||||
intValues = ByteStreamUtils.serializeIntToBytes(locationY);
|
||||
for(int i = 0; i < 4; i++){
|
||||
rawBytes[18+i] = intValues[i];
|
||||
}
|
||||
break;
|
||||
case SPAWNPOSITION:
|
||||
rawBytes = new byte[2+4+4];
|
||||
//message header
|
||||
|
||||
@ -2,6 +2,8 @@ package electrosphere.net.server;
|
||||
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.types.creature.CreatureUtils;
|
||||
import electrosphere.game.server.terrain.manager.ServerTerrainChunk;
|
||||
import electrosphere.game.server.terrain.models.TerrainModification;
|
||||
import electrosphere.main.Globals;
|
||||
import electrosphere.net.parser.net.message.EntityMessage;
|
||||
import electrosphere.net.parser.net.message.NetworkMessage;
|
||||
@ -58,7 +60,7 @@ public class ServerProtocol {
|
||||
|
||||
void handleWorldMessage(WorldMessage message){
|
||||
switch(message.getMessageSubtype()){
|
||||
case REQUESTMACROVALUES:
|
||||
case REQUESTCHUNK:
|
||||
/*
|
||||
int locationX,
|
||||
int locationY,
|
||||
@ -81,12 +83,23 @@ public class ServerProtocol {
|
||||
long randomizerValue21,
|
||||
long randomizerValue22
|
||||
*/
|
||||
float[][] macroValues = Globals.serverTerrainManager.getRad5MacroValues(message.getlocationX(), message.getlocationY());
|
||||
long[][] randomizer = Globals.serverTerrainManager.getRandomizer(message.getlocationX(), message.getlocationY());
|
||||
|
||||
ServerTerrainChunk chunk = Globals.serverTerrainManager.getChunk(message.getworldX(), message.getworldY());
|
||||
|
||||
float[][] macroValues = chunk.getMacroValues();//Globals.serverTerrainManager.getRad5MacroValues(message.getworldX(), message.getworldY());
|
||||
|
||||
long[][] randomizer = chunk.getRandomizer();//Globals.serverTerrainManager.getRandomizer(message.getworldX(), message.getworldY());
|
||||
|
||||
int numMessages = 2 + chunk.getModifications().size();
|
||||
|
||||
connectionHandler.addMessagetoOutgoingQueue(
|
||||
WorldMessage.constructchunkLoadStartMessage(message.getworldX(), message.getworldY(), numMessages)
|
||||
);
|
||||
|
||||
connectionHandler.addMessagetoOutgoingQueue(
|
||||
WorldMessage.constructMacroValueMessage(
|
||||
message.getlocationX(),
|
||||
message.getlocationY(),
|
||||
message.getworldX(),
|
||||
message.getworldY(),
|
||||
|
||||
|
||||
macroValues[0][0],
|
||||
@ -143,6 +156,18 @@ public class ServerProtocol {
|
||||
randomizer[4][4]
|
||||
)
|
||||
);
|
||||
|
||||
for(TerrainModification modification : chunk.getModifications()){
|
||||
connectionHandler.addMessagetoOutgoingQueue(
|
||||
WorldMessage.constructheightMapModificationMessage(
|
||||
modification.getValue(),
|
||||
modification.getWorldX(),
|
||||
modification.getWorldY(),
|
||||
modification.getLocationX(),
|
||||
modification.getLocationY()
|
||||
)
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,6 +56,18 @@
|
||||
"name" : "worldMaxY",
|
||||
"type" : "FIXED_INT"
|
||||
},
|
||||
{
|
||||
"name" : "worldX",
|
||||
"type" : "FIXED_INT"
|
||||
},
|
||||
{
|
||||
"name" : "worldY",
|
||||
"type" : "FIXED_INT"
|
||||
},
|
||||
{
|
||||
"name" : "value",
|
||||
"type" : "FIXED_FLOAT"
|
||||
},
|
||||
|
||||
|
||||
|
||||
@ -302,10 +314,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"messageName" : "RequestMacroValues",
|
||||
"messageName" : "RequestChunk",
|
||||
"data" : [
|
||||
"locationX",
|
||||
"locationY"
|
||||
"worldX",
|
||||
"worldY"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -315,11 +327,19 @@
|
||||
"locationY"
|
||||
]
|
||||
},
|
||||
{
|
||||
"messageName" : "chunkLoadStart",
|
||||
"data" : [
|
||||
"worldX",
|
||||
"worldY",
|
||||
"value"
|
||||
]
|
||||
},
|
||||
{
|
||||
"messageName" : "MacroValue",
|
||||
"data" : [
|
||||
"locationX",
|
||||
"locationY",
|
||||
"worldX",
|
||||
"worldY",
|
||||
"macroValue00",
|
||||
"macroValue01",
|
||||
"macroValue02",
|
||||
@ -372,6 +392,16 @@
|
||||
"randomizerValue44"
|
||||
]
|
||||
},
|
||||
{
|
||||
"messageName" : "heightMapModification",
|
||||
"data" : [
|
||||
"value",
|
||||
"worldX",
|
||||
"worldY",
|
||||
"locationX",
|
||||
"locationY"
|
||||
]
|
||||
},
|
||||
{
|
||||
"messageName" : "SpawnPosition",
|
||||
"data" : [
|
||||
|
||||
Loading…
Reference in New Issue
Block a user