diff --git a/.gitignore b/.gitignore index 8f41756..6a655bd 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,4 @@ .godot/ rust/target godot/jolt -venv +godot_tools diff --git a/Makefile b/Makefile index f59b0de..3111991 100644 --- a/Makefile +++ b/Makefile @@ -18,3 +18,17 @@ rust_build: rust_fmt: cd rust && cargo fmt + + +GODOT_TOOLS ?= $(shell pwd)/godot_tools + +godot_tools: + test -s $(GODOT_TOOLS)/bin/activate || python3 -m venv $(GODOT_TOOLS) + source $(GODOT_TOOLS)/bin/activate &&\ + python3 -m pip install "gdtoolkit==4.*" + +godot_lint: godot_tools + $(GODOT_TOOLS)/bin/gdlint ./godot + +godot_fmt: godot_tools + $(GODOT_TOOLS)/bin/gdformat ./godot diff --git a/docs/docs/game_root.md b/docs/docs/game_root.md new file mode 100644 index 0000000..6902e02 --- /dev/null +++ b/docs/docs/game_root.md @@ -0,0 +1,18 @@ +# EntryPoint + +The `EntryPoint` is kind of second root in the `Tree`. We're using it to structure all the game components and impleent the game loading logic + +Structure: + +``` +EntryPoint +├── LevelPlacehoder +└── MainMenu +``` + +`EntryPoint` should also be aware of the launch mode. The game can be started in two modes: + +- Default game mode +- Dedicated server mode + +Depending on the mode, `EntryPoint` should be able to either read the config and run the dedicated server, or run the game diff --git a/docs/docs/multiplayer_design.md b/docs/docs/multiplayer_design.md new file mode 100644 index 0000000..2f405b0 --- /dev/null +++ b/docs/docs/multiplayer_design.md @@ -0,0 +1,15 @@ +# Multiplayer Design + +The server is responsible of holding all the information about all the players. Once the server is loaded it should have a current map set as one of the properties that will be sent to all the connected clients. We are not using the Godot built-in Multiplayer objects as they seem to be uncapable of handling big scenes and we need to implement our own logic for handling player movement anyway, so the built-in objects will be only interfering and we will have to find workarounds. + +# Level loading + +Once the server is created, it's waiting for the requests from the clients. It's aware of the map that is laoded and also should be aware of the checksum of the loaded map to make it possible to verify the map on the client side. + +When a client is connected it should be added to the `Dictionary` that holds the data about all the players. and also it should receive the copy of the current server data, so its instance can load the desired map and place other players there. + +Each client should have 'its' node on the server that would represent client's position, rotation, velocity, etc. Only the server should be able to modify it's properties, and hence clients must send the data in order to make server aware of their descisions. + +Each client should have a node that would reflect its server node. It should listen to the inputs and send the input data to the server in order to make the server node instance move. Once it's moved on the server, server will send it's new position/transfotm/... to the client via RPC, so all the clients are in sync. + +Every player mode but the client's one should end up in the model that is representing the player's model. It should exist in the client's local space, since theses nodes should move smoothly, we need to process the logic on the client's side. From time to time we need to sync its position to the corresponding `ServerNode`, that same applies to the `PlayerNode` diff --git a/godot/project.godot b/godot/project.godot index 7718442..440d163 100644 --- a/godot/project.godot +++ b/godot/project.godot @@ -12,16 +12,10 @@ config_version=5 config/name="Killbox" config/version="0.1.0" -run/main_scene="res://scenes/utils/game_root/game_root.tscn" +run/main_scene="res://src/entrypoint.tscn" config/features=PackedStringArray("4.3", "Forward Plus") config/icon="res://icon.svg" -[autoload] - -helpers="*res://scenes/helpers/functions.gd" -consts="*res://scenes/helpers/consts.gd" -logger="*res://scenes/helpers/logger.gd" - [display] window/size/mode=4 diff --git a/godot/rust_bindings.gdextension b/godot/rust_bindings.gdextension index d3400dd..dfb76ff 100644 --- a/godot/rust_bindings.gdextension +++ b/godot/rust_bindings.gdextension @@ -4,11 +4,11 @@ compatibility_minimum = 4.1 reloadable = true [libraries] -linux.debug.x86_64 = "res://../rust/target/debug/libopen_strike_2.so" -linux.release.x86_64 = "res://../rust/target/release/libopen_strike_2.so" -windows.debug.x86_64 = "res://../rust/target/debug/open_strike_2.dll" -windows.release.x86_64 = "res://../rust/target/release/open_strike_2.dll" -macos.debug = "res://../rust/target/debug/libopen_strike_2.dylib" -macos.release = "res://../rust/target/release/libopen_strike_2.dylib" -macos.debug.arm64 = "res://../rust/target/debug/libopen_strike_2.dylib" -macos.release.arm64 = "res://../rust/target/release/libopen_strike_2.dylib" +linux.debug.x86_64 = "res://../rust/target/debug/libkillbox.so" +linux.release.x86_64 = "res://../rust/target/release/libkillbox.so" +windows.debug.x86_64 = "res://../rust/target/debug/killbox.dll" +windows.release.x86_64 = "res://../rust/target/release/killbox.dll" +macos.debug = "res://../rust/target/debug/libkillbox.dylib" +macos.release = "res://../rust/target/release/libkillbox.dylib" +macos.debug.arm64 = "res://../rust/target/debug/libkillbox.dylib" +macos.release.arm64 = "res://../rust/target/release/libkillbox.dylib" diff --git a/godot/src/entrypoint.gd b/godot/src/entrypoint.gd new file mode 100644 index 0000000..6547ffc --- /dev/null +++ b/godot/src/entrypoint.gd @@ -0,0 +1,32 @@ +extends EntryPoint + +# -- A path to the config file for setting up the dedicated server +var config_file_path: String = "" + +# -- Called when the node enters the scene tree for the first time. +func _ready() -> void: + parse_args() + + if OS.has_feature("dedicated_server") or DisplayServer.get_name() == "headless": + var err := start_dedicated_server() + if err != OK: + push_error("Couldn't start the dedicated server, err: " + str(err)) + else: + var err := start_game() + if err != OK: + push_error("Couldn't start the game, err: " + str(err)) + +# -- Parse command line arguments +func parse_args() -> void: + var args := Array(OS.get_cmdline_args()) + var config_arg: String = "--config" + if args.has(config_arg): + var index := args.find(config_arg) + config_file_path = args[index + 1] + +func start_dedicated_server() -> Error: + push_error("Dedicated server is not yet implemented") + return ERR_METHOD_NOT_FOUND + +func start_game() -> Error: + return OK diff --git a/godot/src/entrypoint.tscn b/godot/src/entrypoint.tscn new file mode 100644 index 0000000..89fa199 --- /dev/null +++ b/godot/src/entrypoint.tscn @@ -0,0 +1,9 @@ +[gd_scene load_steps=2 format=3 uid="uid://0hsqnr1kunv5"] + +[ext_resource type="Script" path="res://src/entrypoint.gd" id="1_ce80t"] + +[node name="Entrypoint" type="EntryPoint"] +script = ExtResource("1_ce80t") + +[node name="LevelPlaceholder" type="Node3D" parent="."] +editor_description = "This node should be used for storing the map that is currently loaded" diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 08c7816..666648c 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -11,12 +11,91 @@ dependencies = [ "memchr", ] +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +dependencies = [ + "anstyle", + "once_cell", + "windows-sys", +] + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "env_filter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + [[package]] name = "gdextension-api" version = "0.2.1" @@ -135,12 +214,39 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "killbox" +version = "0.1.0" +dependencies = [ + "env_logger", + "godot", + "log", +] + [[package]] name = "libc" version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +[[package]] +name = "log" +version = "0.4.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" + [[package]] name = "memchr" version = "2.7.4" @@ -163,11 +269,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e943b2c21337b7e3ec6678500687cdc741b7639ad457f234693352075c082204" [[package]] -name = "open-strike-2" -version = "0.1.0" -dependencies = [ - "godot", -] +name = "once_cell" +version = "1.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" [[package]] name = "paste" @@ -239,6 +344,12 @@ version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" version = "1.12.1" @@ -263,3 +374,76 @@ name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index f62c96c..c59cc9a 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,10 +1,12 @@ [package] -name = "open-strike-2" +name = "killbox" version = "0.1.0" edition = "2021" [dependencies] +env_logger = "0.11.6" godot = "0.2.3" +log = "0.4.25" [lib] crate-type = ["cdylib"] diff --git a/rust/src/entrypoint.rs b/rust/src/entrypoint.rs new file mode 100644 index 0000000..0df8f49 --- /dev/null +++ b/rust/src/entrypoint.rs @@ -0,0 +1,23 @@ +use godot::classes::{INode, Node}; +use godot::prelude::*; +use std; + +#[derive(GodotClass)] +#[class(base=Node)] +// EntryPoint should decide whether the game should be launched in the +// server or the playing mode and load corresponding resources +struct EntryPoint { + base: Base, +} + +#[godot_api] +impl INode for EntryPoint { + fn init(base: Base) -> Self { + Self { base } + } + + fn ready(&mut self) {} +} + +#[godot_api] +impl EntryPoint {} diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 154228e..bffcdfb 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -5,6 +5,7 @@ struct MyExtension; mod player; //mod server; mod globals; +mod entrypoint; #[gdextension] unsafe impl ExtensionLibrary for MyExtension {} diff --git a/rust/src/server/game_server.rs b/rust/src/server/game_server.rs index 972b5b8..c57d882 100644 --- a/rust/src/server/game_server.rs +++ b/rust/src/server/game_server.rs @@ -13,68 +13,16 @@ use super::player_data::PlayerData; #[class(base=Node)] struct GameServer { base: Base, - #[export] - port: i32, - #[export] - player_limit: i32, - #[export] - current_map: GString, - #[export] - current_player_data: Gd, - #[export] - pub(crate) players: Dictionary } #[godot_api] impl INode for GameServer { fn init(base: Base) -> Self { - let players = Dictionary::new(); - Self { - base, - players, - port: 27015, - player_limit: 10, - current_map: "lowpoly_tdm_2".into(), - current_player_data: PlayerData::new_gd(), - } + Self { base } } - fn ready(&mut self) { - if let Some(multiplayer) = self.base().get_multiplayer() { - let on_connected = multiplayer.callable("peer_connected"); - self.base_mut().connect("on_player_connected", &on_connected); - } - } + fn ready(&mut self) {} } #[godot_api] -impl GameServer { - // Signals - #[func] - fn on_player_connected(&mut self, id: i32) { - godot_print!("test"); - } - // Main methods - #[func] - fn create_server(&mut self, server_only: bool) { - let mut peer = ENetMultiplayerPeer::new_gd(); - let server = peer.create_server_ex(self.port) - .max_clients(self.player_limit) - .done(); - - if let Some(mut multiplayer) = self.base().get_multiplayer() { - let id = multiplayer.get_unique_id(); - multiplayer.set_multiplayer_peer(&peer); - let player = PlayerData::new_gd(); - self.players.set(id, player); - } - } - #[func] - fn join_server(&mut self, ip: GString, port: i32) { - let mut peer = ENetMultiplayerPeer::new_gd(); - peer.create_client(&ip, port); - if let Some(mut multiplayer) = self.base().get_multiplayer() { - multiplayer.set_multiplayer_peer(&peer); - } - } -} +impl GameServer {} diff --git a/godot/scenes/characters/character_wrapper.gd b/scenes_old_2/characters/character_wrapper.gd similarity index 94% rename from godot/scenes/characters/character_wrapper.gd rename to scenes_old_2/characters/character_wrapper.gd index 1909515..b8f4170 100644 --- a/godot/scenes/characters/character_wrapper.gd +++ b/scenes_old_2/characters/character_wrapper.gd @@ -13,6 +13,7 @@ var previous_position: Vector3 = Vector3.ZERO var previous_rotation: Quaternion = Quaternion.IDENTITY var pseudo_velocity: Vector3 = Vector3.ZERO # Approximate velocity without CharacterBody3D + func _physics_process(delta: float) -> void: var server_pos = owner_placeholder.global_transform.origin var server_rot = owner_placeholder.global_transform.basis.get_rotation_quaternion() @@ -26,7 +27,10 @@ func _physics_process(delta: float) -> void: position_buffer.append([Time.get_ticks_msec() / 1000.0, server_pos, server_rot]) # Remove old positions to keep buffer clean - while position_buffer.size() > 2 and position_buffer[1][0] < (Time.get_ticks_msec() / 1000.0) - interpolation_delay: + while ( + position_buffer.size() > 2 + and position_buffer[1][0] < (Time.get_ticks_msec() / 1000.0) - interpolation_delay + ): position_buffer.pop_front() # Get current client position @@ -53,17 +57,20 @@ func _physics_process(delta: float) -> void: # Interpolate rotation using slerp var interpolated_rot = prev_point[2].slerp(next_point[2], alpha) - global_transform.basis = Basis(interpolated_rot) + global_transform.basis = Basis(interpolated_rot) + func _ready() -> void: set_multiplayer_authority(multiplayer.get_unique_id()) global_position = owner_placeholder.global_position - + + # Set the owner placeholder, so the characters can send the requests to a node # it depends on func set_owner_placeholder(owner_placeholder: Node3D): owner_placeholder = owner_placeholder - + + func die(): push_warning("TODO: Implement ragdoll kind of dying and respawn character as an object") queue_free() @@ -78,5 +85,6 @@ func _on_area_body_part_hit(damage: int) -> void: else: push_warning("Node doesn't know how to take the damage") + func is_vector_a_lower_than_b(vec_a: Vector3, vec_b: Vector3) -> bool: return vec_a.x < vec_b.x and vec_a.y < vec_b.y and vec_a.z < vec_b.z diff --git a/godot/scenes/characters/hit_detected.gd b/scenes_old_2/characters/hit_detected.gd similarity index 99% rename from godot/scenes/characters/hit_detected.gd rename to scenes_old_2/characters/hit_detected.gd index 6a2f1a4..ac7a477 100644 --- a/godot/scenes/characters/hit_detected.gd +++ b/scenes_old_2/characters/hit_detected.gd @@ -5,9 +5,11 @@ extends Area3D signal body_part_hit(damage: int) + func _ready() -> void: add_to_group("target") + func hit(base_damage: int): var final_damage = round(base_damage * damage_multiplexer) body_part_hit.emit(final_damage) diff --git a/godot/scenes/characters/y-bot/character.tscn b/scenes_old_2/characters/y-bot/character.tscn similarity index 100% rename from godot/scenes/characters/y-bot/character.tscn rename to scenes_old_2/characters/y-bot/character.tscn diff --git a/godot/scenes/helpers/consts.gd b/scenes_old_2/helpers/consts.gd similarity index 100% rename from godot/scenes/helpers/consts.gd rename to scenes_old_2/helpers/consts.gd diff --git a/godot/scenes/helpers/functions.gd b/scenes_old_2/helpers/functions.gd similarity index 96% rename from godot/scenes/helpers/functions.gd rename to scenes_old_2/helpers/functions.gd index 10f5595..5b1576d 100644 --- a/godot/scenes/helpers/functions.gd +++ b/scenes_old_2/helpers/functions.gd @@ -1,14 +1,18 @@ class_name Functions extends Node + func get_root_node() -> GameRoot: return get_tree().get_root().find_child("GameRoot", true, false) + func get_server_node() -> ServerData: return get_tree().get_root().find_child("ServerData", true, false) - + + func get_map_node() -> MapController: return get_tree().get_root().find_child("Map", true, false) + func player_data_into_dict(player_data: PlayerData) -> Dictionary: var result: Dictionary = { "id": player_data.id, @@ -22,13 +26,14 @@ func player_data_into_dict(player_data: PlayerData) -> Dictionary: match player_data.side: -1: side = PlayerData.underfined - 0: + 0: side = PlayerData.blue - 1: + 1: side = PlayerData.red result["side"] = side return result + func player_data_from_dict(player_data: Dictionary) -> PlayerData: var result := PlayerData.new() result.id = player_data.get("id") @@ -41,9 +46,9 @@ func player_data_from_dict(player_data: Dictionary) -> PlayerData: match player_data.side: "undefined": side = -1 - "attack": + "attack": side = 0 - "defend": + "defend": side = 1 result.side = side return result diff --git a/godot/scenes/helpers/logger.gd b/scenes_old_2/helpers/logger.gd similarity index 99% rename from godot/scenes/helpers/logger.gd rename to scenes_old_2/helpers/logger.gd index 7f5fd75..9789618 100644 --- a/godot/scenes/helpers/logger.gd +++ b/scenes_old_2/helpers/logger.gd @@ -1,7 +1,6 @@ extends Node class_name Logger - var thread: Thread = Thread.new() var mutex: Mutex = Mutex.new() var log_queue: Array[String] = [] @@ -10,30 +9,34 @@ var running: bool = true func _ready(): thread.start(log_writer) - + + func info(msg: Variant): mutex.lock() log_queue.append("[color=white][b]INFO:[/b] [/color]" + msg) mutex.unlock() + func debug(msg: Variant): mutex.lock() log_queue.append("[color=cyan][b]DEBUG:[/b] [/color]" + msg) mutex.unlock() + func warning(msg: Variant): mutex.lock() log_queue.append("[color=yellow][b]WARN:[/b] [/color]" + msg) push_warning(msg) mutex.unlock() - + func error(msg: Variant): mutex.lock() log_queue.append("[color=red][b]ERROR:[/b] [/color]" + msg) push_error(msg) mutex.unlock() + func log_writer(): while running: mutex.lock() @@ -41,10 +44,11 @@ func log_writer(): var log_message = log_queue.pop_front() print_rich(log_message) mutex.unlock() - + # Prevent high CPU usage await get_tree().create_timer(0.1).timeout + func _exit_tree(): running = false thread.wait_to_finish() diff --git a/godot/scenes/hud/in_game_tab/in_game_tab.tscn b/scenes_old_2/hud/in_game_tab/in_game_tab.tscn similarity index 100% rename from godot/scenes/hud/in_game_tab/in_game_tab.tscn rename to scenes_old_2/hud/in_game_tab/in_game_tab.tscn diff --git a/godot/scenes/interface/main_menu/main_menu.gd b/scenes_old_2/interface/main_menu/main_menu.gd similarity index 99% rename from godot/scenes/interface/main_menu/main_menu.gd rename to scenes_old_2/interface/main_menu/main_menu.gd index f82c449..bf7a1ce 100644 --- a/godot/scenes/interface/main_menu/main_menu.gd +++ b/scenes_old_2/interface/main_menu/main_menu.gd @@ -9,6 +9,7 @@ const MAP_DIR := "res://scenes/maps/maps/" var game_root: GameRoot var chosen_map: String + # Called when the node enters the scene tree for the first time. func _ready() -> void: game_root = helpers.get_root_node() @@ -45,6 +46,7 @@ func _on_close_join_pressed() -> void: func _on_close_create_pressed() -> void: create_server_panel.visible = false + func _on_map_list_item_selected(index: int) -> void: chosen_map = map_list.get_item_text(index) @@ -62,4 +64,3 @@ func _on_join_server_pressed() -> void: var err := game_root.join_server(ip, port) var server_data: ServerData = null visible = false - diff --git a/godot/scenes/interface/main_menu/main_menu.tscn b/scenes_old_2/interface/main_menu/main_menu.tscn similarity index 100% rename from godot/scenes/interface/main_menu/main_menu.tscn rename to scenes_old_2/interface/main_menu/main_menu.tscn diff --git a/godot/scenes/maps/base/bullet_spawner/bullet_controller.gd b/scenes_old_2/maps/base/bullet_spawner/bullet_controller.gd similarity index 92% rename from godot/scenes/maps/base/bullet_spawner/bullet_controller.gd rename to scenes_old_2/maps/base/bullet_spawner/bullet_controller.gd index 96c5ebc..281b67a 100644 --- a/godot/scenes/maps/base/bullet_spawner/bullet_controller.gd +++ b/scenes_old_2/maps/base/bullet_spawner/bullet_controller.gd @@ -1,15 +1,20 @@ extends Node class_name BulletSpawnerController -# This script shoud be able to find the player +# This script shoud be able to find the player + func _get_spawner() -> MultiplayerSpawner: return $MultiplayerSpawner - + + func _get_root() -> Node3D: return $Bullets + # -- TODO: Better bullet naming handler var bullet_amount: int = -2147483647 + + func spawn_bullet(starting_point: Node3D, speed: int, damage: int): var node: Node3D = ResourceLoader.load("res://scenes/weapon/bullet.tscn").instantiate() node.position = starting_point.global_position diff --git a/godot/scenes/maps/base/bullet_spawner/bullet_spawner.tscn b/scenes_old_2/maps/base/bullet_spawner/bullet_spawner.tscn similarity index 100% rename from godot/scenes/maps/base/bullet_spawner/bullet_spawner.tscn rename to scenes_old_2/maps/base/bullet_spawner/bullet_spawner.tscn diff --git a/godot/scenes/maps/base/entry_screen/entry_screen.gd b/scenes_old_2/maps/base/entry_screen/entry_screen.gd similarity index 99% rename from godot/scenes/maps/base/entry_screen/entry_screen.gd rename to scenes_old_2/maps/base/entry_screen/entry_screen.gd index 6d26f78..807029d 100644 --- a/godot/scenes/maps/base/entry_screen/entry_screen.gd +++ b/scenes_old_2/maps/base/entry_screen/entry_screen.gd @@ -1,7 +1,6 @@ extends Control - func _on_blue_pressed() -> void: helpers.get_server_node().set_player_side.rpc_id(1, PlayerData.blue) visible = false diff --git a/godot/scenes/maps/base/entry_screen/entry_screen.tscn b/scenes_old_2/maps/base/entry_screen/entry_screen.tscn similarity index 100% rename from godot/scenes/maps/base/entry_screen/entry_screen.tscn rename to scenes_old_2/maps/base/entry_screen/entry_screen.tscn diff --git a/godot/scenes/maps/base/map_controller.gd b/scenes_old_2/maps/base/map_controller.gd similarity index 93% rename from godot/scenes/maps/base/map_controller.gd rename to scenes_old_2/maps/base/map_controller.gd index e4959d9..ddb1fb6 100644 --- a/godot/scenes/maps/base/map_controller.gd +++ b/scenes_old_2/maps/base/map_controller.gd @@ -13,6 +13,7 @@ var client_node: Node3D @onready var spawn_controller: SpawnController = $SpawnLocations + # Called when the node enters the scene tree for the first time. func _ready() -> void: # add player spawner @@ -20,17 +21,17 @@ func _ready() -> void: err = _add_player_spawner() if err != OK: push_error("Couldn't load player spawner") - + err = _add_bullet_spawner() if err != OK: push_error("Couldn't load bullet spawner") - + # add objects spawner if not OS.has_feature("dedicated_server"): err = _add_entry_screen() if err != OK: logger.error("Couldn't load the entry screen, err " + str(err)) - + @rpc("any_peer", "call_local", "unreliable") func _spawn_player_controller_node(x: float, y: float, z: float): @@ -41,31 +42,34 @@ func _spawn_player_controller_node(x: float, y: float, z: float): var controlled_node: ServerNode = player_spawner.get_player_node(multiplayer.get_unique_id()) player_node.controlled_node = controlled_node client_node.add_child(player_node) - player_node.shared_node.global_position = Vector3(x,y,z) + player_node.shared_node.global_position = Vector3(x, y, z) controlled_node.bind_player_node() - + + func spawn_player_model(owner_node: CharacterBody3D, owner_id: int): if multiplayer.get_unique_id() != owner_id: player_spawner.spawn_player_model(owner_node) - + + func _remove_player(id: int): player_spawner.remove_player(id) - -func _add_player_spawner() -> Error : + +func _add_player_spawner() -> Error: if not ResourceLoader.exists(PLAYER_SPAWNER): return ERR_DOES_NOT_EXIST var scene: PackedScene = ResourceLoader.load(PLAYER_SPAWNER) if not scene.can_instantiate(): return ERR_CANT_OPEN - + var node: PlayerSpawnerController = scene.instantiate() add_child(node) player_spawner = node player_spawner.spawn_controller = spawn_controller return OK - -func _add_bullet_spawner() -> Error : + + +func _add_bullet_spawner() -> Error: if not ResourceLoader.exists(BULLET_SPAWNER): return ERR_DOES_NOT_EXIST var scene: PackedScene = ResourceLoader.load(BULLET_SPAWNER) @@ -76,7 +80,8 @@ func _add_bullet_spawner() -> Error : bullet_spawner = node return OK -func _add_entry_screen() -> Error : + +func _add_entry_screen() -> Error: if not ResourceLoader.exists(ENTRY_SCREEN): return ERR_DOES_NOT_EXIST var scene: PackedScene = ResourceLoader.load(ENTRY_SCREEN) @@ -86,8 +91,11 @@ func _add_entry_screen() -> Error : add_child(node) entry_screen = node return OK - + + # -- TODO: Better bullet naming handler var bullet_amount: int = -2147483647 + + func spawn_bullet(starting_point: Node3D, speed: int, damage: int): bullet_spawner.spawn_bullet(starting_point, speed, damage) diff --git a/godot/scenes/maps/base/player_spawner/player_spawner.gd b/scenes_old_2/maps/base/player_spawner/player_spawner.gd similarity index 80% rename from godot/scenes/maps/base/player_spawner/player_spawner.gd rename to scenes_old_2/maps/base/player_spawner/player_spawner.gd index 14ec73c..63556d1 100644 --- a/godot/scenes/maps/base/player_spawner/player_spawner.gd +++ b/scenes_old_2/maps/base/player_spawner/player_spawner.gd @@ -1,27 +1,38 @@ -class_name PlayerSpawnerController +class_name PlayerSpawnerController extends Node3D var spawned_players: Dictionary = {} @export var spawn_controller: SpawnController var server_node: ServerData + + func _get_spawner() -> MultiplayerSpawner: return $PlayersSpawner - + + func _get_root() -> Node3D: return $Players - + + func _get_model_spawner() -> MultiplayerSpawner: return $ModelSpawner - + + func _get_model_root() -> Node3D: return $Models + + func _ready() -> void: server_node = helpers.get_server_node() + func _process(delta: float) -> void: for player in server_node.players: if not spawned_players.has(player): - if server_node.players[player].has("side") and server_node.players[player].get("side") != PlayerData.underfined: + if ( + server_node.players[player].has("side") + and server_node.players[player].get("side") != PlayerData.underfined + ): logger.debug("Spawning a player with id: " + str(player)) var err := spawn_players(server_node.players[player]) if err != OK: @@ -29,10 +40,11 @@ func _process(delta: float) -> void: else: spawned_players[player] = 1 + # -- Spawn a player node and sync it across all peers func spawn_players(player_data: Dictionary) -> Error: - var char : ServerNode = null - + var char: ServerNode = null + char = ResourceLoader.load("res://scenes/player/server_node.tscn").instantiate() char.name = "PlayerPlaceholder_" + str(player_data.get("id")) var side = "attack" @@ -47,19 +59,23 @@ func spawn_players(player_data: Dictionary) -> Error: char.owner_id = player_data.get("id") _get_root().add_child(char) char.shared_node.global_position = new_position - + return OK - + + func spawn_player_model(owner_node: CharacterBody3D): - var model_scene: PackedScene = ResourceLoader.load("res://scenes/characters/y-bot/character.tscn") + var model_scene: PackedScene = ResourceLoader.load( + "res://scenes/characters/y-bot/character.tscn" + ) var model: CharacterWrapper = model_scene.instantiate() model.global_position = owner_node.global_position model.owner_placeholder = owner_node _get_model_root().add_child(model) - + + func remove_player(id: int) -> Error: if multiplayer.is_server(): - var found_childen: Array[Node] =_get_root().get_children() + var found_childen: Array[Node] = _get_root().get_children() for found_child in found_childen: if found_child.owner_id: if found_child.owner_id == id: @@ -67,8 +83,11 @@ func remove_player(id: int) -> Error: return OK return ERR_UNAUTHORIZED + func get_player_node(id: int) -> ServerNode: - var nodes: Array[Node] = _get_root().get_children().filter(func(x: ServerNode): return x.owner_id == id) + var nodes: Array[Node] = _get_root().get_children().filter( + func(x: ServerNode): return x.owner_id == id + ) if nodes.size() > 0: return nodes[0] return null diff --git a/godot/scenes/maps/base/player_spawner/player_spawner.tscn b/scenes_old_2/maps/base/player_spawner/player_spawner.tscn similarity index 100% rename from godot/scenes/maps/base/player_spawner/player_spawner.tscn rename to scenes_old_2/maps/base/player_spawner/player_spawner.tscn diff --git a/godot/scenes/maps/base/player_synchronizer/player_synchronizer.gd b/scenes_old_2/maps/base/player_synchronizer/player_synchronizer.gd similarity index 85% rename from godot/scenes/maps/base/player_synchronizer/player_synchronizer.gd rename to scenes_old_2/maps/base/player_synchronizer/player_synchronizer.gd index fae2c76..5571862 100644 --- a/godot/scenes/maps/base/player_synchronizer/player_synchronizer.gd +++ b/scenes_old_2/maps/base/player_synchronizer/player_synchronizer.gd @@ -3,7 +3,7 @@ extends Node # Called when the node enters the scene tree for the first time. func _ready() -> void: - pass # Replace with function body. + pass # Replace with function body. # Called every frame. 'delta' is the elapsed time since the previous frame. diff --git a/godot/scenes/maps/base/player_synchronizer/player_synchronizer.tscn b/scenes_old_2/maps/base/player_synchronizer/player_synchronizer.tscn similarity index 100% rename from godot/scenes/maps/base/player_synchronizer/player_synchronizer.tscn rename to scenes_old_2/maps/base/player_synchronizer/player_synchronizer.tscn diff --git a/godot/scenes/maps/base/single_spawn_controller.gd b/scenes_old_2/maps/base/single_spawn_controller.gd similarity index 99% rename from godot/scenes/maps/base/single_spawn_controller.gd rename to scenes_old_2/maps/base/single_spawn_controller.gd index 71b1367..1d77c5b 100644 --- a/godot/scenes/maps/base/single_spawn_controller.gd +++ b/scenes_old_2/maps/base/single_spawn_controller.gd @@ -2,6 +2,7 @@ extends Node3D var busy: bool = false + func choose_spawn_location() -> Vector3: busy = true return global_position diff --git a/godot/scenes/maps/base/spawn_controller.gd b/scenes_old_2/maps/base/spawn_controller.gd similarity index 93% rename from godot/scenes/maps/base/spawn_controller.gd rename to scenes_old_2/maps/base/spawn_controller.gd index 454ec73..d2c8332 100644 --- a/godot/scenes/maps/base/spawn_controller.gd +++ b/scenes_old_2/maps/base/spawn_controller.gd @@ -6,10 +6,11 @@ class_name SpawnController extends Node3D @onready var red_spawners: Node3D = $Red const SINGLE_SPAWN_CONTROLLER_PATH = "res://scenes/maps/base/single_spawn_controller.gd" -enum Sides {BLUE, RED, UNDEFINED} +enum Sides { BLUE, RED, UNDEFINED } @export var side: Sides = Sides.UNDEFINED + # Called when the node enters the scene tree for the first time. func _ready() -> void: var single_spawn_controller: GDScript = ResourceLoader.load(SINGLE_SPAWN_CONTROLLER_PATH) @@ -17,7 +18,7 @@ func _ready() -> void: spawn.set_script(single_spawn_controller) for spawn: Node3D in red_spawners.get_children(): spawn.set_script(single_spawn_controller) - pass # Replace with function body. + pass # Replace with function body. # Called every frame. 'delta' is the elapsed time since the previous frame. @@ -45,5 +46,5 @@ func get_spawner(team: Sides) -> Vector3: var spawn := _get_available_spawn(red_spawners) return spawn.choose_spawn_location() _: - return Vector3(0,0,0) + return Vector3(0, 0, 0) # Get all spawners for each team diff --git a/godot/scenes/maps/maps/lowpoly_tdm_1.tscn b/scenes_old_2/maps/maps/lowpoly_tdm_1.tscn similarity index 100% rename from godot/scenes/maps/maps/lowpoly_tdm_1.tscn rename to scenes_old_2/maps/maps/lowpoly_tdm_1.tscn diff --git a/godot/scenes/maps/maps/world.tscn b/scenes_old_2/maps/maps/world.tscn similarity index 100% rename from godot/scenes/maps/maps/world.tscn rename to scenes_old_2/maps/maps/world.tscn diff --git a/godot/scenes/player/gun_mount.gd b/scenes_old_2/player/gun_mount.gd similarity index 91% rename from godot/scenes/player/gun_mount.gd rename to scenes_old_2/player/gun_mount.gd index 5c5b8ce..02a1315 100644 --- a/godot/scenes/player/gun_mount.gd +++ b/scenes_old_2/player/gun_mount.gd @@ -3,9 +3,12 @@ extends Node3D # Called when the node enters the scene tree for the first time. func _ready() -> void: - pass # Replace with function body. + pass # Replace with function body. + @export var follow_speed: float = 5.0 + + # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: var target_position = global_transform.origin # Camera's world position diff --git a/godot/scenes/player/hud.gd b/scenes_old_2/player/hud.gd similarity index 55% rename from godot/scenes/player/hud.gd rename to scenes_old_2/player/hud.gd index 17fcce5..8b0e3a9 100644 --- a/godot/scenes/player/hud.gd +++ b/scenes_old_2/player/hud.gd @@ -2,4 +2,4 @@ extends Control class_name Hud @onready var camera: Camera3D = $SubViewportContainer/SubViewport/Camera3D -@onready var gun_mount: Node3D = $SubViewportContainer/SubViewport/Camera3D/GunMount +@onready var gun_mount: Node3D = $SubViewportContainer/SubViewport/Camera3D/GunMount diff --git a/godot/scenes/player/hud.tscn b/scenes_old_2/player/hud.tscn similarity index 100% rename from godot/scenes/player/hud.tscn rename to scenes_old_2/player/hud.tscn diff --git a/godot/scenes/player/placeholder.tscn b/scenes_old_2/player/placeholder.tscn similarity index 100% rename from godot/scenes/player/placeholder.tscn rename to scenes_old_2/player/placeholder.tscn diff --git a/godot/scenes/player/player_input.tscn b/scenes_old_2/player/player_input.tscn similarity index 100% rename from godot/scenes/player/player_input.tscn rename to scenes_old_2/player/player_input.tscn diff --git a/godot/scenes/player/player_node.gd b/scenes_old_2/player/player_node.gd similarity index 81% rename from godot/scenes/player/player_node.gd rename to scenes_old_2/player/player_node.gd index 814ace2..12e6f78 100644 --- a/godot/scenes/player/player_node.gd +++ b/scenes_old_2/player/player_node.gd @@ -1,5 +1,5 @@ # --------------------------------------------------------------------- -# This script is supposed to control the node that is rendered on the +# This script is supposed to control the node that is rendered on the # client side, and send the changes to the server node # --------------------------------------------------------------------- extends Node3D @@ -27,6 +27,7 @@ var gun_mount: Node3D const DEFAULT_WEAPON := "ak" var first_slot_weapon: WeaponController + func _ready() -> void: set_multiplayer_authority(multiplayer.get_unique_id()) shared_node.set_collision_layer_value(2, true) @@ -40,10 +41,11 @@ func _ready() -> void: gun_mount = hud.gun_mount _load_weapon() #for child in controlled_node.find_child("Model").find_children("*"): - #if child is MeshInstance3D: - #child.set_layer_mask_value(1, false) + #if child is MeshInstance3D: + #child.set_layer_mask_value(1, false) # Load the default weapon and set the current attack properties + func _load_weapon() -> void: var path_tmpl := "res://scenes/weapon/guns/%s/with_hands.tscn" var path := path_tmpl % DEFAULT_WEAPON @@ -55,80 +57,103 @@ func _load_weapon() -> void: child.set_layer_mask_value(1, false) #first_slot_weapon.position = Vector3(-1, -1, -1) hud.find_child("GunMount").add_child(first_slot_weapon) - - + + func initial_position_sync(): shared_node.global_position = controlled_node.shared_node.global_position shared_node.rotation = controlled_node.shared_node.rotation + func _input(event): if multiplayer.get_unique_id() == get_multiplayer_authority(): - if Input.is_action_just_pressed("jump"): jump() - + if Input.is_action_just_pressed("jump"): + jump() + if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED: look_dir = event.relative * 1 shared_node.rotation.y -= look_dir.x * camera_sens * 1.0 - camera_mount.rotation.x = clamp(camera_mount.rotation.x - look_dir.y * camera_sens * 1.0, -1.5, 1.5) + camera_mount.rotation.x = clamp( + camera_mount.rotation.x - look_dir.y * camera_sens * 1.0, -1.5, 1.5 + ) controlled_node.set_rotation_x.rpc_id(1, camera_mount.rotation.x) controlled_node.set_rotation_y.rpc_id(1, shared_node.rotation.y) - - input_direction = Input.get_vector("move_left", "move_right", "move_forward", "move_backward") + + input_direction = Input.get_vector( + "move_left", "move_right", "move_forward", "move_backward" + ) controlled_node.set_input_direction.rpc_id(1, input_direction) - - if Input.is_action_just_pressed("shoot"): shooting = true - if Input.is_action_just_released("shoot"): shooting = false + + if Input.is_action_just_pressed("shoot"): + shooting = true + if Input.is_action_just_released("shoot"): + shooting = false + func jump(): jumping = true controlled_node.jump.rpc_id(1) + func _physics_process(delta: float) -> void: if multiplayer.get_unique_id() == get_multiplayer_authority(): Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) - + if not shared_node.is_on_floor(): shared_node.velocity += shared_node.get_gravity() * delta if shared_node.is_on_floor() && jumping: shared_node.velocity.y = consts.DEFAULT_JUMP_VELOCITY - + #if shooting: jumping = false - + if shooting: controlled_node.shoot.rpc_id(1) first_slot_weapon.shoot() - - var direction := (shared_node.transform.basis * Vector3(input_direction.x, 0, input_direction.y)).normalized() + + var direction := ( + (shared_node.transform.basis * Vector3(input_direction.x, 0, input_direction.y)) + . normalized() + ) if shared_node.is_on_floor(): if direction: shared_node.velocity.x = direction.x * consts.DEFAULT_CHARACTER_SPEED shared_node.velocity.z = direction.z * consts.DEFAULT_CHARACTER_SPEED else: - shared_node.velocity.x = move_toward(shared_node.velocity.x, 0, consts.DEFAULT_CHARACTER_SPEED) - shared_node.velocity.z = move_toward(shared_node.velocity.z, 0, consts.DEFAULT_CHARACTER_SPEED) + shared_node.velocity.x = move_toward( + shared_node.velocity.x, 0, consts.DEFAULT_CHARACTER_SPEED + ) + shared_node.velocity.z = move_toward( + shared_node.velocity.z, 0, consts.DEFAULT_CHARACTER_SPEED + ) hud_camera.global_position = global_position func _process(delta: float) -> void: shared_node.move_and_slide() + # -- This rpc should be called by the server in order to # -- make the client send its position to the server @rpc("any_peer", "call_local", "reliable") func verify_position() -> void: var desired_position: Vector3 = shared_node.global_position controlled_node.send_position.rpc_id(1, desired_position) - + + @rpc("authority", "call_local") func adjust_position(x: float, y: float, z: float): var new_position: Vector3 = Vector3(x, y, z) shared_node.global_position = new_position + @rpc("any_peer", "call_local", "reliable") func verify_rotation() -> void: var desired_rotation: Vector3 = shared_node.global_rotation - controlled_node.send_rotation.rpc_id(1, desired_rotation.x, desired_rotation.y, desired_rotation.z) - + controlled_node.send_rotation.rpc_id( + 1, desired_rotation.x, desired_rotation.y, desired_rotation.z + ) + + @rpc("authority", "call_local") func adjust_rotation(x: float, y: float, z: float): var new_rotation: Vector3 = Vector3(x, y, z) diff --git a/godot/scenes/player/player_node.tscn b/scenes_old_2/player/player_node.tscn similarity index 100% rename from godot/scenes/player/player_node.tscn rename to scenes_old_2/player/player_node.tscn diff --git a/godot/scenes/player/server_node.gd b/scenes_old_2/player/server_node.gd similarity index 90% rename from godot/scenes/player/server_node.gd rename to scenes_old_2/player/server_node.gd index bb9e7f3..39675cb 100644 --- a/godot/scenes/player/server_node.gd +++ b/scenes_old_2/player/server_node.gd @@ -27,6 +27,7 @@ func _ready() -> void: #map_controller.spawn_player_model(shared_node, owner_id) # Load the default weapon and set the current attack properties + func _load_weapon() -> void: var path_tmpl := "res://scenes/weapon/guns/%s/with_hands.tscn" var path := path_tmpl % DEFAULT_WEAPON @@ -36,78 +37,98 @@ func _load_weapon() -> void: first_slot_weapon.make_invisible() first_slot_weapon.set_map_controller(map_controller) add_child(first_slot_weapon) - + + func bind_player_node() -> void: if multiplayer.get_unique_id() == owner_id: player_node = get_tree().get_root().find_child("PlayerController", true, false) + func _physics_process(delta: float) -> void: if not shared_node.is_on_floor(): shared_node.velocity += shared_node.get_gravity() * delta if shared_node.is_on_floor() && jumping: shared_node.velocity.y = consts.DEFAULT_JUMP_VELOCITY jumping = false - var direction := (shared_node.transform.basis * Vector3(input_direction.x, 0, input_direction.y)).normalized() + var direction := ( + (shared_node.transform.basis * Vector3(input_direction.x, 0, input_direction.y)) + . normalized() + ) if shared_node.is_on_floor(): if direction: #first_view_legs_anim.play("Run Forward") shared_node.velocity.x = direction.x * consts.DEFAULT_CHARACTER_SPEED shared_node.velocity.z = direction.z * consts.DEFAULT_CHARACTER_SPEED else: - shared_node.velocity.x = move_toward(shared_node.velocity.x, 0, consts.DEFAULT_CHARACTER_SPEED) - shared_node.velocity.z = move_toward(shared_node.velocity.z, 0, consts.DEFAULT_CHARACTER_SPEED) + shared_node.velocity.x = move_toward( + shared_node.velocity.x, 0, consts.DEFAULT_CHARACTER_SPEED + ) + shared_node.velocity.z = move_toward( + shared_node.velocity.z, 0, consts.DEFAULT_CHARACTER_SPEED + ) shared_node.move_and_slide() - + + @rpc("authority", "call_remote", "unreliable_ordered") func update_position(real_position: Vector3): if not multiplayer.is_server(): - shared_node.global_transform.origin = lerp(shared_node.global_transform.origin, real_position, 1.0) - + shared_node.global_transform.origin = lerp( + shared_node.global_transform.origin, real_position, 1.0 + ) + + @rpc("any_peer", "call_local", "unreliable") func jump(): jumping = true - + + @rpc("any_peer", "call_local", "unreliable") func sync_velocity(x: float, y: float, z: float) -> void: if not multiplayer.is_server(): - shared_node.velocity = Vector3(x, y ,z) - - + shared_node.velocity = Vector3(x, y, z) + + @rpc("any_peer", "call_local", "unreliable") func set_input_direction(new_input_direction: Vector2): input_direction = new_input_direction + @rpc("any_peer", "call_local", "unreliable") func set_rotation_x(x: float): camera_mount.rotation.x = x - + + @rpc("any_peer", "call_local", "unreliable") func set_rotation_y(y: float): shared_node.rotation.y = y + func _on_reconciliation_timer_timeout() -> void: if multiplayer.is_server(): #_veryfy_position_and_rotation.rpc_id(owner_id) #update_position.rpc(shared_node.global_transform.origin) - $ReconciliationTimer.start() + $ReconciliationTimer.start() + @rpc("any_peer", "call_local", "reliable") func _veryfy_position_and_rotation() -> void: player_node.verify_position() player_node.verify_rotation() + #@rpc("authority", "call_remote", "unreliable") #func _sync_transorm(): - - + @rpc("any_peer", "call_local", "reliable") func _adjust_position(x: float, y: float, z: float) -> void: player_node.adjust_position(x, y, z) + @rpc("any_peer", "call_local", "reliable") func _adjust_rotation(x: float, y: float, z: float) -> void: player_node.adjust_rotation(x, y, z) + @rpc("any_peer", "call_local", "reliable") func send_position(desired_position: Vector3): if multiplayer.is_server(): @@ -122,7 +143,8 @@ func send_position(desired_position: Vector3): else: push_warning("player position is not valid, adjusting") _adjust_position.rpc_id(owner_id, real_position.x, real_position.y, real_position.z) - + + @rpc("any_peer", "call_local") func send_rotation(x: float, y: float, z: float): if multiplayer.is_server(): @@ -135,10 +157,12 @@ func send_rotation(x: float, y: float, z: float): else: var new_rotation: Vector3 = desired_rotation.lerp(real_rotation, 0.5) _adjust_rotation.rpc_id(owner_id, new_rotation.x, new_rotation.y, new_rotation.z) - + + @rpc("any_peer", "call_local", "unreliable_ordered") func shoot(): first_slot_weapon.attack(bullet_starting_point) - + + func is_vector_a_lower_than_b(vec_a: Vector3, vec_b: Vector3) -> bool: return vec_a.x < vec_b.x and vec_a.y < vec_b.y and vec_a.z < vec_b.z diff --git a/godot/scenes/player/server_node.tscn b/scenes_old_2/player/server_node.tscn similarity index 100% rename from godot/scenes/player/server_node.tscn rename to scenes_old_2/player/server_node.tscn diff --git a/godot/scenes/player/shared_node.tscn b/scenes_old_2/player/shared_node.tscn similarity index 100% rename from godot/scenes/player/shared_node.tscn rename to scenes_old_2/player/shared_node.tscn diff --git a/godot/scenes/utils/camera_mount/camera_mount.gd b/scenes_old_2/utils/camera_mount/camera_mount.gd similarity index 93% rename from godot/scenes/utils/camera_mount/camera_mount.gd rename to scenes_old_2/utils/camera_mount/camera_mount.gd index 3f9ca13..c47766b 100644 --- a/godot/scenes/utils/camera_mount/camera_mount.gd +++ b/scenes_old_2/utils/camera_mount/camera_mount.gd @@ -7,16 +7,20 @@ class_name CameraMount @export var accept_input: bool = false var camera: Camera3D + + # Called when the node enters the scene tree for the first time. func _ready() -> void: camera = Camera3D.new() add_child(camera) + @rpc("any_peer", "call_local", "reliable") -func connect_to_camera() -> void : +func connect_to_camera() -> void: if active: camera.make_current() + # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: pass diff --git a/godot/scenes/utils/camera_mount/camera_mount.tscn b/scenes_old_2/utils/camera_mount/camera_mount.tscn similarity index 100% rename from godot/scenes/utils/camera_mount/camera_mount.tscn rename to scenes_old_2/utils/camera_mount/camera_mount.tscn diff --git a/godot/scenes/utils/client_node/client_node.gd b/scenes_old_2/utils/client_node/client_node.gd similarity index 81% rename from godot/scenes/utils/client_node/client_node.gd rename to scenes_old_2/utils/client_node/client_node.gd index f4a1457..b9a4e9c 100644 --- a/godot/scenes/utils/client_node/client_node.gd +++ b/scenes_old_2/utils/client_node/client_node.gd @@ -5,11 +5,14 @@ class_name ClientNode var available_cameras: Array[CameraMount] = [] + # Called every frame. 'delta' is the elapsed time since the previous frame. func _physics_process(delta: float) -> void: if not is_connected_to_camera: var game_root := helpers.get_root_node() - var available_cameras_raw: Array[Node] = game_root.find_children("*", "CameraMount", true, false) + var available_cameras_raw: Array[Node] = game_root.find_children( + "*", "CameraMount", true, false + ) for camera_raw in available_cameras_raw: var camera: CameraMount = camera_raw as CameraMount if camera.active: @@ -19,6 +22,7 @@ func _physics_process(delta: float) -> void: camera.connect_to_camera() available_cameras.append(camera) -@rpc("authority", "reliable", "call_local") -func force_camera_attachment(camera_mount: CameraMount) -> void: + +@rpc("authority", "reliable", "call_local") +func force_camera_attachment(camera_mount: CameraMount) -> void: camera_mount.connect_to_camera() diff --git a/godot/scenes/utils/client_node/client_node.tscn b/scenes_old_2/utils/client_node/client_node.tscn similarity index 100% rename from godot/scenes/utils/client_node/client_node.tscn rename to scenes_old_2/utils/client_node/client_node.tscn diff --git a/godot/scenes/utils/game_root/game_root.gd b/scenes_old_2/utils/game_root/game_root.gd similarity index 95% rename from godot/scenes/utils/game_root/game_root.gd rename to scenes_old_2/utils/game_root/game_root.gd index 6023482..d6aec8b 100644 --- a/godot/scenes/utils/game_root/game_root.gd +++ b/scenes_old_2/utils/game_root/game_root.gd @@ -1,30 +1,31 @@ -extends Node -class_name GameRoot +class_name GameRoot extends Node signal load_map(name: String) +const MAIN_MENU_SCENE := "res://scenes/interface/main_menu/main_menu.tscn" +const SERVER_DATA_NODE := "res://scenes/utils/server_data/server_data.tscn" + # -- config from args var config_file: String = "" -const MAIN_MENU_SCENE := "res://scenes/interface/main_menu/main_menu.tscn" -const SERVER_DATA_NODE := "res://scenes/utils/server_data/server_data.tscn" @onready var level_root: Node3D = $Level @onready var utils_root: Node = $Utils func _parse_args() -> void: var args := Array(OS.get_cmdline_args()) - + var config_arg: String = "--config" if args.has(config_arg): var index := args.find(config_arg) config_file = args[index + 1] + # Called when the node enters the scene tree for the first time. func _ready() -> void: _parse_args() var err: Error - + if err != OK: logger.error("Couldn't load utils node") return @@ -40,24 +41,29 @@ func _ready() -> void: multiplayer.peer_disconnected.connect(_on_player_disconnected) multiplayer.connected_to_server.connect(_on_connected_to_server) + func _on_player_disconnected(id) -> void: logger.info("player is disconnected with id: " + str(id)) - + + func _on_player_connected(id) -> void: # Send the client information about the server if multiplayer.is_server(): logger.info("player is connected with id: " + str(id)) _sync_map_from_server.rpc_id(id) + @rpc("authority", "reliable", "call_remote") func _sync_map_from_server() -> void: var server_node := helpers.get_server_node() load_map.emit(server_node.current_map) - + + func _on_connected_to_server() -> void: logger.info("connection is successful, sending info") register_player.rpc_id(1, multiplayer.get_unique_id(), "client") + @rpc("any_peer", "reliable", "call_remote") func register_player(id: int, name: String): logger.info("registering player: " + str(id)) @@ -69,9 +75,10 @@ func register_player(id: int, name: String): var server_node: ServerData = helpers.get_server_node() server_node.players[id] = helpers.player_data_into_dict(player_data) logger.info("player " + str(id) + " is registered") - else: + else: logger.debug("register player is supposed to be executed on the server") + func _start_dedicated_server() -> Error: if config_file != "": logger.info("reading config from the file: " + config_file) @@ -87,27 +94,29 @@ func _start_game() -> Error: var scene: PackedScene = ResourceLoader.load(MAIN_MENU_SCENE) if not scene.can_instantiate(): return ERR_CANT_OPEN - + var node: MainMenu = scene.instantiate() - add_child(node) + add_child(node) return OK - + + func _load_utils() -> Error: if not ResourceLoader.exists(SERVER_DATA_NODE): return ERR_DOES_NOT_EXIST var scene: PackedScene = ResourceLoader.load(SERVER_DATA_NODE) if not scene.can_instantiate(): return ERR_CANT_OPEN - + var node: ServerData = scene.instantiate() utils_root.add_child(node) return OK + func _on_load_map(map_name: String) -> void: var path_tmpl := "res://scenes/maps/maps/%s" var path := path_tmpl % map_name logger.info("Loading map from " + path) - + if not ResourceLoader.exists(path): logger.error("map " + map_name + " doesn't exist") var scene: PackedScene = ResourceLoader.load(path) @@ -120,8 +129,11 @@ func _on_load_map(map_name: String) -> void: level_root.add_child(node) else: logger.error("Can't initialize") - -func create_server(port: int, player_limit: int, server_only: bool = false, map: String = "lowpoly_tdm_2.tscn") -> Error: + + +func create_server( + port: int, player_limit: int, server_only: bool = false, map: String = "lowpoly_tdm_2.tscn" +) -> Error: var peer := ENetMultiplayerPeer.new() logger.info("starting a server the port: " + str(port)) var err := peer.create_server(port, player_limit) @@ -137,6 +149,7 @@ func create_server(port: int, player_limit: int, server_only: bool = false, map register_player(1, "server") return OK + func join_server(ip: String, port: int) -> Error: var peer = ENetMultiplayerPeer.new() logger.info("trying to connect to: " + ip + ":" + str(port)) diff --git a/godot/scenes/utils/game_root/game_root.tscn b/scenes_old_2/utils/game_root/game_root.tscn similarity index 100% rename from godot/scenes/utils/game_root/game_root.tscn rename to scenes_old_2/utils/game_root/game_root.tscn diff --git a/godot/scenes/utils/player_data/player_data.gd b/scenes_old_2/utils/player_data/player_data.gd similarity index 94% rename from godot/scenes/utils/player_data/player_data.gd rename to scenes_old_2/utils/player_data/player_data.gd index 64a9514..898764c 100644 --- a/godot/scenes/utils/player_data/player_data.gd +++ b/scenes_old_2/utils/player_data/player_data.gd @@ -8,8 +8,8 @@ class_name PlayerData extends Resource @export var headshots: int = 0 enum Side { - BLUE = 0, - RED = 1, + BLUE = 0, + RED = 1, UNDEFINED = -1, } diff --git a/godot/scenes/utils/server_data/server_data.gd b/scenes_old_2/utils/server_data/server_data.gd similarity index 99% rename from godot/scenes/utils/server_data/server_data.gd rename to scenes_old_2/utils/server_data/server_data.gd index e223a0b..3213cbb 100644 --- a/godot/scenes/utils/server_data/server_data.gd +++ b/scenes_old_2/utils/server_data/server_data.gd @@ -11,6 +11,8 @@ func set_player_side(side: String): var id: int = multiplayer.get_remote_sender_id() if players.has(id): players[id]["side"] = side + + # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: pass diff --git a/godot/scenes/utils/server_data/server_data.tscn b/scenes_old_2/utils/server_data/server_data.tscn similarity index 100% rename from godot/scenes/utils/server_data/server_data.tscn rename to scenes_old_2/utils/server_data/server_data.tscn diff --git a/godot/scenes/weapon/bullet.gd b/scenes_old_2/weapon/bullet.gd similarity index 94% rename from godot/scenes/weapon/bullet.gd rename to scenes_old_2/weapon/bullet.gd index 4a79051..fc02952 100644 --- a/godot/scenes/weapon/bullet.gd +++ b/scenes_old_2/weapon/bullet.gd @@ -1,16 +1,17 @@ extends Node3D -@export var speed: int = 0 +@export var speed: int = 0 @export var damage: int = 0 @onready var mesh = $RigidBody3D/MeshInstance3D @onready var rigid_body_3d: RigidBody3D = $RigidBody3D @onready var ray = $RigidBody3D/RayCast3D @onready var particles = $GPUParticles3D + # Called when the node enters the scene tree for the first time. func _ready() -> void: set_multiplayer_authority(1) - pass # Replace with function body. + pass # Replace with function body. # Called every frame. 'delta' is the elapsed time since the previous frame. @@ -31,5 +32,6 @@ func _physics_process(delta): rigid_body_3d.visible = false particles.emitting = true + func _on_timer_timeout(): queue_free() diff --git a/godot/scenes/weapon/bullet.tscn b/scenes_old_2/weapon/bullet.tscn similarity index 100% rename from godot/scenes/weapon/bullet.tscn rename to scenes_old_2/weapon/bullet.tscn diff --git a/godot/scenes/weapon/generic_weapon_controller.gd b/scenes_old_2/weapon/generic_weapon_controller.gd similarity index 99% rename from godot/scenes/weapon/generic_weapon_controller.gd rename to scenes_old_2/weapon/generic_weapon_controller.gd index b292921..5c14f10 100644 --- a/godot/scenes/weapon/generic_weapon_controller.gd +++ b/scenes_old_2/weapon/generic_weapon_controller.gd @@ -11,18 +11,22 @@ class_name WeaponController extends Node3D # bullet speed in m/s @export var bullet_speed: int = 200 @export var bullet_spread_script: GDScript - + var map_controller: MapController @onready var cooldown_timer: Timer = $CooldownTimer var can_shoot: bool = true + + # Called when the node enters the scene tree for the first time. func _ready() -> void: cooldown_timer.wait_time = cooldown - - + + @onready var bullet_trace_distance: Node3D = $BulletTraceDistance @onready var gun_animation = $ShotAnimation + + func shoot() -> Error: if can_shoot: can_shoot = false @@ -30,7 +34,7 @@ func shoot() -> Error: var bullet_end_node: Node3D = bullet_trace_distance.find_child("End") gun_animation.play("shot") cooldown_timer.start() - + if bullet_start_node and bullet_end_node: var path := "res://scenes/weapon/misc/bullet_trail_generic.tscn" if not ResourceLoader.exists(path): @@ -38,7 +42,7 @@ func shoot() -> Error: var scene: PackedScene = ResourceLoader.load(path) if not scene.can_instantiate(): return ERR_CANT_OPEN - + var node: MeshInstance3D = scene.instantiate() node.init(bullet_start_node.position, bullet_end_node.position) #var root := get_tree().get_root() @@ -51,20 +55,25 @@ func shoot() -> Error: # -- TODO: It should not be hardcoded + func set_map_controller(map_node: MapController): map_controller = map_node + func attack(bullet_starting_point: Node3D): if can_shoot: can_shoot = false map_controller.spawn_bullet(bullet_starting_point, bullet_speed, damage) cooldown_timer.start() + func make_invisible() -> void: for child in find_children("*"): if child is MeshInstance3D: child.set_layer_mask_value(1, false) child.set_layer_mask_value(20, false) + + # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: pass diff --git a/godot/scenes/weapon/guns/ak/clip.tscn b/scenes_old_2/weapon/guns/ak/clip.tscn similarity index 100% rename from godot/scenes/weapon/guns/ak/clip.tscn rename to scenes_old_2/weapon/guns/ak/clip.tscn diff --git a/godot/scenes/weapon/guns/ak/gun.tscn b/scenes_old_2/weapon/guns/ak/gun.tscn similarity index 100% rename from godot/scenes/weapon/guns/ak/gun.tscn rename to scenes_old_2/weapon/guns/ak/gun.tscn diff --git a/godot/scenes/weapon/guns/ak/with_hands.tscn b/scenes_old_2/weapon/guns/ak/with_hands.tscn similarity index 100% rename from godot/scenes/weapon/guns/ak/with_hands.tscn rename to scenes_old_2/weapon/guns/ak/with_hands.tscn diff --git a/godot/scenes/weapon/guns/deagle/clip.tscn b/scenes_old_2/weapon/guns/deagle/clip.tscn similarity index 100% rename from godot/scenes/weapon/guns/deagle/clip.tscn rename to scenes_old_2/weapon/guns/deagle/clip.tscn diff --git a/godot/scenes/weapon/guns/deagle/deagle.tscn b/scenes_old_2/weapon/guns/deagle/deagle.tscn similarity index 100% rename from godot/scenes/weapon/guns/deagle/deagle.tscn rename to scenes_old_2/weapon/guns/deagle/deagle.tscn diff --git a/godot/scenes/weapon/guns/deagle/gun.tscn b/scenes_old_2/weapon/guns/deagle/gun.tscn similarity index 100% rename from godot/scenes/weapon/guns/deagle/gun.tscn rename to scenes_old_2/weapon/guns/deagle/gun.tscn diff --git a/godot/scenes/weapon/guns/deagle/with_hands.tscn b/scenes_old_2/weapon/guns/deagle/with_hands.tscn similarity index 100% rename from godot/scenes/weapon/guns/deagle/with_hands.tscn rename to scenes_old_2/weapon/guns/deagle/with_hands.tscn diff --git a/godot/scenes/weapon/guns/hk/clip.tscn b/scenes_old_2/weapon/guns/hk/clip.tscn similarity index 100% rename from godot/scenes/weapon/guns/hk/clip.tscn rename to scenes_old_2/weapon/guns/hk/clip.tscn diff --git a/godot/scenes/weapon/guns/hk/gun.tscn b/scenes_old_2/weapon/guns/hk/gun.tscn similarity index 100% rename from godot/scenes/weapon/guns/hk/gun.tscn rename to scenes_old_2/weapon/guns/hk/gun.tscn diff --git a/godot/scenes/weapon/guns/hk/with_hands.tscn b/scenes_old_2/weapon/guns/hk/with_hands.tscn similarity index 100% rename from godot/scenes/weapon/guns/hk/with_hands.tscn rename to scenes_old_2/weapon/guns/hk/with_hands.tscn diff --git a/godot/scenes/weapon/guns/m1/clip.tscn b/scenes_old_2/weapon/guns/m1/clip.tscn similarity index 100% rename from godot/scenes/weapon/guns/m1/clip.tscn rename to scenes_old_2/weapon/guns/m1/clip.tscn diff --git a/godot/scenes/weapon/guns/m1/gun.tscn b/scenes_old_2/weapon/guns/m1/gun.tscn similarity index 100% rename from godot/scenes/weapon/guns/m1/gun.tscn rename to scenes_old_2/weapon/guns/m1/gun.tscn diff --git a/godot/scenes/weapon/guns/m1/with_hands.tscn b/scenes_old_2/weapon/guns/m1/with_hands.tscn similarity index 100% rename from godot/scenes/weapon/guns/m1/with_hands.tscn rename to scenes_old_2/weapon/guns/m1/with_hands.tscn diff --git a/godot/scenes/weapon/guns/vector/clip.tscn b/scenes_old_2/weapon/guns/vector/clip.tscn similarity index 100% rename from godot/scenes/weapon/guns/vector/clip.tscn rename to scenes_old_2/weapon/guns/vector/clip.tscn diff --git a/godot/scenes/weapon/guns/vector/gun.tscn b/scenes_old_2/weapon/guns/vector/gun.tscn similarity index 100% rename from godot/scenes/weapon/guns/vector/gun.tscn rename to scenes_old_2/weapon/guns/vector/gun.tscn diff --git a/godot/scenes/weapon/guns/vector/with_hands.tscn b/scenes_old_2/weapon/guns/vector/with_hands.tscn similarity index 100% rename from godot/scenes/weapon/guns/vector/with_hands.tscn rename to scenes_old_2/weapon/guns/vector/with_hands.tscn diff --git a/godot/scenes/weapon/misc/bullet_trace_distance.tscn b/scenes_old_2/weapon/misc/bullet_trace_distance.tscn similarity index 100% rename from godot/scenes/weapon/misc/bullet_trace_distance.tscn rename to scenes_old_2/weapon/misc/bullet_trace_distance.tscn diff --git a/godot/scenes/weapon/misc/bullet_trail_generic.gd b/scenes_old_2/weapon/misc/bullet_trail_generic.gd similarity index 87% rename from godot/scenes/weapon/misc/bullet_trail_generic.gd rename to scenes_old_2/weapon/misc/bullet_trail_generic.gd index 408e0a9..05172a4 100644 --- a/godot/scenes/weapon/misc/bullet_trail_generic.gd +++ b/scenes_old_2/weapon/misc/bullet_trail_generic.gd @@ -1,6 +1,8 @@ extends MeshInstance3D -var alpha = 1.0 +var alpha = 1.0 + + func init(pos1, pos2): var draw_mesh := ImmediateMesh.new() mesh = draw_mesh @@ -9,11 +11,12 @@ func init(pos1, pos2): draw_mesh.surface_add_vertex(pos2) draw_mesh.surface_end() + # Called when the node enters the scene tree for the first time. func _ready() -> void: var dup_material = material_override.duplicate() - material_override = dup_material - pass # Replace with function body. + material_override = dup_material + pass # Replace with function body. # Called every frame. 'delta' is the elapsed time since the previous frame. diff --git a/godot/scenes/weapon/misc/bullet_trail_generic.tscn b/scenes_old_2/weapon/misc/bullet_trail_generic.tscn similarity index 100% rename from godot/scenes/weapon/misc/bullet_trail_generic.tscn rename to scenes_old_2/weapon/misc/bullet_trail_generic.tscn diff --git a/godot/scenes/weapon/misc/muzzle_flash.tscn b/scenes_old_2/weapon/misc/muzzle_flash.tscn similarity index 100% rename from godot/scenes/weapon/misc/muzzle_flash.tscn rename to scenes_old_2/weapon/misc/muzzle_flash.tscn