diff --git a/godot/Scenes/Characters/first_person_player.tscn b/godot/Scenes/Characters/first_person_player.tscn index 71fb28c..1449b9f 100644 --- a/godot/Scenes/Characters/first_person_player.tscn +++ b/godot/Scenes/Characters/first_person_player.tscn @@ -3274,25 +3274,25 @@ nodes/output/position = Vector2(860, 160) node_connections = [&"ground_air_transition", 0, &"iwr_blend", &"ground_air_transition", 1, &"Air", &"iwr_blend", 0, &"Idle", &"iwr_blend", 1, &"Walk", &"iwr_blend", 2, &"Run", &"output", 0, &"ground_air_transition"] [node name="FirstPersonPlayer" type="FirstPersonPlayer"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) [node name="MeshInstance3D" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) visible = false layers = 2 mesh = SubResource("CapsuleMesh_ky6st") [node name="CollisionShape3D" type="CollisionShape3D" parent="."] -visible = false +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) shape = SubResource("ConvexPolygonShape3D_qjfxs") [node name="Head" type="Node3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.578545, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.579, 0) [node name="Camera" type="Camera3D" parent="Head"] cull_mask = 1048573 [node name="Mesh" type="Node3D" parent="."] -transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, -1, 0) +transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, 0) [node name="Armature" type="Node3D" parent="Mesh"] transform = Transform3D(0.01, 0, 0, 0, -3.57628e-09, -0.01, 0, 0.01, -3.57628e-09, 0, 0, 0) diff --git a/godot/Scenes/Characters/player.tscn b/godot/Scenes/Characters/player.tscn index 3a2f9d3..2ebef8c 100644 --- a/godot/Scenes/Characters/player.tscn +++ b/godot/Scenes/Characters/player.tscn @@ -3276,7 +3276,6 @@ node_connections = [&"ground_air_transition", 0, &"iwr_blend", &"ground_air_tran velocity = Vector3(0, -5821.84, 0) [node name="Mesh" type="Node3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.0730165, 0) [node name="Armature" type="Node3D" parent="Mesh"] transform = Transform3D(0.01, 0, 0, 0, -3.57628e-09, -0.01, 0, 0.01, -3.57628e-09, 0, 0, 0) diff --git a/godot/Scenes/Levels/world.tscn b/godot/Scenes/Levels/world.tscn index 013e2b1..80d3526 100644 --- a/godot/Scenes/Levels/world.tscn +++ b/godot/Scenes/Levels/world.tscn @@ -1,10 +1,9 @@ -[gd_scene load_steps=18 format=3 uid="uid://coue2qehpn4fr"] +[gd_scene load_steps=17 format=3 uid="uid://coue2qehpn4fr"] [ext_resource type="Texture2D" path="res://Assets/Textures/Sky.png" id="1_mnexj"] [ext_resource type="Texture2D" path="res://Assets/Textures/Black.png" id="2_fkwcn"] [ext_resource type="Texture2D" path="res://Assets/Textures/Orange.png" id="3_ux02w"] [ext_resource type="Texture2D" path="res://Assets/Textures/Green.png" id="4_wp15n"] -[ext_resource type="PackedScene" path="res://Scenes/Characters/first_person_player.tscn" id="5_8ctht"] [sub_resource type="PanoramaSkyMaterial" id="PanoramaSkyMaterial_6c4vd"] panorama = ExtResource("1_mnexj") @@ -87,4 +86,4 @@ surface_material_override/0 = SubResource("StandardMaterial3D_pfpgv") [node name="CollisionShape3D" type="CollisionShape3D" parent="Slope/StaticBody3D"] shape = SubResource("ConcavePolygonShape3D_rit6o") -[node name="FirstPersonPlayer" parent="." instance=ExtResource("5_8ctht")] +[node name="Players" type="Node" parent="."] diff --git a/godot/Scenes/Network/networking.tscn b/godot/Scenes/Network/networking.tscn index 70df01d..9ad3fb5 100644 --- a/godot/Scenes/Network/networking.tscn +++ b/godot/Scenes/Network/networking.tscn @@ -1,3 +1,5 @@ [gd_scene format=3 uid="uid://clafls1xhludi"] [node name="Lobby" type="Lobby"] + +[node name="NetworkInterface" type="NetworkInterface" parent="."] diff --git a/godot/Scenes/Network/server.tscn b/godot/Scenes/Network/server.tscn new file mode 100644 index 0000000..0bc31e6 --- /dev/null +++ b/godot/Scenes/Network/server.tscn @@ -0,0 +1,3 @@ +[gd_scene format=3 uid="uid://us5sb4a0kq8d"] + +[node name="Server" type="Server"] diff --git a/src/FirstPersonPlayer.cpp b/src/FirstPersonPlayer.cpp index 5114087..f7fe3b6 100644 --- a/src/FirstPersonPlayer.cpp +++ b/src/FirstPersonPlayer.cpp @@ -1,5 +1,6 @@ #include "FirstPersonPlayer.h" +#include #include #include #include @@ -104,7 +105,7 @@ void FirstPersonPlayer::UpdateBobbing(float a_Delta) { void FirstPersonPlayer::UpdateCamera(const InputEventMouseMotion& a_Event) { m_Head->rotate_y(-a_Event.get_relative().x * SENSITIVITY); - m_Mesh->rotate_y(-a_Event.get_relative().x * 0.005); + m_Mesh->rotate_y(-a_Event.get_relative().x * SENSITIVITY); m_Camera->rotate_x(-a_Event.get_relative().y * SENSITIVITY); float rotationX = m_Camera->get_rotation().x; diff --git a/src/FirstPersonPlayer.h b/src/FirstPersonPlayer.h index 3236b30..c1edd84 100644 --- a/src/FirstPersonPlayer.h +++ b/src/FirstPersonPlayer.h @@ -1,14 +1,11 @@ #pragma once -#include -#include -#include +#include "Player.h" #include -#include namespace blitz { -class FirstPersonPlayer : public godot::CharacterBody3D { +class FirstPersonPlayer : public Player { GDCLASS(FirstPersonPlayer, godot::CharacterBody3D) protected: static void _bind_methods(); @@ -20,13 +17,11 @@ class FirstPersonPlayer : public godot::CharacterBody3D { // Godot overrides void _unhandled_input(const godot::Ref&); void _physics_process(float delta); - void _ready(); + void _ready() override; private: - godot::AnimationTree* m_AnimationTree; godot::Camera3D* m_Camera; godot::Node3D* m_Head; - godot::Node3D* m_Mesh; float m_BobTime; float m_Speed; diff --git a/src/Lobby.cpp b/src/Lobby.cpp index 44eb2d3..105c6c9 100644 --- a/src/Lobby.cpp +++ b/src/Lobby.cpp @@ -2,15 +2,21 @@ #include #include +#include +#include +#include +#include using namespace godot; +static const char ServerScenePath[] = "res://Scenes/Network/server.tscn"; + namespace blitz { void Lobby::_bind_methods() { godot::ClassDB::bind_method(godot::D_METHOD("create_game", "port", "dedicated"), &Lobby::CreateGame); godot::ClassDB::bind_method(godot::D_METHOD("join_game", "address", "port"), &Lobby::JoinGame); - ADD_SIGNAL(MethodInfo("player_connected", PropertyInfo(Variant::INT, "peer_id"), PropertyInfo(Variant::STRING, "player_name"))); + ADD_SIGNAL(MethodInfo("player_connected", PropertyInfo(Variant::INT, "peer_id"))); ADD_SIGNAL(MethodInfo("player_disconnected", PropertyInfo(Variant::INT, "peer_id"))); ADD_SIGNAL(MethodInfo("server_disconnected")); ADD_SIGNAL(MethodInfo("local_player_connected")); @@ -46,11 +52,12 @@ Error Lobby::CreateGame(uint16_t a_Port, bool a_Dedicated) { get_multiplayer()->set_multiplayer_peer(peer); + Ref serverScene = ResourceLoader::get_singleton()->load(ServerScenePath); + add_child(serverScene->instantiate()); + if (!a_Dedicated) { emit_signal("local_player_connected"); - String playerName = "Imtheadmin"; - m_Players.insert({get_multiplayer()->get_unique_id(), {playerName}}); - emit_signal("player_connected", get_multiplayer()->get_unique_id(), playerName); + emit_signal("player_connected", get_multiplayer()->get_unique_id()); } return Error::OK; @@ -58,29 +65,25 @@ Error Lobby::CreateGame(uint16_t a_Port, bool a_Dedicated) { void Lobby::Shutdown() { get_multiplayer()->set_multiplayer_peer(nullptr); - m_Players.clear(); -} - -void Lobby::OnPlayerConnected(int32_t a_PeerId) { - emit_signal("player_connected", a_PeerId, "anonymous"); - if (get_multiplayer()->is_server()) { - // TODO: broadcast player join + if (auto* server = find_child("Server")) { + remove_child(server); } } -void Lobby::OnPlayerDisconnected(int32_t a_PeerId) { - m_Players.erase(a_PeerId); - emit_signal("player_disconnected", a_PeerId); +void Lobby::OnPlayerConnected(int64_t a_PeerId) { if (get_multiplayer()->is_server()) { - // TODO: broadcast player leave + emit_signal("player_connected", a_PeerId); + } +} + +void Lobby::OnPlayerDisconnected(int64_t a_PeerId) { + if (get_multiplayer()->is_server()) { + emit_signal("player_disconnected", a_PeerId); } } void Lobby::OnConnectOk() { int32_t peerId = get_multiplayer()->get_unique_id(); - PlayerInfo localPlayer{"MonPseudo"}; - m_Players.insert({peerId, localPlayer}); - emit_signal("player_connected", peerId, localPlayer.m_Name); emit_signal("local_player_connected"); } diff --git a/src/Lobby.h b/src/Lobby.h index 4d97307..ffa49cf 100644 --- a/src/Lobby.h +++ b/src/Lobby.h @@ -1,8 +1,7 @@ #pragma once -#include "PlayerInfo.h" #include -#include +#include "NetworkInterface.h" namespace blitz { @@ -23,10 +22,8 @@ class Lobby : public godot::Node { void Shutdown(); private: - std::map m_Players; - - void OnPlayerConnected(int32_t a_PeerId); - void OnPlayerDisconnected(int32_t a_PeerId); + void OnPlayerConnected(int64_t a_PeerId); + void OnPlayerDisconnected(int64_t a_PeerId); void OnConnectOk(); void OnConnectFail(); void OnServerDisconnected(); diff --git a/src/Main.cpp b/src/Main.cpp index 1538425..2d1f63b 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -1,10 +1,10 @@ #include "Main.h" -#include -#include +#include #include #include -#include +#include +#include #include #include "Lobby.h" @@ -17,7 +17,7 @@ namespace blitz { static constexpr char MainScenePath[] = "res://Scenes/Levels/world.tscn"; void Main::_bind_methods() { - godot::ClassDB::bind_method(godot::D_METHOD("change_scene"), &Main::ChangeScene); + godot::ClassDB::bind_method(godot::D_METHOD("change_scene"), &Main::ChangeScene); } Main::Main() {} @@ -25,16 +25,9 @@ Main::Main() {} Main::~Main() {} void Main::ChangeScene() { - Ref sceneData = ResourceLoader::get_singleton()->load(MainScenePath); + Ref sceneData = ResourceLoader::get_singleton()->load(MainScenePath); World* world = Object::cast_to(sceneData->instantiate()); - get_parent()->add_child(world); - - Lobby* lobby = Object::cast_to(find_child("Lobby")); - DEV_ASSERT(lobby); - - // connect signals - lobby->connect("player_connected", callable_mp(world, &World::AddPlayer)); - lobby->connect("player_disconnected", callable_mp(world, &World::RemovePlayer)); + add_child(world); } } // namespace blitz \ No newline at end of file diff --git a/src/MainMenu.cpp b/src/MainMenu.cpp index 76b0afa..0f4d289 100644 --- a/src/MainMenu.cpp +++ b/src/MainMenu.cpp @@ -35,7 +35,7 @@ void MainMenu::_ready() { m_QuitButton->connect("pressed", callable_mp(this, &MainMenu::OnQuitPressed)); } -void MainMenu::OnConnected() { +void MainMenu::OnConnected() { emit_signal("change_scene"); set_visible(false); } diff --git a/src/NetworkInterface.cpp b/src/NetworkInterface.cpp new file mode 100644 index 0000000..b71bc4b --- /dev/null +++ b/src/NetworkInterface.cpp @@ -0,0 +1,57 @@ +#include "NetworkInterface.h" + +#include +#include +#include + +namespace blitz { + +using namespace godot; + +void NetworkInterface::_bind_methods() { + ClassDB::bind_method(D_METHOD("AddPlayer", "a_PlayerId", "a_PlayerName"), &NetworkInterface::AddPlayer); + ClassDB::bind_method(D_METHOD("RemovePlayer", "a_PlayerId"), &NetworkInterface::RemovePlayer); + ClassDB::bind_method(D_METHOD("SetPlayerPositionAndRotation", "a_PlayerId", "a_Position", "a_Rotation"), + &NetworkInterface::SetPlayerPositionAndRotation); + + ADD_SIGNAL(MethodInfo("AddPlayer", PropertyInfo(Variant::INT, "a_PlayerId"), PropertyInfo(Variant::STRING, "a_PlayerName"))); + ADD_SIGNAL(MethodInfo("RemovePlayer", PropertyInfo(Variant::INT, "a_PlayerId"))); + ADD_SIGNAL(MethodInfo("SetPlayerPositionAndRotation", PropertyInfo(Variant::INT, "a_PlayerId"), + PropertyInfo(Variant::VECTOR3, "a_Position"), PropertyInfo(Variant::VECTOR3, "a_Rotation"))); +} + +NetworkInterface::NetworkInterface() {} + +NetworkInterface::~NetworkInterface() {} + +void NetworkInterface::AddPlayer(int64_t a_PlayerId, godot::String a_PlayerName) { + emit_signal("AddPlayer", a_PlayerId, a_PlayerName); +} + +void NetworkInterface::RemovePlayer(int64_t a_PlayerId) { + emit_signal("RemovePlayer", a_PlayerId); +} + +void NetworkInterface::SetPlayerPositionAndRotation(int64_t a_PlayerId, Vector3 a_Position, Vector3 a_Rotation) { + emit_signal("SetPlayerPositionAndRotation", a_PlayerId, a_Position, a_Rotation); +} + +void NetworkInterface::_ready() { + Dictionary config; + config["rpc_mode"] = MultiplayerAPI::RPC_MODE_AUTHORITY; + config["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_RELIABLE; + config["call_local"] = true; + config["channel"] = 0; + rpc_config("AddPlayer", config); + rpc_config("RemovePlayer", config); + + Dictionary config2; + config["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_RELIABLE; + config["channel"] = 0; + config2["rpc_mode"] = MultiplayerAPI::RPC_MODE_ANY_PEER; + config2["call_local"] = false; + rpc_config("SetPlayerPositionAndRotation", config2); +} + + +} // namespace blitz \ No newline at end of file diff --git a/src/NetworkInterface.h b/src/NetworkInterface.h new file mode 100644 index 0000000..0b86a1a --- /dev/null +++ b/src/NetworkInterface.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +namespace blitz { +class NetworkInterface : public godot::Node { + GDCLASS(NetworkInterface, godot::Node) + protected: + static void _bind_methods(); + + public: + NetworkInterface(); + ~NetworkInterface(); + + void AddPlayer(int64_t a_PlayerId, godot::String a_PlayerName); + void RemovePlayer(int64_t a_PlayerId); + void SetPlayerPositionAndRotation(int64_t a_PlayerId, godot::Vector3 a_Position, godot::Vector3 a_Rotation); + + void _ready() override; +}; + +} // namespace blitz \ No newline at end of file diff --git a/src/Player.cpp b/src/Player.cpp index 4803b58..4bb3bb1 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -16,16 +16,19 @@ static const float AnimationBlend = 7.0; namespace blitz { +using namespace godot; + void Player::_bind_methods() {} Player::Player() {} + Player::~Player() {} void Player::_ready() { godot::InputMap::get_singleton()->load_from_project_settings(); - m_PlayerMesh = Object::cast_to(find_child("Mesh")); + m_Mesh = Object::cast_to(find_child("Mesh")); m_AnimationTree = Object::cast_to(find_child("AnimationTree")); - DEV_ASSERT(m_PlayerMesh); + DEV_ASSERT(m_Mesh); DEV_ASSERT(m_AnimationTree); apply_floor_snap(); @@ -36,9 +39,6 @@ void Player::_physics_process(float delta) { if (godot::Engine::get_singleton()->is_editor_hint()) return; - - apply_floor_snap(); - move_and_slide(); animate(delta); } @@ -65,4 +65,13 @@ void Player::animate(float delta) { m_AnimationTree->set("parameters/ground_air_transition/transition_request", "air"); } } + +Vector3 Player::GetCameraRotation() const { + return m_Mesh->get_rotation(); +} + +void Player::SetCameraRotation(const Vector3& a_Rotation) { + m_Mesh->set_rotation(a_Rotation); +} + } // namespace blitz diff --git a/src/Player.h b/src/Player.h index d01a093..d69f7f9 100644 --- a/src/Player.h +++ b/src/Player.h @@ -5,6 +5,9 @@ #include namespace blitz { + +class World; + class Player : public godot::CharacterBody3D { GDCLASS(Player, godot::CharacterBody3D); @@ -20,11 +23,21 @@ class Player : public godot::CharacterBody3D { void _physics_process(float delta); void animate(float delta); - private: - godot::Node3D* m_PlayerMesh; + godot::Vector3 GetCameraRotation() const; + void SetCameraRotation(const godot::Vector3& a_Rotation); + + uint64_t GetId() const { + return m_PeerId; + } + + protected: + godot::Node3D* m_Mesh; godot::AnimationTree* m_AnimationTree; godot::Vector3 m_SnapVector; float m_Speed; + uint64_t m_PeerId; + + friend class World; }; } // namespace blitz diff --git a/src/Server.cpp b/src/Server.cpp new file mode 100644 index 0000000..883e9c2 --- /dev/null +++ b/src/Server.cpp @@ -0,0 +1,44 @@ +#include "Server.h" + +#include "Lobby.h" +#include "NetworkInterface.h" +#include + +using namespace godot; + +namespace blitz { + +void Server::_bind_methods() {} + +Server::Server() {} + +Server::~Server() {} + +void Server::_ready() { + if (Engine::get_singleton()->is_editor_hint()) + return; + + + m_Lobby = Object::cast_to(get_parent()); + DEV_ASSERT(m_Lobby); + m_NetworkInterface = Object::cast_to(m_Lobby->find_child("NetworkInterface")); + DEV_ASSERT(m_NetworkInterface); + + m_Lobby->connect("player_connected", callable_mp(this, &Server::OnPlayerConnect)); + m_Lobby->connect("player_disconnected", callable_mp(this, &Server::OnPlayerDisconnect)); +} + +void Server::OnPlayerConnect(uint64_t a_PeerId) { + for (int i = 0; i < m_Peers.size(); i++) { + m_NetworkInterface->rpc_id(a_PeerId, "AddPlayer", m_Peers[i], "Aucuneidee"); + } + m_Peers.push_back(a_PeerId); + m_NetworkInterface->rpc("AddPlayer", a_PeerId, "Aucuneidee"); +} + +void Server::OnPlayerDisconnect(uint64_t a_PeerId) { + m_Peers.erase(a_PeerId); + m_NetworkInterface->rpc("RemovePlayer", a_PeerId); +} + +} // namespace blitz \ No newline at end of file diff --git a/src/Server.h b/src/Server.h new file mode 100644 index 0000000..2f98f08 --- /dev/null +++ b/src/Server.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +namespace blitz { + +class Lobby; +class NetworkInterface; + +class Server : public godot::Node { + GDCLASS(Server, godot::Node) + protected: + static void _bind_methods(); + + public: + Server(); + ~Server(); + + void _ready() override; + + void OnPlayerConnect(uint64_t a_PeerId); + void OnPlayerDisconnect(uint64_t a_PeerId); + + private: + Lobby* m_Lobby; + NetworkInterface* m_NetworkInterface; + + godot::TypedArray m_Peers; +}; + +} // namespace blitz \ No newline at end of file diff --git a/src/World.cpp b/src/World.cpp index a39d27e..4b63e27 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1,28 +1,112 @@ #include "World.h" +#include "FirstPersonPlayer.h" +#include "NetworkInterface.h" +#include "Player.h" +#include +#include +#include +#include #include + using namespace godot; namespace blitz { -void World::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_player", "id", "name"), &World::AddPlayer); - ClassDB::bind_method(D_METHOD("remove_player", "id"), &World::RemovePlayer); +static const char FirstPersonPlayerScenePath[] = "res://Scenes/Characters/first_person_player.tscn"; +static const char PlayerScenePath[] = "res://Scenes/Characters/player.tscn"; + +void World::_bind_methods() {} + +void World::_ready() { + if (Engine::get_singleton()->is_editor_hint()) + return; + + m_Players = find_child("Players"); + DEV_ASSERT(m_Players); + + auto* lobby = get_parent()->find_child("Lobby"); + DEV_ASSERT(lobby); + + m_NetworkInterface = Object::cast_to(lobby->find_child("NetworkInterface")); + DEV_ASSERT(m_NetworkInterface); + + m_NetworkInterface->connect("AddPlayer", callable_mp(this, &World::AddPlayer)); + m_NetworkInterface->connect("RemovePlayer", callable_mp(this, &World::RemovePlayer)); + m_NetworkInterface->connect("SetPlayerPositionAndRotation", callable_mp(this, &World::SetPlayerPositionAndRotation)); } + World::World() {} World::~World() {} void World::_process(float delta) { - // do update here +#if DEBUG_ENABLED + if (Engine::get_singleton()->is_editor_hint()) + return; +#endif + if (get_multiplayer()->is_server()) { + for (int i = 0; i < m_Players->get_child_count(); i++) { + Player* player = Object::cast_to(m_Players->get_child(i)); + DEV_ASSERT(player); + m_NetworkInterface->rpc( + "SetPlayerPositionAndRotation", player->m_PeerId, player->get_position(), player->GetCameraRotation()); + } + } else { + Player* player = GetPlayerById(get_multiplayer()->get_unique_id()); + if (player) + m_NetworkInterface->rpc("SetPlayerPositionAndRotation", get_multiplayer()->get_unique_id(), player->get_position(), + player->GetCameraRotation()); + } +} + +Player* World::GetPlayerById(uint64_t a_PlayerId) { + String stringId = UtilityFunctions::var_to_str(a_PlayerId); + for (int i = 0; i < m_Players->get_child_count(); i++) { + Node* player = m_Players->get_child(i); + if (player->get_name() == stringId) { + return Object::cast_to(player); + } + } + return nullptr; } void World::AddPlayer(int32_t a_PlayerId, String a_PlayerName) { - UtilityFunctions::print_rich("New player joined ! Id : ", a_PlayerId, ", Name : ", a_PlayerName); + UtilityFunctions::print("New Player with id : ", a_PlayerId); + if (a_PlayerId == get_multiplayer()->get_unique_id()) { + Ref serverScene = ResourceLoader::get_singleton()->load(FirstPersonPlayerScenePath); + FirstPersonPlayer* player = Object::cast_to(serverScene->instantiate()); + player->set_name(UtilityFunctions::var_to_str(a_PlayerId)); + player->m_PeerId = a_PlayerId; + m_Players->add_child(player); + } else { + Ref serverScene = ResourceLoader::get_singleton()->load(PlayerScenePath); + Player* player = Object::cast_to(serverScene->instantiate()); + player->set_name(UtilityFunctions::var_to_str(a_PlayerId)); + player->m_PeerId = a_PlayerId; + m_Players->add_child(player); + } } -void World::RemovePlayer(int32_t a_PlayerId) {} +void World::RemovePlayer(int32_t a_PlayerId) { + UtilityFunctions::print("Removing Player with id : ", a_PlayerId); + Player* player = GetPlayerById(a_PlayerId); + if (player) { + player->queue_free(); + } +} + +void World::SetPlayerPositionAndRotation(int64_t a_PlayerId, Vector3 a_Position, Vector3 a_Rotation) { + if (a_PlayerId == get_multiplayer()->get_unique_id()) + return; + + Player* player = GetPlayerById(a_PlayerId); + if (player) { + player->set_position(a_Position); + player->SetCameraRotation(a_Rotation); + } +} } // namespace blitz \ No newline at end of file diff --git a/src/World.h b/src/World.h index 705d505..8618bfd 100644 --- a/src/World.h +++ b/src/World.h @@ -3,6 +3,10 @@ #include namespace blitz { + +class Player; +class NetworkInterface; + class World : public godot::Node3D { GDCLASS(World, godot::Node3D) protected: @@ -14,7 +18,17 @@ class World : public godot::Node3D { void _process(float delta); + void _ready() override; + + Player* GetPlayerById(uint64_t a_PlayerId); + void AddPlayer(int32_t a_PlayerId, godot::String a_PlayerName); void RemovePlayer(int32_t a_PlayerId); + void SetPlayerPositionAndRotation(int64_t a_PlayerId, godot::Vector3 a_Position, godot::Vector3 a_Rotation); + + private: + NetworkInterface* m_NetworkInterface; + godot::Node* m_Players; + float m_PassedTime; }; } // namespace blitz \ No newline at end of file diff --git a/src/register_types.cpp b/src/register_types.cpp index acb18e6..f58997d 100644 --- a/src/register_types.cpp +++ b/src/register_types.cpp @@ -4,7 +4,9 @@ #include "Lobby.h" #include "Main.h" #include "MainMenu.h" +#include "NetworkInterface.h" #include "Player.h" +#include "Server.h" #include "SpringArmPivot.h" #include "World.h" @@ -22,6 +24,8 @@ static void RegisterClasses() { ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); } void initialize_example_module(ModuleInitializationLevel p_level) {