Server side terrain deformation

This commit is contained in:
austin 2021-07-25 21:51:01 -04:00
parent b5a0987ea1
commit b5743b3a1f
26 changed files with 867 additions and 164 deletions

Binary file not shown.

BIN
assets/Models/wheat2.fbx Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
assets/Textures/wheat2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

View File

@ -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));
}

View 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();
}
}
}

View File

@ -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;
}
}

View 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;
}
}

View File

@ -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){

View 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;
}
}

View 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));
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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){
}
}

View File

@ -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);
}
}

View File

@ -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));
}
}

View File

@ -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;
}
}

View File

@ -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();
///

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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" : [