package electrosphere.engine; import java.lang.management.ManagementFactory; import java.util.ArrayList; import org.joml.Matrix4d; import org.joml.Vector3f; import electrosphere.audio.AudioEngine; import electrosphere.audio.VirtualAudioSourceManager; import electrosphere.audio.collision.HitboxAudioService; import electrosphere.audio.movement.MovementAudioService; import electrosphere.auth.AuthenticationManager; import electrosphere.client.ClientState; import electrosphere.client.block.cells.BlockTextureAtlas; import electrosphere.client.entity.particle.ParticleService; import electrosphere.client.fluid.cells.FluidCellManager; import electrosphere.client.terrain.cells.VoxelTextureAtlas; import electrosphere.client.ui.menu.WindowUtils; import electrosphere.collision.CollisionWorldData; import electrosphere.controls.CameraHandler; import electrosphere.controls.ControlCallback; import electrosphere.controls.ControlHandler; import electrosphere.controls.MouseCallback; import electrosphere.controls.ScrollCallback; import electrosphere.controls.cursor.CursorState; import electrosphere.data.particle.ParticleDefinition; import electrosphere.data.settings.UserSettings; import electrosphere.data.voxel.VoxelType; import electrosphere.engine.assetmanager.AssetDataStrings; import electrosphere.engine.assetmanager.AssetManager; import electrosphere.engine.loadingthreads.InitialAssetLoading; import electrosphere.engine.os.fs.FileWatcherService; import electrosphere.engine.profiler.Profiler; import electrosphere.engine.service.ServiceManager; import electrosphere.engine.signal.SignalSystem; import electrosphere.engine.signal.sync.MainThreadSignalService; import electrosphere.engine.threads.ThreadManager; import electrosphere.engine.time.Timekeeper; import electrosphere.logger.LoggerInterface; import electrosphere.net.config.NetConfig; import electrosphere.net.monitor.NetMonitor; import electrosphere.net.server.player.PlayerManager; import electrosphere.net.synchronization.server.EntityValueTrackingService; import electrosphere.renderer.RenderUtils; import electrosphere.renderer.RenderingEngine; import electrosphere.renderer.actor.instance.InstanceManager; import electrosphere.renderer.light.PointLight; import electrosphere.renderer.light.SpotLight; import electrosphere.renderer.loading.ModelPretransforms; import electrosphere.renderer.meshgen.FluidChunkModelGeneration; import electrosphere.renderer.model.Material; import electrosphere.renderer.shader.ShaderOptionMap; import electrosphere.renderer.shader.VisualShader; import electrosphere.renderer.texture.TextureMap; import electrosphere.renderer.ui.ElementService; import electrosphere.renderer.ui.elements.ImagePanel; import electrosphere.renderer.ui.font.FontManager; import electrosphere.script.ScriptEngine; import electrosphere.server.ServerState; import electrosphere.server.db.DatabaseController; import electrosphere.server.entity.poseactor.PoseModel; import electrosphere.server.service.CharacterService; import electrosphere.server.service.StructureScanningService; import electrosphere.server.simulation.MicroSimulation; import electrosphere.util.FileUtils; /** * Global values */ public class Globals { // //Process data // public static String javaPID; // //Thread manager // public static ThreadManager threadManager; // //Service manager // public static ServiceManager serviceManager; // //Signal system // public static SignalSystem signalSystem; // //Top level user settings object // public static UserSettings userSettings; // //Timekeeper // public static Timekeeper timekeeper; // //Rendering Engine // public static RenderingEngine renderingEngine; // //Audio Engine // public static AudioEngine audioEngine; public static VirtualAudioSourceManager virtualAudioSourceManager; public static MovementAudioService movementAudioService; public static HitboxAudioService hitboxAudioService; // //Core Engine signals // public static boolean ENGINE_SHUTDOWN_FLAG = false; //main debug flag //current enables imgui debug menu or not public static boolean ENGINE_DEBUG = true; // //Profiler // public static Profiler profiler; // //Garbage Collection // //set to true to trigger full GC every frame //a full GC includes collecting old generations as well -- likely very laggy!! public static boolean EXPLICIT_GC = false; /** * Number of frames to wait before triggering gc again */ public static final int GC_FRAME_FREQUENCY = 15; // //Engine timing // public static boolean EXPLICIT_SLEEP = true; // //Signals for running various parts of the engine // public static boolean RUN_DEMO = false; public static boolean RUN_CLIENT = true; public static boolean RUN_HIDDEN = false; //glfw session will be created with hidden window public static boolean RUN_AUDIO = true; public static boolean RUN_SCRIPTS = true; public static boolean RUN_PHYSICS = true; //toggles whether physics is run or not public static boolean RUN_FLUIDS = false; //toggles whether fluid physics is run or not public static int clientCharacterID; public static NetConfig netConfig = null; // //Server manager thing // public static boolean RUN_SERVER = true; // //Authentication manager // public static AuthenticationManager authenticationManager; // //Controls Handler // public static ControlHandler controlHandler; public static boolean updateCamera = true; public static ControlCallback controlCallback = new ControlCallback(); public static MouseCallback mouseCallback = new MouseCallback(); public static ScrollCallback scrollCallback = new ScrollCallback(); public static CursorState cursorState = new CursorState(); // // Game config // public static electrosphere.data.Config gameConfigDefault; public static electrosphere.data.Config gameConfigCurrent; // // Database stuff // public static DatabaseController dbController = new DatabaseController(); // //Camera handler stuff // public static CameraHandler cameraHandler = new CameraHandler(); // //behavior tree tracking service // public static EntityValueTrackingService entityValueTrackingService; // //Player manager // public static PlayerManager playerManager; // //Generic OpenGL Statements // public static long window = -1; // //OpenGL - Other // public static int WINDOW_WIDTH; public static int WINDOW_HEIGHT; public static boolean WINDOW_DECORATED = true; //used to control whether the window is created with decorations or not (ie for testing) public static boolean WINDOW_FULLSCREEN = false; //used to control whether the window is created fullscreen or not (ie for testing) //title bar dimensions public static int WINDOW_TITLE_BAR_HEIGHT = 0; public static float verticalFOV = 90; public static float aspectRatio = 2.0f; public static float nearClip = 0.01f; //matrices for drawing models public static Matrix4d viewMatrix = new Matrix4d(); public static Matrix4d projectionMatrix; public static Matrix4d lightDepthMatrix = new Matrix4d(); //locations for shadow map specific variables public static int depthMapShaderProgramLoc = 0; // //OpenGL - Abstracted engine objects // public static String textureDiffuseDefault; public static String textureSpecularDefault; public static Material materialDefault; public static final String blackTexture = "Textures/b1.png"; public static final String whiteTexture = "Textures/w1.png"; public static final String offWhiteTexture = "Textures/ow1.png"; public static String imagePlaneModelID; public static String solidPlaneModelID; public static ArrayList lightPointListDefault; public static SpotLight lightSpotDefault; public static TextureMap textureMapDefault; public static ModelPretransforms modelPretransforms; public static VisualShader defaultMeshShader; public static VisualShader terrainShaderProgram; public static VisualShader blockShader; // // Particle stuff // public static ParticleDefinition particleDefinition; public static ParticleService particleService; public static ShaderOptionMap shaderOptionMap; //manages all loaded fonts public static FontManager fontManager; // //Engine - Main managers/variables // //manages all models loaded into memory public static AssetManager assetManager; //micro simulation public static MicroSimulation microSimulation; //script engine public static ScriptEngine scriptEngine; //services public static MainThreadSignalService mainThreadSignalService; //instanced actor manager public static InstanceManager clientInstanceManager = new InstanceManager(); //chunk stuff public static VoxelTextureAtlas voxelTextureAtlas = new VoxelTextureAtlas(); public static BlockTextureAtlas blockTextureAtlas = new BlockTextureAtlas(); //fluid cell manager public static FluidCellManager fluidCellManager; //famous fuckin last words, but temporary solution //global arraylist of values for the skybox colors //edit(6/1/21): :upside_down_smile: public static ArrayList skyboxColors; //thread for loading different game states public static InitialAssetLoading initialAssetLoadingThread = new InitialAssetLoading(); //manager for all widgets currently being drawn to screen public static ElementService elementService; public static int openInventoriesCount = 0; //services public static FileWatcherService fileWatcherService; public static StructureScanningService structureScanningService; //collision world data public static CollisionWorldData commonWorldData; /** * State for the client */ public static ClientState clientState = new ClientState(); /** * State for the server */ public static ServerState serverState = new ServerState(); // //Base engine creation flags // public static boolean HEADLESS = false; // // // Renderer flags // // public static boolean RENDER_FLAG_RENDER_SHADOW_MAP = false; public static boolean RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER_CONTENT = false; public static boolean RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER = false; public static boolean RENDER_FLAG_RENDER_BLACK_BACKGROUND = true; public static boolean RENDER_FLAG_RENDER_WHITE_BACKGROUND = false; public static boolean RENDER_FLAG_RENDER_UI = true; public static boolean RENDER_FLAG_RENDER_UI_BOUNDS = false; // // Debugging tools // public static NetMonitor netMonitor; /** * Inits globals */ public static void initGlobals(){ //initialize logging interfaces LoggerInterface.initLoggers(); LoggerInterface.loggerStartup.INFO("Initialize global variables"); //gets java pid of engine if(Globals.javaPID == null){ Globals.javaPID = ManagementFactory.getRuntimeMXBean().getName(); } //load user settings Globals.WINDOW_WIDTH = 1920; Globals.WINDOW_HEIGHT = 1080; UserSettings.loadUserSettings(); //timekeeper timekeeper = new Timekeeper(); Globals.threadManager = new ThreadManager(); Globals.threadManager.init(); //render flags RENDER_FLAG_RENDER_SHADOW_MAP = false; RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER_CONTENT = false; RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER = false; RENDER_FLAG_RENDER_BLACK_BACKGROUND = true; RENDER_FLAG_RENDER_WHITE_BACKGROUND = false; RENDER_FLAG_RENDER_UI = true; RENDER_FLAG_RENDER_UI_BOUNDS = false; // //Service manager serviceManager = ServiceManager.create(); //client state Globals.clientState = new ClientState(); //server state Globals.serverState = new ServerState(); Globals.serverState.characterService = (CharacterService)serviceManager.registerService(new CharacterService()); //load in default texture map textureMapDefault = TextureMap.construct("Textures/default_texture_map.json"); //load model pretransforms modelPretransforms = FileUtils.loadObjectFromAssetPath("Models/modelPretransforms.json", ModelPretransforms.class); modelPretransforms.init(); //load in shader options map shaderOptionMap = FileUtils.loadObjectFromAssetPath("Shaders/shaderoptions.json", ShaderOptionMap.class); shaderOptionMap.debug(); //temporary hold for skybox colors skyboxColors = new ArrayList(); //load asset manager assetManager = new AssetManager(); //game config gameConfigDefault = electrosphere.data.Config.loadDefaultConfig(); gameConfigCurrent = gameConfigDefault; NetConfig.readNetConfig(); // //Values that depend on the loaded config Globals.clientState.clientSelectedVoxelType = (VoxelType)gameConfigCurrent.getVoxelData().getTypes().toArray()[1]; //player manager playerManager = new PlayerManager(); //behavior tree tracking service entityValueTrackingService = new EntityValueTrackingService(); //net monitor if(Globals.userSettings.getNetRunNetMonitor()){ netMonitor = new NetMonitor(); } //profiler profiler = new Profiler(); Globals.movementAudioService = new MovementAudioService(); Globals.hitboxAudioService = new HitboxAudioService(); //add services here Globals.signalSystem = (SignalSystem)serviceManager.registerService(new SignalSystem()); Globals.elementService = (ElementService)serviceManager.registerService(new ElementService()); Globals.particleService = (ParticleService)serviceManager.registerService(new ParticleService()); Globals.scriptEngine = (ScriptEngine)serviceManager.registerService(new ScriptEngine()); Globals.mainThreadSignalService = (MainThreadSignalService)serviceManager.registerService(new MainThreadSignalService()); Globals.fileWatcherService = (FileWatcherService)serviceManager.registerService(new FileWatcherService()); Globals.structureScanningService = (StructureScanningService)serviceManager.registerService(new StructureScanningService()); serviceManager.instantiate(); // //End service manager } /** * Inits default audio resources */ public static void initDefaultAudioResources(){ String[] audioToInit = new String[]{ "/Audio/ambienceWind1SeamlessMono.ogg", "/Audio/weapons/swordUnsheath1.ogg", "/Audio/weapons/swoosh-03.ogg", "/Audio/movement/Equip A.wav", "/Audio/weapons/collisions/FleshWeaponHit1.wav", "/Audio/weapons/collisions/Massive Punch A.wav", "/Audio/weapons/collisions/Massive Punch B.wav", "/Audio/weapons/collisions/Massive Punch C.wav", "Audio/weapons/collisions/Sword Hit A.wav", "Audio/weapons/collisions/Sword Hit B.wav", "Audio/weapons/collisions/Sword Hit C.wav", "Audio/weapons/collisions/Sword Hit D.wav", "Audio/weapons/collisions/Sword Hit E.wav", AssetDataStrings.UI_TONE_CONFIRM_PRIMARY, AssetDataStrings.UI_TONE_CONFIRM_SECONDARY, AssetDataStrings.UI_TONE_CURSOR_PRIMARY, AssetDataStrings.UI_TONE_CURSOR_SECONDARY, AssetDataStrings.UI_TONE_BACK_PRIMARY, AssetDataStrings.UI_TONE_BACK_SECONDARY, AssetDataStrings.UI_TONE_ERROR_PRIMARY, AssetDataStrings.UI_TONE_ERROR_SECONDARY, AssetDataStrings.UI_TONE_BUTTON_TITLE, AssetDataStrings.UI_SFX_ITEM_GRAB, AssetDataStrings.UI_SFX_ITEM_RELEASE, AssetDataStrings.UI_SFX_INVENTORY_OPEN, AssetDataStrings.UI_SFX_INVENTORY_CLOSE, AssetDataStrings.INTERACT_SFX_BLOCK_PICKUP, AssetDataStrings.INTERACT_SFX_BLOCK_PLACE, AssetDataStrings.INTERACT_SFX_DIG, }; LoggerInterface.loggerStartup.INFO("Loading default audio resources"); for(String path : audioToInit){ Globals.assetManager.addAudioPathToQueue(path); } Globals.movementAudioService.init(); } /** * Texture paths to be loaded when renderer inits */ private static String[] defaultTexturePaths = new String[]{ AssetDataStrings.TEXTURE_DEFAULT, "Textures/default_diffuse.png", "Textures/default_specular.png", "Textures/b1.png", "Textures/w1.png", "Textures/ow1.png", "Textures/ui/WindowBorder.png", "Textures/ui/uiOutline1.png", AssetDataStrings.UI_ENGINE_LOGO_1, AssetDataStrings.UI_FRAME_TEXTURE_DEFAULT_1, AssetDataStrings.UI_FRAME_TEXTURE_DEFAULT_2, AssetDataStrings.UI_FRAME_TEXTURE_DEFAULT_3, "Textures/ui/circle.png", "Textures/ui/square.png", "Textures/color/transparent_green.png", "Textures/color/transparent_magenta.png", "Textures/color/transparent_orange.png", "Textures/color/transparent_teal.png", "Textures/color/transparent_yellow.png", "Textures/bloodsplat1.png", }; /** * The set of models who should correspond to no pose model */ private static String[] defaultModelsWithNoPose = new String[]{ AssetDataStrings.POSE_EMPTY, AssetDataStrings.UNITSPHERE, AssetDataStrings.UNITCYLINDER, AssetDataStrings.UNITCUBE, AssetDataStrings.MODEL_BLOCK_SINGLE, }; /** * Inits default graphical resources */ public static void initDefaultGraphicalResources(){ LoggerInterface.loggerStartup.INFO("Loading default graphical resources"); //load default textures for(String defaultTexturePath: defaultTexturePaths){ Globals.assetManager.addTexturePathtoQueue(defaultTexturePath); } //create default material materialDefault = new Material(); materialDefault.setDiffuse(AssetDataStrings.TEXTURE_DEFAULT); materialDefault.setSpecular(AssetDataStrings.TEXTURE_DEFAULT); //create font manager fontManager = new FontManager(); fontManager.loadFonts(); assetManager.registerModelWithPath(RenderUtils.createBitmapCharacter(), AssetDataStrings.BITMAP_CHARACTER_MODEL); //particle billboard model assetManager.registerModelWithPath(RenderUtils.createParticleModel(), AssetDataStrings.MODEL_PARTICLE); //initialize required windows WindowUtils.initBaseWindows(); //init default shaderProgram defaultMeshShader = VisualShader.smartAssembleShader(false,true); //init terrain shader program terrainShaderProgram = VisualShader.loadSpecificShader("/Shaders/entities/terrain2/terrain2.vs", "/Shaders/entities/terrain2/terrain2.fs"); blockShader = VisualShader.loadSpecificShader("/Shaders/entities/block/block.vs", "/Shaders/entities/block/block.fs"); //init fluid shader program FluidChunkModelGeneration.fluidChunkShaderProgram = VisualShader.loadSpecificShader("/Shaders/entities/fluid2/fluid2.vs", "/Shaders/entities/fluid2/fluid2.fs"); //init models assetManager.registerModelWithPath(RenderUtils.createUnitsphere(), AssetDataStrings.UNITSPHERE); assetManager.registerModelWithPath(RenderUtils.createUnitCylinder(), AssetDataStrings.UNITCYLINDER); assetManager.registerModelWithPath(RenderUtils.createUnitCube(), AssetDataStrings.UNITCUBE); assetManager.registerModelWithPath(RenderUtils.createBlockSingleModel(), AssetDataStrings.MODEL_BLOCK_SINGLE); assetManager.addModelPathToQueue("Models/basic/geometry/SmallCube.fbx"); assetManager.addModelPathToQueue("Models/basic/geometry/unitcapsule.glb"); assetManager.addModelPathToQueue("Models/basic/geometry/unitplane.fbx"); assetManager.addModelPathToQueue("Models/basic/geometry/unitcube.fbx"); imagePlaneModelID = assetManager.registerModel(RenderUtils.createPlaneModel("Shaders/core/plane/plane.vs", "Shaders/core/plane/plane.fs")); assetManager.addShaderToQueue("Shaders/core/plane/plane.vs", "Shaders/core/plane/plane.fs"); solidPlaneModelID = assetManager.registerModel(RenderUtils.createInWindowPanel("Shaders/ui/plainBox/plainBox.vs", "Shaders/ui/plainBox/plainBox.fs")); //init pose models for basic shapes PoseModel emptyPoseModel = PoseModel.createEmpty(); for(String modelPath : defaultModelsWithNoPose){ assetManager.registerPoseModelWithPath(emptyPoseModel, modelPath); } //image panel ImagePanel.imagePanelModelPath = assetManager.registerModel(RenderUtils.createPlaneModel("Shaders/core/imagepanel/imagepanel.vs", "Shaders/core/imagepanel/imagepanel.fs")); Globals.assetManager.addShaderToQueue("Shaders/ui/plainBox/plainBox.vs", "Shaders/ui/plainBox/plainBox.fs"); //window content shader assetManager.addShaderToQueue("Shaders/ui/windowContent/windowContent.vs", "Shaders/ui/windowContent/windowContent.fs"); //debug shaders assetManager.addShaderToQueue("Shaders/ui/debug/windowBorder/windowBound.vs", "Shaders/ui/debug/windowBorder/windowBound.fs"); assetManager.addShaderToQueue("Shaders/ui/debug/windowContentBorder/windowContentBound.vs", "Shaders/ui/debug/windowContentBorder/windowContentBound.fs"); //compute shaders assetManager.addComputeShaderToQueue(AssetDataStrings.COMPUTE_LIGHT_CLUSTER); assetManager.addComputeShaderToQueue(AssetDataStrings.COMPUTE_LIGHT_CULL); //as these assets are required for the renderer to work, we go ahead and //load them into memory now. The loading time penalty is worth it I think. Globals.assetManager.loadAssetsInQueue(); } /** * Unloads scene */ public static void unloadScene(){ Globals.serverState.aiManager.shutdown(); Globals.serverState.realmManager.reset(); Globals.playerManager = new PlayerManager(); Globals.clientState = new ClientState(); Globals.serverState = new ServerState(); if(Globals.serviceManager != null){ Globals.serverState.characterService = (CharacterService)Globals.serviceManager.registerService(new CharacterService()); } Globals.dbController.disconnect(); Globals.serviceManager.unloadScene(); } /** * Resets global values */ public static void resetGlobals(){ Globals.unloadScene(); if(Globals.serverState != null && Globals.serverState.aiManager != null){ Globals.serverState.aiManager.shutdown(); } // //Actual globals to destroy Globals.assetManager = null; Globals.elementService = null; Globals.clientState = null; Globals.serverState = null; Globals.audioEngine = null; Globals.renderingEngine = null; Globals.threadManager = null; Globals.signalSystem = null; Globals.serviceManager = null; Globals.fileWatcherService = null; Globals.playerManager = null; Globals.javaPID = null; Globals.RENDER_FLAG_RENDER_SHADOW_MAP = true; Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER_CONTENT = false; Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER = false; Globals.RENDER_FLAG_RENDER_UI = false; Globals.RENDER_FLAG_RENDER_BLACK_BACKGROUND = false; Globals.RENDER_FLAG_RENDER_WHITE_BACKGROUND = false; Globals.window = -1; LoggerInterface.destroyLoggers(); } }