Multiplayer networking + broke a bunch of things, we'll need to redo gun switching

This commit is contained in:
Halbear 2026-07-09 00:18:29 +01:00
parent c270a049b5
commit f3c83bea80
23 changed files with 23298 additions and 1071 deletions

21244
ClientLog.t4jlog Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

151
ServerLog.t4jlog Normal file
View file

@ -0,0 +1,151 @@
190:07:2026 00:11:08.410 INFO:
Launching New Terrain4J Powered Software!
190:07:2026 00:11:08.414 DEBUG: File [terrain4j.properties] read
190:07:2026 00:11:08.418 DEBUG:
successfully loaded configuration:
{compatibility_mode=false, ShaderRecompiling=true, cap_main_to_tickrate=true, LoadingScreenLocation=resources/EngineResources/Texture/Terrain4JTitleImage.png, z_near_plane=10000.0f, display_width=640, anti_alias_mode=0, main_thread_tickrate=120, Software_Icon=ProgramIcon.png, MaxAllowedVulkanCrashes=10, throttle_on_unfocus=false, vsync=false, cap_fast_to_tickrate=true, Software_Icon_Path=/WindowResources/Icon/, RequestedImages=3, throttle_accuracy=4000000, DualPassRendering=false, field_of_view=60.0f, ShadowMapSize=2048, PhysicalDeviceName=, fast_thread_tickrate=240, vkValidated=true, cap_master_to_tickrate=true, AlphaToCoverage=false, display_height=480, Renderer=1, Software_Title=Terrain4J Game Engine, z_far_plane=0.1f, frame_accuracy=0, master_tick_rate=240, Debug_Shaders=false, DefaultTexturePath=resources/EngineResources/Texture/NoTexture.png}
190:07:2026 00:11:08.465 DEBUG: Loading Models From [resources/models/cube/Cube.json]
190:07:2026 00:11:08.508 DEBUG: Loaded Model Data: [ModelData[ID=Cube, Meshes=[MeshData[ID=mesh_0, MaterialID=Cube-mat-1, OffsetVertex=0, VertexSize=1344, OffsetIndex=0, IndexSize=144]], VertexPath=resources/models/cube/Cube.vtx, IndexPath=resources/models/cube/Cube.idx]]
190:07:2026 00:11:08.508 DEBUG: Loading Materials From [resources/models/cube/Cube_mat.json]
190:07:2026 00:11:08.518 DEBUG: Loaded Material Data: [[MaterialData[ID=Cube-mat-0, TexturePath=, NormalTexturePath=, MetalRoughnessMap=, DiffuseColour=( 6.000E-1 6.000E-1 6.000E-1 1.000E+0), Roughness=0.0, Metallic=0.0], MaterialData[ID=Cube-mat-1, TexturePath=resources\models\cube\cubetexture.png, NormalTexturePath=, MetalRoughnessMap=, DiffuseColour=( 6.000E-1 6.000E-1 6.000E-1 1.000E+0), Roughness=0.0, Metallic=0.0], MaterialData[ID=Cube-mat-2, TexturePath=, NormalTexturePath=, MetalRoughnessMap=, DiffuseColour=( 6.000E-1 6.000E-1 6.000E-1 1.000E+0), Roughness=0.0, Metallic=0.0]]]
190:07:2026 00:11:08.518 DEBUG: Loading Models From [resources/models/musket/musket.json]
190:07:2026 00:11:08.519 DEBUG: Loaded Model Data: [ModelData[ID=musket, Meshes=[MeshData[ID=cube_0, MaterialID=musket-mat-1, OffsetVertex=0, VertexSize=25088, OffsetIndex=0, IndexSize=2880]], VertexPath=resources/models/musket/musket.vtx, IndexPath=resources/models/musket/musket.idx]]
190:07:2026 00:11:08.519 DEBUG: Loading Materials From [resources/models/musket/musket_mat.json]
190:07:2026 00:11:08.519 DEBUG: Loaded Material Data: [[MaterialData[ID=musket-mat-0, TexturePath=, NormalTexturePath=, MetalRoughnessMap=, DiffuseColour=( 6.000E-1 6.000E-1 6.000E-1 1.000E+0), Roughness=0.0, Metallic=0.0], MaterialData[ID=musket-mat-1, TexturePath=resources\models\musket\Musket.png, NormalTexturePath=, MetalRoughnessMap=, DiffuseColour=( 6.000E-1 6.000E-1 6.000E-1 1.000E+0), Roughness=0.0, Metallic=0.0], MaterialData[ID=musket-mat-2, TexturePath=, NormalTexturePath=, MetalRoughnessMap=, DiffuseColour=( 6.000E-1 6.000E-1 6.000E-1 1.000E+0), Roughness=0.0, Metallic=0.0]]]
190:07:2026 00:11:08.519 DEBUG: Loading Models From [resources/models/Revolver/Revolver.json]
190:07:2026 00:11:08.520 DEBUG: Loaded Model Data: [ModelData[ID=Revolver, Meshes=[MeshData[ID=cube_0, MaterialID=Revolver-mat-1, OffsetVertex=0, VertexSize=21280, OffsetIndex=0, IndexSize=2304]], VertexPath=resources/models/Revolver/Revolver.vtx, IndexPath=resources/models/Revolver/Revolver.idx]]
190:07:2026 00:11:08.520 DEBUG: Loading Materials From [resources/models/Revolver/Revolver_mat.json]
190:07:2026 00:11:08.521 DEBUG: Loaded Material Data: [[MaterialData[ID=Revolver-mat-0, TexturePath=, NormalTexturePath=, MetalRoughnessMap=, DiffuseColour=( 6.000E-1 6.000E-1 6.000E-1 1.000E+0), Roughness=0.0, Metallic=0.0], MaterialData[ID=Revolver-mat-1, TexturePath=resources\models\Revolver\Revolver.png, NormalTexturePath=, MetalRoughnessMap=, DiffuseColour=( 6.000E-1 6.000E-1 6.000E-1 1.000E+0), Roughness=0.0, Metallic=0.0], MaterialData[ID=Revolver-mat-2, TexturePath=, NormalTexturePath=, MetalRoughnessMap=, DiffuseColour=( 6.000E-1 6.000E-1 6.000E-1 1.000E+0), Roughness=0.0, Metallic=0.0]]]
190:07:2026 00:11:08.524 INFO: Spawning static cube actor [MelonaSpawned0] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.527 INFO: Spawning static cube actor [MelonaSpawned1] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.527 INFO: Spawning static cube actor [MelonaSpawned2] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.527 INFO: Spawning static cube actor [MelonaSpawned3] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.527 INFO: Spawning static cube actor [MelonaSpawned4] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.527 INFO: Spawning static cube actor [MelonaSpawned5] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.528 INFO: Spawning static cube actor [MelonaSpawned6] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.528 INFO: Spawning static cube actor [MelonaSpawned7] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.528 INFO: Spawning static cube actor [MelonaSpawned8] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.528 INFO: Spawning static cube actor [MelonaSpawned9] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.528 INFO: Spawning static cube actor [MelonaSpawned10] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.528 INFO: Spawning static cube actor [MelonaSpawned11] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.528 INFO: Spawning static cube actor [MelonaSpawned12] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.528 INFO: Spawning static cube actor [MelonaSpawned13] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.528 INFO: Spawning static cube actor [MelonaSpawned14] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.529 INFO: Spawning static cube actor [MelonaSpawned15] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.529 INFO: Spawning static cube actor [MelonaSpawned16] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.529 INFO: Spawning static cube actor [MelonaSpawned17] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.529 INFO: Spawning static cube actor [MelonaSpawned18] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.529 INFO: Spawning static cube actor [MelonaSpawned19] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.529 INFO: Spawning static cube actor [MelonaSpawned20] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.529 INFO: Spawning static cube actor [MelonaSpawned21] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.529 INFO: Spawning static cube actor [MelonaSpawned22] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.529 INFO: Spawning static cube actor [MelonaSpawned23] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.529 INFO: Spawning static cube actor [MelonaSpawned24] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.529 INFO: Spawning static cube actor [MelonaSpawned25] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.529 INFO: Spawning static cube actor [MelonaSpawned26] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.529 INFO: Spawning static cube actor [MelonaSpawned27] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.529 INFO: Spawning static cube actor [MelonaSpawned28] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.529 INFO: Spawning static cube actor [MelonaSpawned29] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.530 INFO: Spawning static cube actor [MelonaSpawned30] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.530 INFO: Spawning static cube actor [MelonaSpawned31] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.530 INFO: Spawning static cube actor [MelonaSpawned32] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.530 INFO: Spawning static cube actor [MelonaSpawned33] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.530 INFO: Spawning static cube actor [MelonaSpawned34] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.530 INFO: Spawning static cube actor [MelonaSpawned35] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.531 INFO: Spawning static cube actor [MelonaSpawned36] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.531 INFO: Spawning static cube actor [MelonaSpawned37] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.531 INFO: Spawning static cube actor [MelonaSpawned38] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.531 INFO: Spawning static cube actor [MelonaSpawned39] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.531 INFO: Spawning static cube actor [MelonaSpawned40] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.531 INFO: Spawning static cube actor [MelonaSpawned41] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.531 INFO: Spawning static cube actor [MelonaSpawned42] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.531 INFO: Spawning static cube actor [MelonaSpawned43] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.531 INFO: Spawning static cube actor [MelonaSpawned44] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.531 INFO: Spawning static cube actor [MelonaSpawned45] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.531 INFO: Spawning static cube actor [MelonaSpawned46] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.531 INFO: Spawning static cube actor [MelonaSpawned47] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.531 INFO: Spawning static cube actor [MelonaSpawned48] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.531 INFO: Spawning static cube actor [MelonaSpawned49] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.531 INFO: Spawning static cube actor [MelonaSpawned50] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.531 INFO: Spawning static cube actor [MelonaSpawned51] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.531 INFO: Spawning static cube actor [MelonaSpawned52] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.531 INFO: Spawning static cube actor [MelonaSpawned53] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.532 INFO: Spawning static cube actor [MelonaSpawned54] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.532 INFO: Spawning static cube actor [MelonaSpawned55] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.532 INFO: Spawning static cube actor [MelonaSpawned56] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.532 INFO: Spawning static cube actor [MelonaSpawned57] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.532 INFO: Spawning static cube actor [MelonaSpawned58] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.532 INFO: Spawning static cube actor [MelonaSpawned59] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.532 INFO: Spawning static cube actor [MelonaSpawned60] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.532 INFO: Spawning static cube actor [MelonaSpawned61] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.532 INFO: Spawning static cube actor [MelonaSpawned62] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.532 INFO: Spawning static cube actor [MelonaSpawned63] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.532 INFO: Spawning static cube actor [MelonaSpawned64] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.532 INFO: Spawning static cube actor [MelonaSpawned65] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.532 INFO: Spawning static cube actor [MelonaSpawned66] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.532 INFO: Spawning static cube actor [MelonaSpawned67] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.532 INFO: Spawning static cube actor [MelonaSpawned68] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.532 INFO: Spawning static cube actor [MelonaSpawned69] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.533 INFO: Spawning static cube actor [MelonaSpawned70] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.533 INFO: Spawning static cube actor [MelonaSpawned71] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.533 INFO: Spawning static cube actor [MelonaSpawned72] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.533 INFO: Spawning static cube actor [MelonaSpawned73] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.533 INFO: Spawning static cube actor [MelonaSpawned74] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.533 INFO: Spawning static cube actor [MelonaSpawned75] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.533 INFO: Spawning static cube actor [MelonaSpawned76] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.533 INFO: Spawning static cube actor [MelonaSpawned77] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.533 INFO: Spawning static cube actor [MelonaSpawned78] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.533 INFO: Spawning static cube actor [MelonaSpawned79] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.533 INFO: Spawning static cube actor [MelonaSpawned80] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.533 INFO: Spawning static cube actor [MelonaSpawned81] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.533 INFO: Spawning static cube actor [MelonaSpawned82] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.533 INFO: Spawning static cube actor [MelonaSpawned83] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.533 INFO: Spawning static cube actor [MelonaSpawned84] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.534 INFO: Spawning static cube actor [MelonaSpawned85] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.534 INFO: Spawning static cube actor [MelonaSpawned86] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.534 INFO: Spawning static cube actor [MelonaSpawned87] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.534 INFO: Spawning static cube actor [MelonaSpawned88] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.534 INFO: Spawning static cube actor [MelonaSpawned89] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.534 INFO: Spawning static cube actor [MelonaSpawned90] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.534 INFO: Spawning static cube actor [MelonaSpawned91] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.534 INFO: Spawning static cube actor [MelonaSpawned92] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.534 INFO: Spawning static cube actor [MelonaSpawned93] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.534 INFO: Spawning static cube actor [MelonaSpawned94] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.534 INFO: Spawning static cube actor [MelonaSpawned95] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.534 INFO: Spawning static cube actor [MelonaSpawned96] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.534 INFO: Spawning static cube actor [MelonaSpawned97] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.534 INFO: Spawning static cube actor [MelonaSpawned98] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned99] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned100] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned101] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned102] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned103] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned104] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned105] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned106] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned107] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned108] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned109] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned110] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned111] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned112] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned113] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned114] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned115] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned116] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned117] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned118] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned119] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.535 INFO: Spawning static cube actor [MelonaSpawned120] with model ID [Cube], with cached ID of [Cube]
190:07:2026 00:11:08.537 DEBUG: Starting Main Thread
190:07:2026 00:11:08.537 DEBUG: Starting Fast Thread
190:07:2026 00:11:08.537 DEBUG: Starting Render Thread
190:07:2026 00:11:08.619 INFO: Launched Terrain4J Engine
190:07:2026 00:11:08.619 DEBUG: Primary Thread Started
190:07:2026 00:11:08.619 INFO: Terrain4J dedicated server running without GLFW/Vulkan/OpenAL
190:07:2026 00:11:08.620 DEBUG: Main Thread Started
190:07:2026 00:11:08.620 DEBUG: Render Thread Started
190:07:2026 00:11:08.620 DEBUG: Fast Thread Started

View file

@ -4,10 +4,12 @@ import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Main.GameCore; import net.halbear.Terrain4J.EngineCore.Main.GameCore;
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime; import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import org.tinylog.Logger; import org.tinylog.Logger;
import org.tinylog.configuration.Configuration;
//Halbear was here //Halbear was here
public class Init { public class Init {
public static void main(String[] args){ public static void main(String[] args){
Configuration.set("writer.file", "ClientLog.t4jlog");
Logger.info("\nLaunching New Terrain4J Powered Software!"); Logger.info("\nLaunching New Terrain4J Powered Software!");
var GameEngine = new PrimaryRuntime(EngineConfig.getInstance().GetSoftwareName(), new GameCore()); var GameEngine = new PrimaryRuntime(EngineConfig.getInstance().GetSoftwareName(), new GameCore());
Logger.info("Launched Terrain4J Engine"); Logger.info("Launched Terrain4J Engine");

View file

@ -0,0 +1,82 @@
package net.halbear.Executable;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Main.GameCore;
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import net.halbear.Terrain4J.EngineCore.ServerNetworking.Packet;
import net.halbear.Terrain4J.EngineCore.Threads.RenderThread;
import net.halbear.Terrain4J.EngineCore.Threads.ServerConnectionThread;
import org.tinylog.Logger;
import org.tinylog.configuration.Configuration;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
public class Server {
public static Map<UUID, ServerConnectionThread> ConnectedClients = new ConcurrentHashMap<>();
public static final Queue<Packet> OutGoingPacketQueue = new ConcurrentLinkedQueue<>();
public static final Queue<Packet> IncomingPacketQueue = new ConcurrentLinkedQueue<>();
public static void CollectIncomingPackets(){
ConnectedClients.forEach((uuid,client)->{
client.CollectIncomingPackets(IncomingPacketQueue);
});
}
public static void ProcessIncomingPackets(){
Packet packet;
while((packet = IncomingPacketQueue.poll()) != null){
ServerConnectionThread.ProcessClientPacket(packet);
}
}
public static void ProcessOutgoingPackets(){
Packet packet;
while((packet = OutGoingPacketQueue.poll()) != null){
Packet packetToSend = packet;
ConnectedClients.forEach((uuid,client)->{
client.AddOutgoingPacket(packetToSend);
});
}
}
public static void RemoveClient(UUID clientID){
ServerConnectionThread connection = ConnectedClients.remove(clientID);
if(connection != null){
connection.DestroyOwnedActor();
}
}
public static void main(String[] args) throws IOException {
Configuration.set("writer.file", "ServerLog.t4jlog");
ServerSocket server = new ServerSocket(25565);
Logger.info("\nLaunching New Terrain4J Powered Software!");
RenderThread.Headless = true;
PrimaryRuntime.Server = true;
Thread acceptThread = new Thread(() -> {
while(true) {
try {
Socket clientSocket = server.accept();
new Thread(new ServerConnectionThread(clientSocket)).start();
} catch (IOException e) {
Logger.error(e, "Failed to accept client connection");
}
}
}, "Terrain4J Server Accept Thread");
acceptThread.start();
var GameEngine = new PrimaryRuntime(EngineConfig.getInstance().GetSoftwareName(), new GameCore());
Logger.info("Launched Terrain4J Engine");
GameEngine.run();
}
}

View file

@ -25,6 +25,7 @@ public class Window {
private boolean displayFPS = false; private boolean displayFPS = false;
public Window(String title){ public Window(String title){
if (!glfwInit()) { if (!glfwInit()) {
throw new RuntimeException("Unable to initialize GLFW"); throw new RuntimeException("Unable to initialize GLFW");
} }

View file

@ -27,6 +27,7 @@ public class ConvexMesh {
public final Vector3f Position = new Vector3f(); public final Vector3f Position = new Vector3f();
public final Quaternionf Orientation = new Quaternionf(); public final Quaternionf Orientation = new Quaternionf();
public Vector3f hxhyhz = new Vector3f();
public Vector3f WorldVertex(int i) { public Vector3f WorldVertex(int i) {
Vector3f vertex = new Vector3f(LocalVertices.get(i)); Vector3f vertex = new Vector3f(LocalVertices.get(i));
@ -81,6 +82,7 @@ public class ConvexMesh {
//Creates a basic AABB, that said, its not really axis aligned so idk why im referring to is as one //Creates a basic AABB, that said, its not really axis aligned so idk why im referring to is as one
public static ConvexMesh Box(float hx, float hy, float hz) { public static ConvexMesh Box(float hx, float hy, float hz) {
ConvexMesh mesh = new ConvexMesh(); ConvexMesh mesh = new ConvexMesh();
mesh.hxhyhz.set(hx,hy,hz);
mesh.LocalVertices.add(new Vector3f(-hx, -hy, -hz)); // 0 mesh.LocalVertices.add(new Vector3f(-hx, -hy, -hz)); // 0
mesh.LocalVertices.add(new Vector3f( hx, -hy, -hz)); // 1 mesh.LocalVertices.add(new Vector3f( hx, -hy, -hz)); // 1
mesh.LocalVertices.add(new Vector3f( hx, hy, -hz)); // 2 mesh.LocalVertices.add(new Vector3f( hx, hy, -hz)); // 2

View file

@ -3,7 +3,9 @@ package net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.LegacyCollision.CollisionMesh; import net.halbear.Terrain4J.EngineCore.Logic.Physics.LegacyCollision.CollisionMesh;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.IPhysicsController; import net.halbear.Terrain4J.EngineCore.Logic.Physics.IPhysicsController;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.WorldPhysicsManager; import net.halbear.Terrain4J.EngineCore.Logic.Physics.WorldPhysicsManager;
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor; import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor;
import net.halbear.Terrain4J.EngineCore.Threads.ClientConnectionThread;
import org.joml.Vector2f; import org.joml.Vector2f;
import org.joml.Vector3f; import org.joml.Vector3f;
@ -101,8 +103,18 @@ public class RigidPhysicsController implements IPhysicsController {
@Override @Override
public void PhysicsTick(float DeltaTime, float TargetFrameRate) { public void PhysicsTick(float DeltaTime, float TargetFrameRate) {
Actor actor = Actor.Actors.get(ActorID);
if(!PrimaryRuntime.Server
&& ClientConnectionThread.Connected
&& actor != null
&& actor.IsServerSynced()
&& !ActorID.equals(ClientConnectionThread.OwnedActorID)) {
return;
}
DeltaTime/=10f; DeltaTime/=10f;
// if(DeltaTime >0.1f) DeltaTime = 0.1f; // if(DeltaTime >0.1f) DeltaTime = 0.1f;
if(RigidBodyID != null && RigidBodyRegister.get(RigidBodyID) != null && ActorID != "NULL") { if(RigidBodyID != null && RigidBodyRegister.get(RigidBodyID) != null && ActorID != "NULL") {
RigidBody rigidBody = RigidBodyRegister.get(RigidBodyID); RigidBody rigidBody = RigidBodyRegister.get(RigidBodyID);

View file

@ -1,11 +1,11 @@
package net.halbear.Terrain4J.EngineCore.Logic.Physics; package net.halbear.Terrain4J.EngineCore.Logic.Physics;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.ConvexMesh; import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.*;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidBody; import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidCollision; import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.SeparatingAxisTheoremTester; import net.halbear.Terrain4J.EngineCore.Threads.ClientConnectionThread;
import net.halbear.Terrain4J.EngineCore.Threads.PhysicsThread; import net.halbear.Terrain4J.EngineCore.Threads.InstancedPhysicsThread;
import org.joml.Vector2f; import org.joml.Vector2f;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.joml.primitives.AABBf; import org.joml.primitives.AABBf;
@ -28,7 +28,7 @@ public class WorldPhysicsManager {
public static int MaxSubStepsPerFrame = 8; public static int MaxSubStepsPerFrame = 8;
private static float Accumulator = 0f; private static float Accumulator = 0f;
private static boolean SingleThread = false; private static boolean SingleThread = false;
private static List<PhysicsThread> physicsThreads = new ArrayList<>(); private static List<InstancedPhysicsThread> physicsThreads = new ArrayList<>();
public static void SteppedPhysicsTick(float DeltaTime, float TargetFrameTime){ public static void SteppedPhysicsTick(float DeltaTime, float TargetFrameTime){
int ThreadsNeeded = (int)Math.floor(ActiveControllers.size()/100f); int ThreadsNeeded = (int)Math.floor(ActiveControllers.size()/100f);
@ -99,6 +99,7 @@ public class WorldPhysicsManager {
for (int i = 0; i < ids.size(); i++) { for (int i = 0; i < ids.size(); i++) {
RigidBody body = RigidBody.RigidBodyRegister.get(ids.get(i)); RigidBody body = RigidBody.RigidBodyRegister.get(ids.get(i));
if (body == null) continue; if (body == null) continue;
if(IsClientRemoteNetworkBody(body)) continue;
AABBf bounds = body.shape.GetWorldAABB(); AABBf bounds = body.shape.GetWorldAABB();
worldBounds.put(body.RigidBodyID, bounds); worldBounds.put(body.RigidBodyID, bounds);
@ -133,6 +134,37 @@ public class WorldPhysicsManager {
} }
} }
private static boolean IsClientRemoteNetworkBody(RigidBody body) {
if (PrimaryRuntime.Server || !ClientConnectionThread.Connected || body == null) {
return false;
}
if(body.IsStatic) {
return false;
}
Actor actor = GetActorForRigidBody(body);
return actor != null
&& actor.IsServerSynced()
&& !actor.GetID().equals(ClientConnectionThread.OwnedActorID);
}
private static Actor GetActorForRigidBody(RigidBody body) {
for (Actor actor : Actor.Actors.values()) {
if (!(actor.GetPhysicsController() instanceof RigidPhysicsController rigidPhysicsController)) {
continue;
}
if (rigidPhysicsController.RigidBodyID.equals(body.RigidBodyID)) {
return actor;
}
}
return null;
}
private static void TryResolve(RigidBody a, RigidBody b, Map<String, AABBf> worldBounds, Set<String> testedPairs) { private static void TryResolve(RigidBody a, RigidBody b, Map<String, AABBf> worldBounds, Set<String> testedPairs) {
String key = a.RigidBodyID.compareTo(b.RigidBodyID) < 0 String key = a.RigidBodyID.compareTo(b.RigidBodyID) < 0
? a.RigidBodyID + "|" + b.RigidBodyID ? a.RigidBodyID + "|" + b.RigidBodyID
@ -151,14 +183,48 @@ public class WorldPhysicsManager {
DeltaTime *= EngineConfig.getInstance().PhysicsSpeed(); DeltaTime *= EngineConfig.getInstance().PhysicsSpeed();
if(EngineConfig.getInstance().IsEngineThrottled()) return; if(EngineConfig.getInstance().IsEngineThrottled()) return;
PhysicsTick++; PhysicsTick++;
for (int i = 0; i < ActiveControllers.size(); i++) { for (int i = 0; i < ActiveControllers.size(); i++) {
PhysicsObjects.get(ActiveControllers.get(i)).PhysicsTick(DeltaTime, TargetFrameTime); IPhysicsController controller = PhysicsObjects.get(ActiveControllers.get(i));
if(controller != null) {
controller.PhysicsTick(DeltaTime, TargetFrameTime);
}
} }
SweepForTunneling(); SweepForTunneling();
ResetGroundedFlags(); ResetGroundedFlags();
ResolveAllCollisions(); ResolveAllCollisions();
SyncRigidBodiesToActors();
for (int i = 0; i < ActiveControllers.size(); i++) { for (int i = 0; i < ActiveControllers.size(); i++) {
PhysicsObjects.get(ActiveControllers.get(i)).Collisions().clear(); IPhysicsController controller = PhysicsObjects.get(ActiveControllers.get(i));
if(controller != null) {
controller.Collisions().clear();
}
}
}
private static void SyncRigidBodiesToActors(){
for (int i = 0; i < ActiveControllers.size(); i++) {
IPhysicsController controller = PhysicsObjects.get(ActiveControllers.get(i));
if(!(controller instanceof RigidPhysicsController rigidPhysicsController)) continue;
Actor actor = Actor.Actors.get(rigidPhysicsController.ActorID);
RigidBody body = RigidBody.RigidBodyRegister.get(rigidPhysicsController.RigidBodyID);
if(actor == null || body == null) continue;
if(!PrimaryRuntime.Server
&& ClientConnectionThread.Connected
&& actor.IsServerSynced()
&& !actor.GetID().equals(ClientConnectionThread.OwnedActorID)) {
continue;
}
actor.SetPosition(new Vector3f(body.Position));
if(rigidPhysicsController.ApplyRotation) {
actor.SetRotation(body.Rotation);
}
} }
} }

View file

@ -5,6 +5,7 @@ import imgui.ImGuiIO;
import imgui.ImGuiViewport; import imgui.ImGuiViewport;
import imgui.flag.ImGuiCond; import imgui.flag.ImGuiCond;
import imgui.flag.ImGuiWindowFlags; import imgui.flag.ImGuiWindowFlags;
import net.halbear.Executable.Server;
import net.halbear.Terrain4J.EngineCore.Audio.AudioManager; import net.halbear.Terrain4J.EngineCore.Audio.AudioManager;
import net.halbear.Terrain4J.EngineCore.Audio.SoundListener; import net.halbear.Terrain4J.EngineCore.Audio.SoundListener;
import net.halbear.Terrain4J.EngineCore.Display.Window; import net.halbear.Terrain4J.EngineCore.Display.Window;
@ -26,6 +27,9 @@ import net.halbear.Terrain4J.EngineCore.Main.Scene.GUIs.Gimbal;
import net.halbear.Terrain4J.EngineCore.Main.Scene.GUIs.LoadingScreen; import net.halbear.Terrain4J.EngineCore.Main.Scene.GUIs.LoadingScreen;
import net.halbear.Terrain4J.EngineCore.Profiling.CPUMonitor; import net.halbear.Terrain4J.EngineCore.Profiling.CPUMonitor;
import net.halbear.Terrain4J.EngineCore.Profiling.GPUProfiler; import net.halbear.Terrain4J.EngineCore.Profiling.GPUProfiler;
import net.halbear.Terrain4J.EngineCore.Threads.ClientConnectionThread;
import net.halbear.Terrain4J.EngineCore.Threads.RenderThread;
import net.halbear.Terrain4J.EngineCore.Threads.ServerConnectionThread;
import net.halbear.Terrain4J.EngineCore.Vulkan.GUI.GuiTexture; import net.halbear.Terrain4J.EngineCore.Vulkan.GUI.GuiTexture;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.MaterialData; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.MaterialData;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.ModelData; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.ModelData;
@ -39,6 +43,7 @@ import org.tinylog.Logger;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID;
import static org.lwjgl.glfw.GLFW.*; import static org.lwjgl.glfw.GLFW.*;
@ -48,9 +53,7 @@ public class GameCore implements GameLogic {
private static final float MOVEMENT_SPEED = 0.01f; private static final float MOVEMENT_SPEED = 0.01f;
public static boolean LoadingLevel = false; public static boolean LoadingLevel = false;
public List<Actor> CubeActors = new ArrayList<>();
private Vector2f LastMousePos = new Vector2f(0,0); private Vector2f LastMousePos = new Vector2f(0,0);
private int GUI_MODE = 0;
private GuiTexture guiTexture; private GuiTexture guiTexture;
public List<String[]> PerformanceMetrics = new ArrayList<>(); public List<String[]> PerformanceMetrics = new ArrayList<>();
public List<String[]> SettingPerformanceMetrics = new ArrayList<>(); public List<String[]> SettingPerformanceMetrics = new ArrayList<>();
@ -59,13 +62,13 @@ public class GameCore implements GameLogic {
public int NextAAMode = -1; public int NextAAMode = -1;
public long LastFrameTime = 0; public long LastFrameTime = 0;
public long CoolDown = 1000; public long CoolDown = 1000;
public ModelData MusicParticle;
public ModelData radio;
public ModelData MelonaData; public ModelData MelonaData;
private String CubeModelID = "Cube";
private ModelData MusketData;
private ModelData RevolverData;
public ILight SkyLight; public ILight SkyLight;
private LoadingScreen loadingScreen; private LoadingScreen loadingScreen;
public List<IMoveableActorComponent> ActorEditorComponents = new ArrayList<>(); public List<IMoveableActorComponent> ActorEditorComponents = new ArrayList<>();
private Gimbal gimbal;
private Vector2f DeltaPos = new Vector2f(0,0); private Vector2f DeltaPos = new Vector2f(0,0);
private String PlayerActorID = "NULL"; private String PlayerActorID = "NULL";
@ -81,47 +84,41 @@ public class GameCore implements GameLogic {
List<ModelData> models = new ArrayList<>(); List<ModelData> models = new ArrayList<>();
MelonaData = ModelLoader.LoadModel("resources/models/cube/Cube.json"); MelonaData = ModelLoader.LoadModel("resources/models/cube/Cube.json");
CubeModelID = MelonaData.ID();
List<MaterialData> MelonaMat = ModelLoader.LoadMaterials("resources/models/cube/Cube_mat.json"); List<MaterialData> MelonaMat = ModelLoader.LoadMaterials("resources/models/cube/Cube_mat.json");
CollisionMesh mesh = new CollisionMesh("Super Collision Mesh","NULL");
mesh.AddNewCollisionPoly(new Vector3f(-100,-5,100),new Vector3f(-100,-5.5f,-100),new Vector3f(100,-6,-100));
mesh.AddNewCollisionPoly(new Vector3f(100,-5.5f,100),new Vector3f(100,-6,-100),new Vector3f(-100,-5,100));
ModelData MusketData = ModelLoader.LoadModel("resources/models/musket/musket.json");
List<MaterialData> MusketMat = ModelLoader.LoadMaterials("resources/models/musket/musket_mat.json");
var Musket = new PlayerActor("DebugCamera","Player_Musket", MusketData.ID(), new Vector3f(0,5f,-5f)).SetCameraOffset(new Vector3f(0,1.0f,0));
Musket.SetPositionOffset(new Vector3f(0.5f,1.0f,-1.25f));
Musket.SetRotation(0,(float)Math.toRadians(180),0);
Musket.CreatePhysicsController( ConvexMesh.Box(0.5f,0.75f,0.5f),200f);
PlayerActorID = "Player_Musket";
scene.Musket = Musket;
scene.CreatePlayerController(scene.Musket);
RigidPhysicsController physicsController = (RigidPhysicsController) Musket.GetPhysicsController();
RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).LockRotation();
ModelData RevolverData = ModelLoader.LoadModel("resources/models/Revolver/Revolver.json");
List<MaterialData> RevolverMat = ModelLoader.LoadMaterials("resources/models/Revolver/Revolver_mat.json");
var Revolver = new PlayerActor("NULL","Player_Revolver", RevolverData.ID(), new Vector3f(0,5f,-5f)).SetCameraOffset(new Vector3f(0,1.0f,0));
Revolver.SetPositionOffset(new Vector3f(0.5f,1.0f,-1.25f));
Revolver.SetRotation(0,(float)Math.toRadians(180),0);
Revolver.CreatePhysicsController( ConvexMesh.Box(0.5f,0.75f,0.5f),200f);
scene.Revolver = Revolver;
PlayerActorID = "Player_Revolver";
physicsController = (RigidPhysicsController) Revolver.GetPhysicsController();
RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).LockRotation();
// if I put PlayerActorID = "Player_Revolver" it just crashes
mesh.RegisterMesh();
scene.AddActor(Musket);
scene.AddActor(Revolver);
CubeActors.forEach(scene::AddActor);
List<MaterialData> materials = new ArrayList<>(); List<MaterialData> materials = new ArrayList<>();
MusketData = ModelLoader.LoadModel("resources/models/musket/musket.json");
List<MaterialData> MusketMat = ModelLoader.LoadMaterials("resources/models/musket/musket_mat.json");
RevolverData = ModelLoader.LoadModel("resources/models/Revolver/Revolver.json");
List<MaterialData> RevolverMat = ModelLoader.LoadMaterials("resources/models/Revolver/Revolver_mat.json");
boolean createOfflinePlayer = !PrimaryRuntime.Server && !ClientConnectionThread.Connected;
if(createOfflinePlayer) {
var Musket = new PlayerActor("DebugCamera","Player_Musket", MusketData.ID(), new Vector3f(0,5f,-5f)).SetCameraOffset(new Vector3f(0,1.0f,0));
Musket.SetPositionOffset(new Vector3f(0.5f,1.0f,-1.25f));
Musket.SetRotation(0,(float)Math.toRadians(180),0);
Musket.CreatePhysicsController( ConvexMesh.Box(0.5f,0.75f,0.5f),200f);
PlayerActorID = "Player_Musket";
scene.Musket = Musket;
scene.CreatePlayerController(scene.Musket);
RigidPhysicsController physicsController = (RigidPhysicsController) Musket.GetPhysicsController();
RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).LockRotation();
var Revolver = new PlayerActor("NULL","Player_Revolver", RevolverData.ID(), new Vector3f(0,5f,-5f)).SetCameraOffset(new Vector3f(0,1.0f,0));
Revolver.SetPositionOffset(new Vector3f(0.5f,1.0f,-1.25f));
Revolver.SetRotation(0,(float)Math.toRadians(180),0);
Revolver.CreatePhysicsController( ConvexMesh.Box(0.5f,0.75f,0.5f),200f);
scene.Revolver = Revolver;
PlayerActorID = "Player_Revolver";
physicsController = (RigidPhysicsController) Revolver.GetPhysicsController();
RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).LockRotation();
scene.AddActor(Musket);
scene.AddActor(Revolver);
materials.addAll(RevolverMat);
}
materials.addAll(MelonaMat);
materials.addAll(MusketMat); materials.addAll(MusketMat);
materials.addAll(RevolverMat); materials.addAll(RevolverMat);
materials.addAll(MelonaMat);
models.add(MelonaData); models.add(MelonaData);
models.add(MusketData); models.add(MusketData);
models.add(RevolverData); models.add(RevolverData);
@ -129,18 +126,22 @@ public class GameCore implements GameLogic {
camera.SetPosition(0,0,0); camera.SetPosition(0,0,0);
camera.SetRotation(0,0,0); camera.SetRotation(0,0,0);
var LoadingScreenTexture = new GuiTexture(EngineConfig.getInstance().GetLoadingScreenImageLocation());
loadingScreen = new LoadingScreen(LoadingScreenTexture);
guiTexture = new GuiTexture("resources/EngineResources/Texture/Billy.png");
List<GuiTexture> guiTextures = new ArrayList<>(); List<GuiTexture> guiTextures = new ArrayList<>();
guiTextures.add(LoadingScreenTexture);
guiTextures.add(guiTexture);
scene.GetLightingManager().GetAmbientLightColour().set(1.0f, 0.9f, 0.75f);
scene.GetLightingManager().SetAmbientLightIntensity(0.4f);
SkyLight = new Light(new Vector3f(1.5f, 1.20f, 1.0f),new Vector3f(0.0f, -1.0f, 0.3f), true, 10.00f); if(!PrimaryRuntime.Server && !RenderThread.Headless) {
var LoadingScreenTexture = new GuiTexture(EngineConfig.getInstance().GetLoadingScreenImageLocation());
loadingScreen = new LoadingScreen(LoadingScreenTexture);
guiTexture = new GuiTexture("resources/EngineResources/Texture/Billy.png");
guiTextures.add(LoadingScreenTexture);
guiTextures.add(guiTexture);
}
scene.GetLightingManager().GetAmbientLightColour().set(1.0f, 0.9f, 0.75f);
scene.GetLightingManager().SetAmbientLightIntensity(0.6f);
SkyLight = new Light(new Vector3f(1.5f, 1.20f, 1.0f),new Vector3f(0.0f, -1.0f, 0.3f), true, 2.00f);
List<ILight> lights = new ArrayList<>(); List<ILight> lights = new ArrayList<>();
@ -154,9 +155,11 @@ public class GameCore implements GameLogic {
for(int i = 0; i < ActorEditorComponents.size(); i++){ for(int i = 0; i < ActorEditorComponents.size(); i++){
ActorEditorComponents.get(i).UpdateAll(); ActorEditorComponents.get(i).UpdateAll();
} }
for(int x = -5; x < 6; x++){ if(PrimaryRuntime.Server) {
for(int y = -5; y < 6; y++){ for (int x = -5; x < 6; x++) {
SpawnNewStaticActor(engineInstance, new Vector3f(x * 4f, -4 *(float)Math.random(), y * 4f), new Vector3f(0,0,0),new Vector3f(1,1,1)); for (int y = -5; y < 6; y++) {
SpawnNewStaticActor(engineInstance, new Vector3f(x * 4f, -4 * (float) Math.random(), y * 4f), new Vector3f(0, 0, 0), new Vector3f(1, 1, 1));
}
} }
} }
return new InitData(models,materials,guiTextures); return new InitData(models,materials,guiTextures);
@ -180,9 +183,19 @@ public class GameCore implements GameLogic {
SpawnDirection.set(new Vector3f(Direction)); SpawnDirection.set(new Vector3f(Direction));
rotationMatrix.positiveZ(SpawnDirection).negate().mul(5); rotationMatrix.positiveZ(SpawnDirection).negate().mul(5);
SpawnPosition.add(SpawnDirection); SpawnPosition.add(SpawnDirection);
var Melona = new Actor("MelonaSpawned" + scene.GetActors().size(), MelonaData.ID(), new Vector3f(SpawnPosition)); var Melona = new Actor("MelonaSpawned" + scene.GetActors().size(), CubeModelID, new Vector3f(SpawnPosition));
Logger.info("Spawning static cube actor [{}] with model ID [{}], with cached ID of [{}]", Melona.GetID(), Melona.GetModelID(),CubeModelID);
Melona.SetScale(4f); Melona.SetScale(4f);
Melona.CreatePhysicsController( ConvexMesh.Box(2.0f,2.0f,2.0f),0); Melona.CreatePhysicsController( ConvexMesh.Box(2.0f,2.0f,2.0f),0);
Melona.SetServerSynced(false);
scene.AddActor(Melona);
if(PrimaryRuntime.Server) {
ServerConnectionThread.BroadcastCreateActorPacket(Melona);
}
RigidPhysicsController physicsController = (RigidPhysicsController) Melona.GetPhysicsController(); RigidPhysicsController physicsController = (RigidPhysicsController) Melona.GetPhysicsController();
//RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).LinearVelocity.set(0,0,-20f -(40f * (float)Math.random())); //RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).LinearVelocity.set(0,0,-20f -(40f * (float)Math.random()));
scene.AddActor(Melona); scene.AddActor(Melona);
@ -190,6 +203,30 @@ public class GameCore implements GameLogic {
public void SetPlayerActorID(String id) { public void SetPlayerActorID(String id) {
this.PlayerActorID = id; this.PlayerActorID = id;
} }
public PlayerActor SpawnNetworkPlayer(EngineInstance engineInstance, UUID clientID){
var scene = engineInstance.scene();
String actorID = "Player_" + clientID;
PlayerActor player = new PlayerActor(
"NULL",
actorID,
MusketData.ID(),
new Vector3f(0, 8f, 0)
).SetCameraOffset(new Vector3f(0, 1.0f, 0));
player.SetPositionOffset(new Vector3f(0.5f, 1.0f, -1.25f));
player.SetRotation(0, (float)Math.toRadians(180), 0);
player.CreatePhysicsController(ConvexMesh.Box(0.5f, 0.75f, 0.5f), 200f);
player.SetServerSynced(true);
RigidPhysicsController physicsController = (RigidPhysicsController) player.GetPhysicsController();
RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).LockRotation();
scene.AddActor(player);
return player;
}
public void SpawnNewActor(EngineInstance engineInstance, Vector3f Position, Vector3f Rotation, Vector3f Direction){ public void SpawnNewActor(EngineInstance engineInstance, Vector3f Position, Vector3f Rotation, Vector3f Direction){
var scene = engineInstance.scene(); var scene = engineInstance.scene();
Camera camera = scene.GetCamera(); Camera camera = scene.GetCamera();
@ -198,9 +235,15 @@ public class GameCore implements GameLogic {
SpawnDirection.set(new Vector3f(Direction)); SpawnDirection.set(new Vector3f(Direction));
rotationMatrix.positiveZ(SpawnDirection).negate().mul(5); rotationMatrix.positiveZ(SpawnDirection).negate().mul(5);
SpawnPosition.add(SpawnDirection); SpawnPosition.add(SpawnDirection);
var Melona = new Actor("MelonaSpawned" + scene.GetActors().size(), MelonaData.ID(), new Vector3f(SpawnPosition)); var Melona = new Actor("MelonaSpawned" + scene.GetActors().size(), CubeModelID, new Vector3f(SpawnPosition));
Melona.CreatePhysicsController( ConvexMesh.Box(0.5f,0.5f,0.5f),20); Melona.CreatePhysicsController( ConvexMesh.Box(0.5f,0.5f,0.5f),20);
Melona.SetServerSynced(true);
if(PrimaryRuntime.Server) {
ServerConnectionThread.BroadcastCreateActorPacket(Melona);
}
RigidPhysicsController physicsController = (RigidPhysicsController) Melona.GetPhysicsController(); RigidPhysicsController physicsController = (RigidPhysicsController) Melona.GetPhysicsController();
//RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).LinearVelocity.set(0,0,-20f -(40f * (float)Math.random())); //RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).LinearVelocity.set(0,0,-20f -(40f * (float)Math.random()));
scene.AddActor(Melona); scene.AddActor(Melona);
@ -214,7 +257,7 @@ public class GameCore implements GameLogic {
SpawnDirection.set(new Vector3f(Direction)); SpawnDirection.set(new Vector3f(Direction));
rotationMatrix.positiveZ(SpawnDirection).negate().mul(5); rotationMatrix.positiveZ(SpawnDirection).negate().mul(5);
SpawnPosition.add(SpawnDirection); SpawnPosition.add(SpawnDirection);
var Melona = new Actor("MelonaSpawned" + scene.GetActors().size(), MelonaData.ID(), new Vector3f(SpawnPosition)); var Melona = new Actor("MelonaSpawned" + scene.GetActors().size(), CubeModelID, new Vector3f(SpawnPosition));
Melona.CreatePhysicsController( ConvexMesh.Box(0.75f,1.2f,0.5f),20); Melona.CreatePhysicsController( ConvexMesh.Box(0.75f,1.2f,0.5f),20);
scene.AddActor(Melona); scene.AddActor(Melona);
@ -222,6 +265,7 @@ public class GameCore implements GameLogic {
} }
private void InitiateAudio(EngineInstance engineInstance){ private void InitiateAudio(EngineInstance engineInstance){
if(RenderThread.Headless || PrimaryRuntime.Server) return;
AudioManager audioManager = engineInstance.audioManager(); AudioManager audioManager = engineInstance.audioManager();
Camera camera = engineInstance.scene().GetCamera(); Camera camera = engineInstance.scene().GetCamera();
audioManager.SetAttenuationModel(AL11.AL_EXPONENT_DISTANCE); audioManager.SetAttenuationModel(AL11.AL_EXPONENT_DISTANCE);
@ -231,6 +275,10 @@ public class GameCore implements GameLogic {
@Override @Override
public void CameraInput(EngineInstance engineInstance, long FrameDiffNanoSeconds) { public void CameraInput(EngineInstance engineInstance, long FrameDiffNanoSeconds) {
if(PrimaryRuntime.Server || RenderThread.Headless || engineInstance.window() == null) {
return;
}
float Multiplier = MOUSE_SENSITIVITY; float Multiplier = MOUSE_SENSITIVITY;
IScene scene = engineInstance.scene(); IScene scene = engineInstance.scene();
Camera camera = scene.GetCamera(); Camera camera = scene.GetCamera();
@ -257,10 +305,25 @@ public class GameCore implements GameLogic {
@Override @Override
public void RenderThreadInput(EngineInstance engineInstance, long FrameDiffNanoSeconds) { public void RenderThreadInput(EngineInstance engineInstance, long FrameDiffNanoSeconds) {
if(ClientConnectionThread.Connected && !"NULL".equals(ClientConnectionThread.OwnedActorID)) {
PlayerActorID = ClientConnectionThread.OwnedActorID;
}
Actor player = Actor.Actors.get(PlayerActorID); Actor player = Actor.Actors.get(PlayerActorID);
if(player != null){ if(player != null){
player.TickUpdate(); player.TickUpdate();
} }
for(Actor actor : engineInstance.scene().GetActors()) {
if(actor != null
&& actor.IsServerSynced()
&& !actor.IsStaticRigidBody()
&& !actor.GetID().equals(ClientConnectionThread.OwnedActorID)) {
actor.InterpolateNetworkTarget(0.12f);
}
}
if(PrimaryRuntime.Server || RenderThread.Headless) return;
engineInstance.scene().CameraTick(FrameDiffNanoSeconds); engineInstance.scene().CameraTick(FrameDiffNanoSeconds);
if(ChangeGraphicsSettings){ if(ChangeGraphicsSettings){
if(NextAAMode != -1){ if(NextAAMode != -1){
@ -279,14 +342,47 @@ public class GameCore implements GameLogic {
@Override @Override
public void Input(EngineInstance engineInstance, long FrameDiffNanoSeconds) { public void Input(EngineInstance engineInstance, long FrameDiffNanoSeconds) {
IScene scene = engineInstance.scene(); if(PrimaryRuntime.Server || RenderThread.Headless) return;
Window window = engineInstance.window();
PlayerActor playerActor = (PlayerActor) Actor.Actors.get(PlayerActorID);
scene.Input(engineInstance,FrameDiffNanoSeconds, playerActor, MOVEMENT_SPEED,this);
IScene scene = engineInstance.scene();
if(ClientConnectionThread.Connected) {
if("NULL".equals(ClientConnectionThread.OwnedActorID)) {
return;
}
Actor ownedActor = Actor.Actors.get(ClientConnectionThread.OwnedActorID);
if(!(ownedActor instanceof PlayerActor networkPlayer)) {
return;
}
if(scene instanceof Scene concreteScene) {
if(networkPlayer.GetPlayerCamera() == null) {
networkPlayer.AttachCamera(concreteScene.GetCamera().GetID());
concreteScene.SetNetworkControlledPlayer(networkPlayer);
}
}
PlayerActorID = ClientConnectionThread.OwnedActorID;
Logger.trace(
"Input using network player [{}], camera [{}]",
networkPlayer.GetID(),
networkPlayer.AttachedCameraID
);
scene.Input(engineInstance, FrameDiffNanoSeconds, networkPlayer, MOVEMENT_SPEED, this);
return;
}
Actor localActor = Actor.Actors.get(PlayerActorID);
if(!(localActor instanceof PlayerActor playerActor)) {
return;
}
scene.Input(engineInstance,FrameDiffNanoSeconds, playerActor, MOVEMENT_SPEED,this);
} }
private boolean HandleGui(EngineInstance engineInstance, long frameTimeNS){ private boolean HandleGui(EngineInstance engineInstance, long frameTimeNS){
if(PrimaryRuntime.Server || RenderThread.Headless) return false;
FetchingMetrics = true; FetchingMetrics = true;
ImGuiIO imGuiIO = ImGui.getIO(); ImGuiIO imGuiIO = ImGui.getIO();
MouseListener mouseListener = engineInstance.window().getMouseInput(); MouseListener mouseListener = engineInstance.window().getMouseInput();
@ -332,14 +428,30 @@ public class GameCore implements GameLogic {
float PhysicsFramerate = 24f; float PhysicsFramerate = 24f;
float PhysicsFrameTime = 1000f/PhysicsFramerate; float PhysicsFrameTime = 1000f/PhysicsFramerate;
float DeltaTime = (float)FrameDiffNanoSeconds/(PhysicsFrameTime*1000000f); float DeltaTime = (float)FrameDiffNanoSeconds/(PhysicsFrameTime*1000000f);
if(PrimaryRuntime.GetFastThread().Ticks(20)==0){ if(PrimaryRuntime.Server){
//CollisionManager.UpdateCollisionChunks(); Server.CollectIncomingPackets();
Server.ProcessIncomingPackets();
WorldPhysicsManager.PhysicsTick2(DeltaTime, PhysicsFramerate);
if(PrimaryRuntime.GetFastThread().Ticks(6) == 0) {
for(Actor actor : engineInstance.scene().GetActors()) {
if(actor.IsServerSynced() && !actor.IsStaticRigidBody()) {
ServerConnectionThread.SendEntityUpdatePacket(actor);
}
}
}
Server.ProcessOutgoingPackets();
} else {
ClientConnectionThread.DecodePackets(engineInstance, this, engineInstance.scene());
WorldPhysicsManager.PhysicsTick2(DeltaTime, PhysicsFramerate);
} }
WorldPhysicsManager.PhysicsTick2(DeltaTime, PhysicsFramerate);
} }
@Override @Override
public void SecondUpdate(EngineInstance engineInstance) { public void SecondUpdate(EngineInstance engineInstance) {
if(PrimaryRuntime.Server || RenderThread.Headless) return;
SettingPerformanceMetrics.clear(); SettingPerformanceMetrics.clear();
List<String[]> Metrics = new ArrayList<>(); List<String[]> Metrics = new ArrayList<>();
String[] ISceneDetails = new String[8]; String[] ISceneDetails = new String[8];

View file

@ -9,17 +9,24 @@ import net.halbear.Terrain4J.EngineCore.Logic.InitData;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Scene; import net.halbear.Terrain4J.EngineCore.Main.Scene.Scene;
import net.halbear.Terrain4J.EngineCore.Profiling.CPUMonitor; import net.halbear.Terrain4J.EngineCore.Profiling.CPUMonitor;
import net.halbear.Terrain4J.EngineCore.Threads.ClientConnectionThread;
import net.halbear.Terrain4J.EngineCore.Threads.FastTickThread; import net.halbear.Terrain4J.EngineCore.Threads.FastTickThread;
import net.halbear.Terrain4J.EngineCore.Threads.MainThread; import net.halbear.Terrain4J.EngineCore.Threads.MainThread;
import net.halbear.Terrain4J.EngineCore.Threads.RenderThread; import net.halbear.Terrain4J.EngineCore.Threads.RenderThread;
import org.tinylog.Logger; import org.tinylog.Logger;
import java.io.IOException; import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.Timer;
import java.util.TimerTask;
public class PrimaryRuntime { public class PrimaryRuntime {
public static boolean Server = false;
private int Frames = 0; private int Frames = 0;
private int TickFrames = 0; private int TickFrames = 0;
private double TickRate = 0; private double TickRate = 0;
@ -38,6 +45,8 @@ public class PrimaryRuntime {
public final CPUMonitor cpuProfiler; public final CPUMonitor cpuProfiler;
private static GameLogic gameLogic; private static GameLogic gameLogic;
public static ClientConnectionThread ServerCon;
public static Thread ServerThread;
public static GameLogic GetGameCore(){return gameLogic;} public static GameLogic GetGameCore(){return gameLogic;}
public PrimaryRuntime(String windowTitle, GameLogic appLogic) { public PrimaryRuntime(String windowTitle, GameLogic appLogic) {
@ -55,17 +64,74 @@ public class PrimaryRuntime {
} }
} }
} }
window = new Window(windowTitle); if (Server) {
gameLogic = appLogic; window = null;
engineInstance = new EngineInstance(window, new Scene(window),this, new AudioManager()); gameLogic = appLogic;
engineInstance = new EngineInstance(null, new Scene(null), this, null);
} else {
window = new Window(windowTitle);
gameLogic = appLogic;
engineInstance = new EngineInstance(window, new Scene(window), this, new AudioManager());
}
InitData initData = appLogic.Initialise(engineInstance); InitData initData = appLogic.Initialise(engineInstance);
PrimaryThread = new MainThread(engineInstance, appLogic); PrimaryThread = new MainThread(engineInstance, appLogic);
FastThread = new FastTickThread(engineInstance, appLogic); FastThread = new FastTickThread(engineInstance, appLogic);
DrawingThread = new RenderThread(window, engineInstance, initData, appLogic); DrawingThread = new RenderThread(window, engineInstance, initData, appLogic);
cpuProfiler = new CPUMonitor(); cpuProfiler = new CPUMonitor();
if(!Server) {
ServerCon = new ClientConnectionThread();
ServerThread = new Thread(ServerCon);
ServerThread.start();
}
EngineConfig.getInstance().SetCPU(CPUMonitor.getCpuName(), CPUMonitor.getCoreCount()); EngineConfig.getInstance().SetCPU(CPUMonitor.getCpuName(), CPUMonitor.getCoreCount());
Thread.currentThread().setName("Terrain4J Primary Runtime Thread"); Thread.currentThread().setName("Terrain4J Primary Runtime Thread");
} }
public static void StartPingTimer() {
Timer timer = new Timer();
ClientConnectionThread.pinging = true;
timer.scheduleAtFixedRate(new TimerTask() {;
@Override
public void run() {
String text = "Halbear.Net Launcher : " + PingServer(ClientConnectionThread.ServerIP, false);
if (ClientConnectionThread.Connected){
ClientConnectionThread.pinging = false;
this.cancel();
}
}
}, 0, 2000);
}
public static String PingServer(String ipAddress, boolean DomainOnly) {
if (DomainOnly) {
try {
HttpURLConnection connection = (HttpURLConnection) new URL(ipAddress).openConnection();
connection.setRequestMethod("HEAD");
connection.setConnectTimeout(1000);
int responseCode = connection.getResponseCode();
if (responseCode >= 300 && responseCode < 400) {
return "Connected to server with problems";
}
if (responseCode >= 400 && responseCode < 500) {
return "Client Problem, Check Internet Connection";
}
if (responseCode >= 500) {
return "Server Problem, Unable To Connect";
} else return "Online";
} catch ( MalformedURLException e) {
//System.out.println(e);
return "Bad URL";
} catch ( IOException e ) {
//System.out.println(e);
return "Connection Error, Server Unreachable";
}
} else if (!ClientConnectionThread.Connected) {
ServerCon = new ClientConnectionThread();
ServerThread = new Thread(ServerCon);
ServerThread.start();
}
return "Connecting...";
}
public static MainThread GetMainThread(){return PrimaryThread;} public static MainThread GetMainThread(){return PrimaryThread;}
public static RenderThread GetRenderThread(){return DrawingThread;} public static RenderThread GetRenderThread(){return DrawingThread;}
public static FastTickThread GetFastThread(){return FastThread;} public static FastTickThread GetFastThread(){return FastThread;}
@ -91,24 +157,52 @@ public class PrimaryRuntime {
} }
public void PrimaryRuntimeInputUpdate(long nsTimeDiff){ public void PrimaryRuntimeInputUpdate(long nsTimeDiff){
gameLogic.Input(PrimaryRuntime.GetEngineInstance(), (nsTimeDiff)); try {
gameLogic.CameraInput(PrimaryRuntime.GetEngineInstance(), (nsTimeDiff)); gameLogic.Input(PrimaryRuntime.GetEngineInstance(), (nsTimeDiff));
gameLogic.CameraInput(PrimaryRuntime.GetEngineInstance(), (nsTimeDiff));
} catch (Exception e) {
Logger.error(e, "Primary runtime input update failed");
}
} }
public void run(){ public void run(){
UpdateTickRateThreshold(); UpdateTickRateThreshold();
PrimaryThread.StartThread();
DrawingThread.StartThread();
FastThread.StartThread();
FrameAccuracy = EngineConfig.getInstance().getAccuracy();
OriginalFrameAccuracy = FrameAccuracy;
Logger.debug("Primary Thread Started");
if(Server) {
Logger.info("Terrain4J dedicated server running without GLFW/Vulkan/OpenAL");
while(running) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
ShutDownStart = System.nanoTime();
Logger.debug("Closing dedicated server [{}]", EngineConfig.getInstance().GetSoftwareName());
FastThread.KillThread();
PrimaryThread.KillThread();
DrawingThread.KillThread();
cleanup();
return;
}
long InitialTime = System.nanoTime(); long InitialTime = System.nanoTime();
long updateTime = InitialTime; long updateTime = InitialTime;
double FrameDiff =0; double FrameDiff =0;
double TickDiff =0; double TickDiff =0;
double SecondCounter =0; double SecondCounter =0;
double cycleDiff = 0; double cycleDiff = 0;
PrimaryThread.StartThread();
DrawingThread.StartThread();
FastThread.StartThread();
FrameAccuracy = EngineConfig.getInstance().getAccuracy();
OriginalFrameAccuracy = FrameAccuracy;
Logger.debug("Primary Thread Started");
while (!window.shouldClose() && running){ while (!window.shouldClose() && running){
long now = System.nanoTime(); long now = System.nanoTime();
cycleDiff = now - InitialTime; cycleDiff = now - InitialTime;
@ -138,6 +232,11 @@ public class PrimaryRuntime {
} }
InitialTime = now; InitialTime = now;
} }
ClientConnectionThread.Connected = false;
if(ServerThread != null) {
ServerThread.interrupt();
}
ShutDownStart = System.nanoTime(); ShutDownStart = System.nanoTime();
Logger.debug("Closing Software of name [{}]",EngineConfig.getInstance().GetSoftwareName()); Logger.debug("Closing Software of name [{}]",EngineConfig.getInstance().GetSoftwareName());
FastThread.KillThread(); FastThread.KillThread();
@ -155,7 +254,7 @@ public class PrimaryRuntime {
} }
private void cleanup() { private void cleanup() {
engineInstance.cleanup(); engineInstance.cleanup();
window.cleanup();
Logger.debug("Process still running: [{}]",Thread.getAllStackTraces().keySet().toString()); Logger.debug("Process still running: [{}]",Thread.getAllStackTraces().keySet().toString());
if (ThreadsOpen > 0 || VulkanContext.VulkanLayersOpen > -1) { if (ThreadsOpen > 0 || VulkanContext.VulkanLayersOpen > -1) {
Logger.debug("Waiting to close Primary Thread, making sure vulkan has shut down properly first and Engine Threads are closed\nThreads Open:[{}]\nVulkan Layers Open:[{}]", ThreadsOpen, VulkanContext.VulkanLayersOpen < 0 ? "All processes closed and vulkan instance removed" : VulkanContext.VulkanLayersOpen); Logger.debug("Waiting to close Primary Thread, making sure vulkan has shut down properly first and Engine Threads are closed\nThreads Open:[{}]\nVulkan Layers Open:[{}]", ThreadsOpen, VulkanContext.VulkanLayersOpen < 0 ? "All processes closed and vulkan instance removed" : VulkanContext.VulkanLayersOpen);

View file

@ -4,6 +4,7 @@ import net.halbear.Terrain4J.EngineCore.Logic.Physics.LegacyCollision.CollisionM
import net.halbear.Terrain4J.EngineCore.Logic.Physics.IPhysicsController; import net.halbear.Terrain4J.EngineCore.Logic.Physics.IPhysicsController;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.LegacyPhysicsController; import net.halbear.Terrain4J.EngineCore.Logic.Physics.LegacyPhysicsController;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.ConvexMesh; import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.ConvexMesh;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidBody;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidCollision; import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidCollision;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidPhysicsController; import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidPhysicsController;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.ModelData; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.ModelData;
@ -38,6 +39,10 @@ public class Actor{
protected final Vector3f PivotOffset; protected final Vector3f PivotOffset;
protected final Vector3f AdditionalPivotOffset; protected final Vector3f AdditionalPivotOffset;
protected final Vector3f TemporaryVector; protected final Vector3f TemporaryVector;
protected boolean ServerSynced = false;
protected boolean HasNetworkTarget = false;
protected final Vector3f NetworkTargetPosition = new Vector3f();
protected final Quaternionf NetworkTargetRotation = new Quaternionf();
public PhysicsControllerType PhysicsType = PhysicsControllerType.RigidBodySeparatingAxisTheory; public PhysicsControllerType PhysicsType = PhysicsControllerType.RigidBodySeparatingAxisTheory;
public void SetPhysicsType(PhysicsControllerType type){ public void SetPhysicsType(PhysicsControllerType type){
@ -64,10 +69,6 @@ public class Actor{
Actors.put(ID,this); Actors.put(ID,this);
} }
public Vector3f GetPositionOffset(){
return PositionOffset;
}
public Actor SetPositionOffset(Vector3f PositionOffset){ public Actor SetPositionOffset(Vector3f PositionOffset){
this.PositionOffset.set(PositionOffset); this.PositionOffset.set(PositionOffset);
return this; return this;
@ -95,6 +96,47 @@ public class Actor{
public void TickUpdate() { public void TickUpdate() {
} }
public Actor SetServerSynced(boolean synced){
this.ServerSynced = synced;
return this;
}
public boolean IsServerSynced(){
return ServerSynced;
}
public boolean IsStaticRigidBody(){
RigidBody rigidBody = GetRigidBody();
return rigidBody != null && rigidBody.IsStatic;
}
public void SetNetworkTarget(Vector3f position, Quaternionf rotation){
NetworkTargetPosition.set(position);
NetworkTargetRotation.set(rotation);
HasNetworkTarget = true;
}
public void InterpolateNetworkTarget(float alpha){
if(!HasNetworkTarget) return;
Position.lerp(NetworkTargetPosition, alpha);
Rotation.slerp(NetworkTargetRotation, alpha);
UpdateModelMatrix();
RigidBody rigidBody = GetRigidBody();
if(rigidBody != null) {
rigidBody.Position.set(Position);
rigidBody.Rotation.set(Rotation);
}
}
public Vector3f GetPositionOffset(){
return PositionOffset;
}
public Vector3f GetAdditionalPivotOffset(){
return AdditionalPivotOffset;
}
public IPhysicsController GetPhysicsController(){return physicsController;} public IPhysicsController GetPhysicsController(){return physicsController;}
@ -142,6 +184,7 @@ public class Actor{
return this; return this;
} }
public Actor SetRotation(float x, float y, float z){ public Actor SetRotation(float x, float y, float z){
Rotation.identity();
Rotation.rotateX(x); Rotation.rotateX(x);
Rotation.rotateY(y); Rotation.rotateY(y);
Rotation.rotateZ(z); Rotation.rotateZ(z);
@ -165,6 +208,54 @@ public class Actor{
return this; return this;
} }
public void SetNewAngularVelocity(Vector3f Velocity){
RigidBody rigidBody = GetRigidBody();
if (rigidBody == null) return;
rigidBody.AngularVelocity.set(Velocity);
}
public void SetNewVelocity(Vector3f Velocity){
RigidBody rigidBody = GetRigidBody();
if (rigidBody == null) return;
rigidBody.LinearVelocity.set(Velocity);
}
public void SetNewRotation(Quaternionf Rotation){
RigidBody rigidBody = GetRigidBody();
if (rigidBody == null) return;
rigidBody.Rotation.set(Rotation);
this.Rotation.set(Rotation);
UpdateModelMatrix();
}
public void SetNewPosition(Vector3f Position){
RigidBody rigidBody = GetRigidBody();
if (rigidBody == null) {
SetPosition(Position);
return;
}
rigidBody.Position.set(Position);
this.Position.set(Position);
UpdateModelMatrix();
if(collisionMesh != null) collisionMesh.SetWorldPosition(this.Position);
}
private RigidBody GetRigidBody() {
if (PhysicsType != PhysicsControllerType.RigidBodySeparatingAxisTheory) return null;
if (!(GetPhysicsController() instanceof RigidPhysicsController rigidPhysicsController)) return null;
return RigidBody.RigidBodyRegister.get(rigidPhysicsController.RigidBodyID);
}
public Actor SetScale(Vector3f Scale){
this.Scale = new Vector3f(Scale);
UpdateModelMatrix();
return this;
}
public Actor SetScale(float Scale){ public Actor SetScale(float Scale){
this.Scale = new Vector3f(Scale,Scale,Scale); this.Scale = new Vector3f(Scale,Scale,Scale);

View file

@ -26,36 +26,82 @@ import static org.lwjgl.glfw.GLFW.GLFW_KEY_TAB;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_W; import static org.lwjgl.glfw.GLFW.GLFW_KEY_W;
public class PhysicsPlayerController implements IPlayerInputEvents { public class PhysicsPlayerController implements IPlayerInputEvents {
public PhysicsPlayerController(){
}
@Override @Override
public void Input(KeyboardInput input, long FrameDiffNanoSeconds, PlayerActor playerActor, float MOVEMENT_SPEED, GameCore GameCore, IScene ParentScene) { public void Input(
Scene scene = (Scene)ParentScene; KeyboardInput input,
float MovementDist = (float)(FrameDiffNanoSeconds / 1000000L) * MOVEMENT_SPEED; long frameDiffNanoseconds,
PlayerActor playerActor,
float movementSpeed,
GameCore gameCore,
IScene parentScene
) {
if (input == null || playerActor == null || !(parentScene instanceof Scene scene)) {
return;
}
Camera camera = scene.GetCamera(); Camera camera = scene.GetCamera();
if(playerActor!= null)camera = Camera.GetCamera(playerActor.AttachedCameraID);
if(input.keyPressed(GLFW_KEY_W)){ Camera attachedCamera = Camera.GetCamera(playerActor.AttachedCameraID);
playerActor.Move(new Vector3f(MovementDist* (float)Math.sin((camera.GetRotation().y)),0,-MovementDist* (float)Math.cos((camera.GetRotation().y)))); if (attachedCamera != null) {
camera = attachedCamera;
} }
if(input.keyPressed(GLFW_KEY_S)){
playerActor.Move(new Vector3f(-MovementDist* (float)Math.sin((camera.GetRotation().y)),0,MovementDist * (float)Math.cos((camera.GetRotation().y)))); if (camera == null) {
return;
} }
if(input.keyPressed(GLFW_KEY_A)){
playerActor.Move(new Vector3f(-MovementDist * (float)Math.cos((camera.GetRotation().y)),0,-MovementDist * (float)Math.sin((camera.GetRotation().y)))); float deltaMilliseconds = frameDiffNanoseconds / 1_000_000.0f;
float movementDist = deltaMilliseconds * movementSpeed;
float yaw = camera.GetRotation().y;
float sinYaw = (float) Math.sin(yaw);
float cosYaw = (float) Math.cos(yaw);
Vector3f movement = new Vector3f();
if (input.keyPressed(GLFW_KEY_W)) {
movement.add(sinYaw, 0, -cosYaw);
} }
if(input.keyPressed(GLFW_KEY_D)){ if (input.keyPressed(GLFW_KEY_S)) {
playerActor.Move(new Vector3f(MovementDist * (float)Math.cos((camera.GetRotation().y)),0,MovementDist * (float)Math.sin((camera.GetRotation().y)))); movement.add(-sinYaw, 0, cosYaw);
} }
if (input.keyPressed(GLFW_KEY_A)) {
movement.add(-cosYaw, 0, -sinYaw);
}
if (input.keyPressed(GLFW_KEY_D)) {
movement.add(cosYaw, 0, sinYaw);
}
if (movement.lengthSquared() > 0.0f) {
movement.normalize().mul(movementDist);
playerActor.Move(movement);
}
if (playerActor != null) { if (playerActor != null) {
RigidPhysicsController physicsController = (RigidPhysicsController) playerActor.GetPhysicsController(); RigidPhysicsController physicsController = (RigidPhysicsController) playerActor.GetPhysicsController();
RigidBody body = RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID); RigidBody body = RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID);
if (body != null && body.Grounded) { if (body != null && body.Grounded) {
scene.Jumps = 0; scene.Jumps = 0;
scene.GroundedGraceTicks = scene.MaxGroundedGraceTicks;
} else if(scene.GroundedGraceTicks > 0) {
scene.GroundedGraceTicks--;
} }
} }
if (input.keySinglePress(GLFW_KEY_SPACE)) { if (input.keySinglePress(GLFW_KEY_SPACE)) {
if (scene.Jumps < scene.MaxJumps) { boolean canUseGroundJump = scene.GroundedGraceTicks > 0 && scene.Jumps == 0;
if (playerActor != null) playerActor.Move(new Vector3f(0, 5f, 0));
if (canUseGroundJump || scene.Jumps < scene.MaxJumps) {
if (playerActor != null) playerActor.Jump(5.0f);
scene.Jumps++; scene.Jumps++;
scene.GroundedGraceTicks = 0;
} }
} }
} }
} }

View file

@ -4,6 +4,8 @@ import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.ConvexMesh; import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.ConvexMesh;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidBody; import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidBody;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidPhysicsController; import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidPhysicsController;
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import net.halbear.Terrain4J.EngineCore.Threads.ClientConnectionThread;
import org.joml.Quaternionf; import org.joml.Quaternionf;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.tinylog.Logger; import org.tinylog.Logger;
@ -32,37 +34,23 @@ public class PlayerActor extends Actor{
return PlayerCam; return PlayerCam;
} }
public PlayerActor SetCameraOffset(Vector3f Offset){ public PlayerActor AttachCamera(String cameraID){
CameraOffset.set(Offset); Camera camera = Camera.CameraRegistry.get(cameraID);
if(camera == null) {
Logger.warn("Could not attach camera [{}] to player actor [{}]", cameraID, GetID());
return this;
}
AttachedCameraID = cameraID;
PlayerCam = camera;
Logger.info("Attached camera [{}] to player actor [{}]", cameraID, GetID());
return this; return this;
} }
public void SetNewAngularVelocity(Vector3f Velocity){
if(PhysicsType == PhysicsControllerType.RigidBodySeparatingAxisTheory) {
RigidPhysicsController physicsController = (RigidPhysicsController) GetPhysicsController();
RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).AngularVelocity.set(Velocity);
}
}
public void SetNewVelocity(Vector3f Velocity){ public PlayerActor SetCameraOffset(Vector3f Offset){
if(PhysicsType == PhysicsControllerType.RigidBodySeparatingAxisTheory) { CameraOffset.set(Offset);
RigidPhysicsController physicsController = (RigidPhysicsController) GetPhysicsController(); return this;
RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).LinearVelocity.set(Velocity);
}
}
public void SetNewRotation(Quaternionf Rotation){
if(PhysicsType == PhysicsControllerType.RigidBodySeparatingAxisTheory) {
RigidPhysicsController physicsController = (RigidPhysicsController) GetPhysicsController();
RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).Rotation.set(Rotation);
}
}
public void SetNewPosition(Vector3f Position){
if(PhysicsType == PhysicsControllerType.RigidBodySeparatingAxisTheory) {
RigidPhysicsController physicsController = (RigidPhysicsController) GetPhysicsController();
RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).Position.set(Position);
}
} }
@Override @Override
@ -72,22 +60,58 @@ public class PlayerActor extends Actor{
PlayerCam = Camera.CameraRegistry.get(AttachedCameraID); PlayerCam = Camera.CameraRegistry.get(AttachedCameraID);
if(PlayerCam == null) return; if(PlayerCam == null) return;
} }
Vector3f Rotation = PlayerCam.GetRotation(); Vector3f Rotation = PlayerCam.GetRotation();
Vector3f Position = new Vector3f(GetPosition()); Vector3f Position = new Vector3f(GetPosition());
GetRotation().identity().rotateYXZ(-Rotation.y, -Rotation.x, Rotation.z);
GetRotation().identity().rotateYXZ(-Rotation.y, -Rotation.x, Rotation.z);
SetNewRotation(GetRotation());
UpdateModelMatrix(); UpdateModelMatrix();
if(Position == null || CameraOffset == null) return; if(Position == null || CameraOffset == null) return;
Position.add(CameraOffset); Position.add(CameraOffset);
PlayerCam.SetPosition(Position.x, Position.y, Position.z); PlayerCam.SetPosition(Position.x, Position.y, Position.z);
if(!PrimaryRuntime.Server
&& ClientConnectionThread.Connected
&& GetID().equals(ClientConnectionThread.OwnedActorID)) {
ClientConnectionThread.SendEntityUpdatePacket(this);
}
} }
public void Move(Vector3f Velocity){ public void Move(Vector3f Velocity){
if(PhysicsType == PhysicsControllerType.RigidBodySeparatingAxisTheory) { if(PhysicsType == PhysicsControllerType.RigidBodySeparatingAxisTheory) {
RigidPhysicsController physicsController = (RigidPhysicsController) GetPhysicsController(); RigidPhysicsController physicsController = (RigidPhysicsController) GetPhysicsController();
RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).LinearVelocity.add(Velocity); RigidBody body = RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID);
if(body == null) return;
body.LinearVelocity.add(Velocity);
float maxHorizontalSpeed = 8.0f;
float horizontalSpeedSquared =
body.LinearVelocity.x * body.LinearVelocity.x +
body.LinearVelocity.z * body.LinearVelocity.z;
if(horizontalSpeedSquared > maxHorizontalSpeed * maxHorizontalSpeed) {
float horizontalSpeed = (float)Math.sqrt(horizontalSpeedSquared);
float scale = maxHorizontalSpeed / horizontalSpeed;
body.LinearVelocity.x *= scale;
body.LinearVelocity.z *= scale;
}
} }
} }
public void Jump(float jumpVelocity){
if(PhysicsType == PhysicsControllerType.RigidBodySeparatingAxisTheory) {
RigidPhysicsController physicsController = (RigidPhysicsController) GetPhysicsController();
RigidBody body = RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID);
if(body == null) return;
body.LinearVelocity.y = jumpVelocity;
body.Grounded = false;
}
}
/* @Override /* @Override
public void UpdateModelMatrix(){ public void UpdateModelMatrix(){
if(PlayerCam != null){ if(PlayerCam != null){

View file

@ -23,13 +23,27 @@ public class PlayerController implements IPlayerController{
public PlayerController(PlayerActor Player, String ContollerID){ public PlayerController(PlayerActor Player, String ContollerID){
this.playerActor = Player; this.playerActor = Player;
PlayerCamera = Player.PlayerCam.GetID();
if(Player.PlayerCam != null) {
PlayerCamera = Player.PlayerCam.GetID();
} else if(Player.AttachedCameraID != null) {
PlayerCamera = Player.AttachedCameraID;
} else {
PlayerCamera = "DebugCamera";
}
ID = ContollerID; ID = ContollerID;
ControllerRegistry.put(ContollerID,this); ControllerRegistry.put(ContollerID,this);
} }
public void SwitchActor(PlayerActor newActor){ public void SwitchActor(PlayerActor newActor){
if(newActor == null) return;
if(newActor.PlayerCam == null && newActor.AttachedCameraID != null) {
newActor.AttachCamera(newActor.AttachedCameraID);
}
if(newActor.PlayerCam == null) return; if(newActor.PlayerCam == null) return;
if(playerActor.PhysicsType == Actor.PhysicsControllerType.RigidBodySeparatingAxisTheory) { if(playerActor.PhysicsType == Actor.PhysicsControllerType.RigidBodySeparatingAxisTheory) {
RigidPhysicsController physicsController = (RigidPhysicsController) playerActor.GetPhysicsController(); RigidPhysicsController physicsController = (RigidPhysicsController) playerActor.GetPhysicsController();
newActor.SetNewPosition(RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).Position); newActor.SetNewPosition(RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).Position);
@ -37,6 +51,7 @@ public class PlayerController implements IPlayerController{
newActor.SetNewVelocity(RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).LinearVelocity); newActor.SetNewVelocity(RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).LinearVelocity);
newActor.SetNewAngularVelocity(RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).AngularVelocity); newActor.SetNewAngularVelocity(RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).AngularVelocity);
} }
playerActor = newActor; playerActor = newActor;
PlayerCamera = newActor.PlayerCam.GetID(); PlayerCamera = newActor.PlayerCam.GetID();
} }

View file

@ -14,6 +14,8 @@ import net.halbear.Terrain4J.EngineCore.Main.GameCore;
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime; import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import net.halbear.Terrain4J.EngineCore.Main.Scene.GUIs.Gimbal; import net.halbear.Terrain4J.EngineCore.Main.Scene.GUIs.Gimbal;
import net.halbear.Terrain4J.EngineCore.Main.Scene.GUIs.PerformanceOverlay; import net.halbear.Terrain4J.EngineCore.Main.Scene.GUIs.PerformanceOverlay;
import net.halbear.Terrain4J.EngineCore.Threads.ClientConnectionThread;
import net.halbear.Terrain4J.EngineCore.Threads.RenderThread;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.DynamicMesh.DynamicTerrainMesh; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.DynamicMesh.DynamicTerrainMesh;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Projection.Project3D; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Projection.Project3D;
import org.joml.Vector2f; import org.joml.Vector2f;
@ -54,6 +56,8 @@ public class Scene implements IScene {
public int Jumps = 0; public int Jumps = 0;
public final int MaxJumps = 2; public final int MaxJumps = 2;
public int GroundedGraceTicks = 0;
public final int MaxGroundedGraceTicks = 8;
public PlayerActor CurrentWeapon; public PlayerActor CurrentWeapon;
public PlayerActor Musket; public PlayerActor Musket;
public PlayerActor Revolver; public PlayerActor Revolver;
@ -84,7 +88,7 @@ public class Scene implements IScene {
public SkyBox GetSkyBox(){return skyBox;} public SkyBox GetSkyBox(){return skyBox;}
public Scene(Window window) { public Scene(Window window) {
// CreateTerrainMesh(); // CreateTerrainMesh();
lightingManager = new SceneLightingManager(1000,new Vector3f(1f,1f,1f), 0.5f); lightingManager = new SceneLightingManager(1000,new Vector3f(1f,1f,1f), 0.5f);
Actors = new HashMap<>(); Actors = new HashMap<>();
audioInstances = new HashMap<>(); audioInstances = new HashMap<>();
@ -93,12 +97,18 @@ public class Scene implements IScene {
var EngConfig = EngineConfig.getInstance(); var EngConfig = EngineConfig.getInstance();
camera = new Camera("DebugCamera"); camera = new Camera("DebugCamera");
LastCameraFrame = new CameraFrame(camera.GetPosition(),camera.GetRotation(),camera.GetFOV(), "NO_FRAME"); LastCameraFrame = new CameraFrame(camera.GetPosition(),camera.GetRotation(),camera.GetFOV(), "NO_FRAME");
Projection = new Project3D(camera.GetFOV(),EngConfig.GetZNearPlane(), EngConfig.GetZFarPlane(),
window.getWidth(), window.getHeight());
GUIReg.put("PerformanceOverlay",new PerformanceOverlay());
ActiveGUIs.add("PerformanceOverlay");
}
int projectionWidth = window != null ? window.getWidth() : EngConfig.getWidth();
int projectionHeight = window != null ? window.getHeight() : EngConfig.getHeight();
Projection = new Project3D(camera.GetFOV(),EngConfig.GetZNearPlane(), EngConfig.GetZFarPlane(),
projectionWidth, projectionHeight);
if(!PrimaryRuntime.Server && !RenderThread.Headless) {
GUIReg.put("PerformanceOverlay",new PerformanceOverlay());
ActiveGUIs.add("PerformanceOverlay");
}
}
public ISceneLightingManager GetLightingManager(){return lightingManager;} public ISceneLightingManager GetLightingManager(){return lightingManager;}
public void CameraTick(long FrameDiffNanoSeconds){ public void CameraTick(long FrameDiffNanoSeconds){
@ -143,11 +153,6 @@ public class Scene implements IScene {
} }
} }
public void CreatePlayerController(PlayerActor CurrentActor){
CurrentWeapon = CurrentActor;
playerController = new PlayerController(CurrentWeapon, "PLAYERCONTROLLER");
}
public Map<String, CameraFrame> GetCameraFrameReg(){return CameraFrames;} public Map<String, CameraFrame> GetCameraFrameReg(){return CameraFrames;}
public CameraFrame GetCameraFrame(String Name){return CameraFrames.get(Name);} public CameraFrame GetCameraFrame(String Name){return CameraFrames.get(Name);}
public Scene AddCameraFrame(String Name, CameraFrame frame){ public Scene AddCameraFrame(String Name, CameraFrame frame){
@ -165,6 +170,7 @@ public class Scene implements IScene {
@Override @Override
public void SetUpAudio(EngineInstance engineInstance, AudioManager manager) { public void SetUpAudio(EngineInstance engineInstance, AudioManager manager) {
if(RenderThread.Headless || PrimaryRuntime.Server) return;
AudioInstance newInstance = new AudioInstance("resources/EngineResources/audio/music/MENUMUSIC_RetroFutureClean.ogg","BGM",manager,true); AudioInstance newInstance = new AudioInstance("resources/EngineResources/audio/music/MENUMUSIC_RetroFutureClean.ogg","BGM",manager,true);
newInstance.Play(); newInstance.Play();
audioInstances.put("BGM",newInstance); audioInstances.put("BGM",newInstance);
@ -172,8 +178,13 @@ public class Scene implements IScene {
public Camera GetCamera(){return camera;} public Camera GetCamera(){return camera;}
public void AddActor(Actor NewActor){ public void AddActor(Actor NewActor){
if(NewActor == null) return;
Actors.put(NewActor.GetID(), NewActor); Actors.put(NewActor.GetID(), NewActor);
ActiveActors.add(NewActor.GetID());
if(!ActiveActors.contains(NewActor.GetID())) {
ActiveActors.add(NewActor.GetID());
}
} }
public List<Actor> GetActors(){ public List<Actor> GetActors(){
List<Actor> actors = new ArrayList<>(); List<Actor> actors = new ArrayList<>();
@ -184,7 +195,44 @@ public class Scene implements IScene {
} }
public Project3D GetProjection(){return Projection;} public Project3D GetProjection(){return Projection;}
public void RemoveAllActors(){Actors.clear();} public void RemoveAllActors(){Actors.clear();}
public Actor RemoveActor(Actor actor){return Actors.remove(actor.GetID());} public Actor RemoveActor(Actor actor){
if(actor == null) return null;
ActiveActors.remove(actor.GetID());
Actor.Actors.remove(actor.GetID());
Actor.ActorNames.remove(actor.GetID());
return Actors.remove(actor.GetID());
}
public void CreatePlayerController(PlayerActor CurrentActor){
CurrentWeapon = CurrentActor;
playerController = new PlayerController(CurrentWeapon, "PLAYERCONTROLLER");
}
public void SetNetworkControlledPlayer(PlayerActor networkPlayer){
if(networkPlayer == null) return;
if(Musket != null && Musket != networkPlayer) {
Musket.AttachedCameraID = "NULL";
}
if(Revolver != null && Revolver != networkPlayer) {
Revolver.AttachedCameraID = "NULL";
}
Camera camera = GetCamera();
if(camera == null) return;
networkPlayer.AttachCamera(camera.GetID());
networkPlayer.SetCameraOffset(new Vector3f(0, 1.0f, 0));
CurrentWeapon = networkPlayer;
Musket = networkPlayer;
Revolver = networkPlayer;
playerController = new PlayerController(networkPlayer, "PLAYERCONTROLLER");
playerController.SetPlayerCamera(camera.GetID());
}
public void SetCurrentWeapon(PlayerActor Weapon) {this.CurrentWeapon = Weapon; } public void SetCurrentWeapon(PlayerActor Weapon) {this.CurrentWeapon = Weapon; }
@ -205,28 +253,31 @@ public class Scene implements IScene {
if(input.keyPressed(GLFW_KEY_ENTER)) { if(input.keyPressed(GLFW_KEY_ENTER)) {
parent.SpawnNewActor(engineInstance, new Vector3f( (float)(5 * Math.random()),20 + (float)(10 * Math.random()), (float)(5 * Math.random())),new Vector3f(-1f + (float)(2 * Math.random()),-1f + (float)(2 * Math.random()),-1f + (float)(2 * Math.random())),new Vector3f((float)Math.random(),(float)Math.random(),(float)Math.random())); parent.SpawnNewActor(engineInstance, new Vector3f( (float)(5 * Math.random()),20 + (float)(10 * Math.random()), (float)(5 * Math.random())),new Vector3f(-1f + (float)(2 * Math.random()),-1f + (float)(2 * Math.random()),-1f + (float)(2 * Math.random())),new Vector3f((float)Math.random(),(float)Math.random(),(float)Math.random()));
} }
if (input.keySinglePress(GLFW_KEY_R) && CurrentWeapon != Revolver) { if(!ClientConnectionThread.Connected) {
scene.RemoveActor(Musket); if (input.keySinglePress(GLFW_KEY_R) && CurrentWeapon != Revolver) {
scene.AddActor(Revolver); scene.RemoveActor(Musket);
playerController.SwitchActor(Revolver); scene.AddActor(Revolver);
CurrentWeapon = Revolver; playerController.SwitchActor(Revolver);
playerActor = Revolver; CurrentWeapon = Revolver;
parent.SetPlayerActorID(Revolver.GetID()); playerActor = Revolver;
Musket.AttachedCameraID = "NULL"; parent.SetPlayerActorID(Revolver.GetID());
Revolver.AttachedCameraID = "DebugCamera"; Musket.AttachedCameraID = "NULL";
Revolver.AttachedCameraID = "DebugCamera";
} }
if (input.keySinglePress(GLFW_KEY_M) && CurrentWeapon != Musket) { if (input.keySinglePress(GLFW_KEY_M) && CurrentWeapon != Musket) {
scene.RemoveActor(Revolver); scene.RemoveActor(Revolver);
scene.AddActor(Musket); scene.AddActor(Musket);
playerController.SwitchActor(Musket); playerController.SwitchActor(Musket);
CurrentWeapon = Musket; CurrentWeapon = Musket;
playerActor = Musket; playerActor = Musket;
parent.SetPlayerActorID(Musket.GetID()); parent.SetPlayerActorID(Musket.GetID());
Musket.AttachedCameraID = "DebugCamera"; Musket.AttachedCameraID = "DebugCamera";
Revolver.AttachedCameraID = "NULL"; Revolver.AttachedCameraID = "NULL";
}
} }
if(input.keyPressed(GLFW_KEY_1)) { if(input.keyPressed(GLFW_KEY_1)) {
Gimbal.universalType = Gimbal.GimbalType.Move; Gimbal.universalType = Gimbal.GimbalType.Move;
} }
@ -244,6 +295,11 @@ public class Scene implements IScene {
if(input.keySinglePress(GLFW_KEY_F2)) { if(input.keySinglePress(GLFW_KEY_F2)) {
EngineConfig.getInstance().SetRenderCollisionMesh(!EngineConfig.getInstance().RenderCollisionMeshes()); EngineConfig.getInstance().SetRenderCollisionMesh(!EngineConfig.getInstance().RenderCollisionMeshes());
} }
if(playerActor == null || CurrentWeapon == null || playerController == null) {
return;
}
playerController.GetControls().Input(input, FrameDiffNanoSeconds, CurrentWeapon, MOVEMENT_SPEED, parent, this); playerController.GetControls().Input(input, FrameDiffNanoSeconds, CurrentWeapon, MOVEMENT_SPEED, parent, this);
if(GUI_MODE == 0 && !ActiveGUIs.contains("PerformanceOverlay")) ActiveGUIs.add("PerformanceOverlay"); if(GUI_MODE == 0 && !ActiveGUIs.contains("PerformanceOverlay")) ActiveGUIs.add("PerformanceOverlay");
else if (GUI_MODE != 0) ActiveGUIs.remove("PerformanceOverlay"); else if (GUI_MODE != 0) ActiveGUIs.remove("PerformanceOverlay");

View file

@ -0,0 +1,145 @@
package net.halbear.Terrain4J.EngineCore.ServerNetworking;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
public class Packet {
public static final byte PACKET_UPDATE_LOCATION = 0;
public static final byte PACKET_UPDATE_ROTATION = 1;
public static final byte PACKET_UPDATE_LINEAR_VELOCITY =2;
public static final byte PACKET_UPDATE_ANGULAR_VELOCITY =3;
public static final byte PACKET_CREATE_ACTOR = 4;
public static final byte PACKET_PING = 5;
public static final byte PACKET_MOVEMENT_UPDATE = 6;
public static final byte PACKET_ASSIGN_UUID = 7;
public static final byte PACKET_POSSESS_ACTOR = 8;
public static final byte PACKET_DESTROY_ACTOR = 9;
public static final byte PACKET_CLIENT_INPUT = 10;
public byte PacketTypeByte; //0 Location 1 Rotation 2 LinearVelocity 3 AngularVelocity 4 CombinedActorDownload 5 Ping 6 PosRotVelAngularVel 7 AssignUUID
public byte TargetType; //0 Actor
public byte[] Data;
public String TargetID;
public UUID ClientID;
public Packet(byte Type){
PacketTypeByte = Type;
TargetType = 0;
Data = new byte[0];
TargetID = "";
}
public Packet SetTargetType(byte TargetType){
this.TargetType = TargetType;
return this;
}
public Packet SetData(byte[] Data){
this.Data = Data;
return this;
}
public Packet SetID(String TargetID){
this.TargetID = TargetID;
return this;
}
public int GetByteSize(){
byte[] idBytes = TargetID.getBytes(StandardCharsets.UTF_8);
return 2 + 4 + Data.length + 4 + idBytes.length;
}
public static byte[] GetOutgoingData(Packet packet){
int ByteSize = packet.GetByteSize();
byte[] Data = new byte[ByteSize];
int Offset = 0;
Data[Offset] = packet.PacketTypeByte;
Offset++;
Data[Offset] = packet.TargetType;
Offset++;
byte[] dataLengthBytes = ByteBuffer.allocate(4).putInt(packet.Data.length).array();
for(int i = 0; i < dataLengthBytes.length; i++){
Data[Offset] = dataLengthBytes[i];
Offset++;
}
for(int i = 0; i < packet.Data.length; i++){
Data[Offset] = packet.Data[i];
Offset++;
}
byte[] IDBytes = packet.TargetID.getBytes(StandardCharsets.UTF_8);
byte[] idLengthBytes = ByteBuffer.allocate(4).putInt(IDBytes.length).array();
for(int i = 0; i < idLengthBytes.length; i++){
Data[Offset] = idLengthBytes[i];
Offset++;
}
for(int i = 0; i < IDBytes.length; i++){
Data[Offset] = IDBytes[i];
Offset++;
}
return Data;
}
public static byte[] EncodeMovementData(Vector3f Position,Quaternionf Rotation,Vector3f LinearVelocity,Vector3f AngularVelocity){
float[] floats = new float[]{Position.x,Position.y,Position.z,Rotation.x,Rotation.y,Rotation.z,Rotation.w,LinearVelocity.x,LinearVelocity.y,LinearVelocity.z,AngularVelocity.x,AngularVelocity.y,AngularVelocity.z};
byte[] Data = new byte[floats.length* VulkanUtils.FLOAT_SIZE];
int Offset = 0;
for(int i = 0; i < floats.length; i++) {
byte[] SizeBytes = ByteBuffer.allocate(4).putFloat(floats[i]).array();
for(int j = 0; j < SizeBytes.length; j++){
Data[Offset] = SizeBytes[j];
Offset++;
}
}
return Data;
}
public static Quaternionf DecodeAsQuaternation(byte[] DataIn){
Quaternionf newVector = new Quaternionf();
ByteBuffer buffer = ByteBuffer.wrap(DataIn);
newVector.set(buffer.getFloat(),buffer.getFloat(),buffer.getFloat(),buffer.getFloat());
return newVector;
}
public static DecodedMovementPacket DecodeAsMovementUpdate(byte[] DataIn){
DecodedMovementPacket Packet = new DecodedMovementPacket();
Vector3f newVector = new Vector3f();
ByteBuffer buffer = ByteBuffer.wrap(DataIn);
newVector.set(buffer.getFloat(),buffer.getFloat(),buffer.getFloat());
Packet.Position = new Vector3f(newVector);
Packet.Rotation = new Quaternionf(buffer.getFloat(),buffer.getFloat(),buffer.getFloat(),buffer.getFloat());
newVector.set(buffer.getFloat(),buffer.getFloat(),buffer.getFloat());
Packet.LinearVelocity = new Vector3f(newVector);
newVector.set(buffer.getFloat(),buffer.getFloat(),buffer.getFloat());
Packet.AngularVelocity = new Vector3f(newVector);
return Packet;
}
public static Vector3f DecodeAsVector3f(byte[] DataIn){
Vector3f newVector = new Vector3f();
ByteBuffer buffer = ByteBuffer.wrap(DataIn);
newVector.set(buffer.getFloat(),buffer.getFloat(),buffer.getFloat());
return newVector;
}
public static String DecodeAsString(byte[] DataIn){
return new String(DataIn, StandardCharsets.UTF_8);
}
public static class DecodedMovementPacket{
public Vector3f Position;
public Vector3f LinearVelocity;
public Vector3f AngularVelocity;
public Quaternionf Rotation;
public DecodedMovementPacket(){
}
}
}

View file

@ -0,0 +1,358 @@
package net.halbear.Terrain4J.EngineCore.Threads;
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.ConvexMesh;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidBody;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidPhysicsController;
import net.halbear.Terrain4J.EngineCore.Main.GameCore;
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import net.halbear.Terrain4J.EngineCore.Main.Scene.*;
import net.halbear.Terrain4J.EngineCore.ServerNetworking.Packet;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import org.tinylog.Logger;
import java.io.*;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
public class ClientConnectionThread implements Runnable{
public static boolean Connected = false;
public static boolean pinging = false;
public static String ServerIP = "localhost";
public static String ServerMessage = "Offline";
public static Socket SocketToServer;
public static final Queue<Packet> OutGoingPacketQueue = new ConcurrentLinkedQueue<>();
public static final Queue<Packet> IncomingPacketQueue = new ConcurrentLinkedQueue<>();
public static DataOutputStream outToServer;
public static DataInputStream in;
public static long UUID;
public static String OwnedActorID = "NULL";
public static String PendingPossessActorID = "NULL";
private static boolean TryPossessActor(String actorID, GameCore gameCore, IScene scene){
Actor actor = Actor.Actors.get(actorID);
if(!(actor instanceof PlayerActor playerActor)) {
PendingPossessActorID = actorID;
Logger.info("Possess actor [{}] is not created yet. Deferring possession.", actorID);
return false;
}
if(!(scene instanceof Scene concreteScene)) {
PendingPossessActorID = actorID;
Logger.warn("Cannot possess actor [{}] because scene is not a Scene instance", actorID);
return false;
}
Camera debugCamera = concreteScene.GetCamera();
if(debugCamera == null) {
PendingPossessActorID = actorID;
Logger.warn("Cannot possess actor [{}] because DebugCamera is missing", actorID);
return false;
}
OwnedActorID = actorID;
PendingPossessActorID = "NULL";
playerActor.AttachCamera(debugCamera.GetID());
concreteScene.SetNetworkControlledPlayer(playerActor);
gameCore.SetPlayerActorID(actorID);
Logger.info(
"Client now controls server actor [{}], attached camera [{}]",
actorID,
debugCamera.GetID()
);
return true;
}
public static void DecodePackets(EngineInstance engineInstance, GameCore gameCore, IScene scene){
if(!IncomingPacketQueue.isEmpty()){
Packet packet;
while((packet = IncomingPacketQueue.poll()) != null){
System.out.println("Packet: " + packet.PacketTypeByte);
Actor Target = Actor.Actors.get(packet.TargetID);
Vector3f vector3f = new Vector3f();
String stringdata = "";
Quaternionf quaternionfdata = new Quaternionf();
Packet.DecodedMovementPacket MovementUpdate;
if(packet.PacketTypeByte >= 0 && packet.PacketTypeByte < 4 && packet.PacketTypeByte != 1){
vector3f = Packet.DecodeAsVector3f(packet.Data);
}
if(Target == null
&& packet.PacketTypeByte != Packet.PACKET_CREATE_ACTOR
&& packet.PacketTypeByte != Packet.PACKET_PING
&& packet.PacketTypeByte != Packet.PACKET_POSSESS_ACTOR
&& packet.PacketTypeByte != Packet.PACKET_DESTROY_ACTOR) {
continue;
}
switch (packet.PacketTypeByte) {
case 0:
Target.SetNewPosition(vector3f);
break;
case 1:
quaternionfdata = Packet.DecodeAsQuaternation(packet.Data);
Target.SetNewRotation(quaternionfdata);
break;
case 2:
Target.SetNewVelocity(vector3f);
break;
case 3:
Target.SetNewAngularVelocity(vector3f);
break;
case 4: //"ACtorType:ModelID:x:y:z:rx:ry:rz:sx:sy:sz:hx:hy:hz:MassKG:vx:vy:vz:avx:avy:avz:posOffx:posOffy:posOffz:camOffx:camOffy:camOffz"
try {
stringdata = Packet.DecodeAsString(packet.Data);
String[] Split = stringdata.split(":");
if(Split.length < 22) {
Logger.error("Create actor packet [{}] has too few fields: [{}] data=[{}]", packet.TargetID, Split.length, stringdata);
break;
}
Vector3f Position = new Vector3f(
Float.parseFloat(Split[2]),
Float.parseFloat(Split[3]),
Float.parseFloat(Split[4])
);
Quaternionf Rotation = new Quaternionf(
Float.parseFloat(Split[5]),
Float.parseFloat(Split[6]),
Float.parseFloat(Split[7]),
Float.parseFloat(Split[8])
);
Vector3f Scale = new Vector3f(
Float.parseFloat(Split[9]),
Float.parseFloat(Split[10]),
Float.parseFloat(Split[11])
);
Vector3f CollisionBox = new Vector3f(
Float.parseFloat(Split[12]),
Float.parseFloat(Split[13]),
Float.parseFloat(Split[14])
);
float MassKG = Float.parseFloat(Split[15]);
Vector3f Velocity = new Vector3f(
Float.parseFloat(Split[16]),
Float.parseFloat(Split[17]),
Float.parseFloat(Split[18])
);
Vector3f AngularVelocity = new Vector3f(
Float.parseFloat(Split[19]),
Float.parseFloat(Split[20]),
Float.parseFloat(Split[21])
);
Vector3f PositionOffset = new Vector3f();
if(Split.length >= 25) {
PositionOffset.set(
Float.parseFloat(Split[22]),
Float.parseFloat(Split[23]),
Float.parseFloat(Split[24])
);
}
Vector3f CameraOffset = new Vector3f(0, 1.0f, 0);
if(Split.length >= 28) {
CameraOffset.set(
Float.parseFloat(Split[25]),
Float.parseFloat(Split[26]),
Float.parseFloat(Split[27])
);
}
String actorType = Split[0];
String modelID = Split[1];
Logger.info("Received create actor packet: actorID=[{}], type=[{}], modelID=[{}]", packet.TargetID, actorType, modelID);
if (actorType.equals("PlayerActor")) {
Target = new PlayerActor("NULL", packet.TargetID, modelID, Position).SetCameraOffset(CameraOffset);
Target.SetPositionOffset(PositionOffset);
} else {
Target = new Actor(packet.TargetID, modelID, Position);
}
Target.SetScale(Scale);
Target.CreatePhysicsController(ConvexMesh.Box(CollisionBox.x, CollisionBox.y, CollisionBox.z), MassKG);
Target.SetServerSynced(MassKG > 0.0f || actorType.equals("PlayerActor"));
Target.SetNewRotation(Rotation);
RigidPhysicsController physicsController = (RigidPhysicsController) Target.GetPhysicsController();
RigidBody rigidBody = RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID);
if (rigidBody != null) {
rigidBody.LinearVelocity.set(Velocity);
rigidBody.AngularVelocity.set(AngularVelocity);
if(actorType.equals("PlayerActor")){
rigidBody.LockRotation();
}
}
scene.AddActor(Target);
Logger.info("Created network actor [{}] of type [{}]", packet.TargetID, actorType);
if(packet.TargetID.equals(PendingPossessActorID)) {
TryPossessActor(packet.TargetID, gameCore, scene);
}
} catch (Exception e) {
Logger.error(e, "Failed to decode create actor packet for actor [{}]", packet.TargetID);
}
break;
case 6:
MovementUpdate = Packet.DecodeAsMovementUpdate(packet.Data);
if(packet.TargetID.equals(OwnedActorID)) {
Target.SetNewVelocity(MovementUpdate.LinearVelocity);
Target.SetNewAngularVelocity(MovementUpdate.AngularVelocity);
break;
}
Target.SetNetworkTarget(MovementUpdate.Position, MovementUpdate.Rotation);
Target.SetNewVelocity(MovementUpdate.LinearVelocity);
Target.SetNewAngularVelocity(MovementUpdate.AngularVelocity);
break;
case 8:
Logger.info("Received possess packet for actor [{}]", packet.TargetID);
TryPossessActor(packet.TargetID, gameCore, scene);
break;
case 9:
Actor actorToDestroy = Actor.Actors.get(packet.TargetID);
if(actorToDestroy != null) {
scene.RemoveActor(actorToDestroy);
}
break;
}
}
}
}
public ClientConnectionThread(){
Connected = true;
try {
SocketToServer = new Socket(ServerIP, 25565);
SocketToServer.setSoTimeout(5);
} catch (IOException e) {
Connected = false;
//e.printStackTrace();
}
}
public static void SetServerIP(String ServerIP, Thread serverThread){
if(Connected){
Connected = false;
serverThread.interrupt();
ClientConnectionThread.ServerIP = ServerIP;
PrimaryRuntime.ServerCon = new ClientConnectionThread();
serverThread = new Thread(PrimaryRuntime.ServerCon);
serverThread.start();
}
}
public static void SendEntityUpdatePacket(Actor actor){
Packet newOutgoingPacket = new Packet((byte)6);
newOutgoingPacket.SetTargetType((byte) 0);
RigidPhysicsController physicsController = (RigidPhysicsController) actor.GetPhysicsController();
if(physicsController == null) return;
RigidBody rigidBody = RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID);
if(rigidBody == null) return;
newOutgoingPacket.SetData(Packet.EncodeMovementData(rigidBody.Position,rigidBody.Rotation,rigidBody.LinearVelocity,rigidBody.AngularVelocity));
newOutgoingPacket.SetID(actor.GetID());
OutGoingPacketQueue.add(newOutgoingPacket);
}
public static int readPacket(DataInputStream in) throws IOException {
if(in == null) return 0;
Packet newIncomingPacket = new Packet(in.readByte());
if(newIncomingPacket.PacketTypeByte == 5) {
return 5;
}
newIncomingPacket.SetTargetType(in.readByte());
int DataLength = in.readInt();
byte[] IncomingData = new byte[DataLength];
in.readFully(IncomingData);
newIncomingPacket.Data = IncomingData;
int IDLength = in.readInt();
byte[] IDData = new byte[IDLength];
in.readFully(IDData);
String ID = new String(IDData, StandardCharsets.UTF_8);
newIncomingPacket.SetID(ID);
IncomingPacketQueue.add(newIncomingPacket);
return 0;
}
public static void WritePacket(Packet outPacket, DataOutputStream Outgoing) throws IOException {
if(Outgoing == null ) return;
byte[] DataToSend = Packet.GetOutgoingData(outPacket);
Outgoing.write(DataToSend);
}
@Override
public void run() {
try {
outToServer = new DataOutputStream(SocketToServer.getOutputStream());
in = new DataInputStream(SocketToServer.getInputStream());
Connected = true;
while(Connected) {
int PacketRead = 0;
try {
PacketRead = readPacket(in);
} catch (SocketTimeoutException ignored) {
// No incoming packet this moment. Continue so outgoing packets can still flush.
}
if(PacketRead == Packet.PACKET_PING){
WritePacket(new Packet(Packet.PACKET_PING),outToServer);
}
if(PacketRead == -1) break;
if(!OutGoingPacketQueue.isEmpty()){
Packet outgoingPacket;
while((outgoingPacket = OutGoingPacketQueue.poll()) != null){
WritePacket(outgoingPacket,outToServer);
}
}
}
System.out.println("Connection closed");
Connected = false;
if(!EngineThread.running) return;
if (!pinging) {
PrimaryRuntime.StartPingTimer();
}
SocketToServer.close();
} catch (Exception e) {
//e.printStackTrace();
Connected = false;
ServerMessage = "Offline";
if(!EngineThread.running) return;
if (!pinging) {
PrimaryRuntime.StartPingTimer();
}
}
}
}

View file

@ -1,16 +1,11 @@
package net.halbear.Terrain4J.EngineCore.Threads; package net.halbear.Terrain4J.EngineCore.Threads;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
import net.halbear.Terrain4J.EngineCore.Logic.GameLogic;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.WorldPhysicsManager;
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import org.tinylog.Logger; import org.tinylog.Logger;
import static net.halbear.Terrain4J.EngineCore.Logic.Physics.WorldPhysicsManager.ActiveControllers; import static net.halbear.Terrain4J.EngineCore.Logic.Physics.WorldPhysicsManager.ActiveControllers;
import static net.halbear.Terrain4J.EngineCore.Logic.Physics.WorldPhysicsManager.PhysicsObjects; import static net.halbear.Terrain4J.EngineCore.Logic.Physics.WorldPhysicsManager.PhysicsObjects;
public class PhysicsThread implements Runnable{ public class InstancedPhysicsThread implements Runnable{
public static boolean running = true; public static boolean running = true;
public final Thread EngineThread; public final Thread EngineThread;
public static float FixedTimeStep = 1f / 60f; public static float FixedTimeStep = 1f / 60f;
@ -27,12 +22,12 @@ public class PhysicsThread implements Runnable{
return EngineThread; return EngineThread;
} }
public PhysicsThread StartThread(){ public InstancedPhysicsThread StartThread(){
EngineThread.start(); EngineThread.start();
return this; return this;
} }
public PhysicsThread(String ThreadName, int Index, int TotalCount){ public InstancedPhysicsThread(String ThreadName, int Index, int TotalCount){
this.ThreadName = ThreadName; this.ThreadName = ThreadName;
Logger.debug("Starting {} Thread",ThreadName); Logger.debug("Starting {} Thread",ThreadName);
EngineThread = new Thread(this); EngineThread = new Thread(this);

View file

@ -16,16 +16,19 @@ public class RenderThread extends EngineThread {
private Window window; private Window window;
private final InitData initData; private final InitData initData;
public static int VulkanCrashCount = 0; public static int VulkanCrashCount = 0;
public static boolean Headless = false;
public RenderThread(Window window, EngineInstance engineInstance, InitData initData, GameLogic appLogic) { public RenderThread(Window window, EngineInstance engineInstance, InitData initData, GameLogic appLogic) {
//this.window = window; //this.window = window;
render = new Render(engineInstance); if(!Headless)render = new Render(engineInstance);
super(engineInstance,appLogic,"Render"); super(engineInstance,appLogic,"Render");
this.initData = initData; this.initData = initData;
if(Headless) return;
render.Initialise(initData); render.Initialise(initData);
} }
public void RestartCrashedRenderer(){ public void RestartCrashedRenderer(){
if(Headless) return;
if(VulkanCrashCount < EngineConfig.getInstance().GetMaxVulkanCrashes()){ if(VulkanCrashCount < EngineConfig.getInstance().GetMaxVulkanCrashes()){
RefreshRenderer(); RefreshRenderer();
VulkanCrashCount++; VulkanCrashCount++;
@ -44,6 +47,7 @@ public class RenderThread extends EngineThread {
@Override @Override
public void FrameEvent(long now, long InitialTime){ public void FrameEvent(long now, long InitialTime){
gameLogic.RenderThreadInput(PrimaryRuntime.GetEngineInstance(), (now-InitialTime)); gameLogic.RenderThreadInput(PrimaryRuntime.GetEngineInstance(), (now-InitialTime));
if(Headless) return;
render.render(PrimaryRuntime.GetEngineInstance()); render.render(PrimaryRuntime.GetEngineInstance());
} }
@Override @Override
@ -52,6 +56,7 @@ public class RenderThread extends EngineThread {
} }
public void RefreshRenderer(){ public void RefreshRenderer(){
if(Headless) return;
Logger.debug("REFRESHING RENDERER"); Logger.debug("REFRESHING RENDERER");
render.cleanup(); render.cleanup();
render = new Render(PrimaryRuntime.GetEngineInstance()); render = new Render(PrimaryRuntime.GetEngineInstance());
@ -60,11 +65,12 @@ public class RenderThread extends EngineThread {
@Override @Override
public void SecondEvent(){ public void SecondEvent(){
EngineConfig.FrameRate_RENDERTHREAD = Frames;
EngineConfig.TPS_RENDERTHREAD = TickFrames;
if(Headless) return;
EngineConfig.LAST_AVERAGE_GPU_TIME = DeferredSceneRender.GetGPUTimeNS(); EngineConfig.LAST_AVERAGE_GPU_TIME = DeferredSceneRender.GetGPUTimeNS();
List<String[]> Profiling =GPUProfiler.GetVramUsage(render.GetVulkanContext().GetPhysicalDevice().GetPhysicalDevice()); List<String[]> Profiling =GPUProfiler.GetVramUsage(render.GetVulkanContext().GetPhysicalDevice().GetPhysicalDevice());
EngineConfig.getInstance().SetMemoryProfiling(Profiling); EngineConfig.getInstance().SetMemoryProfiling(Profiling);
EngineConfig.FrameRate_RENDERTHREAD = Frames;
EngineConfig.TPS_RENDERTHREAD = TickFrames;
if(render.GetCurrentAAMode() != EngineConfig.getInstance().RenderAAType() || render.GetDeferred() != EngineConfig.getInstance().DeferredRendering()){ if(render.GetCurrentAAMode() != EngineConfig.getInstance().RenderAAType() || render.GetDeferred() != EngineConfig.getInstance().DeferredRendering()){
RefreshRenderer(); RefreshRenderer();
} }
@ -73,9 +79,12 @@ public class RenderThread extends EngineThread {
@Override @Override
public void cleanup() { public void cleanup() {
render.cleanup(); if(render != null)render.cleanup();
PrimaryRuntime.ThreadsOpen--; PrimaryRuntime.ThreadsOpen--;
Logger.debug("Closing Render Thread, Thread: [{}]",Thread.currentThread().toString()); Logger.debug("Closing Render Thread, Thread: [{}]",Thread.currentThread().toString());
if (PrimaryRuntime.ThreadsOpen <= 0 && VulkanContext.VulkanLayersOpen < 0) PrimaryRuntime.CanClose = true;
if (Headless || (PrimaryRuntime.ThreadsOpen <= 0 && VulkanContext.VulkanLayersOpen < 0)) {
PrimaryRuntime.CanClose = true;
}
} }
} }

View file

@ -0,0 +1,459 @@
package net.halbear.Terrain4J.EngineCore.Threads;
import net.halbear.Executable.Server;
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.ConvexMesh;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidBody;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidPhysicsController;
import net.halbear.Terrain4J.EngineCore.Main.GameCore;
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor;
import net.halbear.Terrain4J.EngineCore.Main.Scene.IScene;
import net.halbear.Terrain4J.EngineCore.Main.Scene.PlayerActor;
import net.halbear.Terrain4J.EngineCore.ServerNetworking.Packet;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import java.io.*;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import static net.halbear.Executable.Server.ConnectedClients;
public class ServerConnectionThread implements Runnable{
private String OwnedActorID;
private final Socket clientSocket;
private final UUID ClientID;
public final Queue<Packet> IncomingPacketQueue = new ConcurrentLinkedQueue<>();
public final Queue<Packet> OutgoingPacketQueue = new ConcurrentLinkedQueue<>();
public UUID GetClientID(){
return ClientID;
}
public String GetOwnedActorID(){
return OwnedActorID;
}
public void SetOwnedActorID(String ownedActorID){
this.OwnedActorID = ownedActorID;
}
public ServerConnectionThread(Socket clientSocket) {
UUID uuid = UUID.randomUUID();
ClientID = uuid;
this.clientSocket = clientSocket;
try {
this.clientSocket.setSoTimeout(5);
} catch (IOException e) {
throw new RuntimeException(e);
}
System.out.println("Connected to client: " + clientSocket.getInetAddress().getHostName());
ConnectedClients.put(uuid, this);
}
public void SendPossessActorPacket(String actorID) {
Packet packet = new Packet((byte) 8);
packet.SetTargetType((byte) 0);
packet.SetData(new byte[0]);
packet.SetID(actorID);
AddOutgoingPacket(packet);
}
public void CollectIncomingPackets(Queue<Packet> ReferenceList){
Packet packet;
while((packet = IncomingPacketQueue.poll()) != null) {
ReferenceList.add(packet);
}
}
public void AddOutgoingPacket(Packet outgoingPacket){
OutgoingPacketQueue.add(outgoingPacket);
}
private void InitialiseJoinedClient(){
EngineInstance engineInstance = PrimaryRuntime.GetEngineInstance();
IScene scene = engineInstance.scene();
for(Actor actor : scene.GetActors()) {
Packet actorPacket = CreateActorPacket(actor);
if(actorPacket != null) {
AddOutgoingPacket(actorPacket);
}
}
GameCore gameCore = (GameCore) PrimaryRuntime.GetGameCore();
PlayerActor player = gameCore.SpawnNetworkPlayer(engineInstance, ClientID);
SetOwnedActorID(player.GetID());
Packet playerCreatePacket = CreateActorPacket(player);
if(playerCreatePacket != null) {
AddOutgoingPacket(playerCreatePacket);
System.out.println("Queued direct create packet for joining player's actor: " + player.GetID());
}
BroadcastCreateActorPacket(player);
SendPossessActorPacket(player.GetID());
System.out.println("Queued possess packet for joining player's actor: " + player.GetID());
}
@Override
public void run() {
try {
DataInputStream in = new DataInputStream(clientSocket.getInputStream());
OutputStream toClient = clientSocket.getOutputStream();
DataOutputStream out = new DataOutputStream(toClient);
boolean Connected = true;
InitialiseJoinedClient();
while(Connected) {
int PacketRead = 0;
try {
PacketRead = readPacket(in);
} catch (SocketTimeoutException ignored) {
// No incoming packet this moment. Continue so outgoing packets can still flush.
}
if(PacketRead == Packet.PACKET_PING){
WritePacket(new Packet(Packet.PACKET_PING),out);
}
if(PacketRead == -1) break;
if(!OutgoingPacketQueue.isEmpty()){
Packet packet;
while((packet = OutgoingPacketQueue.poll()) != null) {
WritePacket(packet,out);
}
}
}
System.out.println("Connection Closing: " + Thread.currentThread() + "\n");
} catch (Exception e) {
System.out.println("Connection Closing: " + Thread.currentThread() + "\n");
//throw new RuntimeException(e);
}
}
public static void ProcessClientPacket(Packet packet){
ServerConnectionThread sender = ConnectedClients.get(packet.ClientID);
if(sender == null) return;
System.out.println("Packet: " + packet.PacketTypeByte);
Actor Target = Actor.Actors.get(packet.TargetID);
if(Target == null
&& packet.PacketTypeByte != Packet.PACKET_CREATE_ACTOR
&& packet.PacketTypeByte != Packet.PACKET_PING) {
return;
}
switch (packet.PacketTypeByte){
case Packet.PACKET_UPDATE_LOCATION:
if(!sender.OwnsActor(packet.TargetID)) return;
Target.SetNewPosition(Packet.DecodeAsVector3f(packet.Data));
break;
case Packet.PACKET_UPDATE_ROTATION:
if(!sender.OwnsActor(packet.TargetID)) return;
Target.SetNewRotation(Packet.DecodeAsQuaternation(packet.Data));
break;
case Packet.PACKET_UPDATE_LINEAR_VELOCITY:
if(!sender.OwnsActor(packet.TargetID)) return;
Target.SetNewVelocity(Packet.DecodeAsVector3f(packet.Data));
break;
case Packet.PACKET_UPDATE_ANGULAR_VELOCITY:
if(!sender.OwnsActor(packet.TargetID)) return;
Target.SetNewAngularVelocity(Packet.DecodeAsVector3f(packet.Data));
break;
case Packet.PACKET_MOVEMENT_UPDATE:
if(!sender.OwnsActor(packet.TargetID)) return;
Packet.DecodedMovementPacket movementUpdate = Packet.DecodeAsMovementUpdate(packet.Data);
Target.SetNewRotation(movementUpdate.Rotation);
Target.SetNewPosition(movementUpdate.Position);
Target.SetNewVelocity(movementUpdate.LinearVelocity);
Target.SetNewAngularVelocity(movementUpdate.AngularVelocity);
break;
case Packet.PACKET_CLIENT_INPUT:
if(!sender.OwnsActor(packet.TargetID)) return;
// Later: decode input commands here instead of trusting full transforms.
// Example future data:
// forward/back/left/right/jump/yaw/pitch/sequenceNumber
break;
}
}
public boolean OwnsActor(String actorID){
return OwnedActorID != null && OwnedActorID.equals(actorID);
}
public static void DecodePackets(EngineInstance engineInstance, GameCore gameCore, IScene scene,List<Packet> IncomingPacketQueue){
if(!IncomingPacketQueue.isEmpty()){
ListIterator<Packet> iter = IncomingPacketQueue.listIterator();
while(iter.hasNext()){
Packet packet = iter.next();
Actor Target = Actor.Actors.get(packet.TargetID);
Vector3f vector3f = new Vector3f();
String stringdata = "";
Quaternionf quaternionfdata = new Quaternionf();
Packet.DecodedMovementPacket MovementUpdate;
if(packet.PacketTypeByte >= 0 && packet.PacketTypeByte < 4 && packet.PacketTypeByte != 1){
vector3f = Packet.DecodeAsVector3f(packet.Data);
}
if(Target == null
&& packet.PacketTypeByte != Packet.PACKET_CREATE_ACTOR
&& packet.PacketTypeByte != Packet.PACKET_PING
&& packet.PacketTypeByte != Packet.PACKET_POSSESS_ACTOR) {
iter.remove();
continue;
}
switch (packet.PacketTypeByte){
case 0:
Target.SetNewPosition(vector3f);
break;
case 1:
quaternionfdata = Packet.DecodeAsQuaternation(packet.Data);
Target.SetNewRotation(quaternionfdata);
break;
case 2:
Target.SetNewVelocity(vector3f);
break;
case 3:
Target.SetNewAngularVelocity(vector3f);
break;
case 4: //"ACtorType:ModelID:x:y:z:rx:ry:rz:sx:sy:sz:hx:hy:hz:MassKG:vx:vy:vz:avx:avy:avz:posOffx:posOffy:posOffz:camOffx:camOffy:camOffz"
stringdata = Packet.DecodeAsString(packet.Data);
String[] Split = stringdata.split(":");
Vector3f Position = new Vector3f(
Float.parseFloat(Split[2]),
Float.parseFloat(Split[3]),
Float.parseFloat(Split[4])
);
Quaternionf Rotation = new Quaternionf(
Float.parseFloat(Split[5]),
Float.parseFloat(Split[6]),
Float.parseFloat(Split[7]),
Float.parseFloat(Split[8])
);
Vector3f Scale = new Vector3f(
Float.parseFloat(Split[9]),
Float.parseFloat(Split[10]),
Float.parseFloat(Split[11])
);
Vector3f CollisionBox = new Vector3f(
Float.parseFloat(Split[12]),
Float.parseFloat(Split[13]),
Float.parseFloat(Split[14])
);
float MassKG = Float.parseFloat(Split[15]);
Vector3f Velocity = new Vector3f(
Float.parseFloat(Split[16]),
Float.parseFloat(Split[17]),
Float.parseFloat(Split[18])
);
Vector3f AngularVelocity = new Vector3f(
Float.parseFloat(Split[19]),
Float.parseFloat(Split[20]),
Float.parseFloat(Split[21])
);
Vector3f PositionOffset = new Vector3f(
Float.parseFloat(Split[22]),
Float.parseFloat(Split[23]),
Float.parseFloat(Split[24])
);
Vector3f CameraOffset = new Vector3f(
Float.parseFloat(Split[25]),
Float.parseFloat(Split[26]),
Float.parseFloat(Split[27])
);
String actorType = Split[0];
String modelID = Split[1];
if(actorType.equals("PlayerActor")) {
Target = new PlayerActor("NULL", packet.TargetID, modelID, Position).SetCameraOffset(CameraOffset);
Target.SetPositionOffset(PositionOffset);
} else {
Target = new Actor(packet.TargetID, modelID, Position);
}
Target.SetNewRotation(Rotation);
Target.SetScale(Scale);
Target.CreatePhysicsController(ConvexMesh.Box(CollisionBox.x, CollisionBox.y, CollisionBox.z), MassKG);
Target.SetServerSynced(MassKG > 0.0f || actorType.equals("PlayerActor"));
Target.SetNewRotation(Rotation);
RigidPhysicsController physicsController = (RigidPhysicsController) Target.GetPhysicsController();
RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).LinearVelocity.set(Velocity);
RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).AngularVelocity.set(AngularVelocity);
if(actorType.equals("PlayerActor")){
RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).LockRotation();
}
scene.AddActor(Target);
break;
case 6:
if(!packet.TargetID.equals(ConnectedClients.get(packet.ClientID).OwnedActorID)) {
return;
}
MovementUpdate = Packet.DecodeAsMovementUpdate(packet.Data);
Target.SetNewRotation(MovementUpdate.Rotation);
Target.SetNewPosition(MovementUpdate.Position);
Target.SetNewVelocity(MovementUpdate.LinearVelocity);
Target.SetNewAngularVelocity(MovementUpdate.AngularVelocity);
break;
}
iter.remove();
}
}
}
public static Packet CreateActorPacket(Actor actor){
Packet newOutgoingPacket = new Packet(Packet.PACKET_CREATE_ACTOR);
newOutgoingPacket.SetTargetType((byte) 0);
RigidPhysicsController physicsController = (RigidPhysicsController) actor.GetPhysicsController();
if(physicsController == null) return null;
RigidBody rigidBody = RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID);
if(rigidBody == null) return null;
String actorType = actor instanceof PlayerActor ? "PlayerActor" : "Actor";
StringBuilder OutgoingData = new StringBuilder(actorType)
.append(":")
.append(actor.GetModelID());
System.out.println("Creating actor packet: actorID=" + actor.GetID() + " modelID=" + actor.GetModelID() + " type=" + actorType);
Vector3f Position = rigidBody.Position;
Quaternionf Rotation = rigidBody.Rotation;
Vector3f Scale = actor.GetScale();
Vector3f ColliderBox = rigidBody.shape.hxhyhz;
float MassKG = rigidBody.MassKG;
Vector3f LinearVelocity = rigidBody.LinearVelocity;
Vector3f AngularVelocity = rigidBody.AngularVelocity;
Vector3f PositionOffset = actor.GetPositionOffset();
Vector3f CameraOffset = new Vector3f();
if(actor instanceof PlayerActor playerActor) {
CameraOffset.set(playerActor.CameraOffset);
}
float[] floats = new float[]{
Position.x, Position.y, Position.z,
Rotation.x, Rotation.y, Rotation.z, Rotation.w,
Scale.x, Scale.y, Scale.z,
ColliderBox.x, ColliderBox.y, ColliderBox.z,
MassKG,
LinearVelocity.x, LinearVelocity.y, LinearVelocity.z,
AngularVelocity.x, AngularVelocity.y, AngularVelocity.z,
PositionOffset.x, PositionOffset.y, PositionOffset.z,
CameraOffset.x, CameraOffset.y, CameraOffset.z
};
for(int i = 0; i < floats.length; i++){
OutgoingData.append(":").append(floats[i]);
}
newOutgoingPacket.SetData(OutgoingData.toString().getBytes(StandardCharsets.UTF_8));
newOutgoingPacket.SetID(actor.GetID());
return newOutgoingPacket;
}
public static void BroadcastCreateActorPacket(Actor actor) {
Packet newOutgoingPacket = CreateActorPacket(actor);
if(newOutgoingPacket != null)Server.OutGoingPacketQueue.add(newOutgoingPacket);
}
public static Packet CreateDestroyActorPacket(String actorID){
Packet packet = new Packet(Packet.PACKET_DESTROY_ACTOR);
packet.SetTargetType((byte) 0);
packet.SetData(new byte[0]);
packet.SetID(actorID);
return packet;
}
public static void BroadcastDestroyActorPacket(String actorID){
Server.OutGoingPacketQueue.add(CreateDestroyActorPacket(actorID));
}
public void DestroyOwnedActor(){
if(OwnedActorID == null) return;
Actor actor = Actor.Actors.get(OwnedActorID);
if(actor != null){
PrimaryRuntime.GetEngineInstance().scene().RemoveActor(actor);
BroadcastDestroyActorPacket(OwnedActorID);
}
OwnedActorID = null;
}
public static void SendEntityUpdatePacket(Actor actor){
Packet newOutgoingPacket = new Packet((byte)6);
newOutgoingPacket.SetTargetType((byte) 0);
RigidPhysicsController physicsController = (RigidPhysicsController) actor.GetPhysicsController();
if(physicsController == null) return;
RigidBody rigidBody = RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID);
if(rigidBody == null) return;
newOutgoingPacket.SetData(Packet.EncodeMovementData(rigidBody.Position,rigidBody.Rotation,rigidBody.LinearVelocity,rigidBody.AngularVelocity));
newOutgoingPacket.SetID(actor.GetID());
Server.OutGoingPacketQueue.add(newOutgoingPacket);
}
public int readPacket(DataInputStream in) throws IOException {
if(in == null) return 0;
Packet newIncomingPacket = new Packet(in.readByte());
if(newIncomingPacket.PacketTypeByte == 5) {
return 5;
}
newIncomingPacket.SetTargetType(in.readByte());
int DataLength = in.readInt();
byte[] IncomingData = new byte[DataLength];
in.readFully(IncomingData);
newIncomingPacket.Data = IncomingData;
int IDLength = in.readInt();
byte[] IDData = new byte[IDLength];
in.readFully(IDData);
String ID = new String(IDData, StandardCharsets.UTF_8);
newIncomingPacket.SetID(ID);
newIncomingPacket.ClientID = ClientID;
IncomingPacketQueue.add(newIncomingPacket);
return 0;
}
public static void WritePacket(Packet outPacket, DataOutputStream Outgoing) throws IOException {
if(Outgoing == null ) return;
byte[] DataToSend = Packet.GetOutgoingData(outPacket);
Outgoing.write(DataToSend);
}
}

View file

@ -1,5 +1,4 @@
writer = file writer = file
writer.file = LastSession.t4jlog
writer.format = {date: DD:MM:YYYY} {date: HH:mm:ss.SSS} {level}: {message} writer.format = {date: DD:MM:YYYY} {date: HH:mm:ss.SSS} {level}: {message}
writer.level = trace writer.level = trace
writingthread = true writingthread = true

View file

@ -11,8 +11,8 @@ display_width=640
#Engine Core Settings #Engine Core Settings
#the precision of frames, set this to 16000000, and it will limit the whole engine to 64FPS #the precision of frames, set this to 16000000, and it will limit the whole engine to 64FPS
frame_accuracy=0 frame_accuracy=0
throttle_on_unfocus=true throttle_on_unfocus=false
throttle_accuracy=100000000 throttle_accuracy=4000000
#event tick rate for game process #event tick rate for game process
master_tick_rate=240 master_tick_rate=240
main_thread_tickrate=120 main_thread_tickrate=120