From e2479261c56c8d1a64b51ad4f084ad3c18505359 Mon Sep 17 00:00:00 2001 From: LaG1924 <12997935+LaG1924@users.noreply.github.com> Date: Sun, 27 Jan 2019 10:10:33 +0500 Subject: GameState double-buffering --- src/GameState.cpp | 17 ----------------- src/GameState.hpp | 19 +++++-------------- src/GlobalState.cpp | 11 +++++++++-- src/GlobalState.hpp | 4 +++- src/Render.cpp | 6 ++++-- src/RendererEntity.cpp | 4 ++-- src/RendererEntity.hpp | 3 ++- src/RendererWorld.cpp | 26 +++++++++++--------------- src/RendererWorld.hpp | 8 ++++++-- src/Section.cpp | 2 ++ src/World.cpp | 11 ++++++----- src/World.hpp | 2 +- 12 files changed, 51 insertions(+), 62 deletions(-) diff --git a/src/GameState.cpp b/src/GameState.cpp index df227b3..ace2488 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -10,8 +10,6 @@ void GameState::Update(float deltaTime) { if (!gameStatus.isGameStarted) return; - std::lock_guard guard(accessMutex); - std::chrono::steady_clock clock; static auto timeOfPreviousSendedPacket(clock.now()); auto delta = clock.now() - timeOfPreviousSendedPacket; @@ -69,7 +67,6 @@ void GameState::Update(float deltaTime) { } void GameState::UpdatePacket(std::shared_ptr ptr) { - std::lock_guard guard(accessMutex); switch ((PacketNamePlayCB)ptr->GetPacketId()) { case SpawnObject: { auto packet = std::static_pointer_cast(ptr); @@ -490,8 +487,6 @@ void GameState::HandleMovement(GameState::MoveType direction, float deltaTime) { if (!gameStatus.isGameStarted) return; - std::lock_guard guard(accessMutex); - const double playerSpeed = 43; float velocity = playerSpeed * deltaTime; @@ -548,8 +543,6 @@ void GameState::HandleRotation(double yaw, double pitch) { if (!gameStatus.isGameStarted) return; - std::lock_guard guard(accessMutex); - double playerYaw = Entity::DecodeYaw(player->yaw); double playerPitch = Entity::DecodePitch(player->pitch); playerYaw += yaw; @@ -563,8 +556,6 @@ void GameState::HandleRotation(double yaw, double pitch) { } glm::mat4 GameState::GetViewMatrix() { - std::lock_guard guard(accessMutex); - double playerYaw = Entity::DecodeYaw(player->yaw); double playerPitch = Entity::DecodePitch(player->pitch); glm::vec3 front, right, worldUp, up; @@ -589,8 +580,6 @@ void GameState::StartDigging() { if (!selectionStatus.isBlockSelected) return; - std::lock_guard guard(accessMutex); - auto packetStart = std::make_shared(0, selectionStatus.selectedBlock, 1); auto packet = std::static_pointer_cast(packetStart); PUSH_EVENT("SendPacket", packet); @@ -599,8 +588,6 @@ void GameState::StartDigging() { } void GameState::FinishDigging() { - std::lock_guard guard(accessMutex); - auto packetFinish = std::make_shared(2, selectionStatus.selectedBlock, 1); auto packet = std::static_pointer_cast(packetFinish); PUSH_EVENT("SendPacket", packet); @@ -612,8 +599,6 @@ void GameState::FinishDigging() { // send_packet(packet_type=start_digging_packet) // remove_delayed_action(finish_digging) void GameState::CancelDigging() { - std::lock_guard guard(accessMutex); - auto packetCancel = std::make_shared(1, selectionStatus.selectedBlock, 1); auto packet = std::static_pointer_cast(packetCancel); PUSH_EVENT("SendPacket", packet); @@ -652,8 +637,6 @@ void GameState::PlaceBlock() { if (!selectionStatus.isBlockSelected) return; - std::lock_guard guard(accessMutex); - BlockFacing face = detectHitFace(selectionStatus.raycastHit, selectionStatus.selectedBlock); auto packetPlace = std::make_shared( selectionStatus.selectedBlock, (unsigned char)face, 0, 0, 0, 0); diff --git a/src/GameState.hpp b/src/GameState.hpp index dbea2c3..41e7080 100644 --- a/src/GameState.hpp +++ b/src/GameState.hpp @@ -68,8 +68,6 @@ class GameState { Window playerInventory; std::vector openedWindows; - - std::mutex accessMutex; public: void Update(float deltaTime); @@ -95,37 +93,30 @@ public: glm::mat4 GetViewMatrix(); inline Entity *GetPlayer() { - std::lock_guard guard(accessMutex); return player; } - inline World GetWorld() { - std::lock_guard guard(accessMutex); + inline World &GetWorld() { return world; } - inline TimeStatus GetTimeStatus() { - std::lock_guard guard(accessMutex); + inline TimeStatus &GetTimeStatus() { return timeStatus; } - inline GameStatus GetGameStatus() { - std::lock_guard guard(accessMutex); + inline GameStatus &GetGameStatus() { return gameStatus; } - inline PlayerStatus GetPlayerStatus() { - std::lock_guard guard(accessMutex); + inline PlayerStatus &GetPlayerStatus() { return playerStatus; } - inline SelectionStatus GetSelectionStatus() { - std::lock_guard guard(accessMutex); + inline SelectionStatus &GetSelectionStatus() { return selectionStatus; } inline Window &GetInventory() { - std::lock_guard guard(accessMutex); return playerInventory; } }; diff --git a/src/GlobalState.cpp b/src/GlobalState.cpp index 9675d4b..afa1a56 100644 --- a/src/GlobalState.cpp +++ b/src/GlobalState.cpp @@ -9,6 +9,7 @@ //Global game variables std::unique_ptr nc; std::unique_ptr gs; +std::shared_ptr gsReadOnly; std::unique_ptr render; bool isRunning; bool isPhysRunning; @@ -16,6 +17,7 @@ EventListener listener; bool isMoving[5] = { 0,0,0,0,0 }; std::thread threadPhys; State state; +std::mutex gsCopyMutex; void PhysExec(); @@ -194,6 +196,10 @@ void PhysExec() { listener.HandleAllEvents(); + gsCopyMutex.lock(); + gsReadOnly = std::make_shared(*gs.get()); + gsCopyMutex.unlock(); + timer.Update(); } } @@ -212,8 +218,9 @@ void GlobalState::Exec() { render.reset(); } -GameState *GlobalState::GetGameState() { - return gs.get(); +std::shared_ptr GlobalState::GetGameState() { + std::lock_guard guard(gsCopyMutex); + return gsReadOnly; } Render *GlobalState::GetRender() { diff --git a/src/GlobalState.hpp b/src/GlobalState.hpp index b3b4635..bc7224f 100644 --- a/src/GlobalState.hpp +++ b/src/GlobalState.hpp @@ -1,5 +1,7 @@ #pragma once +#include + class NetworkClient; class GameState; class Render; @@ -15,7 +17,7 @@ enum class State { }; struct GlobalState { - static GameState *GetGameState(); + static std::shared_ptr GetGameState(); static Render *GetRender(); static void Exec(); static State GetState(); diff --git a/src/Render.cpp b/src/Render.cpp index 5432979..0268bee 100644 --- a/src/Render.cpp +++ b/src/Render.cpp @@ -348,6 +348,9 @@ void Render::SetMouseCapture(bool IsCaptured) { } void Render::Update() { + if (world) + world->UpdateGameState(GlobalState::GetGameState()); + HandleEvents(); if (HasFocus && GlobalState::GetState() == State::Playing) UpdateKeyboard(); if (isMouseCaptured) HandleMouseCapture(); @@ -384,8 +387,7 @@ void Render::RenderGui() { if (world) { Entity *playerPtr = world->GameStatePtr()->GetPlayer(); SelectionStatus selectionStatus = world->GameStatePtr()->GetSelectionStatus(); - World worldObj = world->GameStatePtr()->GetWorld(); - World *worldPtr = &worldObj; + World *worldPtr = &world->GameStatePtr()->GetWorld(); ImGui::Text("TPS: %.1f (%.2fms)", 1000.0f / gameTime, gameTime); ImGui::Text("Sections loaded: %d", (int) DebugInfo::totalSections); diff --git a/src/RendererEntity.cpp b/src/RendererEntity.cpp index fef7dbd..698c934 100644 --- a/src/RendererEntity.cpp +++ b/src/RendererEntity.cpp @@ -123,9 +123,9 @@ RendererEntity::RendererEntity(unsigned int id) RendererEntity::~RendererEntity() { } -void RendererEntity::Render(RenderState & renderState) { +void RendererEntity::Render(RenderState& renderState, World *world) { glm::mat4 model = glm::mat4(1.0); - Entity entity = GlobalState::GetGameState()->GetWorld().GetEntity(entityId); + Entity &entity = world->GetEntity(entityId); model = glm::translate(model, entity.pos.glm()); model = glm::translate(model, glm::vec3(0, entity.height / 2.0, 0)); model = glm::scale(model, glm::vec3(entity.width, entity.height, entity.width)); diff --git a/src/RendererEntity.hpp b/src/RendererEntity.hpp index 961ef45..7f42f7d 100644 --- a/src/RendererEntity.hpp +++ b/src/RendererEntity.hpp @@ -3,6 +3,7 @@ #include class RenderState; +class World; class RendererEntity { unsigned int entityId; @@ -10,7 +11,7 @@ public: RendererEntity(unsigned int id); ~RendererEntity(); - void Render(RenderState& renderState); + void Render(RenderState& renderState, World *world); static GLuint GetVao(); }; diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp index d798343..1743a25 100644 --- a/src/RendererWorld.cpp +++ b/src/RendererWorld.cpp @@ -36,8 +36,6 @@ void RendererWorld::WorkerFunction(size_t workerId) { } void RendererWorld::ParseQueueUpdate() { - World world = gs->GetWorld(); - while (!parseQueue.empty()) { size_t id = 0; for (; id < RendererWorld::parsingBufferSize && parsing[id].parsing; ++id) {} @@ -54,13 +52,13 @@ void RendererWorld::ParseQueueUpdate() { vec.y -= 4500; } - parsing[id].data.section = world.GetSection(vec); - parsing[id].data.north = world.GetSection(vec + Vector(0, 0, 1)); - parsing[id].data.south = world.GetSection(vec + Vector(0, 0, -1)); - parsing[id].data.west = world.GetSection(vec + Vector(1, 0, 0)); - parsing[id].data.east = world.GetSection(vec + Vector(-1, 0, 0)); - parsing[id].data.bottom = world.GetSection(vec + Vector(0, -1, 0)); - parsing[id].data.top = world.GetSection(vec + Vector(0, 1, 0)); + parsing[id].data.section = gs->GetWorld().GetSection(vec); + parsing[id].data.north = gs->GetWorld().GetSection(vec + Vector(0, 0, 1)); + parsing[id].data.south = gs->GetWorld().GetSection(vec + Vector(0, 0, -1)); + parsing[id].data.west = gs->GetWorld().GetSection(vec + Vector(1, 0, 0)); + parsing[id].data.east = gs->GetWorld().GetSection(vec + Vector(-1, 0, 0)); + parsing[id].data.bottom = gs->GetWorld().GetSection(vec + Vector(0, -1, 0)); + parsing[id].data.top = gs->GetWorld().GetSection(vec + Vector(0, 1, 0)); parsing[id].parsing = true; @@ -76,8 +74,6 @@ void RendererWorld::ParseQeueueRemoveUnnecessary() { elements.clear(); elements.reserve(size); - World world = gs->GetWorld(); - for (size_t i = 0; i < size; i++) { Vector vec = parseQueue.front(); parseQueue.pop(); @@ -90,7 +86,7 @@ void RendererWorld::ParseQeueueRemoveUnnecessary() { if (std::find(elements.begin(), elements.end(), vec) != elements.end()) continue; - const Section& section = world.GetSection(vec); + const Section& section = gs->GetWorld().GetSection(vec); bool skip = false; @@ -150,7 +146,7 @@ void RendererWorld::UpdateAllSections(VectorF playerPos) { } } -RendererWorld::RendererWorld(GameState* ptr) { +RendererWorld::RendererWorld(std::shared_ptr ptr) { gs = ptr; MaxRenderingDistance = 2; numOfWorkers = _max(1, (signed int) std::thread::hardware_concurrency() - 2); @@ -291,7 +287,7 @@ void RendererWorld::Render(RenderState & renderState) { renderState.SetActiveVao(RendererEntity::GetVao()); for (auto& it : entities) { - it.Render(renderState); + it.Render(renderState, &gs->GetWorld()); } //Render selected block @@ -449,5 +445,5 @@ void RendererWorld::Update(double timeToUpdate) { } GameState* RendererWorld::GameStatePtr() { - return gs; + return gs.get(); } diff --git a/src/RendererWorld.hpp b/src/RendererWorld.hpp index dbdd852..5148964 100644 --- a/src/RendererWorld.hpp +++ b/src/RendererWorld.hpp @@ -27,7 +27,7 @@ class RendererWorld { }; //General - GameState *gs; + std::shared_ptr gs; std::unique_ptr listener; size_t numOfWorkers; size_t currentWorker = 0; @@ -50,7 +50,7 @@ class RendererWorld { Texture *skyTexture; RendererSky rendererSky; public: - RendererWorld(GameState* ptr); + RendererWorld(std::shared_ptr ptr); ~RendererWorld(); void Render(RenderState& renderState); @@ -63,4 +63,8 @@ public: GameState *GameStatePtr(); int culledSections = 0; + + inline void UpdateGameState(std::shared_ptr newPtr) { + gs = newPtr; + } }; \ No newline at end of file diff --git a/src/Section.cpp b/src/Section.cpp index c8c67dc..29a6a0e 100644 --- a/src/Section.cpp +++ b/src/Section.cpp @@ -45,6 +45,7 @@ Section::Section(Vector pos, unsigned char bitsPerBlock, std::vector packet) { for (int i = 0; i < 16; i++) { if (bitmask[i]) { Vector chunkPosition = Vector(packet->ChunkX, i, packet->ChunkZ); - Section section = ParseSection(&chunkData, chunkPosition); + auto section = std::make_shared
(ParseSection(&chunkData, chunkPosition)); if (packet->GroundUpContinuous) { if (!sections.insert(std::make_pair(chunkPosition, section)).second) { @@ -125,7 +125,7 @@ const Section &World::GetSection(Vector sectionPos) { return fallbackSection; } else { - return result->second; + return *result->second; } } @@ -312,7 +312,7 @@ void World::ParseChunkData(std::shared_ptr packet) { } void World::ParseChunkData(std::shared_ptr packet) { - std::vector::iterator> toRemove; + std::vector>::iterator> toRemove; for (auto it = sections.begin(); it != sections.end(); ++it) { if (it->first.x == packet->ChunkX && it->first.z == packet->ChunkZ) toRemove.push_back(it); @@ -345,8 +345,9 @@ void World::SetBlockId(Vector pos, BlockId block) { std::floor(pos.y / 16.0), std::floor(pos.z / 16.0)); Vector blockPos = pos - (sectionPos * 16); - Section* section = GetSectionPtr(sectionPos); + auto section = std::make_shared
(*GetSectionPtr(sectionPos)); section->SetBlockId(blockPos, block); + sections[sectionPos] = section; PUSH_EVENT("ChunkChanged",sectionPos); if (blockPos.x == 0) PUSH_EVENT("ChunkChangedForce", sectionPos + Vector(-1, 0, 0)); @@ -376,7 +377,7 @@ Section *World::GetSectionPtr(Vector position) { if (it == sections.end()) return nullptr; - return &it->second; + return it->second.get(); } Entity* World::GetEntityPtr(unsigned int EntityId) { diff --git a/src/World.hpp b/src/World.hpp index 94e17f6..591e7a7 100644 --- a/src/World.hpp +++ b/src/World.hpp @@ -28,7 +28,7 @@ struct RaycastResult { class World { int dimension = 0; - std::map sections; + std::map> sections; Section ParseSection(StreamInput *data, Vector position); -- cgit v1.2.3