From bf11da6799abaf0a8a0cc3423c756dc84b5dc35e Mon Sep 17 00:00:00 2001 From: Halbear Date: Sat, 11 Jul 2026 15:27:06 +0100 Subject: [PATCH] Shooting --- ServerLog.t4jlog | 314 +++++++++--------- .../audio/sounds/BulletHit1.ogg | Bin 0 -> 20223 bytes .../audio/sounds/BulletHit2.ogg | Bin 0 -> 11741 bytes .../Logic/Physics/WorldPhysicsManager.java | 2 +- .../Terrain4J/EngineCore/Main/GameCore.java | 6 +- .../EngineCore/Main/Scene/Scene.java | 4 +- .../EngineCore/Main/Util/Maths/T4Raycast.java | 62 ++++ .../EngineCore/ServerNetworking/Packet.java | 54 +++ .../Threads/ClientConnectionThread.java | 29 ++ .../Threads/ServerConnectionThread.java | 35 ++ 10 files changed, 343 insertions(+), 163 deletions(-) create mode 100644 resources/EngineResources/audio/sounds/BulletHit1.ogg create mode 100644 resources/EngineResources/audio/sounds/BulletHit2.ogg create mode 100644 src/main/java/net/halbear/Terrain4J/EngineCore/Main/Util/Maths/T4Raycast.java diff --git a/ServerLog.t4jlog b/ServerLog.t4jlog index 2c4c10c..f3281da 100644 --- a/ServerLog.t4jlog +++ b/ServerLog.t4jlog @@ -1,163 +1,163 @@ -192:07:2026 01:57:48.537 INFO: +192:07:2026 04:32:52.087 INFO: Launching New Terrain4J Powered Software! -192:07:2026 01:57:48.542 DEBUG: File [terrain4j.properties] read -192:07:2026 01:57:48.546 DEBUG: +192:07:2026 04:32:52.092 DEBUG: File [terrain4j.properties] read +192:07:2026 04:32:52.095 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} -192:07:2026 01:57:48.599 DEBUG: Loading Models From [resources/models/cube/Cube.json] -192:07:2026 01:57:48.646 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]] -192:07:2026 01:57:48.646 DEBUG: Loading Materials From [resources/models/cube/Cube_mat.json] -192:07:2026 01:57:48.657 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]]] -192:07:2026 01:57:48.657 DEBUG: Loading Models From [resources/models/VisualCollision/CollisionCube.json] -192:07:2026 01:57:48.658 DEBUG: Loaded Model Data: [ModelData[ID=CollisionCube, Meshes=[MeshData[ID=mesh_0, MaterialID=CollisionCube-mat-1, OffsetVertex=0, VertexSize=1344, OffsetIndex=0, IndexSize=144]], VertexPath=resources/models/VisualCollision/CollisionCube.vtx, IndexPath=resources/models/VisualCollision/CollisionCube.idx]] -192:07:2026 01:57:48.659 DEBUG: Loading Materials From [resources/models/VisualCollision/CollisionCube_mat.json] -192:07:2026 01:57:48.660 DEBUG: Loaded Material Data: [[MaterialData[ID=CollisionCube-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=CollisionCube-mat-1, TexturePath=resources\models\VisualCollision\CollisionCubeTexture.png, NormalTexturePath=, MetalRoughnessMap=, DiffuseColour=( 6.000E-1 6.000E-1 6.000E-1 1.000E+0), Roughness=0.0, Metallic=0.0], MaterialData[ID=CollisionCube-mat-2, TexturePath=, NormalTexturePath=, MetalRoughnessMap=, DiffuseColour=( 6.000E-1 6.000E-1 6.000E-1 1.000E+0), Roughness=0.0, Metallic=0.0]]] -192:07:2026 01:57:48.660 DEBUG: Loading Models From [resources/models/melona/melona.json] -192:07:2026 01:57:48.661 DEBUG: Loaded Model Data: [ModelData[ID=melona, Meshes=[MeshData[ID=m_6d7d0384-980c-6574-37d9-8a8b11a5fdda_0, MaterialID=melona-mat-1, OffsetVertex=0, VertexSize=24192, OffsetIndex=0, IndexSize=2640], MeshData[ID=none_1, MaterialID=melona-mat-2, OffsetVertex=24192, VertexSize=672, OffsetIndex=2640, IndexSize=96]], VertexPath=resources/models/melona/melona.vtx, IndexPath=resources/models/melona/melona.idx]] -192:07:2026 01:57:48.661 DEBUG: Loading Materials From [resources/models/melona/melona_mat.json] -192:07:2026 01:57:48.662 DEBUG: Loaded Material Data: [[MaterialData[ID=melona-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=melona-mat-1, TexturePath=resources\models\melona\Melonamodel.png, NormalTexturePath=, MetalRoughnessMap=, DiffuseColour=( 6.000E-1 6.000E-1 6.000E-1 1.000E+0), Roughness=0.0, Metallic=0.0], MaterialData[ID=melona-mat-2, TexturePath=, NormalTexturePath=, MetalRoughnessMap=, DiffuseColour=( 6.000E-1 6.000E-1 6.000E-1 1.000E+0), Roughness=0.0, Metallic=0.0]]] -192:07:2026 01:57:48.662 DEBUG: Loading Models From [resources/models/musket/musket.json] -192:07:2026 01:57:48.663 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]] -192:07:2026 01:57:48.663 DEBUG: Loading Materials From [resources/models/musket/musket_mat.json] -192:07:2026 01:57:48.665 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]]] -192:07:2026 01:57:48.665 DEBUG: Loading Models From [resources/models/Revolver/Revolver.json] -192:07:2026 01:57:48.666 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]] -192:07:2026 01:57:48.666 DEBUG: Loading Materials From [resources/models/Revolver/Revolver_mat.json] -192:07:2026 01:57:48.668 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]]] -192:07:2026 01:57:48.668 DEBUG: Loading Models From [resources/models/Flintlock/Flintlock.json] -192:07:2026 01:57:48.668 DEBUG: Loaded Model Data: [ModelData[ID=Flintlock, Meshes=[MeshData[ID=cube_0, MaterialID=Flintlock-mat-1, OffsetVertex=0, VertexSize=19936, OffsetIndex=0, IndexSize=2160]], VertexPath=resources/models/Flintlock/Flintlock.vtx, IndexPath=resources/models/Flintlock/Flintlock.idx]] -192:07:2026 01:57:48.668 DEBUG: Loading Materials From [resources/models/Flintlock/Flintlock_mat.json] -192:07:2026 01:57:48.669 DEBUG: Loaded Material Data: [[MaterialData[ID=Flintlock-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=Flintlock-mat-1, TexturePath=resources\models\Flintlock\Flintlock.png, NormalTexturePath=, MetalRoughnessMap=, DiffuseColour=( 6.000E-1 6.000E-1 6.000E-1 1.000E+0), Roughness=0.0, Metallic=0.0], MaterialData[ID=Flintlock-mat-2, TexturePath=, NormalTexturePath=, MetalRoughnessMap=, DiffuseColour=( 6.000E-1 6.000E-1 6.000E-1 1.000E+0), Roughness=0.0, Metallic=0.0]]] -192:07:2026 01:57:48.673 INFO: Spawning static cube actor [MelonaSpawned0] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.694 INFO: Spawning static cube actor [MelonaSpawned1] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.694 INFO: Spawning static cube actor [MelonaSpawned2] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.694 INFO: Spawning static cube actor [MelonaSpawned3] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.694 INFO: Spawning static cube actor [MelonaSpawned4] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.695 INFO: Spawning static cube actor [MelonaSpawned5] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.695 INFO: Spawning static cube actor [MelonaSpawned6] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.695 INFO: Spawning static cube actor [MelonaSpawned7] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.695 INFO: Spawning static cube actor [MelonaSpawned8] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.695 INFO: Spawning static cube actor [MelonaSpawned9] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.695 INFO: Spawning static cube actor [MelonaSpawned10] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.695 INFO: Spawning static cube actor [MelonaSpawned11] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.696 INFO: Spawning static cube actor [MelonaSpawned12] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.696 INFO: Spawning static cube actor [MelonaSpawned13] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.696 INFO: Spawning static cube actor [MelonaSpawned14] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.696 INFO: Spawning static cube actor [MelonaSpawned15] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.696 INFO: Spawning static cube actor [MelonaSpawned16] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.696 INFO: Spawning static cube actor [MelonaSpawned17] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.696 INFO: Spawning static cube actor [MelonaSpawned18] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.696 INFO: Spawning static cube actor [MelonaSpawned19] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.697 INFO: Spawning static cube actor [MelonaSpawned20] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.697 INFO: Spawning static cube actor [MelonaSpawned21] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.697 INFO: Spawning static cube actor [MelonaSpawned22] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.697 INFO: Spawning static cube actor [MelonaSpawned23] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.697 INFO: Spawning static cube actor [MelonaSpawned24] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.697 INFO: Spawning static cube actor [MelonaSpawned25] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.697 INFO: Spawning static cube actor [MelonaSpawned26] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.698 INFO: Spawning static cube actor [MelonaSpawned27] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.698 INFO: Spawning static cube actor [MelonaSpawned28] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.698 INFO: Spawning static cube actor [MelonaSpawned29] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.698 INFO: Spawning static cube actor [MelonaSpawned30] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.698 INFO: Spawning static cube actor [MelonaSpawned31] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.698 INFO: Spawning static cube actor [MelonaSpawned32] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.698 INFO: Spawning static cube actor [MelonaSpawned33] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.698 INFO: Spawning static cube actor [MelonaSpawned34] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.698 INFO: Spawning static cube actor [MelonaSpawned35] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.698 INFO: Spawning static cube actor [MelonaSpawned36] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.698 INFO: Spawning static cube actor [MelonaSpawned37] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.698 INFO: Spawning static cube actor [MelonaSpawned38] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.698 INFO: Spawning static cube actor [MelonaSpawned39] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.699 INFO: Spawning static cube actor [MelonaSpawned40] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.699 INFO: Spawning static cube actor [MelonaSpawned41] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.699 INFO: Spawning static cube actor [MelonaSpawned42] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.699 INFO: Spawning static cube actor [MelonaSpawned43] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.699 INFO: Spawning static cube actor [MelonaSpawned44] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.699 INFO: Spawning static cube actor [MelonaSpawned45] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.699 INFO: Spawning static cube actor [MelonaSpawned46] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.699 INFO: Spawning static cube actor [MelonaSpawned47] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.699 INFO: Spawning static cube actor [MelonaSpawned48] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.699 INFO: Spawning static cube actor [MelonaSpawned49] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.699 INFO: Spawning static cube actor [MelonaSpawned50] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.699 INFO: Spawning static cube actor [MelonaSpawned51] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.699 INFO: Spawning static cube actor [MelonaSpawned52] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.699 INFO: Spawning static cube actor [MelonaSpawned53] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.700 INFO: Spawning static cube actor [MelonaSpawned54] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.700 INFO: Spawning static cube actor [MelonaSpawned55] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.700 INFO: Spawning static cube actor [MelonaSpawned56] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.700 INFO: Spawning static cube actor [MelonaSpawned57] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.700 INFO: Spawning static cube actor [MelonaSpawned58] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.700 INFO: Spawning static cube actor [MelonaSpawned59] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.700 INFO: Spawning static cube actor [MelonaSpawned60] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.700 INFO: Spawning static cube actor [MelonaSpawned61] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.700 INFO: Spawning static cube actor [MelonaSpawned62] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.700 INFO: Spawning static cube actor [MelonaSpawned63] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.700 INFO: Spawning static cube actor [MelonaSpawned64] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.701 INFO: Spawning static cube actor [MelonaSpawned65] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.701 INFO: Spawning static cube actor [MelonaSpawned66] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.701 INFO: Spawning static cube actor [MelonaSpawned67] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.701 INFO: Spawning static cube actor [MelonaSpawned68] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.701 INFO: Spawning static cube actor [MelonaSpawned69] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.701 INFO: Spawning static cube actor [MelonaSpawned70] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.701 INFO: Spawning static cube actor [MelonaSpawned71] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.701 INFO: Spawning static cube actor [MelonaSpawned72] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.702 INFO: Spawning static cube actor [MelonaSpawned73] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.702 INFO: Spawning static cube actor [MelonaSpawned74] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.702 INFO: Spawning static cube actor [MelonaSpawned75] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.702 INFO: Spawning static cube actor [MelonaSpawned76] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.702 INFO: Spawning static cube actor [MelonaSpawned77] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.702 INFO: Spawning static cube actor [MelonaSpawned78] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.702 INFO: Spawning static cube actor [MelonaSpawned79] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.702 INFO: Spawning static cube actor [MelonaSpawned80] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.702 INFO: Spawning static cube actor [MelonaSpawned81] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.702 INFO: Spawning static cube actor [MelonaSpawned82] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.702 INFO: Spawning static cube actor [MelonaSpawned83] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.703 INFO: Spawning static cube actor [MelonaSpawned84] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.703 INFO: Spawning static cube actor [MelonaSpawned85] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.703 INFO: Spawning static cube actor [MelonaSpawned86] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.703 INFO: Spawning static cube actor [MelonaSpawned87] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.704 INFO: Spawning static cube actor [MelonaSpawned88] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.704 INFO: Spawning static cube actor [MelonaSpawned89] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.704 INFO: Spawning static cube actor [MelonaSpawned90] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.704 INFO: Spawning static cube actor [MelonaSpawned91] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.704 INFO: Spawning static cube actor [MelonaSpawned92] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.704 INFO: Spawning static cube actor [MelonaSpawned93] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.704 INFO: Spawning static cube actor [MelonaSpawned94] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.704 INFO: Spawning static cube actor [MelonaSpawned95] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.704 INFO: Spawning static cube actor [MelonaSpawned96] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.704 INFO: Spawning static cube actor [MelonaSpawned97] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.704 INFO: Spawning static cube actor [MelonaSpawned98] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.704 INFO: Spawning static cube actor [MelonaSpawned99] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.705 INFO: Spawning static cube actor [MelonaSpawned100] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.705 INFO: Spawning static cube actor [MelonaSpawned101] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.705 INFO: Spawning static cube actor [MelonaSpawned102] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.705 INFO: Spawning static cube actor [MelonaSpawned103] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.705 INFO: Spawning static cube actor [MelonaSpawned104] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.705 INFO: Spawning static cube actor [MelonaSpawned105] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.705 INFO: Spawning static cube actor [MelonaSpawned106] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.705 INFO: Spawning static cube actor [MelonaSpawned107] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.705 INFO: Spawning static cube actor [MelonaSpawned108] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.705 INFO: Spawning static cube actor [MelonaSpawned109] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.705 INFO: Spawning static cube actor [MelonaSpawned110] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.705 INFO: Spawning static cube actor [MelonaSpawned111] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.705 INFO: Spawning static cube actor [MelonaSpawned112] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.705 INFO: Spawning static cube actor [MelonaSpawned113] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.705 INFO: Spawning static cube actor [MelonaSpawned114] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.705 INFO: Spawning static cube actor [MelonaSpawned115] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.705 INFO: Spawning static cube actor [MelonaSpawned116] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.705 INFO: Spawning static cube actor [MelonaSpawned117] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.705 INFO: Spawning static cube actor [MelonaSpawned118] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.706 INFO: Spawning static cube actor [MelonaSpawned119] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.706 INFO: Spawning static cube actor [MelonaSpawned120] with model ID [Cube], with cached ID of [Cube] -192:07:2026 01:57:48.709 DEBUG: Starting Main Thread -192:07:2026 01:57:48.710 DEBUG: Starting Fast Thread -192:07:2026 01:57:48.710 DEBUG: Starting Render Thread -192:07:2026 01:57:48.924 INFO: Launched Terrain4J Engine -192:07:2026 01:57:48.924 DEBUG: Primary Thread Started -192:07:2026 01:57:48.924 INFO: Terrain4J dedicated server running without GLFW/Vulkan/OpenAL -192:07:2026 01:57:48.924 DEBUG: Main Thread Started -192:07:2026 01:57:48.924 DEBUG: Render Thread Started -192:07:2026 01:57:48.924 DEBUG: Fast Thread Started +192:07:2026 04:32:52.148 DEBUG: Loading Models From [resources/models/cube/Cube.json] +192:07:2026 04:32:52.195 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]] +192:07:2026 04:32:52.195 DEBUG: Loading Materials From [resources/models/cube/Cube_mat.json] +192:07:2026 04:32:52.205 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]]] +192:07:2026 04:32:52.205 DEBUG: Loading Models From [resources/models/VisualCollision/CollisionCube.json] +192:07:2026 04:32:52.206 DEBUG: Loaded Model Data: [ModelData[ID=CollisionCube, Meshes=[MeshData[ID=mesh_0, MaterialID=CollisionCube-mat-1, OffsetVertex=0, VertexSize=1344, OffsetIndex=0, IndexSize=144]], VertexPath=resources/models/VisualCollision/CollisionCube.vtx, IndexPath=resources/models/VisualCollision/CollisionCube.idx]] +192:07:2026 04:32:52.207 DEBUG: Loading Materials From [resources/models/VisualCollision/CollisionCube_mat.json] +192:07:2026 04:32:52.208 DEBUG: Loaded Material Data: [[MaterialData[ID=CollisionCube-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=CollisionCube-mat-1, TexturePath=resources\models\VisualCollision\CollisionCubeTexture.png, NormalTexturePath=, MetalRoughnessMap=, DiffuseColour=( 6.000E-1 6.000E-1 6.000E-1 1.000E+0), Roughness=0.0, Metallic=0.0], MaterialData[ID=CollisionCube-mat-2, TexturePath=, NormalTexturePath=, MetalRoughnessMap=, DiffuseColour=( 6.000E-1 6.000E-1 6.000E-1 1.000E+0), Roughness=0.0, Metallic=0.0]]] +192:07:2026 04:32:52.208 DEBUG: Loading Models From [resources/models/melona/melona.json] +192:07:2026 04:32:52.209 DEBUG: Loaded Model Data: [ModelData[ID=melona, Meshes=[MeshData[ID=m_6d7d0384-980c-6574-37d9-8a8b11a5fdda_0, MaterialID=melona-mat-1, OffsetVertex=0, VertexSize=24192, OffsetIndex=0, IndexSize=2640], MeshData[ID=none_1, MaterialID=melona-mat-2, OffsetVertex=24192, VertexSize=672, OffsetIndex=2640, IndexSize=96]], VertexPath=resources/models/melona/melona.vtx, IndexPath=resources/models/melona/melona.idx]] +192:07:2026 04:32:52.209 DEBUG: Loading Materials From [resources/models/melona/melona_mat.json] +192:07:2026 04:32:52.209 DEBUG: Loaded Material Data: [[MaterialData[ID=melona-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=melona-mat-1, TexturePath=resources\models\melona\Melonamodel.png, NormalTexturePath=, MetalRoughnessMap=, DiffuseColour=( 6.000E-1 6.000E-1 6.000E-1 1.000E+0), Roughness=0.0, Metallic=0.0], MaterialData[ID=melona-mat-2, TexturePath=, NormalTexturePath=, MetalRoughnessMap=, DiffuseColour=( 6.000E-1 6.000E-1 6.000E-1 1.000E+0), Roughness=0.0, Metallic=0.0]]] +192:07:2026 04:32:52.210 DEBUG: Loading Models From [resources/models/musket/musket.json] +192:07:2026 04:32:52.210 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]] +192:07:2026 04:32:52.210 DEBUG: Loading Materials From [resources/models/musket/musket_mat.json] +192:07:2026 04:32:52.211 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]]] +192:07:2026 04:32:52.211 DEBUG: Loading Models From [resources/models/Revolver/Revolver.json] +192:07:2026 04:32:52.211 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]] +192:07:2026 04:32:52.211 DEBUG: Loading Materials From [resources/models/Revolver/Revolver_mat.json] +192:07:2026 04:32:52.212 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]]] +192:07:2026 04:32:52.212 DEBUG: Loading Models From [resources/models/Flintlock/Flintlock.json] +192:07:2026 04:32:52.213 DEBUG: Loaded Model Data: [ModelData[ID=Flintlock, Meshes=[MeshData[ID=cube_0, MaterialID=Flintlock-mat-1, OffsetVertex=0, VertexSize=19936, OffsetIndex=0, IndexSize=2160]], VertexPath=resources/models/Flintlock/Flintlock.vtx, IndexPath=resources/models/Flintlock/Flintlock.idx]] +192:07:2026 04:32:52.213 DEBUG: Loading Materials From [resources/models/Flintlock/Flintlock_mat.json] +192:07:2026 04:32:52.214 DEBUG: Loaded Material Data: [[MaterialData[ID=Flintlock-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=Flintlock-mat-1, TexturePath=resources\models\Flintlock\Flintlock.png, NormalTexturePath=, MetalRoughnessMap=, DiffuseColour=( 6.000E-1 6.000E-1 6.000E-1 1.000E+0), Roughness=0.0, Metallic=0.0], MaterialData[ID=Flintlock-mat-2, TexturePath=, NormalTexturePath=, MetalRoughnessMap=, DiffuseColour=( 6.000E-1 6.000E-1 6.000E-1 1.000E+0), Roughness=0.0, Metallic=0.0]]] +192:07:2026 04:32:52.217 INFO: Spawning static cube actor [MelonaSpawned0] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.237 INFO: Spawning static cube actor [MelonaSpawned1] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.237 INFO: Spawning static cube actor [MelonaSpawned2] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.237 INFO: Spawning static cube actor [MelonaSpawned3] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.237 INFO: Spawning static cube actor [MelonaSpawned4] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.237 INFO: Spawning static cube actor [MelonaSpawned5] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.237 INFO: Spawning static cube actor [MelonaSpawned6] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.237 INFO: Spawning static cube actor [MelonaSpawned7] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.237 INFO: Spawning static cube actor [MelonaSpawned8] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.238 INFO: Spawning static cube actor [MelonaSpawned9] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.238 INFO: Spawning static cube actor [MelonaSpawned10] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.238 INFO: Spawning static cube actor [MelonaSpawned11] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.238 INFO: Spawning static cube actor [MelonaSpawned12] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.239 INFO: Spawning static cube actor [MelonaSpawned13] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.239 INFO: Spawning static cube actor [MelonaSpawned14] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.239 INFO: Spawning static cube actor [MelonaSpawned15] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.239 INFO: Spawning static cube actor [MelonaSpawned16] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.239 INFO: Spawning static cube actor [MelonaSpawned17] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.239 INFO: Spawning static cube actor [MelonaSpawned18] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.239 INFO: Spawning static cube actor [MelonaSpawned19] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.239 INFO: Spawning static cube actor [MelonaSpawned20] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.240 INFO: Spawning static cube actor [MelonaSpawned21] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.240 INFO: Spawning static cube actor [MelonaSpawned22] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.240 INFO: Spawning static cube actor [MelonaSpawned23] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.240 INFO: Spawning static cube actor [MelonaSpawned24] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.240 INFO: Spawning static cube actor [MelonaSpawned25] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.240 INFO: Spawning static cube actor [MelonaSpawned26] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.240 INFO: Spawning static cube actor [MelonaSpawned27] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.240 INFO: Spawning static cube actor [MelonaSpawned28] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.240 INFO: Spawning static cube actor [MelonaSpawned29] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.241 INFO: Spawning static cube actor [MelonaSpawned30] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.241 INFO: Spawning static cube actor [MelonaSpawned31] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.241 INFO: Spawning static cube actor [MelonaSpawned32] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.241 INFO: Spawning static cube actor [MelonaSpawned33] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.241 INFO: Spawning static cube actor [MelonaSpawned34] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.241 INFO: Spawning static cube actor [MelonaSpawned35] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.241 INFO: Spawning static cube actor [MelonaSpawned36] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.241 INFO: Spawning static cube actor [MelonaSpawned37] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.241 INFO: Spawning static cube actor [MelonaSpawned38] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.242 INFO: Spawning static cube actor [MelonaSpawned39] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.242 INFO: Spawning static cube actor [MelonaSpawned40] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.242 INFO: Spawning static cube actor [MelonaSpawned41] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.242 INFO: Spawning static cube actor [MelonaSpawned42] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.242 INFO: Spawning static cube actor [MelonaSpawned43] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.242 INFO: Spawning static cube actor [MelonaSpawned44] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.242 INFO: Spawning static cube actor [MelonaSpawned45] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.242 INFO: Spawning static cube actor [MelonaSpawned46] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.242 INFO: Spawning static cube actor [MelonaSpawned47] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.243 INFO: Spawning static cube actor [MelonaSpawned48] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.243 INFO: Spawning static cube actor [MelonaSpawned49] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.243 INFO: Spawning static cube actor [MelonaSpawned50] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.243 INFO: Spawning static cube actor [MelonaSpawned51] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.243 INFO: Spawning static cube actor [MelonaSpawned52] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.243 INFO: Spawning static cube actor [MelonaSpawned53] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.243 INFO: Spawning static cube actor [MelonaSpawned54] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.243 INFO: Spawning static cube actor [MelonaSpawned55] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.243 INFO: Spawning static cube actor [MelonaSpawned56] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.243 INFO: Spawning static cube actor [MelonaSpawned57] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.243 INFO: Spawning static cube actor [MelonaSpawned58] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.244 INFO: Spawning static cube actor [MelonaSpawned59] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.244 INFO: Spawning static cube actor [MelonaSpawned60] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.244 INFO: Spawning static cube actor [MelonaSpawned61] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.244 INFO: Spawning static cube actor [MelonaSpawned62] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.244 INFO: Spawning static cube actor [MelonaSpawned63] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.244 INFO: Spawning static cube actor [MelonaSpawned64] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.244 INFO: Spawning static cube actor [MelonaSpawned65] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.244 INFO: Spawning static cube actor [MelonaSpawned66] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.244 INFO: Spawning static cube actor [MelonaSpawned67] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.244 INFO: Spawning static cube actor [MelonaSpawned68] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.244 INFO: Spawning static cube actor [MelonaSpawned69] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.244 INFO: Spawning static cube actor [MelonaSpawned70] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.245 INFO: Spawning static cube actor [MelonaSpawned71] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.245 INFO: Spawning static cube actor [MelonaSpawned72] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.245 INFO: Spawning static cube actor [MelonaSpawned73] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.245 INFO: Spawning static cube actor [MelonaSpawned74] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.245 INFO: Spawning static cube actor [MelonaSpawned75] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.245 INFO: Spawning static cube actor [MelonaSpawned76] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.245 INFO: Spawning static cube actor [MelonaSpawned77] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.245 INFO: Spawning static cube actor [MelonaSpawned78] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.245 INFO: Spawning static cube actor [MelonaSpawned79] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.245 INFO: Spawning static cube actor [MelonaSpawned80] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.245 INFO: Spawning static cube actor [MelonaSpawned81] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.245 INFO: Spawning static cube actor [MelonaSpawned82] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.245 INFO: Spawning static cube actor [MelonaSpawned83] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.246 INFO: Spawning static cube actor [MelonaSpawned84] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.246 INFO: Spawning static cube actor [MelonaSpawned85] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.246 INFO: Spawning static cube actor [MelonaSpawned86] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.246 INFO: Spawning static cube actor [MelonaSpawned87] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.246 INFO: Spawning static cube actor [MelonaSpawned88] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.246 INFO: Spawning static cube actor [MelonaSpawned89] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.246 INFO: Spawning static cube actor [MelonaSpawned90] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.246 INFO: Spawning static cube actor [MelonaSpawned91] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.246 INFO: Spawning static cube actor [MelonaSpawned92] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.246 INFO: Spawning static cube actor [MelonaSpawned93] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.247 INFO: Spawning static cube actor [MelonaSpawned94] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.247 INFO: Spawning static cube actor [MelonaSpawned95] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.247 INFO: Spawning static cube actor [MelonaSpawned96] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.247 INFO: Spawning static cube actor [MelonaSpawned97] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.247 INFO: Spawning static cube actor [MelonaSpawned98] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.247 INFO: Spawning static cube actor [MelonaSpawned99] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.247 INFO: Spawning static cube actor [MelonaSpawned100] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.247 INFO: Spawning static cube actor [MelonaSpawned101] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.247 INFO: Spawning static cube actor [MelonaSpawned102] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.247 INFO: Spawning static cube actor [MelonaSpawned103] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.247 INFO: Spawning static cube actor [MelonaSpawned104] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.247 INFO: Spawning static cube actor [MelonaSpawned105] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.247 INFO: Spawning static cube actor [MelonaSpawned106] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.248 INFO: Spawning static cube actor [MelonaSpawned107] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.248 INFO: Spawning static cube actor [MelonaSpawned108] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.248 INFO: Spawning static cube actor [MelonaSpawned109] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.248 INFO: Spawning static cube actor [MelonaSpawned110] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.248 INFO: Spawning static cube actor [MelonaSpawned111] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.248 INFO: Spawning static cube actor [MelonaSpawned112] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.248 INFO: Spawning static cube actor [MelonaSpawned113] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.248 INFO: Spawning static cube actor [MelonaSpawned114] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.248 INFO: Spawning static cube actor [MelonaSpawned115] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.248 INFO: Spawning static cube actor [MelonaSpawned116] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.248 INFO: Spawning static cube actor [MelonaSpawned117] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.248 INFO: Spawning static cube actor [MelonaSpawned118] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.248 INFO: Spawning static cube actor [MelonaSpawned119] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.248 INFO: Spawning static cube actor [MelonaSpawned120] with model ID [Cube], with cached ID of [Cube] +192:07:2026 04:32:52.252 DEBUG: Starting Main Thread +192:07:2026 04:32:52.252 DEBUG: Starting Fast Thread +192:07:2026 04:32:52.253 DEBUG: Starting Render Thread +192:07:2026 04:32:52.391 INFO: Launched Terrain4J Engine +192:07:2026 04:32:52.391 DEBUG: Primary Thread Started +192:07:2026 04:32:52.391 INFO: Terrain4J dedicated server running without GLFW/Vulkan/OpenAL +192:07:2026 04:32:52.391 DEBUG: Main Thread Started +192:07:2026 04:32:52.391 DEBUG: Render Thread Started +192:07:2026 04:32:52.391 DEBUG: Fast Thread Started diff --git a/resources/EngineResources/audio/sounds/BulletHit1.ogg b/resources/EngineResources/audio/sounds/BulletHit1.ogg new file mode 100644 index 0000000000000000000000000000000000000000..ade0702041713b219413aeaa1940a26515f63cf2 GIT binary patch literal 20223 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 literal 0 HcmV?d00001 diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Physics/WorldPhysicsManager.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Physics/WorldPhysicsManager.java index a994c16..aaf38c9 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Physics/WorldPhysicsManager.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Physics/WorldPhysicsManager.java @@ -150,7 +150,7 @@ public class WorldPhysicsManager { } - private static Actor GetActorForRigidBody(RigidBody body) { + public static Actor GetActorForRigidBody(RigidBody body) { for (Actor actor : Actor.Actors.values()) { if (!(actor.GetPhysicsController() instanceof RigidPhysicsController rigidPhysicsController)) { continue; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java index 49b6860..d0b2ec2 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java @@ -106,9 +106,9 @@ public class GameCore implements GameLogic { List RevolverMat = ModelLoader.LoadMaterials("resources/models/Revolver/Revolver_mat.json"); FlintlockData = ModelLoader.LoadModel("resources/models/Flintlock/Flintlock.json"); List FlintlockMat = ModelLoader.LoadMaterials("resources/models/Flintlock/Flintlock_mat.json"); - Item MusketItem = new Item(MusketData.ID(), 1.0f, 1, 10.0f); - Item RevolverItem = new Item(RevolverData.ID(), 4.0f, 6, 10.0f); - Item FlintLock = new Item(FlintlockData.ID(), 1.0f, 2, 10.0f); + Item MusketItem = new Item(MusketData.ID(), 1.0f, 1, 100.0f); + Item RevolverItem = new Item(RevolverData.ID(), 4.0f, 6, 100.0f); + Item FlintLock = new Item(FlintlockData.ID(), 1.0f, 2, 100.0f); scene.MusketItem = MusketItem; scene.RevolverItem = RevolverItem; scene.FlintLockItem = FlintLock; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Scene.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Scene.java index 5436c64..1d573af 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Scene.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Scene.java @@ -314,8 +314,8 @@ public class Scene implements IScene { float FireRate = 1000f/CurrentItem.FireRate(); if (NewTime - LastGunFire > 1_000_000f * FireRate ){ LastGunFire = NewTime; - ClientConnectionThread.FireWeapon(playerActor.ID, CurrentItem.Damage()); - MusketFireSFX.Play(); + ClientConnectionThread.FireWeapon(playerActor.PositionOffset, CurrentItem.Damage(), 100, camera, playerActor.ID); + // MusketFireSFX.Play(); } } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Util/Maths/T4Raycast.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Util/Maths/T4Raycast.java new file mode 100644 index 0000000..e045a23 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Util/Maths/T4Raycast.java @@ -0,0 +1,62 @@ +package net.halbear.Terrain4J.EngineCore.Main.Util.Maths; + +import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidBody; +import org.joml.Quaternionf; +import org.joml.Vector2f; +import org.joml.Vector3f; +import org.joml.primitives.AABBf; +import org.joml.primitives.Intersectionf; + +public class T4Raycast { + public static class Hit { + public final RigidBody Body; + public final Vector3f Point; + public final float Distance; + public Hit(RigidBody body, Vector3f point, float distance){ + Body = body; + Point = point; + Distance = distance; + } + } + + public static Hit Nearest(Vector3f origin, Vector3f direction, float maxRange, String excludeRigidBodyID){ + Vector3f dir = new Vector3f(direction).normalize(); + Vector3f scaledDir = new Vector3f(dir).mul(maxRange); + + RigidBody bestBody = null; + float bestT = 1f; + + for (String id : RigidBody.RigidBodies) { + if (excludeRigidBodyID != null && id.equals(excludeRigidBodyID)) continue; + RigidBody body = RigidBody.RigidBodyRegister.get(id); + if (body == null) continue; + + AABBf worldBounds = body.shape.GetWorldAABB(); + Vector2f coarse = new Vector2f(); + boolean coarseHit = Intersectionf.intersectRayAab(origin, scaledDir, + new Vector3f(worldBounds.minX, worldBounds.minY, worldBounds.minZ), + new Vector3f(worldBounds.maxX, worldBounds.maxY, worldBounds.maxZ), + coarse); + if (!coarseHit || coarse.x > bestT) continue; + + Vector3f localOrigin = new Vector3f(origin).sub(body.Position); + Vector3f localDir = new Vector3f(scaledDir); + Quaternionf inverseOrientation = body.shape.Orientation.conjugate(new Quaternionf()); + inverseOrientation.transform(localOrigin); + inverseOrientation.transform(localDir); + + Vector2f localT = new Vector2f(); + boolean hit = Intersectionf.intersectRayAab(localOrigin, localDir, body.shape.BottomLeftBack, body.shape.TopRightForward, localT); + if (!hit || localT.x < 0f || localT.x > 1f) continue; + + if (localT.x < bestT) { + bestT = localT.x; + bestBody = body; + } + } + + if (bestBody == null) return null; + Vector3f hitPoint = new Vector3f(origin).add(new Vector3f(scaledDir).mul(bestT)); + return new Hit(bestBody, hitPoint, bestT * maxRange); + } +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/ServerNetworking/Packet.java b/src/main/java/net/halbear/Terrain4J/EngineCore/ServerNetworking/Packet.java index 32dd888..bea50ee 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/ServerNetworking/Packet.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/ServerNetworking/Packet.java @@ -25,6 +25,7 @@ public class Packet { public static final byte PACKET_FIRE_WEAPON = 12; public static final byte PACKET_SEND_PLAYER_COUNT = 13; public static final byte PACKET_UPDATE_PLAYER_DISPLAY_NAME = 14; + public static final byte PACKET_FIRE_RESULT = 15; public byte PacketTypeByte; public byte TargetType; //0 Actor @@ -106,6 +107,59 @@ public class Packet { return Data; } + public static byte[] EncodeFireRequest(Vector3f origin, Vector3f direction, float damage, float maxRange){ + return EncodeFloats(new float[]{origin.x,origin.y,origin.z,direction.x,direction.y,direction.z,damage,maxRange}); + } + + public static DecodedFireRequest DecodeAsFireRequest(byte[] DataIn){ + ByteBuffer buffer = ByteBuffer.wrap(DataIn); + DecodedFireRequest request = new DecodedFireRequest(); + request.Origin = new Vector3f(buffer.getFloat(), buffer.getFloat(), buffer.getFloat()); + request.Direction = new Vector3f(buffer.getFloat(), buffer.getFloat(), buffer.getFloat()); + request.Damage = buffer.getFloat(); + request.MaxRange = buffer.getFloat(); + return request; + } + + public static byte[] EncodeFireResult(Vector3f origin, Vector3f hitPoint, boolean hit){ + return EncodeFloats(new float[]{origin.x,origin.y,origin.z,hitPoint.x,hitPoint.y,hitPoint.z, hit ? 1f : 0f}); + } + + public static DecodedFireResult DecodeAsFireResult(byte[] DataIn){ + ByteBuffer buffer = ByteBuffer.wrap(DataIn); + DecodedFireResult result = new DecodedFireResult(); + result.Origin = new Vector3f(buffer.getFloat(), buffer.getFloat(), buffer.getFloat()); + result.HitPoint = new Vector3f(buffer.getFloat(), buffer.getFloat(), buffer.getFloat()); + result.Hit = buffer.getFloat() > 0.5f; + return result; + } + + public static class DecodedFireRequest { + public Vector3f Origin; + public Vector3f Direction; + public float Damage; + public float MaxRange; + } + + public static class DecodedFireResult { + public Vector3f Origin; + public Vector3f HitPoint; + public boolean Hit; + } + + private static byte[] EncodeFloats(float[] floats){ + byte[] Data = new byte[floats.length * VulkanUtils.FLOAT_SIZE]; + int Offset = 0; + for(float value : floats){ + byte[] bytes = ByteBuffer.allocate(4).putFloat(value).array(); + for(byte b : bytes){ + Data[Offset] = b; + Offset++; + } + } + return Data; + } + public static Quaternionf DecodeAsQuaternation(byte[] DataIn){ Quaternionf newVector = new Quaternionf(); ByteBuffer buffer = ByteBuffer.wrap(DataIn); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/ClientConnectionThread.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/ClientConnectionThread.java index 0d61279..79ea579 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/ClientConnectionThread.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/ClientConnectionThread.java @@ -1,10 +1,12 @@ package net.halbear.Terrain4J.EngineCore.Threads; import net.halbear.Executable.Server; +import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; 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.AudioInstance; import net.halbear.Terrain4J.EngineCore.Main.GameCore; import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime; import net.halbear.Terrain4J.EngineCore.Main.Scene.*; @@ -254,6 +256,19 @@ public class ClientConnectionThread implements Runnable{ System.out.println("decoding UUID packet"); clientUUID = Packet.DecodeAsString(packet.Data); break; + case Packet.PACKET_FIRE_RESULT: + System.out.println("Fire Packet Recieved" ); + Packet.DecodedFireResult fireResult = Packet.DecodeAsFireResult(packet.Data); + AudioInstance FireInstance = new AudioInstance("resources/EngineResources/audio/sounds/MusketFire.ogg","GunFireInstance" + packet.TargetID, engineInstance.audioManager(),fireResult.Origin.x, fireResult.Origin.y, fireResult.Origin.z, false); + FireInstance.SetAudioType(AudioInstance.AudioType.WEAPONS); + FireInstance.SetVolume(EngineConfig.getInstance().WeaponVolume); + FireInstance.Play(); + double Rnd = Math.random(); + AudioInstance HitInstance = new AudioInstance(Rnd < 0.5 ? "resources/EngineResources/audio/sounds/BulletHit1.ogg" : "resources/EngineResources/audio/sounds/BulletHit2.ogg","GunHitInstance" + packet.TargetID, engineInstance.audioManager(),fireResult.HitPoint.x, fireResult.HitPoint.y, fireResult.HitPoint.z, false); + HitInstance.SetAudioType(AudioInstance.AudioType.WEAPONS); + HitInstance.SetVolume(EngineConfig.getInstance().WeaponVolume * 10f); + HitInstance.Play(); + break; } } } @@ -354,6 +369,20 @@ public class ClientConnectionThread implements Runnable{ Outgoing.write(DataToSend); } + public static void FireWeapon(Vector3f barrelLocalOffset, float damage, float maxRange, Camera camera, String ShooterID){ + Vector3f camRotation = camera.GetRotation(); + Quaternionf aimRotation = new Quaternionf().rotateYXZ(-camRotation.y, -camRotation.x, camRotation.z); + + Vector3f direction = aimRotation.transform(new Vector3f(0, 0, -1)); + Vector3f origin = new Vector3f(camera.GetPosition()); + /// .add(aimRotation.transform(new Vector3f(barrelLocalOffset), new Vector3f())); + System.out.println("Fire Packet being sent" ); + Packet packet = new Packet(Packet.PACKET_FIRE_WEAPON); + packet.SetID(ShooterID); + packet.SetData(Packet.EncodeFireRequest(origin, direction, damage, maxRange)); + ClientConnectionThread.OutGoingPacketQueue.add(packet); + } + @Override public void run() { try { diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/ServerConnectionThread.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/ServerConnectionThread.java index 040b694..9ab9bcd 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/ServerConnectionThread.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/ServerConnectionThread.java @@ -10,6 +10,7 @@ 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.Main.Util.Maths.T4Raycast; import net.halbear.Terrain4J.EngineCore.ServerNetworking.Packet; import org.joml.Quaternionf; import org.joml.Vector3f; @@ -22,6 +23,7 @@ import java.util.*; import java.util.concurrent.ConcurrentLinkedQueue; import static net.halbear.Executable.Server.ConnectedClients; +import static net.halbear.Terrain4J.EngineCore.Logic.Physics.WorldPhysicsManager.GetActorForRigidBody; public class ServerConnectionThread implements Runnable{ private String OwnedActorID; @@ -217,9 +219,42 @@ public class ServerConnectionThread implements Runnable{ return; } break; + case Packet.PACKET_FIRE_WEAPON: + HandleFireWeapon(packet); + break; } } + private static void HandleFireWeapon(Packet packet){ + Packet.DecodedFireRequest request = Packet.DecodeAsFireRequest(packet.Data); + + Actor shooter = Actor.Actors.get(packet.TargetID); + String excludeBodyID = null; + if (shooter != null && shooter.GetPhysicsController() instanceof RigidPhysicsController rpc) { + excludeBodyID = rpc.RigidBodyID; + } + + T4Raycast.Hit hit = T4Raycast.Nearest(request.Origin, request.Direction, request.MaxRange, excludeBodyID); + boolean didHit = hit != null; + String hitActorID = ""; + Vector3f resultPoint; + + if (didHit) { + resultPoint = hit.Point; + Vector3f impulse = new Vector3f(request.Direction).normalize().mul(request.Damage); + hit.Body.ApplyImpulse(impulse, hit.Point); + Actor hitActor = GetActorForRigidBody(hit.Body); + if (hitActor != null) hitActorID = hitActor.GetID(); + } else { + resultPoint = new Vector3f(request.Direction).normalize().mul(request.MaxRange).add(request.Origin); + } + + Packet result = new Packet(Packet.PACKET_FIRE_RESULT); + result.SetID(hitActorID); + result.SetData(Packet.EncodeFireResult(request.Origin, resultPoint, didHit)); + Server.OutGoingPacketQueue.add(result); + } + public boolean OwnsActor(String actorID){ return OwnedActorID != null && OwnedActorID.equals(actorID); }