diff options
Diffstat (limited to '')
-rw-r--r-- | src/AssetManager.cpp | 7 | ||||
-rw-r--r-- | src/AssetManager.hpp | 2 | ||||
-rw-r--r-- | src/Event.cpp | 33 | ||||
-rw-r--r-- | src/Event.hpp | 96 | ||||
-rw-r--r-- | src/GameState.cpp | 492 | ||||
-rw-r--r-- | src/GameState.hpp | 49 | ||||
-rw-r--r-- | src/Network.cpp | 4 | ||||
-rw-r--r-- | src/NetworkClient.cpp | 9 | ||||
-rw-r--r-- | src/NetworkClient.hpp | 1 | ||||
-rw-r--r-- | src/Render.cpp | 129 | ||||
-rw-r--r-- | src/Render.hpp | 5 | ||||
-rw-r--r-- | src/Renderer.hpp | 14 | ||||
-rw-r--r-- | src/RendererSection.cpp | 4 | ||||
-rw-r--r-- | src/RendererSection.hpp | 2 | ||||
-rw-r--r-- | src/RendererWorld.cpp | 158 | ||||
-rw-r--r-- | src/RendererWorld.hpp | 22 | ||||
-rw-r--r-- | src/Shader.cpp | 35 | ||||
-rw-r--r-- | src/Stream.cpp | 6 | ||||
-rw-r--r-- | src/ThreadGame.cpp | 75 | ||||
-rw-r--r-- | src/ThreadGame.hpp | 3 | ||||
-rw-r--r-- | src/ThreadNetwork.cpp | 36 | ||||
-rw-r--r-- | src/ThreadNetwork.hpp | 2 | ||||
-rw-r--r-- | src/Utility.cpp | 8 | ||||
-rw-r--r-- | src/Utility.hpp | 2 | ||||
-rw-r--r-- | src/World.cpp | 3 | ||||
-rw-r--r-- | src/World.hpp | 4 |
26 files changed, 801 insertions, 400 deletions
diff --git a/src/AssetManager.cpp b/src/AssetManager.cpp index 351a118..28c08fa 100644 --- a/src/AssetManager.cpp +++ b/src/AssetManager.cpp @@ -37,6 +37,7 @@ void AssetManager::LoadTextureResources() { std::string filename = index["meta"]["image"].get<std::string>(); float textureWidth = index["meta"]["size"]["w"].get<int>(); float textureHeight = index["meta"]["size"]["h"].get<int>(); + size_t sizeName = 0,sizeTexture = 0; for (auto &it:index["frames"]) { auto frame = it["frame"]; TextureCoordinates coord; @@ -47,9 +48,11 @@ void AssetManager::LoadTextureResources() { std::string assetName = it["filename"].get<std::string>(); assetName.insert(0, "minecraft/textures/"); assetName.erase(assetName.length() - 4); + assetName.shrink_to_fit(); + sizeName += sizeof(assetName) + assetName.capacity(); + sizeTexture += sizeof(coord); assetTextures[assetName] = coord; } - textureAtlas = new Texture(filename); LOG(INFO) << "Texture atlas id is " << textureAtlas->texture; } @@ -141,7 +144,7 @@ std::string AssetManager::GetTextureAssetNameByBlockId(BlockTextureId block) { } GLuint AssetManager::GetTextureAtlas() { - return textureAtlas->texture; + return textureAtlas->texture; } TextureCoordinates AssetManager::GetTextureByBlock(BlockTextureId block) { diff --git a/src/AssetManager.hpp b/src/AssetManager.hpp index ba5546b..ca8bd35 100644 --- a/src/AssetManager.hpp +++ b/src/AssetManager.hpp @@ -24,7 +24,7 @@ struct TextureCoordinates { return !(*this == TextureCoordinates(-1, -1, -1, -1)); } - float x, y, w, h; + double x, y, w, h; }; struct BlockTextureId { diff --git a/src/Event.cpp b/src/Event.cpp index e58a6f4..94eedba 100644 --- a/src/Event.cpp +++ b/src/Event.cpp @@ -19,13 +19,20 @@ void EventListener::PushEvent(Event event) { eventsMutex.lock(); handlersMutex.lock(); if (handlers[event.type]) { - //LOG(ERROR) << "Listener notified about event " << int(event.type); events.push(event); } handlersMutex.unlock(); eventsMutex.unlock(); } +void EventListener::DirectCall(Event event) +{ + handlersMutex.lock(); + if (handlers[event.type]) + handlers[event.type](event.data); + handlersMutex.unlock(); +} + bool EventListener::IsEventsQueueIsNotEmpty() { eventsMutex.lock(); bool value = !events.empty(); @@ -74,20 +81,33 @@ void EventAgregator::PushEvent(EventType type, EventData data) { Event event; event.type = type; event.data = data; + queueMutex.lock(); eventsToHandle.push(event); + queueMutex.unlock(); if (!isStarted) { isStarted = true; std::thread(&EventAgregator::EventHandlingLoop).detach(); } } +void EventAgregator::DirectEventCall(EventType type, EventData data) +{ + Event event {type, data}; + listenersMutex.lock(); + for (auto &listener : listeners) { + listenersMutex.unlock(); + listener->DirectCall(event); + listenersMutex.lock(); + } + listenersMutex.unlock(); +} + void EventAgregator::EventHandlingLoop() { + LoopExecutionTimeController timer(std::chrono::milliseconds(5)); while (true) { queueMutex.lock(); if (!eventsToHandle.empty()) { - auto queue = eventsToHandle; - while (!eventsToHandle.empty()) - eventsToHandle.pop(); + auto queue = std::move(eventsToHandle); queueMutex.unlock(); while (!queue.empty()) { @@ -103,9 +123,6 @@ void EventAgregator::EventHandlingLoop() { queueMutex.lock(); } queueMutex.unlock(); + timer.Update(); } -} - -void SetGlobalState(GlobalState state) { - EventAgregator::PushEvent(EventType::GlobalAppState, GlobalAppStateData{state}); }
\ No newline at end of file diff --git a/src/Event.hpp b/src/Event.hpp index c553058..232e6f2 100644 --- a/src/Event.hpp +++ b/src/Event.hpp @@ -9,6 +9,8 @@ #include <variant> #include <functional> +#include <SFML/Window.hpp> + #include "Vector.hpp" #include "Packet.hpp" #include "FSM.hpp" @@ -18,13 +20,25 @@ enum class EventType { ChunkChanged, ConnectToServer, ConnectionSuccessfull, - GlobalAppState, Disconnect, RequestNetworkClient, RegisterNetworkClient, PlayerConnected, RemoveLoadingScreen, ConnectionFailed, + Exit, + Disconnected, + Connecting, + NetworkClientException, + MouseMoved, + KeyPressed, + KeyReleased, + InitalizeSectionRender, + UpdateSectionsRender, + CreateSectionRender, + CreatedSectionRender, + PlayerPosChanged, + DeleteSectionRender, }; struct EchoData { @@ -46,24 +60,8 @@ struct ConnectionSuccessfullData { NetworkClient *ptr; }; -enum class GlobalState { - InitialLoading, - MainMenu, - Connecting, - Loading, - Playing, - PauseMenu, - Exiting, -}; - -void SetGlobalState(GlobalState state); - -struct GlobalAppStateData { - GlobalState state; -}; - struct DisconnectData { - + std::string reason; }; struct SendPacketData { @@ -96,9 +94,64 @@ struct ConnectionFailedData { std::string reason; }; +struct ExitData { + +}; + +struct DisconnectedData { + std::string reason; +}; + +struct ConnectingData { + +}; + +struct NetworkClientExceptionData { + std::string what; +}; + +struct MouseMovedData { + double x, y; +}; + +struct KeyPressedData { + sf::Keyboard::Key key; +}; + +struct KeyReleasedData { + sf::Keyboard::Key key; +}; + +struct InitalizeSectionRenderData { + Vector pos; +}; + +struct CreateSectionRenderData { + Vector pos; +}; + +struct CreatedSectionRenderData { + Vector pos; +}; + +struct PlayerPosChangedData { + Vector newPos; +}; + +struct UpdateSectionsRenderData { + +}; + +struct DeleteSectionRenderData { + Vector pos; +}; + using EventData = std::variant<EchoData, ChunkChangedData, ConnectToServerData, ConnectionSuccessfullData, - GlobalAppStateData, DisconnectData, SendPacketData, ReceivePacketData, RequestNetworkClientData, - RegisterNetworkClientData, PlayerConnectedData, RemoveLoadingScreenData, ConnectionFailedData>; + DisconnectData, SendPacketData, ReceivePacketData, RequestNetworkClientData, RegisterNetworkClientData, + PlayerConnectedData, RemoveLoadingScreenData, ConnectionFailedData, ExitData, DisconnectedData, + ConnectingData, NetworkClientExceptionData, MouseMovedData, KeyPressedData, KeyReleasedData, + InitalizeSectionRenderData, CreateSectionRenderData, CreatedSectionRenderData, PlayerPosChangedData, + UpdateSectionsRenderData, DeleteSectionRenderData>; struct Event { EventType type; @@ -120,6 +173,8 @@ class EventListener { void PushEvent(Event event); + void DirectCall(Event event); + public: EventListener(); ~EventListener(); @@ -147,4 +202,5 @@ class EventAgregator { public: static void PushEvent(EventType type, EventData data); + static void DirectEventCall(EventType, EventData data); };
\ No newline at end of file diff --git a/src/GameState.cpp b/src/GameState.cpp index a2c5182..52b5f0f 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -5,7 +5,6 @@ GameState::GameState(NetworkClient *networkClient) : nc(networkClient) { Front = glm::vec3(0.0f, 0.0f, -1.0f); this->SetPosition(glm::vec3(0.0f, 0.0f, 3.0f)); this->WorldUp = glm::vec3(0.0f, 1.0f, 0.0f); - this->updateCameraVectors(); } void GameState::Update(float deltaTime) { @@ -44,7 +43,7 @@ void GameState::Update(float deltaTime) { if (!isCollides) { g_PlayerX += g_PlayerVelocityX * deltaTime; g_PlayerZ += g_PlayerVelocityZ * deltaTime; - } + } const float AirResistance = 10.0f; glm::vec3 vel(g_PlayerVelocityX, 0, g_PlayerVelocityZ); @@ -53,259 +52,265 @@ void GameState::Update(float deltaTime) { g_PlayerVelocityX = vel.x; g_PlayerVelocityZ = vel.z; } +} +void GameState::UpdatePacket() +{ + //Packet handling + auto ptr = nc->ReceivePacket(); + if (ptr) { + switch ((PacketNamePlayCB)ptr->GetPacketId()) { + case SpawnObject: + break; + case SpawnExperienceOrb: + break; + case SpawnGlobalEntity: + break; + case SpawnMob: + break; + case SpawnPainting: + break; + case SpawnPlayer: + break; + case AnimationCB: + break; + case Statistics: + break; + case BlockBreakAnimation: + break; + case UpdateBlockEntity: + break; + case BlockAction: + break; + case BlockChange: + break; + case BossBar: + break; + case ServerDifficulty: + break; + case TabCompleteCB: + break; + case ChatMessageCB: + break; + case MultiBlockChange: + break; + case ConfirmTransactionCB: + break; + case CloseWindowCB: + break; + case OpenWindow: + break; + case WindowItems: + break; + case WindowProperty: + break; + case SetSlot: + break; + case SetCooldown: + break; + case PluginMessageCB: + break; + case NamedSoundEffect: + break; + case DisconnectPlay: { + auto packet = std::static_pointer_cast<PacketDisconnectPlay>(ptr); + LOG(INFO) << "Disconnect reason: " << packet->Reason; + EventAgregator::PushEvent(EventType::Disconnect, DisconnectData{ packet->Reason }); + break; + } + case EntityStatus: + break; + case Explosion: + break; + case UnloadChunk: + break; + case ChangeGameState: + break; + case KeepAliveCB: + LOG(WARNING) << "Receive KeepAlive packet in GameState handler"; + break; + case ChunkData: { + auto packet = std::static_pointer_cast<PacketChunkData>(ptr); + world.ParseChunkData(packet); + break; + } + case Effect: + break; + case Particle: + break; + case JoinGame: { + auto packet = std::static_pointer_cast<PacketJoinGame>(ptr); + g_PlayerEid = packet->EntityId; + g_Gamemode = (packet->Gamemode & 0b11111011); + g_Dimension = packet->Dimension; + g_Difficulty = packet->Difficulty; + g_MaxPlayers = packet->MaxPlayers; + g_LevelType = packet->LevelType; + g_ReducedDebugInfo = packet->ReducedDebugInfo; + LOG(INFO) << "Gamemode is " << g_Gamemode << ", Difficulty is " << (int)g_Difficulty + << ", Level Type is " << g_LevelType; + EventAgregator::PushEvent(EventType::PlayerConnected, PlayerConnectedData{ this }); + break; + } + case Map: + break; + case EntityRelativeMove: + break; + case EntityLookAndRelativeMove: + break; + case EntityLook: + break; + case Entity: + break; + case VehicleMove: + break; + case OpenSignEditor: + break; + case PlayerAbilitiesCB: + break; + case CombatEvent: + break; + case PlayerListItem: + break; + case PlayerPositionAndLookCB: { + auto packet = std::static_pointer_cast<PacketPlayerPositionAndLookCB>(ptr); + if ((packet->Flags & 0x10) != 0) { + g_PlayerPitch += packet->Pitch; + } + else { + g_PlayerPitch = packet->Pitch; + }; - //Packet handling - auto ptr = nc->ReceivePacket(); - while (ptr != nullptr) { - switch ((PacketNamePlayCB) ptr->GetPacketId()) { - case SpawnObject: - break; - case SpawnExperienceOrb: - break; - case SpawnGlobalEntity: - break; - case SpawnMob: - break; - case SpawnPainting: - break; - case SpawnPlayer: - break; - case AnimationCB: - break; - case Statistics: - break; - case BlockBreakAnimation: - break; - case UpdateBlockEntity: - break; - case BlockAction: - break; - case BlockChange: - break; - case BossBar: - break; - case ServerDifficulty: - break; - case TabCompleteCB: - break; - case ChatMessageCB: - break; - case MultiBlockChange: - break; - case ConfirmTransactionCB: - break; - case CloseWindowCB: - break; - case OpenWindow: - break; - case WindowItems: - break; - case WindowProperty: - break; - case SetSlot: - break; - case SetCooldown: - break; - case PluginMessageCB: - break; - case NamedSoundEffect: - break; - case DisconnectPlay: { - auto packet = std::static_pointer_cast<PacketDisconnectPlay>(ptr); - LOG(INFO) << "Disconnect reason: " << packet->Reason; - EventAgregator::PushEvent(EventType::GlobalAppState, GlobalAppStateData{GlobalState::Exiting}); - break; - } - case EntityStatus: - break; - case Explosion: - break; - case UnloadChunk: - break; - case ChangeGameState: - break; - case KeepAliveCB: - LOG(WARNING) << "Receive KeepAlive packet in GameState handler"; - break; - case ChunkData: { - auto packet = std::static_pointer_cast<PacketChunkData>(ptr); - world.ParseChunkData(packet); - break; - } - case Effect: - break; - case Particle: - break; - case JoinGame: { - auto packet = std::static_pointer_cast<PacketJoinGame>(ptr); - g_PlayerEid = packet->EntityId; - g_Gamemode = (packet->Gamemode & 0b11111011); - g_Dimension = packet->Dimension; - g_Difficulty = packet->Difficulty; - g_MaxPlayers = packet->MaxPlayers; - g_LevelType = packet->LevelType; - g_ReducedDebugInfo = packet->ReducedDebugInfo; - LOG(INFO) << "Gamemode is " << g_Gamemode << ", Difficulty is " << (int) g_Difficulty - << ", Level Type is " << g_LevelType; - SetGlobalState(GlobalState::Loading); - EventAgregator::PushEvent(EventType::PlayerConnected, PlayerConnectedData{this}); - break; - } - case Map: - break; - case EntityRelativeMove: - break; - case EntityLookAndRelativeMove: - break; - case EntityLook: - break; - case Entity: - break; - case VehicleMove: - break; - case OpenSignEditor: - break; - case PlayerAbilitiesCB: - break; - case CombatEvent: - break; - case PlayerListItem: - break; - case PlayerPositionAndLookCB: { - auto packet = std::static_pointer_cast<PacketPlayerPositionAndLookCB>(ptr); - if ((packet->Flags & 0x10) != 0) { - g_PlayerPitch += packet->Pitch; - } else { - g_PlayerPitch = packet->Pitch; - }; - - if ((packet->Flags & 0x08) != 0) { - g_PlayerYaw += packet->Yaw; - } else { - g_PlayerYaw = packet->Yaw; - } + if ((packet->Flags & 0x08) != 0) { + g_PlayerYaw += packet->Yaw; + } + else { + g_PlayerYaw = packet->Yaw; + } - if ((packet->Flags & 0x01) != 0) { - g_PlayerX += packet->X; - } else { - g_PlayerX = packet->X; - } + if ((packet->Flags & 0x01) != 0) { + g_PlayerX += packet->X; + } + else { + g_PlayerX = packet->X; + } - if ((packet->Flags & 0x02) != 0) { - g_PlayerY += packet->Y; - } else { - g_PlayerY = packet->Y; - } + if ((packet->Flags & 0x02) != 0) { + g_PlayerY += packet->Y; + } + else { + g_PlayerY = packet->Y; + } - if ((packet->Flags & 0x04) != 0) { - g_PlayerZ += packet->Z; - } else { - g_PlayerZ = packet->Z; - } + if ((packet->Flags & 0x04) != 0) { + g_PlayerZ += packet->Z; + } + else { + g_PlayerZ = packet->Z; + } - //if (!g_IsGameStarted) - LOG(INFO) << "PlayerPos is " << g_PlayerX << ", " << g_PlayerY << ", " << g_PlayerZ << "\t\tAngle: " - << g_PlayerYaw << "," << g_PlayerPitch; + EventAgregator::PushEvent(EventType::PlayerPosChanged, PlayerPosChangedData{ Vector(g_PlayerX,g_PlayerY,g_PlayerZ) }); + LOG(INFO) << "PlayerPos is " << g_PlayerX << ", " << g_PlayerY << ", " << g_PlayerZ << "\t\tAngle: " + << g_PlayerYaw << "," << g_PlayerPitch; - if (!g_IsGameStarted) { - LOG(INFO) << "Game is started"; - EventAgregator::PushEvent(EventType::RemoveLoadingScreen, RemoveLoadingScreenData{}); - SetGlobalState(GlobalState::Playing); - } + if (!g_IsGameStarted) { + LOG(INFO) << "Game is started"; + EventAgregator::PushEvent(EventType::RemoveLoadingScreen, RemoveLoadingScreenData{}); + } - g_IsGameStarted = true; + g_IsGameStarted = true; - auto packetResponse = std::make_shared<PacketTeleportConfirm>(packet->TeleportId); - auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0); + auto packetResponse = std::make_shared<PacketTeleportConfirm>(packet->TeleportId); + auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0); - nc->SendPacket(packetResponse); - nc->SendPacket(packetPerformRespawn); - break; - } - case UseBed: - break; - case UnlockRecipes: - break; - case DestroyEntities: - break; - case RemoveEntityEffect: - break; - case ResourcePackSend: - break; - case Respawn: - break; - case EntityHeadLook: - break; - case SelectAdvancementTab: - break; - case WorldBorder: - break; - case Camera: - break; - case HeldItemChangeCB: - break; - case DisplayScoreboard: - break; - case EntityMetadata: - break; - case AttachEntity: - break; - case EntityVelocity: - break; - case EntityEquipment: - break; - case SetExperience: - break; - case UpdateHealth: { - auto packet = std::static_pointer_cast<PacketUpdateHealth>(ptr); - g_PlayerHealth = packet->Health; - if (g_PlayerHealth <= 0) { - LOG(INFO) << "Player is dead. Respawning..."; - auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0); - nc->SendPacket(packetPerformRespawn); - } - break; - } - case ScoreboardObjective: - break; - case SetPassengers: - break; - case Teams: - break; - case UpdateScore: - break; - case SpawnPosition: { - auto packet = std::static_pointer_cast<PacketSpawnPosition>(ptr); - g_SpawnPosition = packet->Location; - LOG(INFO) << "Spawn position is " << g_SpawnPosition.GetX() << "," << g_SpawnPosition.GetY() << "," - << g_SpawnPosition.GetZ(); - break; - } - case TimeUpdate: - break; - case Title: - break; - case SoundEffect: - break; - case PlayerListHeaderAndFooter: - break; - case CollectItem: - break; - case EntityTeleport: - break; - case Advancements: - break; - case EntityProperties: - break; - case EntityEffect: - break; - } - ptr = nc->ReceivePacket(); - } + nc->SendPacket(packetResponse); + nc->SendPacket(packetPerformRespawn); + break; + } + case UseBed: + break; + case UnlockRecipes: + break; + case DestroyEntities: + break; + case RemoveEntityEffect: + break; + case ResourcePackSend: + break; + case Respawn: + break; + case EntityHeadLook: + break; + case SelectAdvancementTab: + break; + case WorldBorder: + break; + case Camera: + break; + case HeldItemChangeCB: + break; + case DisplayScoreboard: + break; + case EntityMetadata: + break; + case AttachEntity: + break; + case EntityVelocity: + break; + case EntityEquipment: + break; + case SetExperience: + break; + case UpdateHealth: { + auto packet = std::static_pointer_cast<PacketUpdateHealth>(ptr); + g_PlayerHealth = packet->Health; + if (g_PlayerHealth <= 0) { + LOG(INFO) << "Player is dead. Respawning..."; + auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0); + nc->SendPacket(packetPerformRespawn); + } + break; + } + case ScoreboardObjective: + break; + case SetPassengers: + break; + case Teams: + break; + case UpdateScore: + break; + case SpawnPosition: { + auto packet = std::static_pointer_cast<PacketSpawnPosition>(ptr); + g_SpawnPosition = packet->Location; + LOG(INFO) << "Spawn position is " << g_SpawnPosition.GetX() << "," << g_SpawnPosition.GetY() << "," + << g_SpawnPosition.GetZ(); + break; + } + case TimeUpdate: + break; + case Title: + break; + case SoundEffect: + break; + case PlayerListHeaderAndFooter: + break; + case CollectItem: + break; + case EntityTeleport: + break; + case Advancements: + break; + case EntityProperties: + break; + case EntityEffect: + break; + } + } } void GameState::HandleMovement(GameState::Direction direction, float deltaTime) { + if (!g_IsGameStarted) + return; const float PlayerSpeed = 40.0; float velocity = PlayerSpeed * deltaTime; glm::vec3 vel(g_PlayerVelocityX, g_PlayerVelocityY, g_PlayerVelocityZ); @@ -339,6 +344,8 @@ void GameState::HandleMovement(GameState::Direction direction, float deltaTime) } void GameState::HandleRotation(double yaw, double pitch) { + if (!g_IsGameStarted) + return; this->SetYaw(Yaw() + yaw); this->SetPitch(Pitch() + pitch); if (this->Pitch() > 89.0f) @@ -352,6 +359,7 @@ void GameState::HandleRotation(double yaw, double pitch) { } glm::mat4 GameState::GetViewMatrix() { + updateCameraVectors(); auto pos = this->Position(); pos.y += 1.62; return glm::lookAt(pos, pos + this->Front, this->Up); diff --git a/src/GameState.hpp b/src/GameState.hpp index dbe8f9d..d104e54 100644 --- a/src/GameState.hpp +++ b/src/GameState.hpp @@ -16,7 +16,8 @@ public: void Update(float deltaTime); - //Navigation + void UpdatePacket(); + enum Direction { FORWARD, BACKWARD, LEFT, RIGHT, JUMP }; @@ -37,33 +38,31 @@ public: glm::vec3 Right; glm::vec3 WorldUp; - //Everything other World world; - //bool &isRunning; - std::string g_PlayerUuid; - std::string g_PlayerName; - bool g_IsGameStarted; - int g_PlayerEid; - int g_Gamemode; - int g_Dimension; - byte g_Difficulty; - byte g_MaxPlayers; - std::string g_LevelType; - bool g_ReducedDebugInfo; + std::string g_PlayerUuid = ""; + std::string g_PlayerName = ""; + bool g_IsGameStarted = false; + int g_PlayerEid = 0; + int g_Gamemode = 0; + int g_Dimension = 0; + byte g_Difficulty = 0; + byte g_MaxPlayers = 0; + std::string g_LevelType = ""; + bool g_ReducedDebugInfo = false; Vector g_SpawnPosition; - bool g_PlayerInvulnerable; - bool g_PlayerFlying; - bool g_PlayerAllowFlying; - bool g_PlayerCreativeMode; - float g_PlayerFlyingSpeed; - float g_PlayerFovModifier; - float g_PlayerPitch; - float g_PlayerYaw; - double g_PlayerX; - double g_PlayerY; - double g_PlayerZ; - float g_PlayerHealth; + bool g_PlayerInvulnerable = false; + bool g_PlayerFlying = false; + bool g_PlayerAllowFlying = false; + bool g_PlayerCreativeMode = false; + float g_PlayerFlyingSpeed = 0; + float g_PlayerFovModifier = 0; + float g_PlayerPitch = 0; + float g_PlayerYaw = 0; + double g_PlayerX = 0; + double g_PlayerY = 0; + double g_PlayerZ = 0; + float g_PlayerHealth = 0; bool g_OnGround = true; double g_PlayerVelocityX = 0; diff --git a/src/Network.cpp b/src/Network.cpp index 47ae751..62ad1f9 100644 --- a/src/Network.cpp +++ b/src/Network.cpp @@ -4,14 +4,14 @@ Network::Network(std::string address, unsigned short port) { try { socket = new Socket(address, port); } catch (std::exception &e) { - LOG(WARNING) << "CONNECT FAULT"; + LOG(WARNING) << "Connection failed: " << e.what(); throw; } try { stream = new StreamSocket(socket); } catch (std::exception &e) { - LOG(WARNING) << "NOT STREAMED"; + LOG(WARNING) << "Stream creation failed: " << e.what(); } } diff --git a/src/NetworkClient.cpp b/src/NetworkClient.cpp index d944f54..5877952 100644 --- a/src/NetworkClient.cpp +++ b/src/NetworkClient.cpp @@ -51,7 +51,8 @@ void NetworkClient::SendPacket(std::shared_ptr<Packet> packet) { void NetworkClient::NetworkLoop() { auto timeOfLastKeepAlivePacket = std::chrono::steady_clock::now(); el::Helpers::setThreadName("Network"); - LOG(INFO) << "Network thread is started"; + bool validEnded = true; + try { while (isActive) { toSendMutex.lock(); @@ -85,7 +86,7 @@ void NetworkClient::NetworkLoop() { } } } catch (std::exception &e) { - LOG(ERROR) << "Exception catched in NetworkLoop: " << e.what(); + EventAgregator::PushEvent(EventType::NetworkClientException, NetworkClientExceptionData{ e.what() }); + validEnded = false; } - LOG(INFO) << "Network thread is stopped"; -} +}
\ No newline at end of file diff --git a/src/NetworkClient.hpp b/src/NetworkClient.hpp index 83db517..9acae84 100644 --- a/src/NetworkClient.hpp +++ b/src/NetworkClient.hpp @@ -5,6 +5,7 @@ #include <mutex> #include "Network.hpp" +#include "Event.hpp" class NetworkClient { Network network; diff --git a/src/Render.cpp b/src/Render.cpp index 9121d1a..38a6ab0 100644 --- a/src/Render.cpp +++ b/src/Render.cpp @@ -30,6 +30,8 @@ void Render::InitSfml(unsigned int WinWidth, unsigned int WinHeight, std::string window->setPosition(sf::Vector2i(sf::VideoMode::getDesktopMode().width / 2 - window->getSize().x / 2, sf::VideoMode::getDesktopMode().height / 2 - window->getSize().y / 2)); SetMouseCapture(false); + renderState.WindowWidth = WinWidth; + renderState.WindowHeight = WinHeight; } void Render::InitGlew() { @@ -51,19 +53,18 @@ void Render::InitGlew() { } void Render::PrepareToRendering() { - shader = new Shader("./shaders/face.vs", "./shaders/face.fs"); - shader->Use(); - //TextureAtlas texture glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, AssetManager::Instance().GetTextureAtlas()); - glUniform1i(glGetUniformLocation(shader->Program, "textureAtlas"), 0); + glBindTexture(GL_TEXTURE_2D, AssetManager::Instance().GetTextureAtlas()); } void Render::RenderFrame() { glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + if (renderWorld) + world->Render(renderState); + window->display(); } @@ -77,33 +78,78 @@ void Render::HandleEvents() { break; case sf::Event::Resized: glViewport(0, 0, window->getSize().x, window->getSize().y); + renderState.WindowWidth = window->getSize().x; + renderState.WindowHeight = window->getSize().y; break; case sf::Event::KeyPressed: if (!window->hasFocus()) break; - switch (event.key.code) { - case sf::Keyboard::Escape: - LOG(INFO) << "Received close event by esc"; - isRunning = false; - break; - case sf::Keyboard::T: - SetMouseCapture(!isMouseCaptured); - break; - case sf::Keyboard::U: - EventAgregator::PushEvent(EventType::ConnectToServer, ConnectToServerData{"127.0.0.1", 25565}); + switch (event.key.code) { + case sf::Keyboard::Escape: + LOG(INFO) << "Received close event by esc"; + isRunning = false; + break; + case sf::Keyboard::T: + SetMouseCapture(!isMouseCaptured); + break; + case sf::Keyboard::U: + EventAgregator::PushEvent(EventType::ConnectToServer, ConnectToServerData{ "127.0.0.1", 25565 }); + break; + case sf::Keyboard::I: + EventAgregator::PushEvent(EventType::Disconnect, DisconnectData{ "Manual disconnect" }); + break; + case sf::Keyboard::K: + if (renderWorld) { + world->MaxRenderingDistance--; + if (world->MaxRenderingDistance <= 0) + world->MaxRenderingDistance = 1; + LOG(INFO) << "Decreased rendering distance: " << world->MaxRenderingDistance; + EventAgregator::PushEvent(EventType::UpdateSectionsRender, UpdateSectionsRenderData{}); + } + break; + case sf::Keyboard::L: + if (renderWorld) { + world->MaxRenderingDistance++; + LOG(INFO) << "Increased rendering distance: " << world->MaxRenderingDistance; + EventAgregator::PushEvent(EventType::UpdateSectionsRender, UpdateSectionsRenderData{}); + } + break; + case sf::Keyboard::W: + EventAgregator::PushEvent(EventType::KeyPressed, KeyPressedData{ sf::Keyboard::W }); + break; + case sf::Keyboard::A: + EventAgregator::PushEvent(EventType::KeyPressed, KeyPressedData{ sf::Keyboard::A }); + break; + case sf::Keyboard::S: + EventAgregator::PushEvent(EventType::KeyPressed, KeyPressedData{ sf::Keyboard::S }); + break; + case sf::Keyboard::D: + EventAgregator::PushEvent(EventType::KeyPressed, KeyPressedData{ sf::Keyboard::D }); + break; default: break; } + case sf::Event::KeyReleased: + if (!window->hasFocus()) break; + switch (event.key.code) { + case sf::Keyboard::W: + EventAgregator::PushEvent(EventType::KeyReleased, KeyReleasedData{ sf::Keyboard::W }); + break; + case sf::Keyboard::A: + EventAgregator::PushEvent(EventType::KeyReleased, KeyReleasedData{ sf::Keyboard::A }); + break; + case sf::Keyboard::S: + EventAgregator::PushEvent(EventType::KeyReleased, KeyReleasedData{ sf::Keyboard::S }); + break; + case sf::Keyboard::D: + EventAgregator::PushEvent(EventType::KeyReleased, KeyReleasedData{ sf::Keyboard::D }); + break; + default: + break; + } default: break; } - } - if (window->hasFocus()) { - /*if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) gameState->HandleMovement(GameState::FORWARD, deltaTime); - if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) gameState->HandleMovement(GameState::BACKWARD, deltaTime); - if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) gameState->HandleMovement(GameState::LEFT, deltaTime); - if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) gameState->HandleMovement(GameState::RIGHT, deltaTime); - if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space)) gameState->HandleMovement(GameState::JUMP, deltaTime);*/ - } + } } void Render::HandleMouseCapture() { @@ -112,7 +158,7 @@ void Render::HandleMouseCapture() { sf::Mouse::setPosition(center, *window); mouseXDelta = (mousePos - center).x, mouseYDelta = (center - mousePos).y; const float Sensetivity = 0.7f; - //gameState->HandleRotation(mouseXDelta * Sensetivity, mouseYDelta * Sensetivity); + EventAgregator::DirectEventCall(EventType::MouseMoved, MouseMovedData{ mouseXDelta * Sensetivity, mouseYDelta }); } void Render::SetMouseCapture(bool IsCaptured) { @@ -125,11 +171,7 @@ void Render::SetMouseCapture(bool IsCaptured) { void Render::ExecuteRenderLoop() { EventListener listener; - listener.RegisterHandler(EventType::GlobalAppState, [this](EventData eventData) { - - }); - - /*listener.RegisterHandler(EventType::ConnectionSuccessfull, [this](EventData eventData) { + listener.RegisterHandler(EventType::ConnectionSuccessfull, [this](EventData eventData) { auto data = std::get<ConnectionSuccessfullData>(eventData); window->setTitle("Connected"); }); @@ -137,14 +179,31 @@ void Render::ExecuteRenderLoop() { listener.RegisterHandler(EventType::PlayerConnected, [this](EventData eventData) { auto data = std::get<PlayerConnectedData>(eventData); window->setTitle("Joined the game"); + world = std::make_unique<RendererWorld>(data.ptr); }); listener.RegisterHandler(EventType::RemoveLoadingScreen, [this](EventData eventData) { - window->setTitle("Loaded"); - });*/ + window->setTitle("Playing"); + renderWorld = true; + }); + + listener.RegisterHandler(EventType::ConnectionFailed, [this](EventData eventData) { + window->setTitle("Connection failed: " + std::get<ConnectionFailedData>(eventData).reason); + renderWorld = false; + world.reset(); + }); - using namespace std::chrono_literals; - LoopExecutionTimeController timer(16ms); + listener.RegisterHandler(EventType::Disconnected, [this](EventData eventData) { + window->setTitle("Disconnected: " + std::get<DisconnectedData>(eventData).reason); + renderWorld = false; + world.reset(); + }); + + listener.RegisterHandler(EventType::Connecting, [this](EventData eventData) { + window->setTitle("Connecting"); + }); + + LoopExecutionTimeController timer(std::chrono::milliseconds(16)); while (isRunning) { HandleEvents(); if (isMouseCaptured) HandleMouseCapture(); @@ -153,7 +212,9 @@ void Render::ExecuteRenderLoop() { RenderFrame(); while (listener.IsEventsQueueIsNotEmpty()) listener.HandleEvent(); + if (renderWorld) + window->setTitle("FPS: "+std::to_string(1.0/timer.GetDeltaMs()*1000.0)); timer.Update(); } - SetGlobalState(GlobalState::Exiting); + EventAgregator::PushEvent(EventType::Exit, ExitData{}); } diff --git a/src/Render.hpp b/src/Render.hpp index 636c4c7..83b3d1a 100644 --- a/src/Render.hpp +++ b/src/Render.hpp @@ -3,13 +3,16 @@ #include <SFML/Window.hpp> #include "Shader.hpp" +#include "RendererWorld.hpp" class Render { sf::Window *window; bool isRunning=true; bool isMouseCaptured = false; float mouseXDelta, mouseYDelta; - Shader *shader; + std::unique_ptr<RendererWorld> world; + bool renderWorld = false; + RenderState renderState; void SetMouseCapture(bool IsCaptured); diff --git a/src/Renderer.hpp b/src/Renderer.hpp index 81c5c50..de2e331 100644 --- a/src/Renderer.hpp +++ b/src/Renderer.hpp @@ -3,16 +3,18 @@ #include <GL/glew.h> class RenderState { - GLuint ActiveVao; - GLuint ActiveShader; + GLuint ActiveVao = 0; + GLuint ActiveShader = 0; public: void SetActiveVao(GLuint Vao); void SetActiveShader(GLuint Shader); + unsigned int WindowWidth, WindowHeight; }; struct Renderer { - virtual ~Renderer() = default; - virtual void Render(RenderState& renderState) = 0; - virtual void PrepareResources() = 0; - virtual void PrepareRender() = 0; + virtual ~Renderer() = default; + virtual void Render(RenderState& renderState) = 0; + virtual void PrepareResources() = 0; + virtual void PrepareRender() = 0; + virtual bool IsNeedResourcesPrepare() = 0; };
\ No newline at end of file diff --git a/src/RendererSection.cpp b/src/RendererSection.cpp index 62a0dc7..fbb9c19 100644 --- a/src/RendererSection.cpp +++ b/src/RendererSection.cpp @@ -172,7 +172,7 @@ void RendererSection::SetEnabled(bool isEnabled) { this->isEnabled = isEnabled; } -bool RendererSection::IsNeedUpdate() { +bool RendererSection::IsNeedResourcesPrepare() { size_t currentHash = world->GetSection(sectionPosition).GetHash(); bool isNeedUpdate = currentHash != hash; return isNeedUpdate; @@ -188,7 +188,7 @@ void RendererSection::PrepareResources() { for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++) { Vector blockPos = Vector(x, y, z) + (sectionPosition * 16); - Block &block = world->GetBlock(blockPos); + Block block = world->GetBlock(blockPos); if (block.id == 0) continue; diff --git a/src/RendererSection.hpp b/src/RendererSection.hpp index 093a977..c165da4 100644 --- a/src/RendererSection.hpp +++ b/src/RendererSection.hpp @@ -45,5 +45,5 @@ public: Section *GetSection(); - bool IsNeedUpdate(); + bool IsNeedResourcesPrepare() override; };
\ No newline at end of file diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp index c80250c..2ec621a 100644 --- a/src/RendererWorld.cpp +++ b/src/RendererWorld.cpp @@ -1 +1,159 @@ #include "RendererWorld.hpp" + +void RendererWorld::LoadedSectionController() { + + std::function<void(Vector)> updateAllSections = [this](Vector playerPos) { + Vector playerChunk(std::floor(gs->g_PlayerX / 16), 0, std::floor(gs->g_PlayerZ / 16)); + + std::vector<Vector> suitableChunks; + for (auto& it : gs->world.GetSectionsList()) { + double distance = (Vector(it.GetX(),0,it.GetZ()) - playerChunk).GetMagnitude(); + if (distance > MaxRenderingDistance) + continue; + suitableChunks.push_back(it); + } + + std::vector<Vector> toRemove; + + sectionsMutex.lock(); + for (auto& it : sections) { + if (std::find(suitableChunks.begin(), suitableChunks.end(), it.first) == suitableChunks.end()) + toRemove.push_back(it.first); + } + sectionsMutex.unlock(); + + for (auto& it : toRemove) { + EventAgregator::PushEvent(EventType::DeleteSectionRender, DeleteSectionRenderData{ it }); + } + + for (auto& it : suitableChunks) { + EventAgregator::PushEvent(EventType::ChunkChanged, ChunkChangedData{ it }); + } + }; + + + EventListener contentListener; + contentListener.RegisterHandler(EventType::ChunkChanged, [this](EventData eventData) { + auto vec = std::get<ChunkChangedData>(eventData).chunkPosition; + Vector playerChunk(std::floor(gs->g_PlayerX / 16), 0, std::floor(gs->g_PlayerZ / 16)); + + if ((playerChunk - Vector(vec.GetX(), 0, vec.GetZ())).GetMagnitude() > MaxRenderingDistance) + return; + sectionsMutex.lock(); + auto& result = sections.find(vec); + if (result != sections.end()) { + sectionsMutex.unlock(); + if (result->second.IsNeedResourcesPrepare()) + result->second.PrepareResources(); + sectionsMutex.lock(); + } + else { + EventAgregator::PushEvent(EventType::CreateSectionRender, CreateSectionRenderData{ vec }); + } + sectionsMutex.unlock(); + }); + + contentListener.RegisterHandler(EventType::CreatedSectionRender, [this](EventData eventData) { + auto vec = std::get<CreatedSectionRenderData>(eventData).pos; + sectionsMutex.lock(); + sections.find(vec)->second.PrepareResources(); + sectionsMutex.unlock(); + EventAgregator::PushEvent(EventType::InitalizeSectionRender, InitalizeSectionRenderData{ vec }); + }); + + contentListener.RegisterHandler(EventType::PlayerPosChanged, [this,&updateAllSections](EventData eventData) { + auto pos = std::get<PlayerPosChangedData>(eventData).newPos; + updateAllSections(pos); + }); + + contentListener.RegisterHandler(EventType::UpdateSectionsRender, [this,&updateAllSections](EventData eventData) { + updateAllSections(Vector(gs->g_PlayerX, gs->g_PlayerY, gs->g_PlayerZ)); + }); + + LoopExecutionTimeController timer(std::chrono::milliseconds(32)); + auto timeSincePreviousUpdate = std::chrono::steady_clock::now(); + while (isRunning) { + while (contentListener.IsEventsQueueIsNotEmpty()) + contentListener.HandleEvent(); + if (std::chrono::steady_clock::now() - timeSincePreviousUpdate > std::chrono::seconds(15)) { + EventAgregator::PushEvent(EventType::UpdateSectionsRender, UpdateSectionsRenderData{}); + timeSincePreviousUpdate = std::chrono::steady_clock::now(); + } + timer.Update(); + } +} + +RendererWorld::RendererWorld(GameState * ptr):gs(ptr) { + MaxRenderingDistance = 2; + + PrepareRender(); + + listener.RegisterHandler(EventType::InitalizeSectionRender, [this](EventData eventData) { + auto data = std::get<InitalizeSectionRenderData>(eventData); + sectionsMutex.lock(); + sections.find(data.pos)->second.PrepareRender(); + sections.find(data.pos)->second.SetEnabled(true); + sectionsMutex.unlock(); + }); + + listener.RegisterHandler(EventType::CreateSectionRender, [this](EventData eventData) { + auto vec = std::get<CreateSectionRenderData>(eventData).pos; + sectionsMutex.lock(); + sections.insert(std::make_pair(vec, RendererSection(&gs->world, vec))); + sectionsMutex.unlock(); + EventAgregator::PushEvent(EventType::CreatedSectionRender, CreatedSectionRenderData{ vec }); + }); + + listener.RegisterHandler(EventType::DeleteSectionRender, [this](EventData eventData) { + auto vec = std::get<DeleteSectionRenderData>(eventData).pos; + sectionsMutex.lock(); + sections.erase(sections.find(vec)); + sectionsMutex.unlock(); + }); + + resourceLoader = std::thread(&RendererWorld::LoadedSectionController, this); +} + +RendererWorld::~RendererWorld() { + isRunning = false; + resourceLoader.join(); + delete shader; +} + +void RendererWorld::Render(RenderState & renderState) { + renderState.SetActiveShader(shader->Program); + glCheckError(); + + GLint projectionLoc = glGetUniformLocation(shader->Program, "projection"); + GLint viewLoc = glGetUniformLocation(shader->Program, "view"); + GLint windowSizeLoc = glGetUniformLocation(shader->Program, "windowSize"); + glm::mat4 projection = glm::perspective(45.0f, (float)renderState.WindowWidth / (float)renderState.WindowHeight, 0.1f, 10000000.0f); + glm::mat4 view = gs->GetViewMatrix(); + glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection)); + glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); + glUniform2f(windowSizeLoc, renderState.WindowWidth, renderState.WindowHeight); + + glCheckError(); + + sectionsMutex.lock(); + for (auto& it : sections) + it.second.Render(renderState); + sectionsMutex.unlock(); + + listener.HandleEvent(); +} + +void RendererWorld::PrepareResources() { + LOG(ERROR) << "Incorrect call"; +} + +void RendererWorld::PrepareRender() { + shader = new Shader("./shaders/face.vs", "./shaders/face.fs"); + shader->Use(); + glUniform1i(glGetUniformLocation(shader->Program, "textureAtlas"), 0); +} + +bool RendererWorld::IsNeedResourcesPrepare() { + LOG(ERROR) << "Incorrect call"; + return false; +} diff --git a/src/RendererWorld.hpp b/src/RendererWorld.hpp index 83020aa..2ae4e37 100644 --- a/src/RendererWorld.hpp +++ b/src/RendererWorld.hpp @@ -1,12 +1,28 @@ #pragma once #include "RendererSection.hpp" +#include "GameState.hpp" +#include "Shader.hpp" -class RendererWorld { - World* world; +#include <glm/gtc/type_ptr.hpp> + +class RendererWorld: public Renderer { + GameState *gs; + std::mutex sectionsMutex; + std::map<Vector, RendererSection> sections; + EventListener listener; + Shader *shader; + std::thread resourceLoader; + void LoadedSectionController(); + bool isRunning = true; public: - RendererWorld(World* ptr); + RendererWorld(GameState* ptr); ~RendererWorld(); + void Render(RenderState& renderState) override; + void PrepareResources() override; + void PrepareRender() override; + bool IsNeedResourcesPrepare() override; + double MaxRenderingDistance; };
\ No newline at end of file diff --git a/src/Shader.cpp b/src/Shader.cpp index cf43115..164da69 100644 --- a/src/Shader.cpp +++ b/src/Shader.cpp @@ -3,101 +3,94 @@ Shader::Shader(const GLchar *vertexPath, const GLchar *fragmentPath, const GLchar *geometryPath) { vertex = vertexPath; fragment = fragmentPath; - // 1. Получаем исходный код шейдера из filePath + std::string vertexCode; std::string fragmentCode; std::string geometryCode; std::ifstream vShaderFile; std::ifstream fShaderFile; std::ifstream gShaderFile; - // Удостоверимся, что ifstream объекты могут выкидывать исключения + vShaderFile.exceptions(std::ifstream::failbit); fShaderFile.exceptions(std::ifstream::failbit); gShaderFile.exceptions(std::ifstream::failbit); - try { - // Открываем файлы + try { vShaderFile.open(vertexPath); fShaderFile.open(fragmentPath); if (geometryPath != nullptr) gShaderFile.open(geometryPath); std::stringstream vShaderStream, fShaderStream, gShaderStream; - // Считываем данные в потоки + vShaderStream << vShaderFile.rdbuf(); fShaderStream << fShaderFile.rdbuf(); if (geometryPath != nullptr) gShaderStream << gShaderFile.rdbuf(); - // Закрываем файлы + vShaderFile.close(); fShaderFile.close(); if (geometryPath != nullptr) gShaderFile.close(); - // Преобразовываем потоки в массив GLchar + vertexCode = vShaderStream.str(); fragmentCode = fShaderStream.str(); if (geometryPath != nullptr) geometryCode = gShaderStream.str(); } catch (std::ifstream::failure e) { - LOG(ERROR) << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ"; + LOG(ERROR) << "Shader source not readed"; } const GLchar *vShaderCode = vertexCode.c_str(); const GLchar *fShaderCode = fragmentCode.c_str(); const GLchar *gShaderCode = geometryCode.c_str(); - // 2. Сборка шейдеров GLuint vertex, fragment, geometry; GLint success; GLchar infoLog[512]; - // Вершинный шейдер vertex = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertex, 1, &vShaderCode, NULL); glCompileShader(vertex); - // Если есть ошибки - вывести их + glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(vertex, 512, NULL, infoLog); - LOG(ERROR) << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog; + LOG(ERROR) << "Vertex shader compilation failed: " << infoLog; }; - // Вершинный шейдер fragment = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragment, 1, &fShaderCode, NULL); glCompileShader(fragment); - // Если есть ошибки - вывести их + glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(fragment, 512, NULL, infoLog); - LOG(ERROR) << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog; + LOG(ERROR) << "Fragment shader compilation failed: " << infoLog; }; if (geometryPath != nullptr) { geometry = glCreateShader(GL_GEOMETRY_SHADER); glShaderSource(geometry, 1, &gShaderCode, NULL); glCompileShader(geometry); - // Если есть ошибки - вывести их + glGetShaderiv(geometry, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(geometry, 512, NULL, infoLog); - LOG(ERROR) << "ERROR::SHADER::GEOMETRY::COMPILATION_FAILED\n" << infoLog; + LOG(ERROR) << "Geometry shader compilation failed: " << infoLog; }; } - // Шейдерная программа this->Program = glCreateProgram(); glAttachShader(this->Program, vertex); glAttachShader(this->Program, fragment); if (geometryPath != nullptr) glAttachShader(this->Program, geometry); glLinkProgram(this->Program); - //Если есть ошибки - вывести их glGetProgramiv(this->Program, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(this->Program, 512, NULL, infoLog); - LOG(FATAL) << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog; + LOG(FATAL) << "Shader program not linked: " << infoLog; } - // Удаляем шейдеры, поскольку они уже в программу и нам больше не нужны. glDeleteShader(vertex); glDeleteShader(fragment); } diff --git a/src/Stream.cpp b/src/Stream.cpp index 54b1e1b..3931a40 100644 --- a/src/Stream.cpp +++ b/src/Stream.cpp @@ -70,7 +70,7 @@ std::string StreamInput::ReadString() { ReadData(buff, strLength); buff[strLength] = 0; std::string str((char *) buff); - delete buff; + delete[] buff; return str; } @@ -161,7 +161,7 @@ std::vector<unsigned char> StreamInput::ReadByteArray(size_t arrLength) { unsigned char *buffer = new unsigned char[arrLength]; ReadData(buffer, arrLength); std::vector<unsigned char> ret(buffer, buffer + arrLength); - delete buffer; + delete[] buffer; return ret; } @@ -311,7 +311,7 @@ StreamBuffer::StreamBuffer(size_t bufferLen) { } StreamBuffer::~StreamBuffer() { - delete buffer; + delete[] buffer; } std::vector<unsigned char> StreamBuffer::GetBuffer() { diff --git a/src/ThreadGame.cpp b/src/ThreadGame.cpp index 03c2c14..7bb3678 100644 --- a/src/ThreadGame.cpp +++ b/src/ThreadGame.cpp @@ -13,22 +13,83 @@ void ThreadGame::Execute() { EventListener listener; - listener.RegisterHandler(EventType::GlobalAppState, [this](EventData eventData) { - auto data = std::get<GlobalAppStateData>(eventData); - state = data.state; - }); + listener.RegisterHandler(EventType::Exit, [this] (EventData eventData) { + isRunning = false; + }); listener.RegisterHandler(EventType::ConnectionSuccessfull, [this](EventData eventData) { auto data = std::get<ConnectionSuccessfullData>(eventData); gs = new GameState(data.ptr); }); + listener.RegisterHandler(EventType::Disconnected, [this](EventData eventData) { + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + delete gs; + gs = nullptr; + }); + + listener.RegisterHandler(EventType::KeyPressed, [this](EventData eventData) { + if (!gs) + return; + switch (std::get<KeyPressedData>(eventData).key) { + case sf::Keyboard::W: + isMoving[GameState::FORWARD] = true; + break; + case sf::Keyboard::A: + isMoving[GameState::LEFT] = true; + break; + case sf::Keyboard::S: + isMoving[GameState::BACKWARD] = true; + break; + case sf::Keyboard::D: + isMoving[GameState::RIGHT] = true; + break; + } + }); + + listener.RegisterHandler(EventType::KeyReleased, [this](EventData eventData) { + if (!gs) + return; + switch (std::get<KeyReleasedData>(eventData).key) { + case sf::Keyboard::W: + isMoving[GameState::FORWARD] = false; + break; + case sf::Keyboard::A: + isMoving[GameState::LEFT] = false; + break; + case sf::Keyboard::S: + isMoving[GameState::BACKWARD] = false; + break; + case sf::Keyboard::D: + isMoving[GameState::RIGHT] = false; + break; + } + }); + + listener.RegisterHandler(EventType::MouseMoved, [this](EventData eventData) { + if (!gs) + return; + auto data = std::get<MouseMovedData>(eventData); + gs->HandleRotation(data.x, data.y); + }); + LoopExecutionTimeController timer(std::chrono::milliseconds(int(1.0f / 60.0f * 1000.0f))); - while (state != GlobalState::Exiting) { + while (isRunning) { + if (gs != nullptr) + gs->Update(timer.GetDeltaS()); listener.HandleEvent(); - if (gs != nullptr) - gs->Update(timer.GetDeltaMs()); + if (gs != nullptr) { + gs->UpdatePacket(); + if (isMoving[GameState::FORWARD]) + gs->HandleMovement(GameState::FORWARD, timer.GetDeltaS()); + if (isMoving[GameState::BACKWARD]) + gs->HandleMovement(GameState::BACKWARD, timer.GetDeltaS()); + if (isMoving[GameState::LEFT]) + gs->HandleMovement(GameState::LEFT, timer.GetDeltaS()); + if (isMoving[GameState::RIGHT]) + gs->HandleMovement(GameState::RIGHT, timer.GetDeltaS()); + } timer.Update(); } delete gs; diff --git a/src/ThreadGame.hpp b/src/ThreadGame.hpp index 81d135f..1254183 100644 --- a/src/ThreadGame.hpp +++ b/src/ThreadGame.hpp @@ -6,7 +6,8 @@ class ThreadGame: Thread { GameState *gs = nullptr; - GlobalState state = GlobalState::InitialLoading; + bool isRunning = true; + bool isMoving[4] = { 0,0,0,0 }; public: ThreadGame(); ~ThreadGame(); diff --git a/src/ThreadNetwork.cpp b/src/ThreadNetwork.cpp index 51c8989..f734c0c 100644 --- a/src/ThreadNetwork.cpp +++ b/src/ThreadNetwork.cpp @@ -4,18 +4,15 @@ ThreadNetwork::ThreadNetwork() { } -ThreadNetwork::~ThreadNetwork() { - delete nc; +ThreadNetwork::~ThreadNetwork() { } void ThreadNetwork::Execute() { - state = GlobalState::InitialLoading; EventListener listener; - listener.RegisterHandler(EventType::GlobalAppState, [this](EventData eventData) { - auto data = std::get<GlobalAppStateData>(eventData); - state = data.state; - }); + listener.RegisterHandler(EventType::Exit, [this] (EventData eventData) { + isRunning = false; + }); listener.RegisterHandler(EventType::ConnectToServer, [this](EventData eventData) { auto data = std::get<ConnectToServerData>(eventData); @@ -25,8 +22,8 @@ void ThreadNetwork::Execute() { LOG(ERROR) << "Already connected"; return; } - SetGlobalState(GlobalState::Connecting); LOG(INFO) << "Connecting to server"; + EventAgregator::PushEvent(EventType::Connecting, ConnectingData{}); try { nc = new NetworkClient(data.address, data.port, "HelloOne"); } catch (std::exception &e) { @@ -38,11 +35,24 @@ void ThreadNetwork::Execute() { EventAgregator::PushEvent(EventType::ConnectionSuccessfull, ConnectionSuccessfullData{nc}); }); - listener.RegisterHandler(EventType::RequestNetworkClient, [this](EventData eventData) { - EventAgregator::PushEvent(EventType::RegisterNetworkClient, RegisterNetworkClientData{nc}); - }); - - while (state != GlobalState::Exiting) { + listener.RegisterHandler(EventType::Disconnect, [this](EventData eventData) { + auto data = std::get<DisconnectData>(eventData); + EventAgregator::PushEvent(EventType::Disconnected, DisconnectedData{ data.reason }); + LOG(INFO) << "Disconnected: " << data.reason; + delete nc; + nc = nullptr; + }); + + listener.RegisterHandler(EventType::NetworkClientException, [this](EventData eventData) { + auto data = std::get<NetworkClientExceptionData>(eventData); + EventAgregator::PushEvent(EventType::Disconnect, DisconnectData{ data.what }); + }); + + LoopExecutionTimeController timer(std::chrono::milliseconds(16)); + while (isRunning) { listener.HandleEvent(); + + timer.Update(); } + delete nc; }
\ No newline at end of file diff --git a/src/ThreadNetwork.hpp b/src/ThreadNetwork.hpp index a0917cd..60df0d0 100644 --- a/src/ThreadNetwork.hpp +++ b/src/ThreadNetwork.hpp @@ -6,7 +6,7 @@ class ThreadNetwork : Thread { NetworkClient *nc = nullptr; - GlobalState state; + bool isRunning = true; public: ThreadNetwork(); ~ThreadNetwork(); diff --git a/src/Utility.cpp b/src/Utility.cpp index 9fecc08..b4e1d99 100644 --- a/src/Utility.cpp +++ b/src/Utility.cpp @@ -71,3 +71,11 @@ LoopExecutionTimeController::duration LoopExecutionTimeController::GetDelta() { //std::cerr<<duration(now-previousUpdate).count()<<std::endl; return duration(now-previousUpdate); } + +double LoopExecutionTimeController::GetDeltaS() +{ + auto now = clock::now(); + return std::chrono::duration<double, std::ratio<1, 1>>(now - previousUpdate).count(); +} + + diff --git a/src/Utility.hpp b/src/Utility.hpp index 52d6016..0ae3540 100644 --- a/src/Utility.hpp +++ b/src/Utility.hpp @@ -49,4 +49,6 @@ public: double GetDeltaMs(); duration GetDelta(); + + double GetDeltaS(); }; diff --git a/src/World.cpp b/src/World.cpp index 487f4ba..723b006 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1,4 +1,5 @@ #include "World.hpp" +#include "Event.hpp" void World::ParseChunkData(std::shared_ptr<PacketChunkData> packet) { StreamBuffer chunkData(packet->Data.data(), packet->Data.size()); @@ -17,6 +18,8 @@ void World::ParseChunkData(std::shared_ptr<PacketChunkData> packet) { swap(it->second, section); } sectionMutexes[chunkPosition].unlock(); + + EventAgregator::PushEvent(EventType::ChunkChanged, ChunkChangedData{ chunkPosition }); } } } diff --git a/src/World.hpp b/src/World.hpp index 52493a7..805084c 100644 --- a/src/World.hpp +++ b/src/World.hpp @@ -17,9 +17,7 @@ class World { int dimension = 0; Section ParseSection(StreamInput *data, Vector position); - - World(const World &other); - World &operator=(const World &other); + public: World(); |