work on scenes and hooks

This commit is contained in:
austin 2024-07-13 15:26:29 -04:00
parent 068f3979b8
commit 67bdc8ec67
32 changed files with 354 additions and 160 deletions

View File

@ -0,0 +1,8 @@
{
"entities": [
],
"scriptPaths": [
"Scenes/testscene1/someScript.js"
],
"initScriptPath": "Scenes/testscene1/someScript.js"
}

View File

@ -0,0 +1,13 @@
import { Scene } from "/Scripts/types/scene";
/**
* The main scene interface
*/
const TestScene1: Scene = {
}
/**
* The scene to export
*/
export default TestScene1

View File

@ -1,3 +1,3 @@
#maven.buildNumber.plugin properties file
#Fri Jul 12 17:46:19 EDT 2024
buildNumber=182
#Fri Jul 12 17:55:57 EDT 2024
buildNumber=183

View File

@ -1,4 +1,5 @@
+ spawn into the world
Server commands client to load a given scene file
+ there is a sword lying on the ground
+ when you grab the sword, a tutorial popup appears to tell you how to use in
fire a script on a hook

View File

@ -63,6 +63,13 @@
"entityId",
"bTreeId"
]
},
{
"messageName" : "LoadScene",
"description" : "Instructs the client to load a given scene",
"data" : [
"stringValue"
]
}
]
}

View File

@ -74,6 +74,7 @@ import electrosphere.server.datacell.RealmManager;
import electrosphere.server.db.DatabaseController;
import electrosphere.server.fluid.manager.ServerFluidManager;
import electrosphere.server.pathfinding.NavMeshManager;
import electrosphere.server.saves.Save;
import electrosphere.server.simulation.MacroSimulation;
import electrosphere.server.simulation.MicroSimulation;
import electrosphere.server.terrain.manager.ServerTerrainManager;
@ -170,7 +171,7 @@ public class Globals {
//
// Game Save stuff
//
public static String currentSaveName = "default";
public static Save currentSave = null;
//

View File

@ -1,19 +1,8 @@
package electrosphere.engine.loadingthreads;
import java.util.Random;
import org.joml.Quaternionf;
import org.joml.Vector3d;
import electrosphere.engine.Globals;
import electrosphere.engine.assetmanager.AssetDataStrings;
import electrosphere.entity.ClientEntityUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityCreationUtils;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.ServerEntityUtils;
import electrosphere.entity.types.object.ObjectUtils;
import electrosphere.game.server.world.ServerWorldData;
import electrosphere.logger.LoggerInterface;
import electrosphere.server.content.ServerContentManager;
@ -24,7 +13,7 @@ import electrosphere.util.FileUtils;
public class ArenaLoading {
protected static void loadArenaGameServer(){
protected static void loadArenaGameServer(Object[] params){
//init server arena terrain manager separately
initServerArenaTerrainManager();
//init the data of the world

View File

@ -31,7 +31,7 @@ import electrosphere.util.MathUtils;
public class ClientLoading {
protected static void loadMainMenu(){
protected static void loadMainMenu(Object[] params){
Window loadingWindow = (Window)Globals.elementManager.getWindow(WindowStrings.WINDOW_LOADING);
WindowUtils.recursiveSetVisible(loadingWindow,false);
WindowUtils.focusWindow(WindowStrings.WINDOW_MENU_MAIN);
@ -39,7 +39,7 @@ public class ClientLoading {
}
protected static void loadCharacterServer(){
protected static void loadCharacterServer(Object[] params){
Window loadingWindow = (Window)Globals.elementManager.getWindow(WindowStrings.WINDOW_LOADING);
WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_MAIN), false);
WindowUtils.replaceMainMenuContents(MenuGenerators.createEmptyMainMenu());
@ -71,7 +71,7 @@ public class ClientLoading {
}
protected static void loadClientWorld(){
protected static void loadClientWorld(Object[] params){
Window loadingWindow = (Window)Globals.elementManager.getWindow(WindowStrings.WINDOW_LOADING);
WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_MAIN), false);
WindowUtils.replaceMainMenuContents(MenuGenerators.createEmptyMainMenu());

View File

@ -2,12 +2,8 @@ package electrosphere.engine.loadingthreads;
import java.util.concurrent.TimeUnit;
import org.joml.Vector3f;
import electrosphere.auth.AuthenticationManager;
import electrosphere.client.targeting.crosshair.Crosshair;
import electrosphere.engine.Globals;
import electrosphere.entity.types.camera.CameraEntityUtils;
import electrosphere.game.server.world.ServerWorldData;
import electrosphere.logger.LoggerInterface;
import electrosphere.menu.MenuGenerators;
@ -23,12 +19,11 @@ import electrosphere.server.saves.SaveUtils;
import electrosphere.server.terrain.generation.OverworldChunkGenerator;
import electrosphere.server.terrain.manager.ServerTerrainManager;
import electrosphere.util.FileUtils;
import electrosphere.controls.ControlHandler;
public class DebugSPWorldLoading {
protected static void loadDebugSPWorld(){
protected static void loadDebugSPWorld(Object[] params){
Window loadingWindow = (Window)Globals.elementManager.getWindow(WindowStrings.WINDOW_LOADING);
//show loading
WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_MAIN), false);
@ -36,24 +31,24 @@ public class DebugSPWorldLoading {
loadingWindow.setVisible(true);
Globals.serverTerrainManager = new ServerTerrainManager(2000,50,0.0f,0, new OverworldChunkGenerator());
Globals.currentSaveName = "random_sp_world";
if(!SaveUtils.getSaves().contains(Globals.currentSaveName)){
String saveName = "random_sp_world";
if(!SaveUtils.getSaves().contains(saveName)){
//
//the juicy server GENERATION part
//
//init save structure
SaveUtils.createOrOverwriteSave(Globals.currentSaveName);
SaveUtils.createOrOverwriteSave(saveName);
//create terrain
Globals.serverTerrainManager.generate();
Globals.serverTerrainManager.save(Globals.currentSaveName);
Globals.serverTerrainManager.save(saveName);
//create world.json
Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager);
FileUtils.serializeObjectToSavePath(Globals.currentSaveName, "./world.json", Globals.serverWorldData);
FileUtils.serializeObjectToSavePath(saveName, "./world.json", Globals.serverWorldData);
//create mock fluid sim manager
Globals.serverFluidManager = new ServerFluidManager(Globals.serverTerrainManager, 2000, 50, 0.0f, 0, new ArenaFluidGenerator());
}
//load just-created save
SaveUtils.loadSave(Globals.currentSaveName);
SaveUtils.loadSave(saveName);
//start initializing game datastructures
// Globals.griddedDataCellManager.init(Globals.serverWorldData);
//initialize the "virtual" objects simulation
@ -102,7 +97,7 @@ public class DebugSPWorldLoading {
Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestMetadataMessage());
//Run client startup process
ClientLoading.loadClientWorld();
ClientLoading.loadClientWorld(params);
}
}

View File

@ -1,10 +1,10 @@
package electrosphere.engine.loadingthreads;
import electrosphere.engine.Globals;
import electrosphere.menu.WindowStrings;
import electrosphere.menu.WindowUtils;
import electrosphere.menu.mainmenu.MenuGeneratorsDemo;
import electrosphere.renderer.ui.elements.Window;
// import electrosphere.engine.Globals;
// import electrosphere.menu.WindowStrings;
// import electrosphere.menu.WindowUtils;
// import electrosphere.menu.mainmenu.MenuGeneratorsDemo;
// import electrosphere.renderer.ui.elements.Window;
/**
* Loading routines for the demo version of the game
@ -17,15 +17,16 @@ public class DemoLoading {
/**
* Loads the title menu elements for the demo version of the engine
*/
public static void loadDemoMenu(){
Globals.currentSaveName = DEMO_LEVEL_PATH;
public static void loadDemoMenu(Object[] params){
throw new UnsupportedOperationException("Need to find a way to load just the demo level path");
// String savePath = DEMO_LEVEL_PATH;
WindowUtils.replaceMainMenuContents(MenuGeneratorsDemo.createTitleMenu());
// WindowUtils.replaceMainMenuContents(MenuGeneratorsDemo.createTitleMenu());
Window loadingWindow = (Window)Globals.elementManager.getWindow(WindowStrings.WINDOW_LOADING);
WindowUtils.recursiveSetVisible(loadingWindow,false);
WindowUtils.focusWindow(WindowStrings.WINDOW_MENU_MAIN);
WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_MAIN), true);
// Window loadingWindow = (Window)Globals.elementManager.getWindow(WindowStrings.WINDOW_LOADING);
// WindowUtils.recursiveSetVisible(loadingWindow,false);
// WindowUtils.focusWindow(WindowStrings.WINDOW_MENU_MAIN);
// WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_MAIN), true);
}
}

View File

@ -4,7 +4,6 @@ import java.util.concurrent.TimeUnit;
import electrosphere.auth.AuthenticationManager;
import electrosphere.engine.Globals;
import electrosphere.game.server.world.ServerWorldData;
import electrosphere.logger.LoggerInterface;
import electrosphere.menu.MenuGenerators;
import electrosphere.menu.WindowStrings;
@ -13,13 +12,9 @@ import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.renderer.ui.elements.Window;
import electrosphere.server.content.ServerContentManager;
import electrosphere.server.fluid.generation.ArenaFluidGenerator;
import electrosphere.server.fluid.manager.ServerFluidManager;
import electrosphere.server.saves.SaveUtils;
import electrosphere.server.terrain.generation.ArenaChunkGenerator;
import electrosphere.server.terrain.generation.OverworldChunkGenerator;
import electrosphere.server.terrain.manager.ServerTerrainManager;
import electrosphere.util.FileUtils;
/**
* Loads the level editor
@ -29,27 +24,25 @@ public class LevelEditorLoading {
/**
* Loads the level editor
*/
protected static void loadLevelEditor(){
protected static void loadLevelEditor(Object[] params){
if(params.length < 1){
throw new IllegalStateException("Trying to load level editor with insufficient params");
}
String saveName = (String)params[0];
Window loadingWindow = (Window)Globals.elementManager.getWindow(WindowStrings.WINDOW_LOADING);
//show loading
WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_MAIN), false);
WindowUtils.replaceMainMenuContents(MenuGenerators.createEmptyMainMenu());
loadingWindow.setVisible(true);
Globals.serverTerrainManager = new ServerTerrainManager(3,1,0.0f,0, new ArenaChunkGenerator());
if(!SaveUtils.getSaves().contains(Globals.currentSaveName)){
if(!SaveUtils.getSaves().contains(saveName)){
//init save structure
SaveUtils.createOrOverwriteSave(Globals.currentSaveName);
//create world.json
Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager);
FileUtils.serializeObjectToSavePath(Globals.currentSaveName, "./world.json", Globals.serverWorldData);
//create mock fluid sim manager
Globals.serverFluidManager = new ServerFluidManager(Globals.serverTerrainManager, 3, 1, 0.0f, 0, new ArenaFluidGenerator());
//save terrain manager
Globals.serverTerrainManager.save(Globals.currentSaveName);
SaveUtils.createOrOverwriteSave(saveName);
}
//load just-created save
SaveUtils.loadSave(Globals.currentSaveName);
SaveUtils.loadSave(saveName);
//init server content manager
Globals.serverContentManager = ServerContentManager.createServerContentManager(false);
@ -96,7 +89,7 @@ public class LevelEditorLoading {
Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestMetadataMessage());
//Run client startup process
ClientLoading.loadClientWorld();
ClientLoading.loadClientWorld(params);
}
}

View File

@ -22,7 +22,12 @@ public class LevelLoading {
/**
* Loads the level editor
*/
protected static void loadLevel(){
protected static void loadLevel(Object[] params){
if(params.length < 1){
throw new IllegalStateException("Trying to load level editor with insufficient params");
}
String saveName = (String)params[0];
Window loadingWindow = (Window)Globals.elementManager.getWindow(WindowStrings.WINDOW_LOADING);
//show loading
WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_MAIN), false);
@ -30,7 +35,7 @@ public class LevelLoading {
loadingWindow.setVisible(true);
//load just-created save
SaveUtils.loadSave(Globals.currentSaveName);
SaveUtils.loadSave(saveName);
//init server content manager
Globals.serverContentManager = ServerContentManager.createServerContentManager(false);
@ -54,6 +59,8 @@ public class LevelLoading {
e.printStackTrace();
}
}
//load level on server
//initialize the "real" objects simulation
LoadingUtils.initMicroSimulation();
//init game specific stuff (ie different skybox colors)
@ -77,7 +84,7 @@ public class LevelLoading {
Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestMetadataMessage());
//Run client startup process
ClientLoading.loadClientWorld();
ClientLoading.loadClientWorld(params);
}

View File

@ -19,6 +19,9 @@ public class LoadingThread extends Thread {
//the type of loading to do
int threadType;
//the params provided to this thread in particular
Object[] params;
//a lock to track when the loading had completed and block until then
Semaphore lock;
@ -26,9 +29,11 @@ public class LoadingThread extends Thread {
/**
* Creates the work for a loading thread
* @param type The type of thread
* @param params The params provided to the thread
*/
public LoadingThread(int type){
public LoadingThread(int type, Object ... params){
threadType = type;
this.params = params;
lock = new Semaphore(1);
}
@ -38,44 +43,44 @@ public class LoadingThread extends Thread {
switch(threadType){
case LOAD_TITLE_MENU: {
ClientLoading.loadMainMenu();
ClientLoading.loadMainMenu(this.params);
} break;
case LOAD_MAIN_GAME: {
ServerLoading.loadMainGameServer();
ServerLoading.loadMainGameServer(this.params);
} break;
case LOAD_ARENA: {
ArenaLoading.loadArenaGameServer();
ArenaLoading.loadArenaGameServer(this.params);
} break;
case LOAD_CHARACTER_SERVER: {
ClientLoading.loadCharacterServer();
ClientLoading.loadCharacterServer(this.params);
} break;
case LOAD_CLIENT_WORLD: {
ClientLoading.loadClientWorld();
ClientLoading.loadClientWorld(this.params);
} break;
//intended to act like you went through the steps of setting up a vanilla settings SP world
case LOAD_DEBUG_RANDOM_SP_WORLD: {
DebugSPWorldLoading.loadDebugSPWorld();
DebugSPWorldLoading.loadDebugSPWorld(this.params);
} break;
//loads the level editor
case LOAD_LEVEL_EDITOR: {
LevelEditorLoading.loadLevelEditor();
LevelEditorLoading.loadLevelEditor(this.params);
} break;
//loads the save in Globals.currentSave as a level
case LOAD_LEVEL: {
LevelLoading.loadLevel();
LevelLoading.loadLevel(this.params);
} break;
//the demo menu ui
case LOAD_DEMO_MENU: {
DemoLoading.loadDemoMenu();
DemoLoading.loadDemoMenu(this.params);
} break;
}

View File

@ -1,33 +1,18 @@
package electrosphere.engine.loadingthreads;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.concurrent.TimeUnit;
import org.joml.Quaternionf;
import org.joml.Vector2i;
import org.joml.Vector3d;
import org.joml.Vector3f;
import org.joml.Vector3i;
import electrosphere.auth.AuthenticationManager;
import electrosphere.client.terrain.cells.DrawCellManager;
import electrosphere.collision.CollisionWorldData;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.ServerEntityUtils;
import electrosphere.entity.state.movement.ApplyRotationTree;
import electrosphere.entity.types.creature.CreatureTemplate;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.game.data.creature.type.CreatureType;
import electrosphere.game.data.creature.type.visualattribute.VisualAttribute;
import electrosphere.game.server.town.Town;
import electrosphere.game.server.world.MacroData;
import electrosphere.game.server.world.ServerWorldData;
import electrosphere.net.NetUtils;
@ -36,9 +21,7 @@ import electrosphere.net.parser.net.message.CharacterMessage;
import electrosphere.net.server.Server;
import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.net.server.player.Player;
import electrosphere.server.datacell.GriddedDataCellManager;
import electrosphere.server.datacell.Realm;
import electrosphere.server.saves.SaveUtils;
import electrosphere.server.simulation.MacroSimulation;
import electrosphere.server.simulation.MicroSimulation;
import electrosphere.server.terrain.generation.OverworldChunkGenerator;
@ -58,38 +41,6 @@ public class LoadingUtils {
*/
float randomDampener = 0.0f; //0.25f;
Globals.serverTerrainManager = new ServerTerrainManager(2000,50,randomDampener,0,new OverworldChunkGenerator());
if(Globals.userSettings.gameplayGenerateWorld()){
Globals.serverTerrainManager.generate();
Globals.serverTerrainManager.save("./terrain.json");
} else {
SaveUtils.loadSave(Globals.currentSaveName);
}
/*
Set spawn point
*/
int playerStartX = 0;
int playerStartY = 0;
int discreteSize = Globals.serverTerrainManager.getWorldDiscreteSize();
boolean found = false;
for(int x = 0; x < discreteSize; x++){
for(int y = 0; y < discreteSize; y++){
if(Globals.serverTerrainManager.getDiscreteValue(x, y)>1800){
playerStartX = x;
playerStartY = y;
found = true;
}
if(found){
break;
}
}
if(found){
break;
}
}
// Globals.spawnPoint = new Vector3f(playerStartX * chunkSize, Globals.serverTerrainManager.getHeightAtPosition(playerStartX * chunkSize,playerStartY * chunkSize), playerStartY * chunkSize);
}

View File

@ -2,14 +2,13 @@ package electrosphere.engine.loadingthreads;
import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface;
import electrosphere.server.saves.SaveUtils;
import electrosphere.server.terrain.generation.OverworldChunkGenerator;
import electrosphere.server.terrain.manager.ServerTerrainManager;
public class ServerLoading {
protected static void loadMainGameServer(){
protected static void loadMainGameServer(Object[] params){
//initialize the terrain manager (server only)
// if(Globals.RUN_SERVER){
// initServerGameTerrainManager();
@ -17,7 +16,7 @@ public class ServerLoading {
//TODO: Globals.serverTerrainManager = new ServerTerrainManager(2000,50,100,randomDampener,0);
Globals.serverTerrainManager = new ServerTerrainManager(2000,50,0.0f,0, new OverworldChunkGenerator());
SaveUtils.loadSave(Globals.currentSaveName);
// SaveUtils.loadSave(Globals.currentSaveName);
// LoadingUtils.initTerrainDataCellManager();
//TODO: set spawnpoint
//TODO: Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager);

View File

@ -0,0 +1,40 @@
package electrosphere.entity.scene;
/**
* Description of the realm a scene is created within
*/
public class RealmDescriptor {
/**
* A gridded realm
*/
public static final String REALM_DESCRIPTOR_GRIDDED = "gridded";
/**
* The type of realm
*/
String type;
/**
* If this is a gridded realm, what is the dimension of the realm
*/
int griddedRealmDimension;
/**
* Gets the type of realm
* @return The type
*/
public String getType(){
return type;
}
/**
* Gets the dimensions of the gridded realm
* @return The dimension
*/
public int getGriddedRealmDimension(){
return griddedRealmDimension;
}
}

View File

@ -7,23 +7,46 @@ import java.util.List;
*/
public class SceneFile {
//the entities in the scene
/**
* The entities in the scene
*/
List<EntityDescriptor> entities;
//the paths relative to the assets folder of each script to be loaded when the scene is loaded
/**
* The paths relative to the assets folder of each script to be loaded when the scene is loaded
*/
List<String> scriptPaths;
//the initial script to run when the scene is loaded into the engine
/**
* The initial script to run when the scene is loaded into the engine
*/
String initScriptPath;
/**
* The realm this scene is created within
*/
RealmDescriptor realmDescriptor;
/**
* Gets the paths of all scripts in this scene
* @return The list of all paths
*/
public List<String> getScriptPaths(){
return scriptPaths;
}
/**
* Gets the entity descriptors for all entities created on init of this scene
* @return The list of all entity descriptors
*/
public List<EntityDescriptor> getEntities(){
return entities;
}
/**
* Gets the path to the initial script run when this scene is initialized
* @return The path to the initial script
*/
public String getInitScriptPath(){
return initScriptPath;
}

View File

@ -0,0 +1,29 @@
package electrosphere.entity.scene;
import java.util.LinkedList;
/**
* Generates scene files where appropriate (ie, if playing the procedurally generated level)
*/
public class SceneGenerator {
/**
* Creates a scene file for the procedurally generated gamemode
* @return The scene file
*/
public static SceneFile createProceduralSceneFile(int gridDimension){
//base file stuff
SceneFile file = new SceneFile();
file.entities = new LinkedList<EntityDescriptor>();
file.initScriptPath = null;
file.scriptPaths = new LinkedList<String>();
//realm descriptor stuff
file.realmDescriptor = new RealmDescriptor();
file.realmDescriptor.type = RealmDescriptor.REALM_DESCRIPTOR_GRIDDED;
file.realmDescriptor.griddedRealmDimension = gridDimension;
return file;
}
}

View File

@ -62,6 +62,8 @@ public class SceneLoader {
// }
// Globals.scriptEngine.runScript(file.getInitScriptPath());
//instruct client to load the scene
return rVal;
}

View File

@ -77,17 +77,16 @@ public class MenuGenerators {
//need to log client in
Globals.clientUsername = "username";
Globals.clientPassword = AuthenticationManager.getHashedString("password");
LoadingThread clientThread = new LoadingThread(LoadingThread.LOAD_CHARACTER_SERVER);
LoadingThread clientThread = new LoadingThread(LoadingThread.LOAD_CHARACTER_SERVER, null);
Globals.loadingThreadsList.add(clientThread);
LoadingThread serverThread = new LoadingThread(LoadingThread.LOAD_MAIN_GAME);
LoadingThread serverThread = new LoadingThread(LoadingThread.LOAD_MAIN_GAME, null);
Globals.loadingThreadsList.add(serverThread);
Globals.RUN_CLIENT = true;
Globals.RUN_SERVER = true;
serverThread.start();
clientThread.start();
} else {
Globals.currentSaveName = saveName.toLowerCase();
SaveUtils.loadTerrainAndCreateWorldData(saveName.toLowerCase());
SaveUtils.loadSave(saveName.toLowerCase());
WindowUtils.replaceMainMenuContents(MenuGenerators.createSaveCreationMenu());
}
return false;
@ -155,7 +154,7 @@ public class MenuGenerators {
saveButton.addChild(saveLabel);
rVal.addChild(saveButton);
saveButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
SaveUtils.saveWorldData(Globals.currentSaveName);
SaveUtils.saveWorldData(Globals.currentSave.getName());
WindowUtils.replaceMainMenuContents(MenuGenerators.createWorldSelectMenu());
return false;
}});
@ -222,9 +221,9 @@ public class MenuGenerators {
hostButton.addChild(hostLabel);
rVal.addChild(hostButton);
hostButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
LoadingThread clientThread = new LoadingThread(LoadingThread.LOAD_CHARACTER_SERVER);
LoadingThread clientThread = new LoadingThread(LoadingThread.LOAD_CHARACTER_SERVER, null);
Globals.loadingThreadsList.add(clientThread);
LoadingThread serverThread = new LoadingThread(LoadingThread.LOAD_MAIN_GAME);
LoadingThread serverThread = new LoadingThread(LoadingThread.LOAD_MAIN_GAME, null);
Globals.loadingThreadsList.add(serverThread);
Globals.RUN_CLIENT = true;
Globals.RUN_SERVER = true;
@ -314,7 +313,7 @@ public class MenuGenerators {
NetUtils.setPort(Integer.parseInt(portInput.getText()));
Globals.clientUsername = usernameInput.getText();
Globals.clientPassword = AuthenticationManager.getHashedString(passwordInput.getText());
LoadingThread clientThread = new LoadingThread(LoadingThread.LOAD_CHARACTER_SERVER);
LoadingThread clientThread = new LoadingThread(LoadingThread.LOAD_CHARACTER_SERVER, null);
Globals.loadingThreadsList.add(clientThread);
Globals.RUN_CLIENT = true;
Globals.RUN_SERVER = false;

View File

@ -32,6 +32,7 @@ import electrosphere.renderer.ui.elementtypes.ValueElement.ValueChangeEventCallb
import electrosphere.renderer.ui.events.ClickEvent;
import electrosphere.renderer.ui.events.NavigationEvent;
import electrosphere.renderer.ui.events.ValueChangeEvent;
import electrosphere.server.saves.SaveUtils;
public class MenuGeneratorsInGame {
@ -131,11 +132,11 @@ public class MenuGeneratorsInGame {
return rVal;
}
/**
* Saves the world
*/
static void saveWorld(){
if(Globals.serverTerrainManager != null){
Globals.serverTerrainManager.save(Globals.currentSaveName);
Globals.realmManager.save(Globals.currentSaveName);
}
SaveUtils.overwriteSave(Globals.currentSave.getName());
}
public static Window createInGameDebugMainMenu(){

View File

@ -90,8 +90,7 @@ public class MenuGeneratorsLevelEditor {
launchButton.addChild(launchLabel);
launchButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
//launch level
Globals.currentSaveName = saveName;
LoadingThread loadingThread = new LoadingThread(LoadingThread.LOAD_LEVEL);
LoadingThread loadingThread = new LoadingThread(LoadingThread.LOAD_LEVEL, saveName);
Globals.loadingThreadsList.add(loadingThread);
Globals.RUN_CLIENT = true;
Globals.RUN_SERVER = true;
@ -163,8 +162,7 @@ public class MenuGeneratorsLevelEditor {
rVal.addChild(createLevelButton);
createLevelButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
//launch level editor
Globals.currentSaveName = usernameInput.getText();
LoadingThread loadingThread = new LoadingThread(LoadingThread.LOAD_LEVEL_EDITOR);
LoadingThread loadingThread = new LoadingThread(LoadingThread.LOAD_LEVEL_EDITOR, usernameInput.getText());
Globals.loadingThreadsList.add(loadingThread);
Globals.RUN_CLIENT = true;
Globals.RUN_SERVER = true;

View File

@ -351,6 +351,11 @@ SYNCHRONIZATION_MESSAGE,
rVal = SynchronizationMessage.parseDetatchTreeMessage(byteBuffer);
}
break;
case TypeBytes.SYNCHRONIZATION_MESSAGE_TYPE_LOADSCENE:
if(SynchronizationMessage.canParseMessage(byteBuffer,secondByte)){
rVal = SynchronizationMessage.parseLoadSceneMessage(byteBuffer);
}
break;
}
break;
}

View File

@ -12,6 +12,7 @@ public class SynchronizationMessage extends NetworkMessage {
UPDATECLIENTSTRINGSTATE,
ATTACHTREE,
DETATCHTREE,
LOADSCENE,
}
SynchronizationMessageType messageType;
@ -96,6 +97,8 @@ public class SynchronizationMessage extends NetworkMessage {
} else {
return false;
}
case TypeBytes.SYNCHRONIZATION_MESSAGE_TYPE_LOADSCENE:
return SynchronizationMessage.canParseLoadSceneMessage(byteBuffer);
}
return false;
}
@ -200,6 +203,39 @@ public class SynchronizationMessage extends NetworkMessage {
return rVal;
}
public static boolean canParseLoadSceneMessage(CircularByteBuffer byteBuffer){
int currentStreamLength = byteBuffer.getRemaining();
List<Byte> temporaryByteQueue = new LinkedList();
int stringValueSize = 0;
if(currentStreamLength < 6){
return false;
} else {
temporaryByteQueue.add(byteBuffer.peek(2 + 0));
temporaryByteQueue.add(byteBuffer.peek(2 + 1));
temporaryByteQueue.add(byteBuffer.peek(2 + 2));
temporaryByteQueue.add(byteBuffer.peek(2 + 3));
stringValueSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
}
if(currentStreamLength < 6 + stringValueSize){
return false;
}
return true;
}
public static SynchronizationMessage parseLoadSceneMessage(CircularByteBuffer byteBuffer){
SynchronizationMessage rVal = new SynchronizationMessage(SynchronizationMessageType.LOADSCENE);
stripPacketHeader(byteBuffer);
rVal.setstringValue(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
return rVal;
}
public static SynchronizationMessage constructLoadSceneMessage(String stringValue){
SynchronizationMessage rVal = new SynchronizationMessage(SynchronizationMessageType.LOADSCENE);
rVal.setstringValue(stringValue);
rVal.serialize();
return rVal;
}
@Override
void serialize(){
byte[] intValues = new byte[8];
@ -285,6 +321,21 @@ public class SynchronizationMessage extends NetworkMessage {
rawBytes[6+i] = intValues[i];
}
break;
case LOADSCENE:
rawBytes = new byte[2+4+stringValue.length()];
//message header
rawBytes[0] = TypeBytes.MESSAGE_TYPE_SYNCHRONIZATION;
//entity messaage header
rawBytes[1] = TypeBytes.SYNCHRONIZATION_MESSAGE_TYPE_LOADSCENE;
intValues = ByteStreamUtils.serializeIntToBytes(stringValue.length());
for(int i = 0; i < 4; i++){
rawBytes[2+i] = intValues[i];
}
stringBytes = stringValue.getBytes();
for(int i = 0; i < stringValue.length(); i++){
rawBytes[6+i] = stringBytes[i];
}
break;
}
serialized = true;
}

View File

@ -148,6 +148,7 @@ Message categories
public static final byte SYNCHRONIZATION_MESSAGE_TYPE_UPDATECLIENTSTRINGSTATE = 1;
public static final byte SYNCHRONIZATION_MESSAGE_TYPE_ATTACHTREE = 2;
public static final byte SYNCHRONIZATION_MESSAGE_TYPE_DETATCHTREE = 3;
public static final byte SYNCHRONIZATION_MESSAGE_TYPE_LOADSCENE = 4;
/*
Synchronization packet sizes
*/

View File

@ -26,7 +26,7 @@ public class CharacterProtocol {
}
break;
case REQUESTSPAWNCHARACTER:
spawnClientEntity(connectionHandler);
spawnEntityForClient(connectionHandler);
break;
case RESPONSECHARACTERLIST:
case RESPONSECREATECHARACTERSUCCESS:
@ -60,7 +60,7 @@ public class CharacterProtocol {
* Spawns the player's entity
* @param connectionHandler The connection handler for the player
*/
static void spawnClientEntity(ServerConnectionHandler connectionHandler){
static void spawnEntityForClient(ServerConnectionHandler connectionHandler){
PlayerCharacterCreation.spawnPlayerCharacter(connectionHandler);
//set client initial discrete position
connectionHandler.addMessagetoOutgoingQueue(

View File

@ -46,9 +46,9 @@ public class ServerContentManager {
public void generateContentForDataCell(Realm realm, Vector3i worldPos, ServerDataCell cell, String cellKey){
String fullPath = "/content/" + cellKey + ".dat";
if(generateContent){ //in other words, if not arena mode
if(FileUtils.checkSavePathExists(Globals.currentSaveName, fullPath)){
if(FileUtils.checkSavePathExists(Globals.currentSave.getName(), fullPath)){
//if on disk (has already been generated)
ContentSerialization contentRaw = FileUtils.loadObjectFromSavePath(Globals.currentSaveName, fullPath, ContentSerialization.class);
ContentSerialization contentRaw = FileUtils.loadObjectFromSavePath(Globals.currentSave.getName(), fullPath, ContentSerialization.class);
hydrateRawContent(realm,cell,contentRaw);
} else {
//else create from scratch
@ -57,9 +57,9 @@ public class ServerContentManager {
}
} else {
//just because content wasn't generated doesn't mean there isn't data saved under that key
if(FileUtils.checkSavePathExists(Globals.currentSaveName, fullPath)){
if(FileUtils.checkSavePathExists(Globals.currentSave.getName(), fullPath)){
//if on disk (has already been generated)
ContentSerialization contentRaw = FileUtils.loadObjectFromSavePath(Globals.currentSaveName, fullPath, ContentSerialization.class);
ContentSerialization contentRaw = FileUtils.loadObjectFromSavePath(Globals.currentSave.getName(), fullPath, ContentSerialization.class);
hydrateRawContent(realm,cell,contentRaw);
}
}
@ -81,7 +81,7 @@ public class ServerContentManager {
*/
public void saveContentToDisk(String locationKey, List<Entity> entities){
ContentSerialization serialization = ContentSerialization.constructContentSerialization(entities);
String dirPath = SaveUtils.deriveSaveDirectoryPath(Globals.currentSaveName);
String dirPath = SaveUtils.deriveSaveDirectoryPath(Globals.currentSave.getName());
String fullPath = dirPath + "/content/" + locationKey + ".dat";
FileUtils.serializeObjectToFilePath(fullPath, serialization);
}

View File

@ -63,7 +63,7 @@ public class FluidDiskMap {
* Saves the disk map to disk
*/
public void save(){
FileUtils.serializeObjectToSavePath(Globals.currentSaveName, "fluid.map", worldPosFileMap);
FileUtils.serializeObjectToSavePath(Globals.currentSave.getName(), "fluid.map", worldPosFileMap);
}
/**
@ -90,7 +90,7 @@ public class FluidDiskMap {
if(containsFluidAtPosition(worldX, worldY, worldZ)){
//read file
String fileName = worldPosFileMap.get(getFluidChunkKey(worldX, worldY, worldZ));
byte[] rawDataCompressed = FileUtils.loadBinaryFromSavePath(Globals.currentSaveName, fileName);
byte[] rawDataCompressed = FileUtils.loadBinaryFromSavePath(Globals.currentSave.getName(), fileName);
//decompress
byte[] rawData = null;
ByteArrayOutputStream out = new ByteArrayOutputStream();
@ -205,7 +205,7 @@ public class FluidDiskMap {
deflaterInputStream.flush();
deflaterInputStream.close();
//write to disk
FileUtils.saveBinaryToSavePath(Globals.currentSaveName, fileName, out.toByteArray());
FileUtils.saveBinaryToSavePath(Globals.currentSave.getName(), fileName, out.toByteArray());
//save to the map of filenames
worldPosFileMap.put(chunkKey,fileName);
} catch (IOException e) {

View File

@ -21,14 +21,27 @@ public class Save {
//the time the save was created
String timeCreated;
//The name of the save
String name;
//The scenes
List<Scene> scenes;
/**
* Constructor
*/
public Save(){
public Save(String name){
this.name = name;
versionString = "0.0.1";
timeCreated = System.currentTimeMillis() + "";
}
/**
* Gets the name of the save
* @return The name
*/
public String getName(){
return name;
}
}

View File

@ -3,6 +3,7 @@ package electrosphere.server.saves;
import java.util.List;
import electrosphere.engine.Globals;
import electrosphere.entity.scene.SceneLoader;
import electrosphere.game.server.world.ServerWorldData;
import electrosphere.logger.LoggerInterface;
import electrosphere.server.content.ServerContentManager;
@ -11,7 +12,6 @@ import electrosphere.server.fluid.generation.ArenaFluidGenerator;
import electrosphere.server.fluid.manager.ServerFluidManager;
import electrosphere.server.terrain.generation.ArenaChunkGenerator;
import electrosphere.server.terrain.generation.OverworldChunkGenerator;
import electrosphere.server.terrain.generation.interfaces.ChunkGenerator;
import electrosphere.server.terrain.manager.ServerTerrainManager;
import electrosphere.util.FileUtils;
@ -81,13 +81,54 @@ public class SaveUtils {
return false;
}
}
//create main save files
createSave(saveName);
return true;
}
/**
* Creates a save
* @param saveName The name of the save
* @return Returns true if the save was created successfully, returns false if the save was not created successfully
*/
public static boolean createSave(String saveName){
String dirPath = deriveSaveDirectoryPath(saveName);
//create save file
Save save = new Save(saveName);
FileUtils.serializeObjectToSavePath(saveName, "/save.json", save);
//create server structures
Globals.serverTerrainManager = new ServerTerrainManager(ServerTerrainManager.WORLD_SIZE_DISCRETE, ServerTerrainManager.VERTICAL_INTERPOLATION_RATIO, 0, 0, new OverworldChunkGenerator());
Globals.serverWorldData = ServerWorldData.createGameWorld(Globals.serverTerrainManager);
FileUtils.serializeObjectToSavePath(saveName, "./world.json", Globals.serverWorldData);
Globals.serverFluidManager = new ServerFluidManager(Globals.serverTerrainManager, 3, 1, 0.0f, 0, new ArenaFluidGenerator());
if(Globals.serverTerrainManager != null){
Globals.serverTerrainManager.save(saveName);
} else {
LoggerInterface.loggerEngine.ERROR(new IllegalStateException("Trying to create save file and server terrain manager is null!"));
}
//init db file
if(!DatabaseUtils.initCentralDBFile(dirPath)){
return false;
}
return true;
}
/**
* Overwrites a save's data
* @param saveName The name of the save
*/
public static void overwriteSave(String saveName){
if(Globals.serverTerrainManager != null){
Globals.serverTerrainManager.save(saveName);
Globals.realmManager.save(saveName);
}
}
/**
* Deletes a save
* @param saveName The name of the save
@ -117,14 +158,25 @@ public class SaveUtils {
*/
public static boolean loadSave(String saveName){
String dirPath = deriveSaveDirectoryPath(saveName);
//load save file
Globals.currentSave = FileUtils.loadObjectFromSavePath(saveName, "/save.json", Save.class);
//load db
String dbFilePath = FileUtils.sanitizeFilePath(dirPath) + "/central.db";
Globals.dbController.connect(dbFilePath);
//create server structures
if(!saveName.equals("arena")){
Globals.serverWorldData = FileUtils.loadObjectFromSavePath(saveName, "world.json", ServerWorldData.class);
Globals.serverTerrainManager = new ServerTerrainManager(Globals.serverWorldData.getWorldSizeDiscrete(), 1, 0, 0, new ArenaChunkGenerator());
Globals.serverTerrainManager.load(saveName);
Globals.serverFluidManager = new ServerFluidManager(Globals.serverTerrainManager, 2000, 50, 0, 0, new ArenaFluidGenerator());
}
//if the scene file exists, load it
if(FileUtils.checkFileExists("assets/Scenes/" + saveName)){
//TODO: load scene
}
return true;
}

View File

@ -73,7 +73,7 @@ public class ChunkDiskMap {
* Saves the disk map to disk
*/
public void save(){
FileUtils.serializeObjectToSavePath(Globals.currentSaveName, "chunk.map", worldPosFileMap);
FileUtils.serializeObjectToSavePath(Globals.currentSave.getName(), "chunk.map", worldPosFileMap);
}
/**
@ -111,7 +111,7 @@ public class ChunkDiskMap {
if(containsTerrainAtPosition(worldX, worldY, worldZ)){
//read file
String fileName = worldPosFileMap.get(getTerrainChunkKey(worldX, worldY, worldZ));
byte[] rawDataCompressed = FileUtils.loadBinaryFromSavePath(Globals.currentSaveName, fileName);
byte[] rawDataCompressed = FileUtils.loadBinaryFromSavePath(Globals.currentSave.getName(), fileName);
//decompress
byte[] rawData = null;
ByteArrayOutputStream out = new ByteArrayOutputStream();
@ -198,7 +198,7 @@ public class ChunkDiskMap {
deflaterInputStream.flush();
deflaterInputStream.close();
//write to disk
FileUtils.saveBinaryToSavePath(Globals.currentSaveName, fileName, out.toByteArray());
FileUtils.saveBinaryToSavePath(Globals.currentSave.getName(), fileName, out.toByteArray());
//save to the map of filenames
worldPosFileMap.put(chunkKey,fileName);
} catch (IOException e) {

View File

@ -27,6 +27,16 @@ import org.joml.Vector3i;
* Provides an interface for the server to query information about terrain
*/
public class ServerTerrainManager {
/**
* Full world discrete size
*/
public static final int WORLD_SIZE_DISCRETE = 1000;
/**
* Vertical interp ratio
*/
public static final int VERTICAL_INTERPOLATION_RATIO = 50;
//the interpolation width of a server terrain manager is hard coded at the moment to make sure it's divisible by the sub chunk calculations
public static final int SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO = 128;