458 lines
19 KiB
Java
458 lines
19 KiB
Java
package electrosphere.engine.loadingthreads;
|
|
|
|
import java.util.Arrays;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
import org.joml.Vector3d;
|
|
import org.joml.Vector3f;
|
|
|
|
import electrosphere.client.block.cells.ClientBlockCellManager;
|
|
import electrosphere.client.entity.camera.CameraEntityUtils;
|
|
import electrosphere.client.entity.crosshair.Crosshair;
|
|
import electrosphere.client.fluid.cells.FluidCellManager;
|
|
import electrosphere.client.sim.ClientSimulation;
|
|
import electrosphere.client.terrain.cells.ClientDrawCellManager;
|
|
import electrosphere.client.terrain.foliage.FoliageCellManager;
|
|
import electrosphere.client.ui.menu.MenuGenerators;
|
|
import electrosphere.client.ui.menu.WindowStrings;
|
|
import electrosphere.client.ui.menu.WindowUtils;
|
|
import electrosphere.client.ui.menu.mainmenu.MenuCharacterCreation;
|
|
import electrosphere.controls.ControlHandler;
|
|
import electrosphere.engine.Globals;
|
|
import electrosphere.engine.assetmanager.AssetDataStrings;
|
|
import electrosphere.engine.signal.Signal.SignalType;
|
|
import electrosphere.engine.threads.LabeledThread.ThreadLabel;
|
|
import electrosphere.entity.DrawableUtils;
|
|
import electrosphere.entity.Entity;
|
|
import electrosphere.entity.EntityCreationUtils;
|
|
import electrosphere.entity.EntityUtils;
|
|
import electrosphere.logger.LoggerInterface;
|
|
import electrosphere.net.NetUtils;
|
|
import electrosphere.net.client.ClientNetworking;
|
|
import electrosphere.renderer.actor.Actor;
|
|
import electrosphere.renderer.actor.ActorTextureMask;
|
|
|
|
public class ClientLoading {
|
|
|
|
|
|
/**
|
|
* Number of frames to wait before updating status of draw cell manager loading
|
|
*/
|
|
static final int DRAW_CELL_UPDATE_RATE = 60;
|
|
|
|
|
|
/**
|
|
* The number of frames the draw cell is expected to take (minimum) to init
|
|
*/
|
|
static final int DRAW_CELL_EXPECTED_MINIMUM_FRAMES_TO_INIT = 10;
|
|
|
|
|
|
/**
|
|
* Loads the race data from the server
|
|
* @param params no params
|
|
*/
|
|
protected static void loadCharacterServer(Object[] params){
|
|
if(params.length < 1){
|
|
throw new Error("Expected 1 params!");
|
|
}
|
|
|
|
boolean useLocalConnection = (boolean)params[0];
|
|
|
|
WindowUtils.recursiveSetVisible(Globals.elementService.getWindow(WindowStrings.WINDOW_MENU_MAIN), false);
|
|
WindowUtils.replaceMainMenuContents(MenuGenerators.createEmptyMainMenu());
|
|
WindowUtils.recursiveSetVisible(Globals.elementService.getWindow(WindowStrings.WINDOW_LOADING), true);
|
|
WindowUtils.updateLoadingWindow("Waiting on server");
|
|
//disable menu input
|
|
Globals.controlHandler.hintUpdateControlState(ControlHandler.ControlsState.NO_INPUT);
|
|
//initialize the client thread (client)
|
|
if(useLocalConnection){
|
|
LoadingUtils.initLocalConnection(true);
|
|
} else {
|
|
ClientLoading.initClientThread();
|
|
}
|
|
//while we don't know what races are playable, wait
|
|
WindowUtils.updateLoadingWindow("Waiting on lore");
|
|
while(Globals.gameConfigCurrent.getCreatureTypeLoader().getPlayableRaces().size() == 0){
|
|
try {
|
|
TimeUnit.MILLISECONDS.sleep(5);
|
|
} catch (InterruptedException ex) {}
|
|
}
|
|
//once we have them, bring up the character creation interface
|
|
//init character creation window
|
|
//eventually should replace with at ui to select an already created character or create a new one
|
|
WindowUtils.replaceMainMenuContents(MenuCharacterCreation.createCharacterSelectionWindow());
|
|
//make loading dialog disappear
|
|
WindowUtils.recursiveSetVisible(Globals.elementService.getWindow(WindowStrings.WINDOW_LOADING), false);
|
|
//make character creation window visible
|
|
WindowUtils.recursiveSetVisible(Globals.elementService.getWindow(WindowStrings.WINDOW_MENU_MAIN), true);
|
|
//recapture window
|
|
Globals.controlHandler.setRecapture(true);
|
|
//log
|
|
LoggerInterface.loggerEngine.INFO("[Client]Finished loading character creation menu");
|
|
//set menu controls again
|
|
Globals.controlHandler.hintUpdateControlState(ControlHandler.ControlsState.TITLE_MENU);
|
|
}
|
|
|
|
|
|
protected static void loadClientWorld(Object[] params){
|
|
Globals.signalSystem.post(SignalType.UI_MODIFICATION, () -> {
|
|
WindowUtils.closeWindow(WindowStrings.WINDOW_MENU_MAIN);
|
|
WindowUtils.recursiveSetVisible(WindowStrings.WINDOW_LOADING, true);
|
|
WindowUtils.updateLoadingWindow("LOADING");
|
|
});
|
|
//disable menu input
|
|
Globals.controlHandler.hintUpdateControlState(ControlHandler.ControlsState.NO_INPUT);
|
|
//initialize the "real" objects simulation
|
|
initClientSimulation();
|
|
LoadingUtils.setSimulationsToReady();
|
|
//initialize the gridded managers (client)
|
|
initDrawCellManager(true);
|
|
initFoliageManager();
|
|
initFluidCellManager(true);
|
|
initBlockCellManager(true);
|
|
//initialize the basic graphical entities of the world (skybox, camera)
|
|
initWorldBaseGraphicalEntities();
|
|
//init arena specific stuff (ie different skybox colors)
|
|
initArenaGraphicalEntities();
|
|
//sets micro and macro sims to ready if they exist
|
|
setSimulationsToReady();
|
|
//set simulations to ready if they exist
|
|
LoadingUtils.setSimulationsToReady();
|
|
//make loading window disappear
|
|
Globals.signalSystem.post(SignalType.UI_MODIFICATION, () -> {
|
|
WindowUtils.recursiveSetVisible(WindowStrings.WINDOW_LOADING, false);
|
|
Globals.RENDER_FLAG_RENDER_SHADOW_MAP = true;
|
|
Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER_CONTENT = true;
|
|
Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER = true;
|
|
Globals.RENDER_FLAG_RENDER_UI = true;
|
|
Globals.RENDER_FLAG_RENDER_BLACK_BACKGROUND = false;
|
|
Globals.RENDER_FLAG_RENDER_WHITE_BACKGROUND = false;
|
|
});
|
|
//recapture screen
|
|
Globals.controlHandler.setRecapture(true);
|
|
LoggerInterface.loggerEngine.INFO("[Client]Finished loading main game");
|
|
//set controls state
|
|
Globals.controlHandler.hintUpdateControlState(ControlHandler.ControlsState.MAIN_GAME);
|
|
}
|
|
|
|
/**
|
|
* Loads the viewport
|
|
*/
|
|
protected static void loadViewport(Object[] params){
|
|
Globals.signalSystem.post(SignalType.UI_MODIFICATION, () -> {
|
|
WindowUtils.closeWindow(WindowStrings.WINDOW_MENU_MAIN);
|
|
WindowUtils.recursiveSetVisible(WindowStrings.WINDOW_LOADING, true);
|
|
});
|
|
//disable menu input
|
|
Globals.controlHandler.hintUpdateControlState(ControlHandler.ControlsState.NO_INPUT);
|
|
|
|
//init camera
|
|
Globals.playerCamera = CameraEntityUtils.spawnBasicCameraEntity(new Vector3d(0,0,0), new Vector3d(-1,0,0));
|
|
Globals.cameraHandler.setTrackPlayerEntity(false);
|
|
Globals.cameraHandler.setUpdate(false);
|
|
//initialize the "real" objects simulation
|
|
initClientSimulation();
|
|
//initialize the cell managers (client)
|
|
initDrawCellManager(false);
|
|
initFluidCellManager(false);
|
|
initBlockCellManager(false);
|
|
initFoliageManager();
|
|
|
|
//sets micro and macro sims to ready if they exist
|
|
setSimulationsToReady();
|
|
//make loading window disappear
|
|
Globals.signalSystem.post(SignalType.UI_MODIFICATION, () -> {
|
|
WindowUtils.recursiveSetVisible(WindowStrings.WINDOW_LOADING, false);
|
|
Globals.RENDER_FLAG_RENDER_SHADOW_MAP = true;
|
|
Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER_CONTENT = true;
|
|
Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER = true;
|
|
Globals.RENDER_FLAG_RENDER_UI = true;
|
|
Globals.RENDER_FLAG_RENDER_BLACK_BACKGROUND = false;
|
|
Globals.RENDER_FLAG_RENDER_WHITE_BACKGROUND = false;
|
|
});
|
|
//recapture screen
|
|
Globals.controlHandler.setRecapture(true);
|
|
LoggerInterface.loggerEngine.INFO("[Client]Finished loading main game");
|
|
//set controls state
|
|
Globals.controlHandler.hintUpdateControlState(ControlHandler.ControlsState.MAIN_GAME);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Inits the client networking thread and socket
|
|
*/
|
|
private static void initClientThread(){
|
|
//start client networking
|
|
if(Globals.RUN_CLIENT){
|
|
Globals.clientConnection = new ClientNetworking(NetUtils.getAddress(),NetUtils.getPort());
|
|
Globals.threadManager.start(ThreadLabel.NETWORKING_CLIENT, new Thread(Globals.clientConnection));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates client simulation object
|
|
*/
|
|
private static void initClientSimulation(){
|
|
if(Globals.clientSimulation == null){
|
|
Globals.clientSimulation = new ClientSimulation();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets client simulation object state to ready
|
|
*/
|
|
private static void setSimulationsToReady(){
|
|
Globals.clientSimulation.setReady(true);
|
|
}
|
|
|
|
|
|
private static void initWorldBaseGraphicalEntities(){
|
|
/*
|
|
|
|
Skybox
|
|
|
|
*/
|
|
// Model skyboxModel = Globals.assetManager.fetchModel(AssetDataStrings.ASSET_STRING_SKYBOX_BASIC);
|
|
// Globals.skybox = EntityUtils.spawnDrawableEntity(AssetDataStrings.ASSET_STRING_SKYBOX_BASIC);
|
|
|
|
|
|
/*
|
|
|
|
Player Camera
|
|
|
|
*/
|
|
CameraEntityUtils.initCamera();
|
|
|
|
|
|
/*
|
|
Targeting crosshair
|
|
*/
|
|
Crosshair.initCrossHairEntity();
|
|
|
|
}
|
|
|
|
|
|
static void initArenaGraphicalEntities(){
|
|
|
|
float skyR = 150;
|
|
float skyG = 200;
|
|
float skyB = 250;
|
|
|
|
float groundR = 20;
|
|
float groundG = 20;
|
|
float groundB = 20;
|
|
|
|
Globals.skyboxColors.add(new Vector3f(skyR,skyG,skyB));
|
|
Globals.skyboxColors.add(new Vector3f(skyR,skyG,skyB));
|
|
Globals.skyboxColors.add(new Vector3f(groundR,groundG,groundB));
|
|
Globals.skyboxColors.add(new Vector3f(groundR,groundG,groundB));
|
|
Globals.skyboxColors.add(new Vector3f(skyR,skyG,skyB));
|
|
Globals.skyboxColors.add(new Vector3f(skyR,skyG,skyB));
|
|
Globals.skyboxColors.add(new Vector3f(groundR,groundG,groundB));
|
|
Globals.skyboxColors.add(new Vector3f(groundR,groundG,groundB));
|
|
|
|
//starry sky true skybox
|
|
Entity skybox = EntityCreationUtils.createClientSpatialEntity();
|
|
EntityCreationUtils.makeEntityDrawable(skybox, "Models/environment/skyboxSphere.fbx");
|
|
DrawableUtils.disableCulling(skybox);
|
|
EntityUtils.getRotation(skybox).rotateX((float)(-Math.PI/2.0f));
|
|
EntityUtils.getScale(skybox).mul(600000.0f);
|
|
Globals.clientScene.registerBehaviorTree(() -> {
|
|
EntityUtils.getPosition(skybox).set(EntityUtils.getPosition(Globals.playerEntity));
|
|
});
|
|
Globals.assetManager.queueOverrideMeshShader("Models/environment/skyboxSphere.fbx", "Sphere", "Shaders/entities/skysphere/skysphere.vs", "Shaders/entities/skysphere/skysphere.fs");
|
|
|
|
//cloud ring pseudo skybox
|
|
// Entity cloudRing = EntityCreationUtils.createClientSpatialEntity();
|
|
// EntityCreationUtils.makeEntityDrawable(cloudRing, "Models/environment/cloudRing.fbx");
|
|
// DrawableUtils.makeEntityTransparent(cloudRing);
|
|
// DrawableUtils.disableCulling(cloudRing);
|
|
// EntityUtils.getRotation(cloudRing).rotateX((float)(-Math.PI/2.0f));
|
|
// EntityUtils.getScale(cloudRing).mul(100000.0f);
|
|
// Globals.clientScene.registerBehaviorTree(new ApplyRotationTree(cloudRing,new Quaterniond().rotationZ(0.0001)));
|
|
// Globals.assetManager.queueOverrideMeshShader("Models/environment/cloudRing.fbx", "Sphere", "Shaders/skysphere/skysphere.vs", "Shaders/skysphere/skysphere.fs");
|
|
|
|
//player's cursor
|
|
Globals.playerCursor = EntityCreationUtils.createClientSpatialEntity();
|
|
EntityCreationUtils.makeEntityDrawable(Globals.playerCursor, AssetDataStrings.UNITSPHERE);
|
|
Actor cursorActor = EntityUtils.getActor(Globals.playerCursor);
|
|
cursorActor.addTextureMask(new ActorTextureMask("sphere", Arrays.asList(new String[]{"Textures/transparent_red.png"})));
|
|
DrawableUtils.makeEntityTransparent(Globals.playerCursor);
|
|
EntityUtils.getScale(Globals.playerCursor).set(0.2f);
|
|
|
|
//cloud object
|
|
// Entity cloudEnt = EntityCreationUtils.createClientSpatialEntity();
|
|
// EntityCreationUtils.makeEntityDrawablePreexistingModel(cloudEnt, Globals.assetManager.queuedAsset(new QueuedModel(() -> {
|
|
// Model rVal = new Model();
|
|
|
|
// Mesh m = GeometryMeshGen.genBox(1, 1, 1);
|
|
|
|
// //shader logic
|
|
// m.setShader(VisualShader.loadSpecificShader("Shaders/entities/clouds/clouds.vs", "Shaders/entities/clouds/clouds.fs"));
|
|
// m.setParent(rVal);
|
|
|
|
// rVal.getMeshes().add(m);
|
|
// rVal.setBoundingSphere(0,0,0,2);
|
|
// return rVal;
|
|
// })));
|
|
}
|
|
|
|
static final int MAX_DRAW_CELL_WAIT = 1000;
|
|
|
|
/**
|
|
* Inits the drawcell manager
|
|
* @param blockForInit Blocks the thread until the draw cell manager is ready
|
|
*/
|
|
static void initDrawCellManager(boolean blockForInit){
|
|
int iterations = 0;
|
|
WindowUtils.updateLoadingWindow("WAITING ON WORLD DATA");
|
|
while(blockForInit && (Globals.clientWorldData == null || InitialAssetLoading.atlasQueuedTexture == null || !InitialAssetLoading.atlasQueuedTexture.hasLoaded()) && Globals.threadManager.shouldKeepRunning()){
|
|
try {
|
|
TimeUnit.MILLISECONDS.sleep(10);
|
|
iterations++;
|
|
} catch (InterruptedException ex) {
|
|
LoggerInterface.loggerEngine.ERROR(ex);
|
|
}
|
|
if(iterations > MAX_DRAW_CELL_WAIT){
|
|
String message = "Draw cell took too long to init!\n" +
|
|
Globals.clientWorldData + "\n" +
|
|
InitialAssetLoading.atlasQueuedTexture.hasLoaded();
|
|
throw new IllegalStateException(message);
|
|
}
|
|
}
|
|
//initialize draw cell manager
|
|
// Globals.drawCellManager = new DrawCellManager(Globals.clientTerrainManager, 0, 0, 0);
|
|
Globals.clientDrawCellManager = new ClientDrawCellManager(Globals.voxelTextureAtlas, Globals.clientWorldData.getWorldDiscreteSize());
|
|
//Alerts the client simulation that it should start loading terrain
|
|
Globals.clientSimulation.setLoadingTerrain(true);
|
|
//wait for all the terrain data to arrive
|
|
int i = 0;
|
|
while(
|
|
blockForInit &&
|
|
!Globals.clientDrawCellManager.isInitialized() &&
|
|
Globals.threadManager.shouldKeepRunning()
|
|
){
|
|
i++;
|
|
if(i % DRAW_CELL_UPDATE_RATE == 0){
|
|
WindowUtils.updateLoadingWindow("WAITING ON SERVER TO SEND TERRAIN (" + Globals.clientTerrainManager.getAllChunks().size() + ")");
|
|
}
|
|
try {
|
|
TimeUnit.MILLISECONDS.sleep(10);
|
|
} catch (InterruptedException ex) {
|
|
ex.printStackTrace();
|
|
}
|
|
}
|
|
if(i < DRAW_CELL_EXPECTED_MINIMUM_FRAMES_TO_INIT){
|
|
LoggerInterface.loggerEngine.WARNING("Draw cell manager loaded exceptionally fast!");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Inits the fluid cell manager
|
|
* @param blockForInit Blocks the thread until the fluid cell manager is ready
|
|
*/
|
|
static void initFluidCellManager(boolean blockForInit){
|
|
|
|
//wait for world data
|
|
WindowUtils.updateLoadingWindow("WAITING ON WORLD DATA");
|
|
while(blockForInit && Globals.clientWorldData == null && Globals.threadManager.shouldKeepRunning()){
|
|
try {
|
|
TimeUnit.MILLISECONDS.sleep(10);
|
|
} catch (InterruptedException ex) {
|
|
}
|
|
}
|
|
|
|
//initialize draw cell manager
|
|
Globals.fluidCellManager = new FluidCellManager(Globals.clientTerrainManager, 0, 0, 0);
|
|
Globals.fluidCellManager.setGenerateDrawables(true);
|
|
Globals.clientSimulation.setLoadingTerrain(true);
|
|
|
|
//wait for all the terrain data to arrive
|
|
WindowUtils.updateLoadingWindow("REQUESTING FLUID CHUNKS FROM SERVER (" + Globals.fluidCellManager.getUnrequestedSize() + ")");
|
|
while(blockForInit && Globals.fluidCellManager.containsUnrequestedCell() && Globals.threadManager.shouldKeepRunning() && Globals.RUN_FLUIDS){
|
|
try {
|
|
TimeUnit.MILLISECONDS.sleep(10);
|
|
} catch (InterruptedException ex) {
|
|
ex.printStackTrace();
|
|
}
|
|
}
|
|
|
|
//wait for undrawable cells
|
|
// WindowUtils.updateLoadingWindow("WAITING ON SERVER TO SEND FLUID CHUNKS (" + Globals.fluidCellManager.getUndrawableSize() + ")");
|
|
// while(blockForInit && Globals.fluidCellManager.containsUndrawableCell() && Globals.threadManager.shouldKeepRunning()){
|
|
// try {
|
|
// TimeUnit.MILLISECONDS.sleep(10);
|
|
// } catch (InterruptedException ex) {
|
|
// ex.printStackTrace();
|
|
// }
|
|
// }
|
|
}
|
|
|
|
/**
|
|
* Inits the block cell manager
|
|
* @param blockForInit Blocks the thread until the block cell manager is ready
|
|
*/
|
|
static void initBlockCellManager(boolean blockForInit){
|
|
int iterations = 0;
|
|
WindowUtils.updateLoadingWindow("WAITING ON WORLD DATA");
|
|
while(blockForInit && (Globals.clientWorldData == null || InitialAssetLoading.atlasQueuedTexture == null || !InitialAssetLoading.atlasQueuedTexture.hasLoaded()) && Globals.threadManager.shouldKeepRunning()){
|
|
try {
|
|
TimeUnit.MILLISECONDS.sleep(10);
|
|
iterations++;
|
|
} catch (InterruptedException ex) {
|
|
LoggerInterface.loggerEngine.ERROR(ex);
|
|
}
|
|
if(iterations > MAX_DRAW_CELL_WAIT){
|
|
String message = "Draw cell took too long to init!\n" +
|
|
Globals.clientWorldData + "\n" +
|
|
InitialAssetLoading.atlasQueuedTexture.hasLoaded();
|
|
throw new IllegalStateException(message);
|
|
}
|
|
}
|
|
Globals.clientBlockCellManager = new ClientBlockCellManager(Globals.blockTextureAtlas, Globals.clientWorldData.getWorldDiscreteSize());
|
|
//Alerts the client simulation that it should start loading blocks
|
|
Globals.clientSimulation.setLoadingTerrain(true);
|
|
//wait for all the block data to arrive
|
|
int i = 0;
|
|
while(
|
|
blockForInit &&
|
|
!Globals.clientBlockCellManager.isInitialized() &&
|
|
Globals.threadManager.shouldKeepRunning()
|
|
){
|
|
i++;
|
|
if(i % DRAW_CELL_UPDATE_RATE == 0){
|
|
WindowUtils.updateLoadingWindow("WAITING ON SERVER TO SEND BLOCKS (" + Globals.clientTerrainManager.getAllChunks().size() + ")");
|
|
}
|
|
try {
|
|
TimeUnit.MILLISECONDS.sleep(10);
|
|
} catch (InterruptedException ex) {
|
|
ex.printStackTrace();
|
|
}
|
|
}
|
|
if(i < DRAW_CELL_EXPECTED_MINIMUM_FRAMES_TO_INIT){
|
|
LoggerInterface.loggerEngine.WARNING("Block cell manager loaded exceptionally fast!");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Starts up the foliage manager
|
|
*/
|
|
private static void initFoliageManager(){
|
|
Globals.foliageCellManager = new FoliageCellManager(Globals.clientWorldData.getWorldDiscreteSize());
|
|
Globals.foliageCellManager.init();
|
|
// Globals.foliageCellManager.start();
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|