Fix SP debug mode

This commit is contained in:
austin 2023-07-09 15:49:31 -04:00
parent e225cac5cf
commit 8f61e3e00e
33 changed files with 386 additions and 267 deletions

54
pom.xml
View File

@ -255,7 +255,19 @@
<goals> <goals>
<goal>exec</goal> <goal>exec</goal>
</goals> </goals>
<configuration>
<executable>java</executable>
<includeProjectDependencies>false</includeProjectDependencies>
<includePluginDependencies>true</includePluginDependencies>
<mainClass>electrosphere.engine.Main</mainClass>
<!-- <classpathScope>compile</classpathScope> -->
<arguments>
<argument>-cp</argument>
<argument>target/classes;target/Renderer-0.1-jar-with-dependencies.jar</argument>
<argument>electrosphere.engine.Main</argument>
</arguments>
<!-- <classesDirectory>${project.basedir}/target/classes</classesDirectory> -->
</configuration>
</execution> </execution>
<!-- <execution> <!-- <execution>
<id>Telephone</id> <id>Telephone</id>
@ -272,28 +284,30 @@
</configuration> </configuration>
</execution> --> </execution> -->
</executions> </executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<id>buildnumber</id>
<phase>validate</phase>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
<configuration> <configuration>
<executable>java</executable> <format>{0,number}</format>
<includeProjectDependencies>false</includeProjectDependencies> <items>
<includePluginDependencies>true</includePluginDependencies> <item>buildNumber</item>
<mainClass>electrosphere.engine.Main</mainClass> </items>
<!-- <classpathScope>compile</classpathScope> --> <doCheck>false</doCheck>
<arguments> <doUpdate>false</doUpdate>
<argument>-cp</argument> <revisionOnScmFailure>unknownbuild</revisionOnScmFailure>
<argument>target/classes;target/Renderer-0.1-jar-with-dependencies.jar</argument>
<argument>electrosphere.engine.Main</argument>
</arguments>
<!-- <classesDirectory>${project.basedir}/target/classes</classesDirectory> -->
</configuration> </configuration>
</plugin> </plugin>
<!-- <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<argLine>-XstartOnFirstThread</argLine>
</configuration>
</plugin> -->
</plugins> </plugins>
</build> </build>
</project> </project>

View File

@ -60,7 +60,6 @@ public class FluidDrawCell {
rVal.worldPos = worldPos; rVal.worldPos = worldPos;
rVal.program = program; rVal.program = program;
rVal.data = data; rVal.data = data;
System.out.println("Create cell");
return rVal; return rVal;
} }

View File

@ -19,7 +19,7 @@ import electrosphere.renderer.ShaderProgram;
* *
* @author satellite * @author satellite
*/ */
public class DrawCellManager { public class FluidDrawCellManager {
//the center of this cell manager's array in cell space //the center of this cell manager's array in cell space
@ -78,7 +78,7 @@ public class DrawCellManager {
* @param discreteX The initial discrete position X coordinate * @param discreteX The initial discrete position X coordinate
* @param discreteY The initial discrete position Y coordinate * @param discreteY The initial discrete position Y coordinate
*/ */
public DrawCellManager(ClientTerrainManager clientTerrainManager, int discreteX, int discreteY, int discreteZ){ public FluidDrawCellManager(ClientTerrainManager clientTerrainManager, int discreteX, int discreteY, int discreteZ){
worldBoundDiscreteMax = (int)(Globals.clientWorldData.getWorldBoundMin().x / Globals.clientWorldData.getDynamicInterpolationRatio() * 1.0f); worldBoundDiscreteMax = (int)(Globals.clientWorldData.getWorldBoundMin().x / Globals.clientWorldData.getDynamicInterpolationRatio() * 1.0f);
cells = new HashSet<FluidDrawCell>(); cells = new HashSet<FluidDrawCell>();
hasNotRequested = new HashSet<String>(); hasNotRequested = new HashSet<String>();
@ -102,7 +102,7 @@ public class DrawCellManager {
update = true; update = true;
} }
DrawCellManager(){ FluidDrawCellManager(){
} }

View File

@ -61,7 +61,6 @@ public class DrawCell {
rVal.worldPos = worldPos; rVal.worldPos = worldPos;
rVal.program = program; rVal.program = program;
rVal.data = data; rVal.data = data;
System.out.println("Create cell");
return rVal; return rVal;
} }

View File

@ -52,7 +52,7 @@ public class DrawCellManager {
int drawStepdownInterval = 3; int drawStepdownInterval = 3;
int drawStepdownValue = 25; int drawStepdownValue = 25;
double drawRadius = 200; double drawRadius = 50;
int physicsRadius = 3; int physicsRadius = 3;
@ -272,6 +272,7 @@ public class DrawCellManager {
updateable.remove(key); updateable.remove(key);
keyCellMap.remove(key); keyCellMap.remove(key);
hasRequested.remove(key); hasRequested.remove(key);
cell.destroy();
} }
} }
@ -324,14 +325,12 @@ public class DrawCellManager {
* Updates cells that need updating in this manager * Updates cells that need updating in this manager
*/ */
public void update(){ public void update(){
if(update){ if(containsUnrequestedCell() && !containsUndrawableCell()){
if(containsUnrequestedCell() && !containsUndrawableCell()){ updateUnrequestedCell();
updateUnrequestedCell(); } else if(containsUndrawableCell()){
} else if(containsUndrawableCell()){ makeCellDrawable();
makeCellDrawable(); } else if(containsUpdateableCell()){
} else if(containsUpdateableCell()){ updateCellModel();
updateCellModel();
}
} }
} }

View File

@ -443,7 +443,7 @@ public class Globals {
//init default shaderProgram //init default shaderProgram
defaultMeshShader = ShaderProgram.smart_assemble_shader(false,true); defaultMeshShader = ShaderProgram.smart_assemble_shader(false,true);
//init terrain shader program //init terrain shader program
terrainShaderProgram = ShaderProgram.loadSpecificShader("/Shaders/terrain2/terrain.vs", "/Shaders/terrain2/terrain.fs"); terrainShaderProgram = ShaderProgram.loadSpecificShader("/Shaders/terrain2/terrain2.vs", "/Shaders/terrain2/terrain2.fs");
TerrainChunkModelGeneration.terrainChunkShaderProgram = ShaderProgram.loadSpecificShader("/Shaders/terrain2/terrain2.vs", "/Shaders/terrain2/terrain2.fs"); TerrainChunkModelGeneration.terrainChunkShaderProgram = ShaderProgram.loadSpecificShader("/Shaders/terrain2/terrain2.vs", "/Shaders/terrain2/terrain2.fs");
//init fluid shader program //init fluid shader program
terrainShaderProgram = ShaderProgram.loadSpecificShader("/Shaders/fluid1/fluid1.vs", "/Shaders/fluid1/fluid1.fs"); terrainShaderProgram = ShaderProgram.loadSpecificShader("/Shaders/fluid1/fluid1.vs", "/Shaders/fluid1/fluid1.fs");

View File

@ -238,7 +238,7 @@ public class Main {
/// C L I E N T N E T W O R K I N G S T U F F /// C L I E N T N E T W O R K I N G S T U F F
/// ///
//Why is this its own function? Just to get the networking code out of main() //Why is this its own function? Just to get the networking code out of main()
if(Globals.RUN_CLIENT && Globals.clientConnection != null){ if(Globals.clientConnection != null){
Globals.clientConnection.parseMessages(); Globals.clientConnection.parseMessages();
} }

View File

@ -119,6 +119,9 @@ public class ClientLoading {
/**
* Inits the client networking thread and socket
*/
private static void initClientThread(){ private static void initClientThread(){
//start client networking //start client networking
Thread clientThread = null; Thread clientThread = null;
@ -253,6 +256,7 @@ public class ClientLoading {
try { try {
TimeUnit.MILLISECONDS.sleep(10); TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
ex.printStackTrace();
} }
// System.out.println("invalid cell"); // System.out.println("invalid cell");
} }
@ -262,6 +266,7 @@ public class ClientLoading {
try { try {
TimeUnit.MILLISECONDS.sleep(10); TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
ex.printStackTrace();
} }
// System.out.println("undrawable"); // System.out.println("undrawable");
} }

View File

@ -14,6 +14,7 @@ import electrosphere.menu.MenuGenerators;
import electrosphere.menu.WindowStrings; import electrosphere.menu.WindowStrings;
import electrosphere.menu.WindowUtils; import electrosphere.menu.WindowUtils;
import electrosphere.net.parser.net.message.TerrainMessage; import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.renderer.ui.Window; import electrosphere.renderer.ui.Window;
import electrosphere.server.saves.SaveUtils; import electrosphere.server.saves.SaveUtils;
import electrosphere.server.terrain.manager.ServerTerrainManager; import electrosphere.server.terrain.manager.ServerTerrainManager;
@ -30,7 +31,7 @@ public class DebugSPWorldLoading {
WindowUtils.replaceMainMenuContents(MenuGenerators.createEmptyMainMenu()); WindowUtils.replaceMainMenuContents(MenuGenerators.createEmptyMainMenu());
loadingWindow.setVisible(true); loadingWindow.setVisible(true);
Globals.serverTerrainManager = new ServerTerrainManager(2000,50,ServerTerrainManager.SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO,0.0f,0); Globals.serverTerrainManager = new ServerTerrainManager(2000,50,0.0f,0);
if(!SaveUtils.getSaves().contains("random_sp_world")){ if(!SaveUtils.getSaves().contains("random_sp_world")){
// //
//the juicy server GENERATION part //the juicy server GENERATION part
@ -39,7 +40,7 @@ public class DebugSPWorldLoading {
SaveUtils.createOrOverwriteSave("random_sp_world"); SaveUtils.createOrOverwriteSave("random_sp_world");
//create terrain //create terrain
Globals.serverTerrainManager.generate(); Globals.serverTerrainManager.generate();
Globals.serverTerrainManager.save(SaveUtils.deriveSaveDirectoryPath("random_sp_world")); Globals.serverTerrainManager.save("random_sp_world");
//create world.json //create world.json
Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager); Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager);
FileUtils.serializeObjectToSavePath("random_sp_world", "./world.json", Globals.serverWorldData); FileUtils.serializeObjectToSavePath("random_sp_world", "./world.json", Globals.serverWorldData);
@ -59,7 +60,7 @@ public class DebugSPWorldLoading {
//initialize the local connection //initialize the local connection
Globals.clientUsername = "testuser"; Globals.clientUsername = "testuser";
Globals.clientPassword = AuthenticationManager.getHashedString("testpass"); Globals.clientPassword = AuthenticationManager.getHashedString("testpass");
LoadingUtils.initLocalConnection(); ServerConnectionHandler serverPlayerConnection = LoadingUtils.initLocalConnection();
//wait for player object creation //wait for player object creation
while(Globals.playerManager.getPlayers().size() < 1){ while(Globals.playerManager.getPlayers().size() < 1){
try { try {
@ -85,7 +86,7 @@ public class DebugSPWorldLoading {
} }
//spawn player character //spawn player character
LoadingUtils.spawnLocalPlayerTestEntity(); LoadingUtils.spawnLocalPlayerTestEntity(serverPlayerConnection);
//request terrain data //request terrain data
Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestMetadataMessage()); Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestMetadataMessage());

View File

@ -1,6 +1,10 @@
package electrosphere.engine.loadingthreads; package electrosphere.engine.loadingthreads;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream; import java.io.PipedInputStream;
import java.io.PipedOutputStream; import java.io.PipedOutputStream;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -28,7 +32,9 @@ import electrosphere.game.server.world.MacroData;
import electrosphere.game.server.world.ServerWorldData; import electrosphere.game.server.world.ServerWorldData;
import electrosphere.net.NetUtils; import electrosphere.net.NetUtils;
import electrosphere.net.client.ClientNetworking; import electrosphere.net.client.ClientNetworking;
import electrosphere.net.parser.net.message.CharacterMessage;
import electrosphere.net.server.Server; import electrosphere.net.server.Server;
import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.net.server.player.Player; import electrosphere.net.server.player.Player;
import electrosphere.server.datacell.GriddedDataCellManager; import electrosphere.server.datacell.GriddedDataCellManager;
import electrosphere.server.datacell.Realm; import electrosphere.server.datacell.Realm;
@ -54,7 +60,7 @@ public class LoadingUtils {
Actually initialize the terrain manager Actually initialize the terrain manager
*/ */
float randomDampener = 0.0f; //0.25f; float randomDampener = 0.0f; //0.25f;
Globals.serverTerrainManager = new ServerTerrainManager(2000,50,ServerTerrainManager.SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO,randomDampener,0); Globals.serverTerrainManager = new ServerTerrainManager(2000,50,randomDampener,0);
if(Globals.RUN_SERVER){ if(Globals.RUN_SERVER){
if(Globals.userSettings.gameplayGenerateWorld()){ if(Globals.userSettings.gameplayGenerateWorld()){
Globals.serverTerrainManager.generate(); Globals.serverTerrainManager.generate();
@ -70,7 +76,6 @@ public class LoadingUtils {
int playerStartX = 0; int playerStartX = 0;
int playerStartY = 0; int playerStartY = 0;
int discreteSize = Globals.serverTerrainManager.getWorldDiscreteSize(); int discreteSize = Globals.serverTerrainManager.getWorldDiscreteSize();
int chunkSize = Globals.serverTerrainManager.getChunkWidth();
boolean found = false; boolean found = false;
for(int x = 0; x < discreteSize; x++){ for(int x = 0; x < discreteSize; x++){
for(int y = 0; y < discreteSize; y++){ for(int y = 0; y < discreteSize; y++){
@ -164,25 +169,30 @@ public class LoadingUtils {
} }
} }
static void initLocalConnection(){ static final int STREAM_BUFFER_SIZE = 32 * 1024 * 1024;
Globals.server = new Server(NetUtils.getPort()); static ServerConnectionHandler initLocalConnection(){
ServerConnectionHandler rVal = null;
try { try {
Globals.server = new Server(NetUtils.getPort());
//client -> server pipe //client -> server pipe
PipedInputStream clientInput = new PipedInputStream(); PipedInputStream clientInput = new PipedInputStream(STREAM_BUFFER_SIZE);
PipedOutputStream serverOutput = new PipedOutputStream(clientInput); PipedOutputStream serverOutput = new PipedOutputStream(clientInput);
//server -> client pipe //server -> client pipe
PipedInputStream serverInput = new PipedInputStream(); PipedInputStream serverInput = new PipedInputStream();
PipedOutputStream clientOutput = new PipedOutputStream(serverInput); PipedOutputStream clientOutput;
clientOutput = new PipedOutputStream(serverInput);
//start server communication thread //start server communication thread
Globals.server.addLocalPlayer(serverInput, serverOutput); rVal = Globals.server.addLocalPlayer(serverInput, serverOutput);
//start client communication thread //start client communication thread
Globals.clientConnection = new ClientNetworking(clientInput,clientOutput); Globals.clientConnection = new ClientNetworking(clientInput,clientOutput);
Thread clientThread = null; Thread clientThread = null;
clientThread = new Thread(Globals.clientConnection); clientThread = new Thread(Globals.clientConnection);
clientThread.start(); clientThread.start();
} catch (IOException e) { } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }
return rVal;
} }
/** /**
@ -219,7 +229,7 @@ public class LoadingUtils {
/** /**
* Spawns the character, and sets server side connection player object values to the appropriate chunk * Spawns the character, and sets server side connection player object values to the appropriate chunk
*/ */
static void spawnLocalPlayerTestEntity(){ static void spawnLocalPlayerTestEntity(ServerConnectionHandler serverPlayerConnection){
// //
//Create entity //Create entity
// //
@ -238,11 +248,9 @@ public class LoadingUtils {
template.putValue(attribute.getAttributeId(), attribute.getVariants().get(0).getId()); template.putValue(attribute.getAttributeId(), attribute.getVariants().get(0).getId());
} }
} }
Realm realm = Globals.realmManager.getRealms().iterator().next(); //set player character template
//create player serverPlayerConnection.setCreatureTemplate(template);
//spawn entity Globals.clientConnection.queueOutgoingMessage(CharacterMessage.constructRequestSpawnCharacterMessage());
Entity newPlayerEntity = CreatureUtils.serverSpawnBasicCreature(realm,Globals.spawnPoint,template.getCreatureType(),template);
Globals.playerEntity = newPlayerEntity;
//set player world-space coordinates //set player world-space coordinates
Player playerObject = Globals.playerManager.getPlayerFromId(0); Player playerObject = Globals.playerManager.getPlayerFromId(0);
@ -251,12 +259,6 @@ public class LoadingUtils {
Globals.serverWorldData.convertRealToChunkSpace(Globals.spawnPoint.y), Globals.serverWorldData.convertRealToChunkSpace(Globals.spawnPoint.y),
Globals.serverWorldData.convertRealToChunkSpace(Globals.spawnPoint.z) Globals.serverWorldData.convertRealToChunkSpace(Globals.spawnPoint.z)
)); ));
//set client entity data
Globals.clientPlayerData.setWorldPos(playerObject.getWorldPos());
//initially position entity
ServerEntityUtils.initiallyPositionEntity(realm, newPlayerEntity, new Vector3d(Globals.spawnPoint.x + 1,Globals.spawnPoint.y + 5,Globals.spawnPoint.z + 1));
//add entity to correct cells
realm.getDataCellManager().addPlayerToRealm(playerObject);
} }
static void initMacroSimulation(){ static void initMacroSimulation(){

View File

@ -15,7 +15,7 @@ public class ServerLoading {
// } // }
//TODO: Globals.serverTerrainManager = new ServerTerrainManager(2000,50,100,randomDampener,0); //TODO: Globals.serverTerrainManager = new ServerTerrainManager(2000,50,100,randomDampener,0);
Globals.serverTerrainManager = new ServerTerrainManager(2000,50,ServerTerrainManager.SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO,0.0f,0); Globals.serverTerrainManager = new ServerTerrainManager(2000,50,0.0f,0);
SaveUtils.loadSave(Globals.currentSaveName); SaveUtils.loadSave(Globals.currentSaveName);
// LoadingUtils.initTerrainDataCellManager(); // LoadingUtils.initTerrainDataCellManager();
//TODO: set spawnpoint //TODO: set spawnpoint

View File

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

View File

@ -44,6 +44,9 @@ public class MacroData {
return rVal; return rVal;
} }
static final int MAX_PLACEMENT_ATTEMPTS = 50;
public static MacroData generateWorld(long seed){ public static MacroData generateWorld(long seed){
Random random = new Random(seed); Random random = new Random(seed);
MacroData rVal = new MacroData(); MacroData rVal = new MacroData();
@ -80,6 +83,7 @@ public class MacroData {
List<Vector2i> occupiedStartingPositions = new LinkedList<Vector2i>(); List<Vector2i> occupiedStartingPositions = new LinkedList<Vector2i>();
for(Race race : rVal.races){ for(Race race : rVal.races){
boolean foundPlacementLocation = false; boolean foundPlacementLocation = false;
int attempts = 0;
while(!foundPlacementLocation){ while(!foundPlacementLocation){
Vector2i start = new Vector2i(random.nextInt(Globals.serverTerrainManager.getWorldDiscreteSize()),random.nextInt(Globals.serverTerrainManager.getWorldDiscreteSize())); Vector2i start = new Vector2i(random.nextInt(Globals.serverTerrainManager.getWorldDiscreteSize()),random.nextInt(Globals.serverTerrainManager.getWorldDiscreteSize()));
//are we above sea level? //are we above sea level?
@ -107,6 +111,10 @@ public class MacroData {
} }
} }
} }
attempts++;
if(attempts > MAX_PLACEMENT_ATTEMPTS){
break;
}
} }
} }

View File

@ -1,6 +1,7 @@
package electrosphere.game.server.world; package electrosphere.game.server.world;
import electrosphere.server.datacell.ServerDataCell; import electrosphere.server.datacell.ServerDataCell;
import electrosphere.server.terrain.manager.ServerTerrainChunk;
import electrosphere.server.terrain.manager.ServerTerrainManager; import electrosphere.server.terrain.manager.ServerTerrainManager;
import java.util.List; import java.util.List;
@ -67,7 +68,7 @@ public class ServerWorldData {
rVal.type = WorldType.GAME_WORLD; rVal.type = WorldType.GAME_WORLD;
rVal.worldMinPoint = new Vector3f(0,0,0); rVal.worldMinPoint = new Vector3f(0,0,0);
int worldDim = terrainManager.getWorldDiscreteSize() * terrainManager.getChunkWidth(); int worldDim = terrainManager.getWorldDiscreteSize() * ServerTerrainChunk.CHUNK_DIMENSION;
rVal.worldMaxPoint = new Vector3f(worldDim,0,worldDim); rVal.worldMaxPoint = new Vector3f(worldDim,0,worldDim);
rVal.dynamicInterpolationRatio = terrainManager.getDynamicInterpolationRatio(); rVal.dynamicInterpolationRatio = terrainManager.getDynamicInterpolationRatio();

View File

@ -130,7 +130,7 @@ public class MenuGenerators {
//create save dir //create save dir
SaveUtils.createOrOverwriteSave(saveName); SaveUtils.createOrOverwriteSave(saveName);
//create and save terrain //create and save terrain
ServerTerrainManager terrainManager = new ServerTerrainManager(2000,50,100,0.0f,0); ServerTerrainManager terrainManager = new ServerTerrainManager(2000,50,0.0f,0);
terrainManager.generate(); terrainManager.generate();
terrainManager.save(SaveUtils.deriveSaveDirectoryPath(saveName)); terrainManager.save(SaveUtils.deriveSaveDirectoryPath(saveName));
WindowUtils.replaceMainMenuContents(MenuGenerators.createWorldSelectMenu()); WindowUtils.replaceMainMenuContents(MenuGenerators.createWorldSelectMenu());

View File

@ -164,7 +164,7 @@ public class ClientNetworking implements Runnable{
//disconnected from the server //disconnected from the server
LoggerInterface.loggerNetworking.WARNING("Disconnected from server"); LoggerInterface.loggerNetworking.WARNING("Disconnected from server");
//close socket //close socket
if(socket.isConnected()){ if(socket != null && socket.isConnected()){
try { try {
socket.close(); socket.close();
} catch (IOException e) { } catch (IOException e) {
@ -205,13 +205,13 @@ public class ClientNetworking implements Runnable{
(((ServerMessage)message).getMessageSubtype()) == ServerMessageType.PONG (((ServerMessage)message).getMessageSubtype()) == ServerMessageType.PONG
){ ){
if(this.echoPings == true){ if(this.echoPings == true){
LoggerInterface.loggerNetworking.DEBUG("[Server] New message " + message.getType()); LoggerInterface.loggerNetworking.DEBUG("[CLIENT] New message " + message.getType());
} }
} else { } else {
LoggerInterface.loggerNetworking.DEBUG("[Server] New message " + message.getType()); LoggerInterface.loggerNetworking.DEBUG("[CLIENT] New message " + message.getType());
} }
} else { } else {
LoggerInterface.loggerNetworking.DEBUG("[Server] New message " + message.getType()); LoggerInterface.loggerNetworking.DEBUG("[CLIENT] New message " + message.getType());
} }
} }

View File

@ -1,6 +1,6 @@
package electrosphere.net.parser.net.raw; package electrosphere.net.parser.net.raw;
import electrosphere.net.parser.net.message.NetworkMessage; import electrosphere.net.parser.net.message.NetworkMessage;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
@ -15,7 +15,7 @@ public class NetworkParser {
CopyOnWriteArrayList<NetworkMessage> incomingMessageQueue = new CopyOnWriteArrayList<NetworkMessage>(); CopyOnWriteArrayList<NetworkMessage> incomingMessageQueue = new CopyOnWriteArrayList<NetworkMessage>();
CopyOnWriteArrayList<NetworkMessage> outgoingMessageQueue = new CopyOnWriteArrayList<NetworkMessage>(); CopyOnWriteArrayList<NetworkMessage> outgoingMessageQueue = new CopyOnWriteArrayList<NetworkMessage>();
CircularByteBuffer incomingByteBuffer = new CircularByteBuffer(64 * 1024 * 124); CircularByteBuffer incomingByteBuffer = new CircularByteBuffer(64 * 1024 * 1024);
CopyOnWriteArrayList<Byte> outgoingByteQueue = new CopyOnWriteArrayList<Byte>(); CopyOnWriteArrayList<Byte> outgoingByteQueue = new CopyOnWriteArrayList<Byte>();

View File

@ -90,9 +90,10 @@ public class Server implements Runnable{
} }
} }
public void addLocalPlayer(InputStream serverInputStream, OutputStream serverOutputStream){ public ServerConnectionHandler addLocalPlayer(InputStream serverInputStream, OutputStream serverOutputStream){
ServerConnectionHandler newClient = new ServerConnectionHandler(serverInputStream,serverOutputStream); ServerConnectionHandler newClient = new ServerConnectionHandler(serverInputStream,serverOutputStream);
clientMap.put("127.0.0.1", newClient); clientMap.put("127.0.0.1", newClient);
new Thread(newClient).start(); new Thread(newClient).start();
return newClient;
} }
} }

View File

@ -28,6 +28,7 @@ import electrosphere.server.terrain.manager.ServerTerrainChunk;
public class GriddedDataCellManager implements DataCellManager, VoxelCellManager { public class GriddedDataCellManager implements DataCellManager, VoxelCellManager {
//these are going to be the natural ground grid of data cells, but we're going to have more than this //these are going to be the natural ground grid of data cells, but we're going to have more than this
Map<String,ServerDataCell> groundDataCells = new HashMap<String,ServerDataCell>(); Map<String,ServerDataCell> groundDataCells = new HashMap<String,ServerDataCell>();
Map<ServerDataCell,Vector3i> cellPositionMap = new HashMap<ServerDataCell,Vector3i>();
//loaded cells //loaded cells
Semaphore loadedCellsLock = new Semaphore(1); Semaphore loadedCellsLock = new Semaphore(1);
Set<ServerDataCell> loadedCells; Set<ServerDataCell> loadedCells;
@ -211,6 +212,25 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
return playerChangedChunk; return playerChangedChunk;
} }
//Used for cleaning server data cells no longer in use from the realm
Set<ServerDataCell> toCleanQueue = new HashSet<ServerDataCell>();
/**
* Unloads all chunks that haven't had players in them for a set amount of time
*/
public void unloadPlayerlessChunks(){
//TODO: improve to make have less performance impact
for(ServerDataCell cell : loadedCells){
if(cell.getPlayers().size() < 1){
System.out.println("Unload cell");
toCleanQueue.add(cell);
}
}
for(ServerDataCell cell : toCleanQueue){
parent.deregisterCell(cell);
}
toCleanQueue.clear();
}
/** /**
* Get data cell at a given real point in this realm * Get data cell at a given real point in this realm
* @param point The real point * @param point The real point
@ -341,6 +361,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
private ServerDataCell createServerDataCell(Vector3i worldPos){ private ServerDataCell createServerDataCell(Vector3i worldPos){
ServerDataCell rVal = parent.createNewCell(); ServerDataCell rVal = parent.createNewCell();
groundDataCells.put(getServerDataCellKey(worldPos),rVal); groundDataCells.put(getServerDataCellKey(worldPos),rVal);
cellPositionMap.put(rVal,new Vector3i(worldPos));
return rVal; return rVal;
} }
@ -396,4 +417,14 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
terrainEditLock.release(); terrainEditLock.release();
} }
/**
* Gets the world position of a given data cell
* @param cell The data cell
* @return The world position
*/
private Vector3i getCellWorldPosition(ServerDataCell cell){
return cellPositionMap.get(cell);
}
} }

View File

@ -83,24 +83,6 @@ public class Realm {
ServerDataCell cell = Globals.entityDataCellMapper.getEntityDataCell(e); ServerDataCell cell = Globals.entityDataCellMapper.getEntityDataCell(e);
cell.broadcastNetworkMessage(message); cell.broadcastNetworkMessage(message);
} }
//Used for cleaning server data cells no longer in use from the realm
Set<ServerDataCell> toCleanQueue = new HashSet<ServerDataCell>();
/**
* Unloads all chunks that haven't had players in them for a set amount of time
*/
public void unloadPlayerlessChunks(){
//TODO: improve to make have less performance impact
for(ServerDataCell cell : loadedDataCells){
if(cell.getPlayers().size() < 1){
toCleanQueue.add(cell);
}
}
for(ServerDataCell cell : toCleanQueue){
deregisterCell(cell);
}
toCleanQueue.clear();
}
/** /**
@ -179,10 +161,7 @@ public class Realm {
dataCellManager.simulate(); dataCellManager.simulate();
//data cell manager update misc variables (player positions, unload not-in-use cells) //data cell manager update misc variables (player positions, unload not-in-use cells)
if(dataCellManager != null){ if(dataCellManager != null){
// boolean playerHasChangedChunk = dataCellManager.updatePlayerGroundCellPositions(); dataCellManager.unloadPlayerlessChunks();
// if(playerHasChangedChunk){
// dataCellManager.unloadPlayerlessChunks();
// }
} }
//clear collidable impulse lists //clear collidable impulse lists
collisionEngine.clearCollidableImpulseLists(); collisionEngine.clearCollidableImpulseLists();

View File

@ -55,5 +55,10 @@ public interface DataCellManager {
* Calls the simulate function on all loaded cells * Calls the simulate function on all loaded cells
*/ */
public void simulate(); public void simulate();
/**
* Unloads playerless chunks. Strategy for doing this is defined per data cell manager.
*/
public void unloadPlayerlessChunks();
} }

View File

@ -31,11 +31,11 @@ public class NavMeshUtils {
float currentMax = 0; float currentMax = 0;
int startPos = 0; int startPos = 0;
int endPos = 0; int endPos = 0;
for(int x = 0; x < Globals.serverTerrainManager.getAugmentedChunkWidth() - 1; x++){ for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION - 1; x++){
numInCurrent = 0; numInCurrent = 0;
currentMin = 0; currentMin = 0;
currentMax = 0; currentMax = 0;
for(int y = 0; y < Globals.serverTerrainManager.getAugmentedChunkWidth(); y++){ for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){
//create node //create node
if(navMeshGeneratorMask[x][y]){ if(navMeshGeneratorMask[x][y]){
if(numInCurrent > 0){ if(numInCurrent > 0){
@ -183,12 +183,12 @@ public class NavMeshUtils {
//why the -1? I think the array fiddling above is causing the bounds to be off normally //why the -1? I think the array fiddling above is causing the bounds to be off normally
//this fixes that //this fixes that
NavCube cube = new NavCube( NavCube cube = new NavCube(
box.boundMinX + chunk.getWorldX() * Globals.serverTerrainManager.getChunkWidth(), box.boundMinX + chunk.getWorldX() * ServerTerrainChunk.CHUNK_DIMENSION,
box.minHeight - 0.5f, box.minHeight - 0.5f,
box.boundMinY + chunk.getWorldY() * Globals.serverTerrainManager.getChunkWidth(), box.boundMinY + chunk.getWorldY() * ServerTerrainChunk.CHUNK_DIMENSION,
box.boundMaxX + chunk.getWorldX() * Globals.serverTerrainManager.getChunkWidth(), box.boundMaxX + chunk.getWorldX() * ServerTerrainChunk.CHUNK_DIMENSION,
box.maxHeight + 0.5f, box.maxHeight + 0.5f,
box.boundMaxY + chunk.getWorldY() * Globals.serverTerrainManager.getChunkWidth() box.boundMaxY + chunk.getWorldY() * ServerTerrainChunk.CHUNK_DIMENSION
); );
rVal.addNode(cube); rVal.addNode(cube);
} }

View File

@ -1,6 +1,7 @@
package electrosphere.server.pathfinding.blocker; package electrosphere.server.pathfinding.blocker;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.server.terrain.manager.ServerTerrainChunk;
/** /**
* *
@ -13,7 +14,7 @@ public class NavBlocker {
boolean[][] heightfieldBlocker; boolean[][] heightfieldBlocker;
public NavBlocker(){ public NavBlocker(){
heightfieldBlocker = new boolean[Globals.serverTerrainManager.getAugmentedChunkWidth()][Globals.serverTerrainManager.getAugmentedChunkWidth()]; heightfieldBlocker = new boolean[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION];
} }
public NavBlocker(boolean[][] field){ public NavBlocker(boolean[][] field){

View File

@ -89,8 +89,8 @@ public class SaveUtils {
String dbFilePath = FileUtils.sanitizeFilePath(dirPath) + "/central.db"; String dbFilePath = FileUtils.sanitizeFilePath(dirPath) + "/central.db";
Globals.dbController.connect(dbFilePath); Globals.dbController.connect(dbFilePath);
if(!saveName.equals("arena")){ if(!saveName.equals("arena")){
Globals.serverTerrainManager.load(saveName);
Globals.serverWorldData = FileUtils.loadObjectFromSavePath(saveName, "world.json", ServerWorldData.class); Globals.serverWorldData = FileUtils.loadObjectFromSavePath(saveName, "world.json", ServerWorldData.class);
Globals.serverTerrainManager.load(saveName);
} }
return true; return true;
} }
@ -106,7 +106,7 @@ public class SaveUtils {
} }
public static boolean loadTerrainAndCreateWorldData(String currentSaveName){ public static boolean loadTerrainAndCreateWorldData(String currentSaveName){
Globals.serverTerrainManager = new ServerTerrainManager(2000,50,ServerTerrainManager.SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO,0.0f,0); Globals.serverTerrainManager = new ServerTerrainManager(2000,50,0.0f,0);
SaveUtils.loadTerrainAndDB(currentSaveName); SaveUtils.loadTerrainAndDB(currentSaveName);
Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager); Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager);
Globals.realmManager.createGriddedRealm(Globals.serverWorldData); Globals.realmManager.createGriddedRealm(Globals.serverWorldData);

View File

@ -0,0 +1,92 @@
package electrosphere.server.terrain.diskcache;
import java.util.Map;
import electrosphere.net.server.Server;
import electrosphere.server.terrain.manager.ServerTerrainChunk;
import electrosphere.util.FileUtils;
/**
* An interface for accessing the disk cache of chunk information
*/
public class ChunkDiskCache {
//The map of world position+chunk type to the file that actually houses that information
Map<String,String> worldPosFileMap;
/**
* Constructor
*/
public ChunkDiskCache(){
}
/**
* Gets a key for a given chunk file based on a world coordinate
* @param worldX The x component
* @param worldY The y component
* @param worldZ The z component
* @return The key
*/
private static String getTerrainChunkKey(int worldX, int worldY, int worldZ){
return worldX + "_" + worldY + "_" + worldZ + "t";
}
/**
* Gets a key for a given chunk file based on a world coordinate
* @param worldX The x component
* @param worldY The y component
* @param worldZ The z component
* @return The key
*/
private static String getFluidChunkKey(int worldX, int worldY, int worldZ){
return worldX + "_" + worldY + "_" + worldZ + "f";
}
/**
* Initializes a diskcache based on a given save name
* @param saveName The save name
*/
public void init(String saveName){
worldPosFileMap = FileUtils.loadObjectFromSavePath(saveName, "ChunkCache.map", Map.class);
}
/**
* Checks if the cache contains a given chunk position
* @param worldX The x component
* @param worldY The y component
* @param worldZ The z component
* @return True if the cache contains the chunk, false otherwise
*/
public boolean containsTerrainAtPosition(int worldX, int worldY, int worldZ){
return worldPosFileMap.containsKey(getTerrainChunkKey(worldX, worldY, worldZ));
}
/**
* Checks if the cache contains a given chunk position
* @param worldX The x component
* @param worldY The y component
* @param worldZ The z component
* @return True if the cache contains the chunk, false otherwise
*/
public boolean containsFluidAtPosition(int worldX, int worldY, int worldZ){
return worldPosFileMap.containsKey(getFluidChunkKey(worldX, worldY, worldZ));
}
/**
* Gets the server terrain chunk from disk if it exists, otherwise returns null
* @param worldX The x coordinate
* @param worldY The y coordinate
* @param worldZ The z coordinate
* @return The server terrain chunk if it exists, null otherwise
*/
public ServerTerrainChunk getTerrainChunk(int worldX, int worldY, int worldZ){
ServerTerrainChunk rVal = null;
if(containsTerrainAtPosition(worldX, worldY, worldZ)){
String fileName = worldPosFileMap.get(getTerrainChunkKey(worldX, worldY, worldZ));
//TODO: implement
}
return rVal;
}
}

View File

@ -49,13 +49,16 @@ public class TerrainEditing {
float distance = (float)new Vector3d(Math.floor(offsetPos.x),Math.floor(offsetPos.y),Math.floor(offsetPos.z)).distance(position); float distance = (float)new Vector3d(Math.floor(offsetPos.x),Math.floor(offsetPos.y),Math.floor(offsetPos.z)).distance(position);
float currentPositionMagnitude = editMagnitude - distance; float currentPositionMagnitude = editMagnitude - distance;
ServerTerrainChunk data = voxelCellManager.getChunkAtPosition(chunkPos); ServerTerrainChunk data;
if( if(
voxelPos.x < ServerTerrainChunk.CHUNK_DIMENSION && voxelPos.x < ServerTerrainChunk.CHUNK_DIMENSION &&
voxelPos.y < ServerTerrainChunk.CHUNK_DIMENSION && voxelPos.y < ServerTerrainChunk.CHUNK_DIMENSION &&
voxelPos.z < ServerTerrainChunk.CHUNK_DIMENSION && voxelPos.z < ServerTerrainChunk.CHUNK_DIMENSION &&
voxelPos.x > 0 &&
voxelPos.y > 0 &&
voxelPos.z > 0 &&
currentPositionMagnitude > 0 && currentPositionMagnitude > 0 &&
data != null (data = voxelCellManager.getChunkAtPosition(chunkPos)) != null
){ ){
float current = data.getWeights()[voxelPos.x][voxelPos.y][voxelPos.z]; float current = data.getWeights()[voxelPos.x][voxelPos.y][voxelPos.z];
//hard clamp so it doesn't go over 1 //hard clamp so it doesn't go over 1

View File

@ -171,29 +171,29 @@ public class TerrainGenerator {
//create internal renderer //create internal renderer
createRenderer(); // createRenderer();
boolean test = true; // boolean test = true;
while(test){ // while(test){
if(brightnessIncreasing){ // if(brightnessIncreasing){
if(brightness < 100){ // if(brightness < 100){
brightness++; // brightness++;
} else { // } else {
} // }
} else { // } else {
if(brightness > 0){ // if(brightness > 0){
brightness--; // brightness--;
} else { // } else {
brightnessIncreasing = true; // brightnessIncreasing = true;
displayToggle++; // displayToggle++;
if(displayToggle > 1){ // if(displayToggle > 1){
displayToggle = 0; // displayToggle = 0;
} // }
} // }
} // }
frame.repaint(); // frame.repaint();
Utilities.sleep(10); // Utilities.sleep(10);
} // }
return rVal; return rVal;
} }

View File

@ -1,20 +1,18 @@
package electrosphere.server.terrain.manager; package electrosphere.server.terrain.manager;
import com.google.gson.Gson; import com.google.gson.Gson;
import electrosphere.engine.Globals;
import electrosphere.game.terrain.processing.TerrainInterpolator; import electrosphere.game.terrain.processing.TerrainInterpolator;
import electrosphere.server.terrain.generation.TerrainGenerator; import electrosphere.server.terrain.generation.TerrainGenerator;
import electrosphere.server.terrain.models.ModificationList;
import electrosphere.server.terrain.models.TerrainModel; import electrosphere.server.terrain.models.TerrainModel;
import electrosphere.server.terrain.models.TerrainModification; import electrosphere.server.terrain.models.TerrainModification;
import electrosphere.engine.Globals;
import electrosphere.util.FileUtils; import electrosphere.util.FileUtils;
import electrosphere.util.Utilities;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -36,8 +34,6 @@ public class ServerTerrainManager {
//The vertical multiplier applied to the statically generated terrain //The vertical multiplier applied to the statically generated terrain
int verticalInterpolationRatio; int verticalInterpolationRatio;
int dynamicInterpolationRatio;
float interpolationRandomDampener; float interpolationRandomDampener;
long seed; long seed;
@ -59,10 +55,9 @@ public class ServerTerrainManager {
public ServerTerrainManager(int worldSizeDiscrete, int verticalInterpolationRatio, int dynamicInterpolationRatio, float interpolationRandomDampener, long seed){ public ServerTerrainManager(int worldSizeDiscrete, int verticalInterpolationRatio, float interpolationRandomDampener, long seed){
this.worldSizeDiscrete = worldSizeDiscrete; this.worldSizeDiscrete = worldSizeDiscrete;
this.verticalInterpolationRatio = verticalInterpolationRatio; this.verticalInterpolationRatio = verticalInterpolationRatio;
this.dynamicInterpolationRatio = dynamicInterpolationRatio;
this.chunkCache = new ConcurrentHashMap<String, ServerTerrainChunk>(); this.chunkCache = new ConcurrentHashMap<String, ServerTerrainChunk>();
this.chunkCacheContents = new CopyOnWriteArrayList<String>(); this.chunkCacheContents = new CopyOnWriteArrayList<String>();
this.interpolationRandomDampener = interpolationRandomDampener; this.interpolationRandomDampener = interpolationRandomDampener;
@ -77,7 +72,6 @@ public class ServerTerrainManager {
ServerTerrainManager rVal = new ServerTerrainManager(); ServerTerrainManager rVal = new ServerTerrainManager();
rVal.worldSizeDiscrete = 2; rVal.worldSizeDiscrete = 2;
rVal.verticalInterpolationRatio = 0; rVal.verticalInterpolationRatio = 0;
rVal.dynamicInterpolationRatio = SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO;
rVal.chunkCache = new ConcurrentHashMap<String, ServerTerrainChunk>(); rVal.chunkCache = new ConcurrentHashMap<String, ServerTerrainChunk>();
rVal.chunkCacheContents = new CopyOnWriteArrayList<String>(); rVal.chunkCacheContents = new CopyOnWriteArrayList<String>();
rVal.interpolationRandomDampener = 0.0f; rVal.interpolationRandomDampener = 0.0f;
@ -88,115 +82,47 @@ public class ServerTerrainManager {
TerrainGenerator terrainGen = new TerrainGenerator(); TerrainGenerator terrainGen = new TerrainGenerator();
terrainGen.setInterpolationRatio(worldSizeDiscrete/200); terrainGen.setInterpolationRatio(worldSizeDiscrete/200);
terrainGen.setVerticalInterpolationRatio(verticalInterpolationRatio); terrainGen.setVerticalInterpolationRatio(verticalInterpolationRatio);
terrainGen.setDynamicInterpolationRatio(dynamicInterpolationRatio);
terrainGen.setRandomSeed(seed); terrainGen.setRandomSeed(seed);
model = terrainGen.generateModel(); model = terrainGen.generateModel();
model.setInterpolationRandomDampener(interpolationRandomDampener); model.setInterpolationRandomDampener(interpolationRandomDampener);
} }
public void save(String path){ /**
Gson gson = new Gson(); * Saves the terrain model backing this manager to a save file
String terrainOutRaw = gson.toJson(model); * @param saveName The name of the save
try { */
Files.write(new File(path + "./terrain.json").toPath(), terrainOutRaw.getBytes()); public void save(String saveName){
} catch (IOException ex) { ByteBuffer buffer = ByteBuffer.allocate(model.getElevation().length * model.getElevation()[0].length * 4);
ex.printStackTrace(); FloatBuffer floatView = buffer.asFloatBuffer();
for(int x = 0; x < model.getElevation().length; x++){
floatView.put(model.getElevation()[x]);
} }
floatView.flip();
FileUtils.saveBinaryToSavePath(saveName, "./terrain.dat", buffer.array());
FileUtils.serializeObjectToSavePath(saveName, "./terrain.json", model);
} }
public void load(String saveName){ public void load(String saveName){
model = FileUtils.loadObjectFromSavePath(saveName, "./terrain.json", TerrainModel.class); model = FileUtils.loadObjectFromSavePath(saveName, "./terrain.json", TerrainModel.class);
byte[] data = FileUtils.loadBinaryFromSavePath(saveName, "./terrain.dat");
ByteBuffer buffer = ByteBuffer.wrap(data);
FloatBuffer floatView = buffer.asFloatBuffer();
float[][] elevation = new float[Globals.serverWorldData.getWorldSizeDiscrete()][Globals.serverWorldData.getWorldSizeDiscrete()];
for(int x = 0; x < Globals.serverWorldData.getWorldSizeDiscrete(); x++){
for(int y = 0; y < Globals.serverWorldData.getWorldSizeDiscrete(); y++){
elevation[x][y] = floatView.get();
}
}
model.setElevationArray(elevation);
} }
public float[][] getTerrainAtChunk(int x, int y){ public float[][] getTerrainAtChunk(int x, int y){
return model.getElevationForChunk(x, y); return model.getElevationForChunk(x, y);
} }
// 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 double getHeightAtPosition(double x, double y, double z){ public double getHeightAtPosition(double x, double y, double z){
//get chunk coordinate space of input x,y
// int chunkX = (int)Math.floor(x / dynamicInterpolationRatio);
// int chunkY = (int)Math.floor(y / dynamicInterpolationRatio);
// int chunkZ = (int)Math.floor(z / dynamicInterpolationRatio);
// //get local coordinate space of input x,y
// double localX = x - chunkX * dynamicInterpolationRatio;
// double localY = y - chunkY * dynamicInterpolationRatio;
// double localZ = z - chunkZ * dynamicInterpolationRatio;
// //get chunk elevation map
// float[][] chunkElevationMap = getChunk(chunkX,chunkY,chunkZ).heightMap;
// //floored variants of local values
// int localXf = (int)Math.floor(localX);
// int localYf = (int)Math.floor(localY);
// int localZf = (int)Math.floor(localZ);
// /*
// Average some inner value.
// 01 11
// 0.3 0.4 0.5
// 0.1 0.2 0.3
// 00 10
// */
// //interp elevation from map
// float elevation00 = chunkElevationMap[(int)localX+0][(int)localY+0];
// float elevation10 = chunkElevationMap[(int)localX+1][(int)localY+0];
// float elevation01 = chunkElevationMap[(int)localX+0][(int)localY+1];
// float elevation11 = chunkElevationMap[(int)localX+1][(int)localY+1];
// double rVal =
// (1-(localX-localXf))*(1-(localY-localYf)) * elevation00 +
// ( (localX-localXf))*(1-(localY-localYf)) * elevation10 +
// (1-(localX-localXf))*( (localY-localYf)) * elevation01 +
// ( (localX-localXf))*( (localY-localYf)) * elevation11
// ;
return y; return y;
} }
public int getChunkWidth(){
return dynamicInterpolationRatio;
}
public int getAugmentedChunkWidth(){
return dynamicInterpolationRatio + 1;
}
public int getWorldDiscreteSize(){ public int getWorldDiscreteSize(){
return worldSizeDiscrete; return worldSizeDiscrete;
@ -229,36 +155,6 @@ public class ServerTerrainManager {
return 0.0f; return 0.0f;
} }
} }
// public float[][] getMacroValues(int x, int y){
// //THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING
// if(model != null){
// return model.getMacroValuesAtPosition(x, y);
// } else {
// //THIS FIRES IF THERE IS AN ARENA WORLD RUNNING
// return new float[3][3];
// }
// }
// public 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 TerrainModel getModel() { public TerrainModel getModel() {
return model; return model;
@ -294,9 +190,13 @@ public class ServerTerrainManager {
for(int weightX = 0; weightX < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; weightX++){ for(int weightX = 0; weightX < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; weightX++){
for(int weightY = 0; weightY < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; weightY++){ for(int weightY = 0; weightY < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; weightY++){
for(int weightZ = 0; weightZ < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; weightZ++){ for(int weightZ = 0; weightZ < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; weightZ++){
if(weightY < heightmap[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE * worldX + weightX][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE * worldZ + weightZ]){ float height = heightmap[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE * worldX + weightX][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE * worldZ + weightZ];
if(weightY < height){
weights[weightX][weightY][weightZ] = 1; weights[weightX][weightY][weightZ] = 1;
values[weightX][weightY][weightZ] = 1; values[weightX][weightY][weightZ] = 1;
} else if(height == 0 && weightY == 0 && worldY == 0) {
weights[weightX][weightY][weightZ] = 0.1f;
values[weightX][weightY][weightZ] = 1;
} else { } else {
weights[weightX][weightY][weightZ] = -1; weights[weightX][weightY][weightZ] = -1;
values[weightX][weightY][weightZ] = 0; values[weightX][weightY][weightZ] = 0;
@ -304,12 +204,6 @@ public class ServerTerrainManager {
} }
} }
} }
// ModificationList modificationList = model.getModifications(x, y);
// if(modificationList != null){
// for(TerrainModification modification : modificationList.getModifications()){
// heightmap = modification.applyToHeightfield(heightmap);
// }
// }
if(chunkCacheContents.size() > cacheSize){ if(chunkCacheContents.size() > cacheSize){
String oldChunk = chunkCacheContents.remove(chunkCacheContents.size() - 1); String oldChunk = chunkCacheContents.remove(chunkCacheContents.size() - 1);
chunkCache.remove(oldChunk); chunkCache.remove(oldChunk);

View File

@ -6,13 +6,16 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import electrosphere.util.annotation.Exclude;
public class TerrainModel { public class TerrainModel {
int dynamicInterpolationRatio; int dynamicInterpolationRatio;
float interpolationRandomDampener = 0.4f; float interpolationRandomDampener = 0.4f;
int discreteArrayDimension; int discreteArrayDimension;
float[][] elevation; @Exclude
private float[][] elevation;
float realMountainThreshold; float realMountainThreshold;
float realOceanThreshold; float realOceanThreshold;
@ -345,5 +348,13 @@ public class TerrainModel {
// System.out.println("Got modifications at " + worldX + " " + worldY); // System.out.println("Got modifications at " + worldX + " " + worldY);
return modifications.get(getModificationKey(worldX, worldY, worldZ)); return modifications.get(getModificationKey(worldX, worldY, worldZ));
} }
/**
* Sets the elevation array (For instance when read from save file on loading a save)
* @param elevation The elevation array to set to
*/
public void setElevationArray(float[][] elevation){
this.elevation = elevation;
}
} }

View File

@ -6,6 +6,7 @@ import com.google.gson.GsonBuilder;
import electrosphere.engine.Main; import electrosphere.engine.Main;
import electrosphere.game.data.creature.type.movement.MovementSystem; import electrosphere.game.data.creature.type.movement.MovementSystem;
import electrosphere.game.data.creature.type.movement.MovementSystemSerializer; import electrosphere.game.data.creature.type.movement.MovementSystemSerializer;
import electrosphere.util.annotation.AnnotationExclusionStrategy;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
@ -26,6 +27,8 @@ public class FileUtils {
static { static {
GsonBuilder gsonBuilder = new GsonBuilder(); GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(MovementSystem.class, new MovementSystemSerializer()); gsonBuilder.registerTypeAdapter(MovementSystem.class, new MovementSystemSerializer());
gsonBuilder.addDeserializationExclusionStrategy(new AnnotationExclusionStrategy());
gsonBuilder.addSerializationExclusionStrategy(new AnnotationExclusionStrategy());
gson = gsonBuilder.create(); gson = gsonBuilder.create();
} }
@ -209,6 +212,39 @@ public class FileUtils {
ex.printStackTrace(); ex.printStackTrace();
} }
} }
/**
* Reads a binary file as an array of bytes
* @param saveName The save name
* @param pathName The path within the save folder
* @return The array of bytes
*/
public static byte[] loadBinaryFromSavePath(String saveName, String pathName){
byte[] rVal = null;
String sanitizedFilePath = sanitizeFilePath(pathName);
try {
rVal = Files.readAllBytes(getSaveFile(saveName,sanitizedFilePath).toPath());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return rVal;
}
/**
* Writes a binary file to a save folder's file
* @param saveName The name of the save
* @param pathName The path within the save folder
* @param data The data to write
*/
public static void saveBinaryToSavePath(String saveName, String pathName, byte[] data){
String sanitizedFilePath = sanitizeFilePath(pathName);
try {
Files.write(getSaveFile(saveName,sanitizedFilePath).toPath(), data);
} catch (IOException ex) {
ex.printStackTrace();
}
}
/** /**
* Checks if a directory exists * Checks if a directory exists

View File

@ -0,0 +1,22 @@
package electrosphere.util.annotation;
import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
/**
* Used to exclude single fields from a gson serialization in a black list manner.
* Refer to https://stackoverflow.com/a/27986860/ for reference for why this works and what it is.
*/
public class AnnotationExclusionStrategy implements ExclusionStrategy {
@Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getAnnotation(Exclude.class) != null;
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
}

View File

@ -0,0 +1,17 @@
package electrosphere.util.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
/**
* Used to exclude single fields from a gson serialization in a black list manner.
* Refer to https://stackoverflow.com/a/27986860/ for reference for why this works and what it is.
*/
public @interface Exclude {
}

View File

@ -19,7 +19,7 @@ public class TerrainViewer {
TerrainModel terrainModel; TerrainModel terrainModel;
ServerTerrainManager terrainManager = new ServerTerrainManager(2000, 1000, 100, 0.05f, new Random().nextLong()); ServerTerrainManager terrainManager = new ServerTerrainManager(2000, 1000, 0.05f, new Random().nextLong());
terrainManager.generate(); terrainManager.generate();
terrainModel = terrainManager.getModel(); terrainModel = terrainManager.getModel();