Compare commits
2 Commits
7ab0debc45
...
db8ad7d10a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db8ad7d10a | ||
|
|
bfd7690403 |
5
assets/Shaders/shaderlib/shaderlib.glsl
Normal file
5
assets/Shaders/shaderlib/shaderlib.glsl
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
//courtesy https://stackoverflow.com/a/4275343
|
||||||
|
float rand(vec2 co){
|
||||||
|
return fract(sin(dot(co, vec2(12.9898, 78.233))) * 43758.5453);
|
||||||
|
}
|
||||||
@ -1,3 +1,3 @@
|
|||||||
#maven.buildNumber.plugin properties file
|
#maven.buildNumber.plugin properties file
|
||||||
#Sun Mar 17 09:54:23 EDT 2024
|
#Tue Mar 19 19:54:15 EDT 2024
|
||||||
buildNumber=75
|
buildNumber=77
|
||||||
|
|||||||
@ -41,6 +41,8 @@
|
|||||||
|
|
||||||
## Ruins
|
## Ruins
|
||||||
|
|
||||||
|
## Light Valley
|
||||||
|
Valley with lights shooting around the sky from projectors placed sporadically around the valley, tie into lore and provide some kind of function (portal controller or something?)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -287,3 +289,17 @@ Plains with lots of fire
|
|||||||
## Thunder Planes
|
## Thunder Planes
|
||||||
Constant Thunderstorms and lots of lightning strikes
|
Constant Thunderstorms and lots of lightning strikes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Sky Specific
|
||||||
|
|
||||||
|
## Sky Reefs
|
||||||
|
Full of kelp dangling from island, lots of sea-themed flying creatures
|
||||||
|
|
||||||
|
|||||||
@ -5,3 +5,8 @@
|
|||||||
|
|
||||||
### "Black Hole" Zone
|
### "Black Hole" Zone
|
||||||
Zone with a big magical fire in the center or something like that. IE it's a huge pit and the zone you play in is around this pit.
|
Zone with a big magical fire in the center or something like that. IE it's a huge pit and the zone you play in is around this pit.
|
||||||
|
|
||||||
|
### Solitairy Giant
|
||||||
|
Enclosed zone centered around a silent giant performing some toil (walking in circles around the periphery? Moving boulders? idk)
|
||||||
|
Ambient audio effect of him doing work the whole time
|
||||||
|
|
||||||
|
|||||||
@ -181,6 +181,17 @@ Fix Character creation preview not working
|
|||||||
|
|
||||||
Clean up main method/class
|
Clean up main method/class
|
||||||
|
|
||||||
|
Shader library system
|
||||||
|
- Abiltiy to include the shader library in individual files (ie implement #include)
|
||||||
|
|
||||||
|
Level loading/saving + Basic Editor
|
||||||
|
- Spin up voxel level (think arena mode)
|
||||||
|
- Save voxel level
|
||||||
|
- Basic editor functionality
|
||||||
|
- Menu of types of entities to spawn
|
||||||
|
- Button to spawn them at cursor
|
||||||
|
|
||||||
|
|
||||||
Transvoxel Algorithm
|
Transvoxel Algorithm
|
||||||
Client Terrain Entity Management (specifically creation/teardown for client)
|
Client Terrain Entity Management (specifically creation/teardown for client)
|
||||||
- Also queries for far out chunks to load far away terrain
|
- Also queries for far out chunks to load far away terrain
|
||||||
|
|||||||
@ -201,6 +201,15 @@
|
|||||||
"worldZ",
|
"worldZ",
|
||||||
"chunkData"
|
"chunkData"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"messageName" : "updateFluidData",
|
||||||
|
"data" : [
|
||||||
|
"worldX",
|
||||||
|
"worldY",
|
||||||
|
"worldZ",
|
||||||
|
"chunkData"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,10 +25,6 @@ public class FluidChunkData {
|
|||||||
float[][][] velocityY;
|
float[][][] velocityY;
|
||||||
float[][][] velocityZ;
|
float[][][] velocityZ;
|
||||||
|
|
||||||
//the list of positions modified since the last call to resetModifiedPositions
|
|
||||||
//Used in DrawCell to keep track of which positions to invalidate
|
|
||||||
Set<String> modifiedSinceLastGeneration = new HashSet<String>();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the voxel weight array in this container
|
* Gets the voxel weight array in this container
|
||||||
@ -43,43 +39,10 @@ public class FluidChunkData {
|
|||||||
* @param voxelWeight The voxel weight array
|
* @param voxelWeight The voxel weight array
|
||||||
*/
|
*/
|
||||||
public void setVoxelWeight(float[][][] voxelWeight){
|
public void setVoxelWeight(float[][][] voxelWeight){
|
||||||
//mark changed cells
|
|
||||||
if(this.voxelWeight != null){
|
|
||||||
for(int x = 0; x < CHUNK_SIZE; x++){
|
|
||||||
for(int y = 0; y < CHUNK_SIZE; y++){
|
|
||||||
for(int z = 0; z < CHUNK_SIZE; z++){
|
|
||||||
if(voxelWeight[x][y][z] != this.voxelWeight[x][y][z]){
|
|
||||||
String key = getVoxelPositionKey(new Vector3i(x,y,z));
|
|
||||||
if(!modifiedSinceLastGeneration.contains(key)){
|
|
||||||
modifiedSinceLastGeneration.add(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//update data
|
//update data
|
||||||
this.voxelWeight = voxelWeight;
|
this.voxelWeight = voxelWeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Updates the value of a single voxel in the chunk
|
|
||||||
// * @param localX The local position X
|
|
||||||
// * @param localY The local position Y
|
|
||||||
// * @param localZ The local position Z
|
|
||||||
// * @param weight The weight to set it to
|
|
||||||
// * @param type The type to set the voxel to
|
|
||||||
// */
|
|
||||||
// public void updatePosition(int localX, int localY, int localZ, float weight, int type){
|
|
||||||
// voxelWeight[localX][localY][localZ] = weight;
|
|
||||||
// voxelType[localX][localY][localZ] = type;
|
|
||||||
// //store as modified in cache
|
|
||||||
// String key = getVoxelPositionKey(new Vector3i(localX,localY,localZ));
|
|
||||||
// if(!modifiedSinceLastGeneration.contains(key)){
|
|
||||||
// modifiedSinceLastGeneration.add(key);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the weight of a voxel at a poisiton
|
* Gets the weight of a voxel at a poisiton
|
||||||
* @param localPosition The local position
|
* @param localPosition The local position
|
||||||
@ -94,27 +57,7 @@ public class FluidChunkData {
|
|||||||
* @return The weight of the specified voxel
|
* @return The weight of the specified voxel
|
||||||
*/
|
*/
|
||||||
public float getWeight(int x, int y, int z){
|
public float getWeight(int x, int y, int z){
|
||||||
return voxelWeight[z][y][z];
|
return voxelWeight[x][y][z];
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets the cache of modified positions
|
|
||||||
*/
|
|
||||||
public void resetModifiedPositions(){
|
|
||||||
this.modifiedSinceLastGeneration.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the set of all modified positions since the last call to resetModifiedPositions
|
|
||||||
* @return The set of all modified positions
|
|
||||||
*/
|
|
||||||
public Set<Vector3i> getModifiedPositions(){
|
|
||||||
Set<Vector3i> rVal = new HashSet<Vector3i>();
|
|
||||||
for(String key : modifiedSinceLastGeneration){
|
|
||||||
String[] split = key.split("_");
|
|
||||||
rVal.add(new Vector3i(Integer.parseInt(split[0]),Integer.parseInt(split[1]),Integer.parseInt(split[2])));
|
|
||||||
}
|
|
||||||
return rVal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -65,7 +65,7 @@ public class FluidCell {
|
|||||||
rVal.data = data;
|
rVal.data = data;
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a drawable entity based on this chunk
|
* Generates a drawable entity based on this chunk
|
||||||
*/
|
*/
|
||||||
@ -76,7 +76,7 @@ public class FluidCell {
|
|||||||
|
|
||||||
fillInData();
|
fillInData();
|
||||||
|
|
||||||
modelEntity = FluidChunk.clientCreateFluidChunkEntity(data.getVoxelWeight());
|
modelEntity = FluidChunk.clientCreateFluidChunkEntity(weights);
|
||||||
|
|
||||||
ClientEntityUtils.initiallyPositionEntity(modelEntity, getRealPos());
|
ClientEntityUtils.initiallyPositionEntity(modelEntity, getRealPos());
|
||||||
}
|
}
|
||||||
@ -110,6 +110,9 @@ public class FluidCell {
|
|||||||
* Fills in the internal arrays of data for generate terrain models
|
* Fills in the internal arrays of data for generate terrain models
|
||||||
*/
|
*/
|
||||||
private void fillInData(){
|
private void fillInData(){
|
||||||
|
if(worldPos.x == 1 && worldPos.y == 0 && worldPos.z == 0){
|
||||||
|
System.out.println("aaaa");
|
||||||
|
}
|
||||||
//
|
//
|
||||||
//fill in data
|
//fill in data
|
||||||
//
|
//
|
||||||
@ -131,6 +134,12 @@ public class FluidCell {
|
|||||||
weights[ServerTerrainChunk.CHUNK_DIMENSION][i][j] = currentChunk.getWeight(0, i, j);
|
weights[ServerTerrainChunk.CHUNK_DIMENSION][i][j] = currentChunk.getWeight(0, i, j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
||||||
|
for(int j = 0; j < ServerTerrainChunk.CHUNK_DIMENSION; j++){
|
||||||
|
weights[ServerTerrainChunk.CHUNK_DIMENSION][i][j] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
||||||
@ -148,6 +157,12 @@ public class FluidCell {
|
|||||||
weights[i][ServerTerrainChunk.CHUNK_DIMENSION][j] = currentChunk.getWeight(i, 0, j);
|
weights[i][ServerTerrainChunk.CHUNK_DIMENSION][j] = currentChunk.getWeight(i, 0, j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
||||||
|
for(int j = 0; j < ServerTerrainChunk.CHUNK_DIMENSION; j++){
|
||||||
|
weights[i][ServerTerrainChunk.CHUNK_DIMENSION][j] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
||||||
@ -165,6 +180,12 @@ public class FluidCell {
|
|||||||
weights[i][j][ServerTerrainChunk.CHUNK_DIMENSION] = currentChunk.getWeight(i, j, 0);
|
weights[i][j][ServerTerrainChunk.CHUNK_DIMENSION] = currentChunk.getWeight(i, j, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
||||||
|
for(int j = 0; j < ServerTerrainChunk.CHUNK_DIMENSION; j++){
|
||||||
|
weights[i][j][ServerTerrainChunk.CHUNK_DIMENSION] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
||||||
@ -183,6 +204,10 @@ public class FluidCell {
|
|||||||
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
||||||
weights[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][i] = currentChunk.getWeight(0, 0, i);
|
weights[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][i] = currentChunk.getWeight(0, 0, i);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
||||||
|
weights[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][i] = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
||||||
@ -199,6 +224,10 @@ public class FluidCell {
|
|||||||
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
||||||
weights[ServerTerrainChunk.CHUNK_DIMENSION][i][ServerTerrainChunk.CHUNK_DIMENSION] = currentChunk.getWeight(0, i, 0);
|
weights[ServerTerrainChunk.CHUNK_DIMENSION][i][ServerTerrainChunk.CHUNK_DIMENSION] = currentChunk.getWeight(0, i, 0);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
||||||
|
weights[ServerTerrainChunk.CHUNK_DIMENSION][i][ServerTerrainChunk.CHUNK_DIMENSION] = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
||||||
@ -215,6 +244,10 @@ public class FluidCell {
|
|||||||
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
||||||
weights[i][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION] = currentChunk.getWeight(i, 0, 0);
|
weights[i][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION] = currentChunk.getWeight(i, 0, 0);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
||||||
|
weights[i][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION] = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
for(int i = 0; i < ServerTerrainChunk.CHUNK_DIMENSION; i++){
|
||||||
@ -222,15 +255,15 @@ public class FluidCell {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(
|
if(
|
||||||
worldPos.z + 1 < Globals.clientWorldData.getWorldDiscreteSize() &&
|
worldPos.x + 1 < Globals.clientWorldData.getWorldDiscreteSize() &&
|
||||||
worldPos.y + 1 < Globals.clientWorldData.getWorldDiscreteSize() &&
|
worldPos.y + 1 < Globals.clientWorldData.getWorldDiscreteSize() &&
|
||||||
worldPos.z + 1 < Globals.clientWorldData.getWorldDiscreteSize()
|
worldPos.z + 1 < Globals.clientWorldData.getWorldDiscreteSize()
|
||||||
){
|
){
|
||||||
currentChunk = Globals.clientFluidManager.getChunkDataAtWorldPoint(worldPos.x + 1, worldPos.y + 1, worldPos.z + 1);
|
currentChunk = Globals.clientFluidManager.getChunkDataAtWorldPoint(worldPos.x + 1, worldPos.y + 1, worldPos.z + 1);
|
||||||
if(currentChunk != null){
|
if(currentChunk != null){
|
||||||
if(currentChunk != null){
|
weights[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION] = currentChunk.getWeight(0, 0, 0);
|
||||||
weights[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION] = currentChunk.getWeight(0, 0, 0);
|
} else {
|
||||||
}
|
weights[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION] = -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
weights[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION] = -1;
|
weights[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION] = -1;
|
||||||
|
|||||||
@ -58,47 +58,24 @@ public class ClientFluidManager {
|
|||||||
messageQueue.remove(message);
|
messageQueue.remove(message);
|
||||||
switch(message.getMessageSubtype()){
|
switch(message.getMessageSubtype()){
|
||||||
case SENDFLUIDDATA: {
|
case SENDFLUIDDATA: {
|
||||||
float[][][] weights = new float[FluidChunkData.CHUNK_SIZE][FluidChunkData.CHUNK_SIZE][FluidChunkData.CHUNK_SIZE];
|
|
||||||
float[][][] velocityX = new float[FluidChunkData.CHUNK_SIZE][FluidChunkData.CHUNK_SIZE][FluidChunkData.CHUNK_SIZE];
|
|
||||||
float[][][] velocityY = new float[FluidChunkData.CHUNK_SIZE][FluidChunkData.CHUNK_SIZE][FluidChunkData.CHUNK_SIZE];
|
|
||||||
float[][][] velocityZ = new float[FluidChunkData.CHUNK_SIZE][FluidChunkData.CHUNK_SIZE][FluidChunkData.CHUNK_SIZE];
|
|
||||||
ByteBuffer buffer = ByteBuffer.wrap(message.getchunkData());
|
ByteBuffer buffer = ByteBuffer.wrap(message.getchunkData());
|
||||||
FloatBuffer floatBuffer = buffer.asFloatBuffer();
|
FluidChunkData data = parseFluidDataBuffer(buffer);
|
||||||
for(int x = 0; x < FluidChunkData.CHUNK_SIZE; x++){
|
|
||||||
for(int y = 0; y < FluidChunkData.CHUNK_SIZE; y++){
|
|
||||||
for(int z = 0; z < FluidChunkData.CHUNK_SIZE; z++){
|
|
||||||
weights[x][y][z] = floatBuffer.get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(int x = 0; x < FluidChunkData.CHUNK_SIZE; x++){
|
|
||||||
for(int y = 0; y < FluidChunkData.CHUNK_SIZE; y++){
|
|
||||||
for(int z = 0; z < FluidChunkData.CHUNK_SIZE; z++){
|
|
||||||
velocityX[x][y][z] = floatBuffer.get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(int x = 0; x < FluidChunkData.CHUNK_SIZE; x++){
|
|
||||||
for(int y = 0; y < FluidChunkData.CHUNK_SIZE; y++){
|
|
||||||
for(int z = 0; z < FluidChunkData.CHUNK_SIZE; z++){
|
|
||||||
velocityY[x][y][z] = floatBuffer.get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(int x = 0; x < FluidChunkData.CHUNK_SIZE; x++){
|
|
||||||
for(int y = 0; y < FluidChunkData.CHUNK_SIZE; y++){
|
|
||||||
for(int z = 0; z < FluidChunkData.CHUNK_SIZE; z++){
|
|
||||||
velocityZ[x][y][z] = floatBuffer.get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FluidChunkData data = new FluidChunkData();
|
|
||||||
data.setVoxelWeight(weights);
|
|
||||||
fluidCache.addChunkDataToCache(
|
fluidCache.addChunkDataToCache(
|
||||||
message.getworldX(), message.getworldY(), message.getworldZ(),
|
message.getworldX(), message.getworldY(), message.getworldZ(),
|
||||||
data
|
data
|
||||||
);
|
);
|
||||||
} break;
|
} break;
|
||||||
|
case UPDATEFLUIDDATA: {
|
||||||
|
ByteBuffer buffer = ByteBuffer.wrap(message.getchunkData());
|
||||||
|
FluidChunkData data = parseFluidDataBuffer(buffer);
|
||||||
|
fluidCache.addChunkDataToCache(
|
||||||
|
message.getworldX(), message.getworldY(), message.getworldZ(),
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if(Globals.fluidCellManager != null){
|
||||||
|
Globals.fluidCellManager.markUpdateable(message.getworldX(), message.getworldY(), message.getworldZ());
|
||||||
|
}
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
LoggerInterface.loggerEngine.WARNING("ClientFluidManager: unhandled network message of type" + message.getMessageSubtype());
|
LoggerInterface.loggerEngine.WARNING("ClientFluidManager: unhandled network message of type" + message.getMessageSubtype());
|
||||||
break;
|
break;
|
||||||
@ -172,5 +149,52 @@ public class ClientFluidManager {
|
|||||||
}
|
}
|
||||||
fluidChunkGenerationQueue.clear();
|
fluidChunkGenerationQueue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a byte buffer into a fluid data object
|
||||||
|
* @param buffer the buffer
|
||||||
|
* @return the object
|
||||||
|
*/
|
||||||
|
private FluidChunkData parseFluidDataBuffer(ByteBuffer buffer){
|
||||||
|
float[][][] weights = new float[FluidChunkData.CHUNK_SIZE][FluidChunkData.CHUNK_SIZE][FluidChunkData.CHUNK_SIZE];
|
||||||
|
float[][][] velocityX = new float[FluidChunkData.CHUNK_SIZE][FluidChunkData.CHUNK_SIZE][FluidChunkData.CHUNK_SIZE];
|
||||||
|
float[][][] velocityY = new float[FluidChunkData.CHUNK_SIZE][FluidChunkData.CHUNK_SIZE][FluidChunkData.CHUNK_SIZE];
|
||||||
|
float[][][] velocityZ = new float[FluidChunkData.CHUNK_SIZE][FluidChunkData.CHUNK_SIZE][FluidChunkData.CHUNK_SIZE];
|
||||||
|
FloatBuffer floatBuffer = buffer.asFloatBuffer();
|
||||||
|
for(int x = 0; x < FluidChunkData.CHUNK_SIZE; x++){
|
||||||
|
for(int y = 0; y < FluidChunkData.CHUNK_SIZE; y++){
|
||||||
|
for(int z = 0; z < FluidChunkData.CHUNK_SIZE; z++){
|
||||||
|
weights[x][y][z] = floatBuffer.get();
|
||||||
|
if(weights[x][y][z] <= 0){
|
||||||
|
weights[x][y][z] = -1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(int x = 0; x < FluidChunkData.CHUNK_SIZE; x++){
|
||||||
|
for(int y = 0; y < FluidChunkData.CHUNK_SIZE; y++){
|
||||||
|
for(int z = 0; z < FluidChunkData.CHUNK_SIZE; z++){
|
||||||
|
velocityX[x][y][z] = floatBuffer.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(int x = 0; x < FluidChunkData.CHUNK_SIZE; x++){
|
||||||
|
for(int y = 0; y < FluidChunkData.CHUNK_SIZE; y++){
|
||||||
|
for(int z = 0; z < FluidChunkData.CHUNK_SIZE; z++){
|
||||||
|
velocityY[x][y][z] = floatBuffer.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(int x = 0; x < FluidChunkData.CHUNK_SIZE; x++){
|
||||||
|
for(int y = 0; y < FluidChunkData.CHUNK_SIZE; y++){
|
||||||
|
for(int z = 0; z < FluidChunkData.CHUNK_SIZE; z++){
|
||||||
|
velocityZ[x][y][z] = floatBuffer.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FluidChunkData data = new FluidChunkData();
|
||||||
|
data.setVoxelWeight(weights);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,7 +57,7 @@ public class ArenaLoading {
|
|||||||
|
|
||||||
private static void initServerArenaTerrainManager(){
|
private static void initServerArenaTerrainManager(){
|
||||||
Globals.serverTerrainManager = ServerTerrainManager.constructArenaTerrainManager();
|
Globals.serverTerrainManager = ServerTerrainManager.constructArenaTerrainManager();
|
||||||
Globals.serverFluidManager = ServerFluidManager.constructArenaFluidManager();
|
Globals.serverFluidManager = ServerFluidManager.constructArenaFluidManager(Globals.serverTerrainManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void initServerArenaWorldData(){
|
private static void initServerArenaWorldData(){
|
||||||
|
|||||||
@ -30,6 +30,7 @@ public class FluidChunk {
|
|||||||
|
|
||||||
rVal.putData(EntityDataStrings.FLUID_IS_FLUID, true);
|
rVal.putData(EntityDataStrings.FLUID_IS_FLUID, true);
|
||||||
rVal.putData(EntityDataStrings.DRAW_TRANSPARENT_PASS, true);
|
rVal.putData(EntityDataStrings.DRAW_TRANSPARENT_PASS, true);
|
||||||
|
rVal.removeData(EntityDataStrings.DRAW_SOLID_PASS);
|
||||||
|
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,6 +53,9 @@ public class TerrainProtocol {
|
|||||||
case SENDFLUIDDATA: {
|
case SENDFLUIDDATA: {
|
||||||
Globals.clientFluidManager.attachFluidMessage(message);
|
Globals.clientFluidManager.attachFluidMessage(message);
|
||||||
} break;
|
} break;
|
||||||
|
case UPDATEFLUIDDATA: {
|
||||||
|
Globals.clientFluidManager.attachFluidMessage(message);
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
LoggerInterface.loggerNetworking.WARNING("Client networking: Unhandled message of type: " + message.getMessageSubtype());
|
LoggerInterface.loggerNetworking.WARNING("Client networking: Unhandled message of type: " + message.getMessageSubtype());
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -246,6 +246,11 @@ SYNCHRONIZATION_MESSAGE,
|
|||||||
rVal = TerrainMessage.parsesendFluidDataMessage(byteBuffer);
|
rVal = TerrainMessage.parsesendFluidDataMessage(byteBuffer);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case TypeBytes.TERRAIN_MESSAGE_TYPE_UPDATEFLUIDDATA:
|
||||||
|
if(TerrainMessage.canParseMessage(byteBuffer,secondByte)){
|
||||||
|
rVal = TerrainMessage.parseupdateFluidDataMessage(byteBuffer);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TypeBytes.MESSAGE_TYPE_SERVER:
|
case TypeBytes.MESSAGE_TYPE_SERVER:
|
||||||
|
|||||||
@ -19,6 +19,7 @@ public class TerrainMessage extends NetworkMessage {
|
|||||||
SENDCHUNKDATA,
|
SENDCHUNKDATA,
|
||||||
REQUESTFLUIDDATA,
|
REQUESTFLUIDDATA,
|
||||||
SENDFLUIDDATA,
|
SENDFLUIDDATA,
|
||||||
|
UPDATEFLUIDDATA,
|
||||||
}
|
}
|
||||||
|
|
||||||
TerrainMessageType messageType;
|
TerrainMessageType messageType;
|
||||||
@ -276,6 +277,8 @@ public class TerrainMessage extends NetworkMessage {
|
|||||||
}
|
}
|
||||||
case TypeBytes.TERRAIN_MESSAGE_TYPE_SENDFLUIDDATA:
|
case TypeBytes.TERRAIN_MESSAGE_TYPE_SENDFLUIDDATA:
|
||||||
return TerrainMessage.canParsesendFluidDataMessage(byteBuffer);
|
return TerrainMessage.canParsesendFluidDataMessage(byteBuffer);
|
||||||
|
case TypeBytes.TERRAIN_MESSAGE_TYPE_UPDATEFLUIDDATA:
|
||||||
|
return TerrainMessage.canParseupdateFluidDataMessage(byteBuffer);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -564,6 +567,54 @@ public class TerrainMessage extends NetworkMessage {
|
|||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean canParseupdateFluidDataMessage(CircularByteBuffer byteBuffer){
|
||||||
|
int currentStreamLength = byteBuffer.getRemaining();
|
||||||
|
List<Byte> temporaryByteQueue = new LinkedList();
|
||||||
|
if(currentStreamLength < 6){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(currentStreamLength < 10){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(currentStreamLength < 14){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int chunkDataSize = 0;
|
||||||
|
if(currentStreamLength < 18){
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
temporaryByteQueue.add(byteBuffer.peek(14 + 0));
|
||||||
|
temporaryByteQueue.add(byteBuffer.peek(14 + 1));
|
||||||
|
temporaryByteQueue.add(byteBuffer.peek(14 + 2));
|
||||||
|
temporaryByteQueue.add(byteBuffer.peek(14 + 3));
|
||||||
|
chunkDataSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
|
||||||
|
}
|
||||||
|
if(currentStreamLength < 18 + chunkDataSize){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TerrainMessage parseupdateFluidDataMessage(CircularByteBuffer byteBuffer){
|
||||||
|
TerrainMessage rVal = new TerrainMessage(TerrainMessageType.UPDATEFLUIDDATA);
|
||||||
|
stripPacketHeader(byteBuffer);
|
||||||
|
rVal.setworldX(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
|
rVal.setworldY(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
|
rVal.setworldZ(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
|
||||||
|
rVal.setchunkData(ByteStreamUtils.popByteArrayFromByteQueue(byteBuffer));
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TerrainMessage constructupdateFluidDataMessage(int worldX,int worldY,int worldZ,byte[] chunkData){
|
||||||
|
TerrainMessage rVal = new TerrainMessage(TerrainMessageType.UPDATEFLUIDDATA);
|
||||||
|
rVal.setworldX(worldX);
|
||||||
|
rVal.setworldY(worldY);
|
||||||
|
rVal.setworldZ(worldZ);
|
||||||
|
rVal.setchunkData(chunkData);
|
||||||
|
rVal.serialize();
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void serialize(){
|
void serialize(){
|
||||||
byte[] intValues = new byte[8];
|
byte[] intValues = new byte[8];
|
||||||
@ -839,6 +890,32 @@ public class TerrainMessage extends NetworkMessage {
|
|||||||
rawBytes[18+i] = chunkData[i];
|
rawBytes[18+i] = chunkData[i];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case UPDATEFLUIDDATA:
|
||||||
|
rawBytes = new byte[2+4+4+4+4+chunkData.length];
|
||||||
|
//message header
|
||||||
|
rawBytes[0] = TypeBytes.MESSAGE_TYPE_TERRAIN;
|
||||||
|
//entity messaage header
|
||||||
|
rawBytes[1] = TypeBytes.TERRAIN_MESSAGE_TYPE_UPDATEFLUIDDATA;
|
||||||
|
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.serializeIntToBytes(worldZ);
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[10+i] = intValues[i];
|
||||||
|
}
|
||||||
|
intValues = ByteStreamUtils.serializeIntToBytes(chunkData.length);
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
rawBytes[14+i] = intValues[i];
|
||||||
|
}
|
||||||
|
for(int i = 0; i < chunkData.length; i++){
|
||||||
|
rawBytes[18+i] = chunkData[i];
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
serialized = true;
|
serialized = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -90,6 +90,7 @@ Message categories
|
|||||||
public static final byte TERRAIN_MESSAGE_TYPE_SENDCHUNKDATA = 8;
|
public static final byte TERRAIN_MESSAGE_TYPE_SENDCHUNKDATA = 8;
|
||||||
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTFLUIDDATA = 9;
|
public static final byte TERRAIN_MESSAGE_TYPE_REQUESTFLUIDDATA = 9;
|
||||||
public static final byte TERRAIN_MESSAGE_TYPE_SENDFLUIDDATA = 10;
|
public static final byte TERRAIN_MESSAGE_TYPE_SENDFLUIDDATA = 10;
|
||||||
|
public static final byte TERRAIN_MESSAGE_TYPE_UPDATEFLUIDDATA = 11;
|
||||||
/*
|
/*
|
||||||
Terrain packet sizes
|
Terrain packet sizes
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -45,6 +45,7 @@ public class TerrainProtocol {
|
|||||||
);
|
);
|
||||||
} break;
|
} break;
|
||||||
//all ignored message types
|
//all ignored message types
|
||||||
|
case UPDATEFLUIDDATA:
|
||||||
case RESPONSEMETADATA:
|
case RESPONSEMETADATA:
|
||||||
case SPAWNPOSITION:
|
case SPAWNPOSITION:
|
||||||
case UPDATEVOXEL:
|
case UPDATEVOXEL:
|
||||||
@ -207,11 +208,55 @@ public class TerrainProtocol {
|
|||||||
// System.out.println("Received request for chunk " + message.getworldX() + " " + message.getworldY());
|
// System.out.println("Received request for chunk " + message.getworldX() + " " + message.getworldY());
|
||||||
|
|
||||||
ServerFluidChunk chunk = Globals.serverFluidManager.getChunk(worldX, worldY, worldZ);
|
ServerFluidChunk chunk = Globals.serverFluidManager.getChunk(worldX, worldY, worldZ);
|
||||||
|
|
||||||
// float[][] macroValues = chunk.getMacroValues();//Globals.serverTerrainManager.getRad5MacroValues(message.getworldX(), message.getworldY());
|
|
||||||
|
|
||||||
// long[][] randomizer = chunk.getRandomizer();//Globals.serverTerrainManager.getRandomizer(message.getworldX(), message.getworldY());
|
|
||||||
|
ByteBuffer buffer = constructFluidByteBuffer(chunk);
|
||||||
|
|
||||||
|
connectionHandler.addMessagetoOutgoingQueue(TerrainMessage.constructsendFluidDataMessage(worldX, worldY, worldZ, buffer.array()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sendWorldMetadata(ServerConnectionHandler connectionHandler){
|
||||||
|
//world metadata
|
||||||
|
connectionHandler.addMessagetoOutgoingQueue(
|
||||||
|
TerrainMessage.constructResponseMetadataMessage(
|
||||||
|
Globals.serverWorldData.getWorldSizeDiscrete(),
|
||||||
|
Globals.serverWorldData.getDynamicInterpolationRatio(),
|
||||||
|
Globals.serverWorldData.getRandomDampener(),
|
||||||
|
(int)Globals.serverWorldData.getWorldBoundMin().x,
|
||||||
|
(int)Globals.serverWorldData.getWorldBoundMin().z,
|
||||||
|
(int)Globals.serverWorldData.getWorldBoundMax().x,
|
||||||
|
(int)Globals.serverWorldData.getWorldBoundMax().z
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to perform an edit requested by a client
|
||||||
|
* @param message The message containing the edit request
|
||||||
|
*/
|
||||||
|
static void attemptTerrainEdit(ServerConnectionHandler connectionHandler, TerrainMessage message){
|
||||||
|
Player player = Globals.playerManager.getPlayerFromId(connectionHandler.getPlayerId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to use an edit palette on the terrain
|
||||||
|
* @param connectionHandler The connection handler
|
||||||
|
* @param message The message that contains the request to use an edit palette
|
||||||
|
*/
|
||||||
|
static void attemptUseTerrainEditPalette(ServerConnectionHandler connectionHandler, TerrainMessage message){
|
||||||
|
Player player = Globals.playerManager.getPlayerFromId(connectionHandler.getPlayerId());
|
||||||
|
Realm realm = Globals.realmManager.getPlayerRealm(player);
|
||||||
|
Vector3d location = new Vector3d(message.getrealLocationX(), message.getrealLocationY(), message.getrealLocationZ());
|
||||||
|
TerrainEditing.editTerrain(realm, location, message.getvalue(), message.getterrainValue(), message.getterrainWeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a buffer to send a fluid chunk to the client
|
||||||
|
* @param chunk The chunk to send
|
||||||
|
* @return the buffer
|
||||||
|
*/
|
||||||
|
public static ByteBuffer constructFluidByteBuffer(ServerFluidChunk chunk){
|
||||||
//The length along each access of the chunk data. Typically, should be at least 17.
|
//The length along each access of the chunk data. Typically, should be at least 17.
|
||||||
//Because CHUNK_SIZE is 16, 17 adds the necessary extra value. Each chunk needs the value of the immediately following position to generate
|
//Because CHUNK_SIZE is 16, 17 adds the necessary extra value. Each chunk needs the value of the immediately following position to generate
|
||||||
//chunk data that connects seamlessly to the next chunk.
|
//chunk data that connects seamlessly to the next chunk.
|
||||||
@ -254,44 +299,7 @@ public class TerrainProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
connectionHandler.addMessagetoOutgoingQueue(TerrainMessage.constructsendFluidDataMessage(worldX, worldY, worldZ, buffer.array()));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sendWorldMetadata(ServerConnectionHandler connectionHandler){
|
|
||||||
//world metadata
|
|
||||||
connectionHandler.addMessagetoOutgoingQueue(
|
|
||||||
TerrainMessage.constructResponseMetadataMessage(
|
|
||||||
Globals.serverWorldData.getWorldSizeDiscrete(),
|
|
||||||
Globals.serverWorldData.getDynamicInterpolationRatio(),
|
|
||||||
Globals.serverWorldData.getRandomDampener(),
|
|
||||||
(int)Globals.serverWorldData.getWorldBoundMin().x,
|
|
||||||
(int)Globals.serverWorldData.getWorldBoundMin().z,
|
|
||||||
(int)Globals.serverWorldData.getWorldBoundMax().x,
|
|
||||||
(int)Globals.serverWorldData.getWorldBoundMax().z
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to perform an edit requested by a client
|
|
||||||
* @param message The message containing the edit request
|
|
||||||
*/
|
|
||||||
static void attemptTerrainEdit(ServerConnectionHandler connectionHandler, TerrainMessage message){
|
|
||||||
Player player = Globals.playerManager.getPlayerFromId(connectionHandler.getPlayerId());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to use an edit palette on the terrain
|
|
||||||
* @param connectionHandler The connection handler
|
|
||||||
* @param message The message that contains the request to use an edit palette
|
|
||||||
*/
|
|
||||||
static void attemptUseTerrainEditPalette(ServerConnectionHandler connectionHandler, TerrainMessage message){
|
|
||||||
Player player = Globals.playerManager.getPlayerFromId(connectionHandler.getPlayerId());
|
|
||||||
Realm realm = Globals.realmManager.getPlayerRealm(player);
|
|
||||||
Vector3d location = new Vector3d(message.getrealLocationX(), message.getrealLocationY(), message.getrealLocationZ());
|
|
||||||
TerrainEditing.editTerrain(realm, location, message.getvalue(), message.getterrainValue(), message.getterrainWeight());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -588,7 +588,7 @@ public class FluidChunkModelGeneration {
|
|||||||
List<Integer> faceElements = new LinkedList<Integer>();
|
List<Integer> faceElements = new LinkedList<Integer>();
|
||||||
//List of UVs
|
//List of UVs
|
||||||
List<Float> UVs = new LinkedList<Float>();
|
List<Float> UVs = new LinkedList<Float>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for(int x = 0; x < weightGrid.length - 1; x++){
|
for(int x = 0; x < weightGrid.length - 1; x++){
|
||||||
@ -602,7 +602,7 @@ public class FluidChunkModelGeneration {
|
|||||||
weightGrid[x+0][y+1][z+0], weightGrid[x+0][y+1][z+1], weightGrid[x+1][y+1][z+1], weightGrid[x+1][y+1][z+0]
|
weightGrid[x+0][y+1][z+0], weightGrid[x+0][y+1][z+1], weightGrid[x+1][y+1][z+1], weightGrid[x+1][y+1][z+0]
|
||||||
);
|
);
|
||||||
//polygonize the current gridcell
|
//polygonize the current gridcell
|
||||||
polygonize(currentCell, 0, triangles, vertMap, verts, normals, trianglesSharingVert);
|
polygonize(currentCell, 0.0f, triangles, vertMap, verts, normals, trianglesSharingVert);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import electrosphere.game.server.world.ServerWorldData;
|
|||||||
import electrosphere.logger.LoggerInterface;
|
import electrosphere.logger.LoggerInterface;
|
||||||
import electrosphere.net.parser.net.message.TerrainMessage;
|
import electrosphere.net.parser.net.message.TerrainMessage;
|
||||||
import electrosphere.net.server.player.Player;
|
import electrosphere.net.server.player.Player;
|
||||||
|
import electrosphere.net.server.protocol.TerrainProtocol;
|
||||||
import electrosphere.server.content.ServerContentManager;
|
import electrosphere.server.content.ServerContentManager;
|
||||||
import electrosphere.server.datacell.interfaces.DataCellManager;
|
import electrosphere.server.datacell.interfaces.DataCellManager;
|
||||||
import electrosphere.server.datacell.interfaces.VoxelCellManager;
|
import electrosphere.server.datacell.interfaces.VoxelCellManager;
|
||||||
@ -353,9 +354,14 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
|||||||
loadedCellsLock.acquireUninterruptibly();
|
loadedCellsLock.acquireUninterruptibly();
|
||||||
for(ServerDataCell cell : loadedCells){
|
for(ServerDataCell cell : loadedCells){
|
||||||
Globals.microSimulation.simulate(cell, parent.getHitboxManager());
|
Globals.microSimulation.simulate(cell, parent.getHitboxManager());
|
||||||
|
|
||||||
|
//simulate fluid
|
||||||
|
Vector3i cellPos = this.getCellWorldPosition(cell);
|
||||||
|
boolean update = this.serverFluidManager.simulate(cellPos.x,cellPos.y,cellPos.z);
|
||||||
|
if(update){
|
||||||
|
rebroadcastFluidChunk(cellPos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//simulate fluid
|
|
||||||
this.serverFluidManager.simulate();
|
|
||||||
loadedCellsLock.release();
|
loadedCellsLock.release();
|
||||||
updatePlayerPositions();
|
updatePlayerPositions();
|
||||||
}
|
}
|
||||||
@ -482,8 +488,23 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
/**
|
||||||
|
* Gets the fluid chunk at a given position
|
||||||
|
*/
|
||||||
public ServerFluidChunk getFluidChunkAtPosition(Vector3i worldPosition) {
|
public ServerFluidChunk getFluidChunkAtPosition(Vector3i worldPosition) {
|
||||||
return serverFluidManager.getChunk(worldPosition.x, worldPosition.y, worldPosition.z);
|
return serverFluidManager.getChunk(worldPosition.x, worldPosition.y, worldPosition.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rebroadcasts the fluid cell at a given position
|
||||||
|
* @param worldPosition the world position
|
||||||
|
*/
|
||||||
|
private void rebroadcastFluidChunk(Vector3i worldPosition){
|
||||||
|
ServerDataCell cell = getCellAtWorldPosition(worldPosition);
|
||||||
|
ServerFluidChunk chunk = getFluidChunkAtPosition(worldPosition);
|
||||||
|
cell.broadcastNetworkMessage(
|
||||||
|
TerrainMessage.constructupdateFluidDataMessage(worldPosition.x, worldPosition.y, worldPosition.z, TerrainProtocol.constructFluidByteBuffer(chunk).array())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,12 +17,14 @@ public class ArenaFluidGenerator implements FluidGenerator {
|
|||||||
for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){
|
for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){
|
||||||
for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){
|
for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){
|
||||||
for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){
|
for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){
|
||||||
weights[x][y][z] = -1.0f;
|
weights[x][y][z] = 0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
weights[3][3][3] = 0.8f;
|
if(worldX == 0 && worldY == 0 && worldZ == 0){
|
||||||
|
weights[7][5][7] = 1f;
|
||||||
|
}
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,10 @@ import electrosphere.server.fluid.diskmap.FluidDiskMap;
|
|||||||
import electrosphere.server.fluid.generation.ArenaFluidGenerator;
|
import electrosphere.server.fluid.generation.ArenaFluidGenerator;
|
||||||
import electrosphere.server.fluid.generation.FluidGenerator;
|
import electrosphere.server.fluid.generation.FluidGenerator;
|
||||||
import electrosphere.server.fluid.models.FluidModel;
|
import electrosphere.server.fluid.models.FluidModel;
|
||||||
|
import electrosphere.server.fluid.simulator.ServerFluidSimulator;
|
||||||
|
import electrosphere.server.fluid.simulator.cellularautomata.FluidCellularAutomataSimulator;
|
||||||
|
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||||
|
import electrosphere.server.terrain.manager.ServerTerrainManager;
|
||||||
import electrosphere.util.FileUtils;
|
import electrosphere.util.FileUtils;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
@ -48,18 +52,26 @@ public class ServerFluidManager {
|
|||||||
|
|
||||||
//The generation algorithm for this fluid manager
|
//The generation algorithm for this fluid manager
|
||||||
FluidGenerator chunkGenerator;
|
FluidGenerator chunkGenerator;
|
||||||
|
|
||||||
|
//the fluid simulator
|
||||||
|
ServerFluidSimulator serverFluidSimulator;
|
||||||
|
|
||||||
|
//the terrain manager associated
|
||||||
|
ServerTerrainManager serverTerrainManager;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
public ServerFluidManager(
|
public ServerFluidManager(
|
||||||
|
ServerTerrainManager serverTerrainManager,
|
||||||
int worldSizeDiscrete,
|
int worldSizeDiscrete,
|
||||||
int verticalInterpolationRatio,
|
int verticalInterpolationRatio,
|
||||||
float interpolationRandomDampener,
|
float interpolationRandomDampener,
|
||||||
long seed,
|
long seed,
|
||||||
FluidGenerator chunkGenerator
|
FluidGenerator chunkGenerator
|
||||||
){
|
){
|
||||||
|
this.serverTerrainManager = serverTerrainManager;
|
||||||
this.worldSizeDiscrete = worldSizeDiscrete;
|
this.worldSizeDiscrete = worldSizeDiscrete;
|
||||||
this.verticalInterpolationRatio = verticalInterpolationRatio;
|
this.verticalInterpolationRatio = verticalInterpolationRatio;
|
||||||
this.chunkCache = new ConcurrentHashMap<String, ServerFluidChunk>();
|
this.chunkCache = new ConcurrentHashMap<String, ServerFluidChunk>();
|
||||||
@ -77,14 +89,16 @@ public class ServerFluidManager {
|
|||||||
* Constructs an arena fluid manager
|
* Constructs an arena fluid manager
|
||||||
* @return The arena fluid manager
|
* @return The arena fluid manager
|
||||||
*/
|
*/
|
||||||
public static ServerFluidManager constructArenaFluidManager(){
|
public static ServerFluidManager constructArenaFluidManager(ServerTerrainManager serverTerrainManager){
|
||||||
ServerFluidManager rVal = new ServerFluidManager();
|
ServerFluidManager rVal = new ServerFluidManager();
|
||||||
|
rVal.serverTerrainManager = serverTerrainManager;
|
||||||
rVal.worldSizeDiscrete = 2;
|
rVal.worldSizeDiscrete = 2;
|
||||||
rVal.verticalInterpolationRatio = 0;
|
rVal.verticalInterpolationRatio = 0;
|
||||||
rVal.chunkCache = new ConcurrentHashMap<String, ServerFluidChunk>();
|
rVal.chunkCache = new ConcurrentHashMap<String, ServerFluidChunk>();
|
||||||
rVal.chunkCacheContents = new CopyOnWriteArrayList<String>();
|
rVal.chunkCacheContents = new CopyOnWriteArrayList<String>();
|
||||||
rVal.interpolationRandomDampener = 0.0f;
|
rVal.interpolationRandomDampener = 0.0f;
|
||||||
rVal.chunkGenerator = new ArenaFluidGenerator();
|
rVal.chunkGenerator = new ArenaFluidGenerator();
|
||||||
|
rVal.serverFluidSimulator = new FluidCellularAutomataSimulator();
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,10 +289,15 @@ public class ServerFluidManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simulates all active fluid chunks
|
* Simulates a chunk
|
||||||
*/
|
*/
|
||||||
public void simulate(){
|
public boolean simulate(int worldX, int worldY, int worldZ){
|
||||||
//TODO: implement
|
ServerFluidChunk fluidChunk = this.getChunk(worldX, worldY, worldZ);
|
||||||
|
ServerTerrainChunk terrainChunk = this.serverTerrainManager.getChunk(worldX, worldY, worldZ);
|
||||||
|
if(fluidChunk != null && terrainChunk != null && this.serverFluidSimulator != null){
|
||||||
|
return this.serverFluidSimulator.simulate(fluidChunk,terrainChunk,worldX,worldY,worldZ);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,22 @@
|
|||||||
|
package electrosphere.server.fluid.simulator;
|
||||||
|
|
||||||
|
import electrosphere.server.fluid.manager.ServerFluidChunk;
|
||||||
|
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A system capable of simulating a server fluid chunk for a single frame
|
||||||
|
*/
|
||||||
|
public interface ServerFluidSimulator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simulates the chunk for single step
|
||||||
|
* @param fluidChunk The fluid chunk
|
||||||
|
* @param terrainChunk The terrain chunk
|
||||||
|
* @param worldX the world x coordinate
|
||||||
|
* @param worldY the world y coordinate
|
||||||
|
* @param worldZ the world z coordinate
|
||||||
|
* @return True if the server data cell should update all players connected to it with new values, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean simulate(ServerFluidChunk fluidChunk, ServerTerrainChunk terrainChunk, int worldX, int worldY, int worldZ);
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,71 @@
|
|||||||
|
package electrosphere.server.fluid.simulator.cellularautomata;
|
||||||
|
|
||||||
|
import electrosphere.server.fluid.manager.ServerFluidChunk;
|
||||||
|
import electrosphere.server.fluid.simulator.ServerFluidSimulator;
|
||||||
|
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simulates server fluid chunks via cellular automata
|
||||||
|
*/
|
||||||
|
public class FluidCellularAutomataSimulator implements ServerFluidSimulator {
|
||||||
|
|
||||||
|
static final float MAX_WEIGHT = 1.0f;
|
||||||
|
|
||||||
|
static final float GRAVITY_DIFF = 0.04f;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean simulate(ServerFluidChunk fluidChunk, ServerTerrainChunk terrainChunk, int worldX, int worldY, int worldZ) {
|
||||||
|
|
||||||
|
float[][][] weights = fluidChunk.getWeights();
|
||||||
|
float[][][] terrainWeights = terrainChunk.getWeights();
|
||||||
|
|
||||||
|
//if true, alerts the server data cell to broadcast a new update message to all clients within it
|
||||||
|
boolean update = false;
|
||||||
|
|
||||||
|
if(worldX == 0 && worldY == 0 && worldZ == 0){
|
||||||
|
if(weights[8][3][8] < MAX_WEIGHT){
|
||||||
|
weights[8][3][8] = MAX_WEIGHT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){
|
||||||
|
for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){
|
||||||
|
for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){
|
||||||
|
if(weights[x][y][z] <= 0){
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
if(y > 0 && weights[x][y-1][z] < MAX_WEIGHT){
|
||||||
|
update = true;
|
||||||
|
weights[x][y][z] -= GRAVITY_DIFF;
|
||||||
|
weights[x][y-1][z] += GRAVITY_DIFF;
|
||||||
|
} else {
|
||||||
|
//propagate sideways
|
||||||
|
int[] offsetX = new int[]{-1,1,0,0};
|
||||||
|
int[] offsetZ = new int[]{0,0,-1,1};
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
int realX = x + offsetX[i];
|
||||||
|
int realZ = z + offsetZ[i];
|
||||||
|
if(realX > 0 && realX < ServerTerrainChunk.CHUNK_DIMENSION - 1 &&
|
||||||
|
realZ > 0 && realZ < ServerTerrainChunk.CHUNK_DIMENSION - 1
|
||||||
|
){
|
||||||
|
if(
|
||||||
|
weights[realX][y][realZ] < weights[x][y][z] &&
|
||||||
|
terrainWeights[realX][y][realZ] < MAX_WEIGHT
|
||||||
|
){
|
||||||
|
update = true;
|
||||||
|
weights[x][y][z] -= GRAVITY_DIFF;
|
||||||
|
weights[realX][y][realZ] += GRAVITY_DIFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return update;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -27,7 +27,19 @@ public class ArenaChunkGenerator implements ChunkGenerator {
|
|||||||
for(int weightX = 0; weightX < ServerTerrainChunk.CHUNK_DIMENSION; weightX++){
|
for(int weightX = 0; weightX < ServerTerrainChunk.CHUNK_DIMENSION; weightX++){
|
||||||
for(int weightZ = 0; weightZ < ServerTerrainChunk.CHUNK_DIMENSION; weightZ++){
|
for(int weightZ = 0; weightZ < ServerTerrainChunk.CHUNK_DIMENSION; weightZ++){
|
||||||
weights[weightX][0][weightZ] = 0.1f;
|
weights[weightX][0][weightZ] = 0.1f;
|
||||||
values[weightX][0][weightZ] = 2;
|
values[weightX][0][weightZ] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(worldX == 0 && worldY == 0 && worldZ == 0){
|
||||||
|
for(int x = 5; x < 11; x++){
|
||||||
|
for(int z = 5; z < 11; z++){
|
||||||
|
if((x == 10 || x == 5 || z == 10 || z == 5)){
|
||||||
|
weights[x][0][z] = 1.0f;
|
||||||
|
weights[x][1][z] = 1.0f;
|
||||||
|
values[x][0][z] = 1;
|
||||||
|
values[x][1][z] = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user