297 lines
11 KiB
Java
297 lines
11 KiB
Java
package electrosphere.client.sim;
|
|
|
|
import org.joml.Vector3d;
|
|
|
|
import electrosphere.client.entity.camera.CameraEntityUtils;
|
|
import electrosphere.client.entity.crosshair.Crosshair;
|
|
import electrosphere.client.entity.instance.InstanceUpdater;
|
|
import electrosphere.client.fluid.manager.ClientFluidManager;
|
|
import electrosphere.client.interact.ClientInteractionEngine;
|
|
import electrosphere.client.terrain.manager.ClientTerrainManager;
|
|
import electrosphere.client.ui.menu.ingame.ToolbarPreviewWindow;
|
|
import electrosphere.engine.EngineState;
|
|
import electrosphere.engine.Globals;
|
|
import electrosphere.entity.Entity;
|
|
import electrosphere.entity.EntityTags;
|
|
import electrosphere.entity.EntityUtils;
|
|
import electrosphere.entity.state.attach.AttachUtils;
|
|
import electrosphere.entity.state.collidable.ClientCollidableTree;
|
|
import electrosphere.entity.state.equip.ClientEquipState;
|
|
import electrosphere.entity.types.creature.CreatureUtils;
|
|
import electrosphere.entity.types.item.ItemUtils;
|
|
import electrosphere.renderer.actor.Actor;
|
|
|
|
public class ClientSimulation {
|
|
|
|
//if true, is ready to simulate
|
|
boolean isReady = false;
|
|
|
|
//if true, should load terrain
|
|
boolean loadTerrain = false;
|
|
|
|
//used for tracking different in player position between frames (principally for draw cell manager)
|
|
Vector3d newPlayerCharacterPosition = new Vector3d();
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
public ClientSimulation(){
|
|
isReady = false;
|
|
}
|
|
|
|
/**
|
|
* Main simulation function
|
|
*/
|
|
public void simulate(){
|
|
|
|
//
|
|
//check for dependencies
|
|
if(Globals.clientState.clientSceneWrapper == null){
|
|
return;
|
|
}
|
|
|
|
Globals.profiler.beginCpuSample("simulate");
|
|
|
|
//
|
|
//load terrain
|
|
if(isLoadingTerrain()){
|
|
loadTerrain();
|
|
}
|
|
|
|
//process all server synchronization messages
|
|
Globals.profiler.beginCpuSample("clientSynchronizationManager.processMessages");
|
|
Globals.clientState.clientSynchronizationManager.processMessages();
|
|
Globals.profiler.endCpuSample();
|
|
//
|
|
//simulate bullet physics engine step
|
|
if(EngineState.EngineFlags.RUN_PHYSICS){
|
|
Globals.clientState.clientSceneWrapper.getCollisionEngine().simulatePhysics();
|
|
Globals.clientState.clientSceneWrapper.getCollisionEngine().updateDynamicObjectTransforms();
|
|
}
|
|
|
|
//update actor animations
|
|
Globals.profiler.beginCpuSample("update actor animations");
|
|
for(Entity currentEntity : Globals.clientState.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.DRAWABLE)){
|
|
Actor currentActor = EntityUtils.getActor(currentEntity);
|
|
if(currentActor.getLodLevel() == Actor.LOD_LEVEL_STATIC){
|
|
continue;
|
|
}
|
|
if(currentActor.getAnimationData().isPlayingAnimation()){
|
|
currentActor.getAnimationData().incrementAnimationTime((float)Globals.engineState.timekeeper.getSimFrameTime());
|
|
}
|
|
}
|
|
Globals.profiler.endCpuSample();
|
|
//
|
|
//make items play idle animation
|
|
Globals.profiler.beginCpuSample("item animations");
|
|
for(Entity item : Globals.clientState.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.ITEM)){
|
|
ItemUtils.updateItemActorAnimation(item);
|
|
}
|
|
Globals.profiler.endCpuSample();
|
|
//
|
|
//update attached entity positions
|
|
AttachUtils.clientUpdateAttachedEntityPositions();
|
|
Globals.particleService.handleAllSignals();
|
|
//
|
|
//Hitbox stuff
|
|
Globals.profiler.beginCpuSample("update hitboxes");
|
|
Globals.clientState.clientSceneWrapper.getHitboxManager().simulate();
|
|
Globals.profiler.endCpuSample();
|
|
//
|
|
//update foliage
|
|
if(Globals.clientState.foliageCellManager != null){
|
|
Globals.clientState.foliageCellManager.update();
|
|
}
|
|
//
|
|
//targeting crosshair
|
|
Globals.profiler.beginCpuSample("crosshair update");
|
|
Crosshair.checkTargetable();
|
|
Crosshair.updateTargetCrosshairPosition();
|
|
Globals.profiler.endCpuSample();
|
|
//
|
|
//simulate behavior trees
|
|
Globals.clientState.clientSceneWrapper.getScene().simulateBehaviorTrees((float)Globals.engineState.timekeeper.getSimFrameTime());
|
|
//
|
|
//sum collidable impulses
|
|
Globals.profiler.beginCpuSample("collidable logic");
|
|
for(Entity collidable : Globals.clientState.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.COLLIDABLE)){
|
|
if(ClientCollidableTree.hasClientCollidableTree(collidable)){
|
|
ClientCollidableTree.getClientCollidableTree(collidable).simulate((float)Globals.engineState.timekeeper.getSimFrameTime());
|
|
}
|
|
}
|
|
//
|
|
//clear collidable impulse lists
|
|
Globals.clientState.clientSceneWrapper.getCollisionEngine().clearCollidableImpulseLists();
|
|
Globals.clientState.clientSceneWrapper.getChemistryEngine().clearCollidableImpulseLists();
|
|
Globals.profiler.endCpuSample();
|
|
|
|
//
|
|
//Rebase world origin
|
|
Globals.clientState.clientSceneWrapper.getCollisionEngine().rebaseWorldOrigin();
|
|
|
|
//
|
|
//wrap up functions
|
|
this.runClientFunctions();
|
|
|
|
Globals.profiler.endCpuSample();
|
|
}
|
|
|
|
/**
|
|
* Client functions
|
|
*/
|
|
public void runClientFunctions(){
|
|
Globals.profiler.beginCpuSample("client functions");
|
|
ClientTerrainManager.generateTerrainChunkGeometry();
|
|
ClientFluidManager.generateFluidChunkGeometry();
|
|
this.updateSkyboxPos();
|
|
Globals.clientState.clientSceneWrapper.destroyEntitiesOutsideSimRange();
|
|
InstanceUpdater.updateInstancedActorPriority();
|
|
Globals.cameraHandler.updateGlobalCamera();
|
|
this.updateFirstPersonAttachments();
|
|
//bones have potenitally moved, so need to update where attached entities actually are before drawing
|
|
AttachUtils.clientUpdateAttachedEntityPositions();
|
|
ClientInteractionEngine.updateInteractionTargetLabel();
|
|
ToolbarPreviewWindow.checkVisibility();
|
|
this.runServices();
|
|
// updateCellManager();
|
|
Globals.profiler.endCpuSample();
|
|
}
|
|
|
|
/**
|
|
* Runs the client services
|
|
*/
|
|
private void runServices(){
|
|
Globals.profiler.beginCpuSample("ClientSimulation.runServices");
|
|
Globals.clientState.clientTemporalService.simulate();
|
|
Globals.profiler.endCpuSample();
|
|
}
|
|
|
|
|
|
/**
|
|
* Updates the skybox position to center on the player
|
|
*/
|
|
private void updateSkyboxPos(){
|
|
Globals.profiler.beginCpuSample("updateSkyboxPos");
|
|
if(Globals.clientState.skybox != null && Globals.clientState.playerEntity != null){
|
|
EntityUtils.setPosition(Globals.clientState.skybox, EntityUtils.getPosition(Globals.clientState.playerEntity));
|
|
}
|
|
Globals.profiler.endCpuSample();
|
|
}
|
|
|
|
/**
|
|
* If in first person, update the spatial transforms of things attached to the player viewmodel
|
|
*/
|
|
private void updateFirstPersonAttachments(){
|
|
Globals.profiler.beginCpuSample("updateFirstPersonAttachments");
|
|
//update the facing vector when camera moves in first person
|
|
if(!Globals.controlHandler.cameraIsThirdPerson() && Globals.clientState.playerCamera != null && Globals.clientState.playerEntity != null){
|
|
CreatureUtils.setFacingVector(Globals.clientState.playerEntity, CameraEntityUtils.getFacingVec(Globals.clientState.playerCamera));
|
|
//flush equipped item state
|
|
if(ClientEquipState.hasEquipState(Globals.clientState.playerEntity)){
|
|
ClientEquipState equipState = ClientEquipState.getClientEquipState(Globals.clientState.playerEntity);
|
|
equipState.evaluatePlayerAttachments();
|
|
}
|
|
}
|
|
Globals.profiler.endCpuSample();
|
|
}
|
|
|
|
/**
|
|
* Loads terrain that is in queue
|
|
*/
|
|
public void loadTerrain(){
|
|
Globals.profiler.beginCpuSample("ClientSimulation.loadTerrain");
|
|
if(Globals.clientState.clientTerrainManager != null){
|
|
Globals.clientState.clientTerrainManager.handleMessages();
|
|
this.updateTerrainCellManager();
|
|
}
|
|
if(Globals.clientState.clientFluidManager != null && EngineState.EngineFlags.RUN_FLUIDS){
|
|
Globals.clientState.clientFluidManager.handleMessages();
|
|
this.updateFluidCellManager();
|
|
}
|
|
if(Globals.clientState.clientBlockManager != null){
|
|
Globals.clientState.clientBlockManager.handleMessages();
|
|
this.updateBlockCellManager();
|
|
}
|
|
Globals.profiler.endCpuSample();
|
|
}
|
|
|
|
/**
|
|
* Updates the terrain cell manager (specifically position handling)
|
|
*/
|
|
private void updateTerrainCellManager(){
|
|
///
|
|
/// C L I E N T C E L L M A N A G E R
|
|
///
|
|
if(Globals.clientState.clientDrawCellManager != null && Globals.clientState.clientWorldData != null){
|
|
//Cell manager do your things
|
|
Globals.clientState.clientDrawCellManager.update();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Updates the fluid cell manager (specifically position handling)
|
|
*/
|
|
private void updateFluidCellManager(){
|
|
//fluid work
|
|
if(Globals.clientState.fluidCellManager != null && Globals.clientState.clientWorldData != null && EngineState.EngineFlags.RUN_FLUIDS){
|
|
Globals.clientState.fluidCellManager.update();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Updates the block cell manager
|
|
*/
|
|
private void updateBlockCellManager(){
|
|
if(Globals.clientState.clientBlockCellManager != null && Globals.clientState.clientWorldData != null){
|
|
Globals.clientState.clientBlockCellManager.update();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets whether the client simulation is ready to execute
|
|
* @return True if ready to execute, false otherwise
|
|
*/
|
|
public boolean isReady(){
|
|
return isReady;
|
|
}
|
|
|
|
/**
|
|
* Sets the ready status of the client simulation
|
|
* @param ready True if ready to simulate, false otherwise
|
|
*/
|
|
public void setReady(boolean ready){
|
|
isReady = ready;
|
|
}
|
|
|
|
/**
|
|
* Freezes simulation (sets ready to false)
|
|
*/
|
|
public void freeze(){
|
|
isReady = false;
|
|
}
|
|
|
|
/**
|
|
* Unfreezes simulation (sets ready to true)
|
|
*/
|
|
public void unfreeze(){
|
|
isReady = true;
|
|
}
|
|
|
|
/**
|
|
* Gets whether the client simulation is loading terrain
|
|
* @return True if loading terrain, false otherwise
|
|
*/
|
|
public boolean isLoadingTerrain(){
|
|
return this.loadTerrain;
|
|
}
|
|
|
|
/**
|
|
* Sets whether the client should load terrain or not
|
|
* @param loadTerrain True if should load terrain, false otherwise
|
|
*/
|
|
public void setLoadingTerrain(boolean loadTerrain){
|
|
this.loadTerrain = loadTerrain;
|
|
}
|
|
|
|
}
|