diff options
-rw-r--r-- | src/DebugInfo.cpp | 3 | ||||
-rw-r--r-- | src/DebugInfo.hpp | 1 | ||||
-rw-r--r-- | src/GameState.cpp | 1178 | ||||
-rw-r--r-- | src/GameState.hpp | 141 | ||||
-rw-r--r-- | src/GlobalState.cpp | 11 | ||||
-rw-r--r-- | src/GlobalState.hpp | 4 | ||||
-rw-r--r-- | src/Render.cpp | 91 | ||||
-rw-r--r-- | src/RendererEntity.cpp | 10 | ||||
-rw-r--r-- | src/RendererEntity.hpp | 7 | ||||
-rw-r--r-- | src/RendererWorld.cpp | 53 | ||||
-rw-r--r-- | src/RendererWorld.hpp | 8 | ||||
-rw-r--r-- | src/Section.cpp | 2 | ||||
-rw-r--r-- | src/World.cpp | 108 | ||||
-rw-r--r-- | src/World.hpp | 35 |
14 files changed, 859 insertions, 793 deletions
diff --git a/src/DebugInfo.cpp b/src/DebugInfo.cpp index e2d439b..89e9425 100644 --- a/src/DebugInfo.cpp +++ b/src/DebugInfo.cpp @@ -3,4 +3,5 @@ std::atomic_int DebugInfo::totalSections(0); std::atomic_int DebugInfo::renderSections(0); std::atomic_int DebugInfo::readyRenderer(0); -std::atomic_int DebugInfo::gameThreadTime(0);
\ No newline at end of file +std::atomic_int DebugInfo::gameThreadTime(0); +std::atomic_int DebugInfo::renderFaces(0);
\ No newline at end of file diff --git a/src/DebugInfo.hpp b/src/DebugInfo.hpp index a29a056..e6aa17c 100644 --- a/src/DebugInfo.hpp +++ b/src/DebugInfo.hpp @@ -7,4 +7,5 @@ struct DebugInfo { static std::atomic_int renderSections; static std::atomic_int readyRenderer; static std::atomic_int gameThreadTime; + static std::atomic_int renderFaces; };
\ No newline at end of file diff --git a/src/GameState.cpp b/src/GameState.cpp index fabfdb8..ace2488 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -7,559 +7,569 @@ #include "Packet.hpp" void GameState::Update(float deltaTime) { - if (g_IsGameStarted) { - std::chrono::steady_clock clock; - static auto timeOfPreviousSendedPacket(clock.now()); - auto delta = clock.now() - timeOfPreviousSendedPacket; - using namespace std::chrono_literals; - if (delta >= 50ms) { - auto packetToSend = std::make_shared<PacketPlayerPositionAndLookSB>( - player->pos.x, player->pos.y, player->pos.z, - player->yaw, player->pitch, player->onGround); - - auto packet = std::static_pointer_cast<Packet>(packetToSend); - PUSH_EVENT("SendPacket", packet); - timeOfPreviousSendedPacket = clock.now(); - } - - bool prevOnGround = player->onGround; - world.UpdatePhysics(deltaTime); - if (player->onGround != prevOnGround) { - auto updatePacket = std::make_shared<PacketPlayerPosition>( - player->pos.x, player->pos.y, - player->pos.z, player->onGround); - - auto packet = std::static_pointer_cast<Packet>(updatePacket); - PUSH_EVENT("SendPacket", packet); - } - - - double playerYaw = Entity::DecodeYaw(player->yaw); - double playerPitch = Entity::DecodePitch(player->pitch); - - glm::vec3 direction; - direction.x = cos(glm::radians(playerYaw)) * cos(glm::radians(playerPitch)); - direction.y = sin(glm::radians(playerPitch)); - direction.z = sin(glm::radians(playerYaw)) * cos(glm::radians(playerPitch)); - - RaycastResult raycast = world.Raycast(player->pos + player->EyeOffset, direction); - if (raycast.isHit != isBlockSelected || ((raycast.isHit == true && isBlockSelected == true) && - selectedBlock != raycast.hitBlock)) { - PUSH_EVENT("SelectedBlockChanged", 0); - } - - if (raycast.isHit) { - selectedBlock = raycast.hitBlock; - distanceToSelectedBlock = (player->pos - raycast.hitPos).GetLength(); - } else { - selectedBlock = Vector(0, 0, 0); - distanceToSelectedBlock = 0.0f; - } - - isBlockSelected = raycast.isHit; - raycastHit = raycast.hitPos; - - if (doDaylightCycle) - interpolatedTimeOfDay += 20.0 * deltaTime; - } + if (!gameStatus.isGameStarted) + return; + + std::chrono::steady_clock clock; + static auto timeOfPreviousSendedPacket(clock.now()); + auto delta = clock.now() - timeOfPreviousSendedPacket; + using namespace std::chrono_literals; + if (delta >= 50ms) { + auto packetToSend = std::make_shared<PacketPlayerPositionAndLookSB>( + player->pos.x, player->pos.y, player->pos.z, + player->yaw, player->pitch, player->onGround); + + auto packet = std::static_pointer_cast<Packet>(packetToSend); + PUSH_EVENT("SendPacket", packet); + timeOfPreviousSendedPacket = clock.now(); + } + + bool prevOnGround = player->onGround; + world.UpdatePhysics(deltaTime); + if (player->onGround != prevOnGround) { + auto updatePacket = std::make_shared<PacketPlayerPosition>( + player->pos.x, player->pos.y, + player->pos.z, player->onGround); + + auto packet = std::static_pointer_cast<Packet>(updatePacket); + PUSH_EVENT("SendPacket", packet); + } + + + double playerYaw = Entity::DecodeYaw(player->yaw); + double playerPitch = Entity::DecodePitch(player->pitch); + + glm::vec3 direction; + direction.x = cos(glm::radians(playerYaw)) * cos(glm::radians(playerPitch)); + direction.y = sin(glm::radians(playerPitch)); + direction.z = sin(glm::radians(playerYaw)) * cos(glm::radians(playerPitch)); + + RaycastResult raycast = world.Raycast(player->pos + player->EyeOffset, direction); + if (raycast.isHit != selectionStatus.isBlockSelected || ((raycast.isHit == true && selectionStatus.isBlockSelected == true) && + selectionStatus.selectedBlock != raycast.hitBlock)) { + PUSH_EVENT("SelectedBlockChanged", 0); + } + + if (raycast.isHit) { + selectionStatus.selectedBlock = raycast.hitBlock; + selectionStatus.distanceToSelectedBlock = (player->pos - raycast.hitPos).GetLength(); + } + else { + selectionStatus.selectedBlock = Vector(0, 0, 0); + selectionStatus.distanceToSelectedBlock = 0.0f; + } + + selectionStatus.isBlockSelected = raycast.isHit; + selectionStatus.raycastHit = raycast.hitPos; + + if (timeStatus.doDaylightCycle) + timeStatus.interpolatedTimeOfDay += 20.0 * deltaTime; } void GameState::UpdatePacket(std::shared_ptr<Packet> ptr) { - switch ((PacketNamePlayCB) ptr->GetPacketId()) { - case SpawnObject: { - auto packet = std::static_pointer_cast<PacketSpawnObject>(ptr); - Entity entity = CreateObject(static_cast<ObjectType>(packet->Type)); - entity.entityId = packet->EntityId; - entity.pos = VectorF(packet->X, packet->Y, packet->Z); - entity.uuid = packet->ObjectUuid; - entity.vel = Entity::DecodeVelocity(packet->VelocityX, packet->VelocityY, packet->VelocityZ); - entity.yaw = packet->Yaw / 256.0; - entity.pitch = packet->Pitch / 256.0; - entity.renderColor = glm::vec3(0, 1, 0); - world.AddEntity(entity); - PUSH_EVENT("EntityChanged", entity.entityId); - break; - } - - case SpawnExperienceOrb: - break; - - case SpawnGlobalEntity: - break; - - case SpawnMob: { - auto packet = std::static_pointer_cast<PacketSpawnMob>(ptr); - Entity entity; - entity.entityId = packet->EntityId; - entity.pos = VectorF(packet->X, packet->Y, packet->Z); - entity.uuid = packet->EntityUuid; - entity.vel = Entity::DecodeVelocity(packet->VelocityX, packet->VelocityY, packet->VelocityZ); - entity.yaw = packet->Yaw / 256.0; - entity.pitch = packet->Pitch / 256.0; - entity.renderColor = glm::vec3(0, 0, 1); - world.AddEntity(entity); - PUSH_EVENT("EntityChanged", entity.entityId); - break; - } - - case SpawnPainting: - break; - - case SpawnPlayer: { - auto packet = std::static_pointer_cast<PacketSpawnPlayer>(ptr); - Entity entity; - entity.entityId = packet->EntityId; - entity.pos = VectorF(packet->X, packet->Y, packet->Z); - entity.uuid = packet->PlayerUuid; - entity.yaw = packet->Yaw / 256.0; - entity.pitch = packet->Pitch / 256.0; - entity.renderColor = glm::vec3(1, 0, 0); - entity.height = 1.8; - entity.width = 0.6; - world.AddEntity(entity); - PUSH_EVENT("EntityChanged", entity.entityId); - break; - } - case AnimationCB: - break; - case Statistics: - break; - case BlockBreakAnimation: - break; - case UpdateBlockEntity: - break; - case BlockAction: - break; - - case BlockChange: { - auto packet = std::static_pointer_cast<PacketBlockChange>(ptr); - world.ParseChunkData(packet); - break; - } - - case BossBar: - break; - case ServerDifficulty: - break; - case TabCompleteCB: - break; - - case ChatMessageCB: { - auto packet = std::static_pointer_cast<PacketChatMessageCB>(ptr); - LOG(INFO) << "Message (" << int(packet->Position) << "): " << packet->JsonData.text; - PUSH_EVENT("ChatMessageReceived", std::make_tuple(packet->JsonData, packet->Position)); - break; - } - - case MultiBlockChange: { - auto packet = std::static_pointer_cast<PacketMultiBlockChange>(ptr); - world.ParseChunkData(packet); - break; - } - - case ConfirmTransactionCB: { - auto packet = std::static_pointer_cast<PacketConfirmTransactionCB>(ptr); - if (packet->WindowId == 0) { - try { - playerInventory.ConfirmTransaction(*packet); - } catch (std::exception &e) { - PUSH_EVENT("Disconnected", std::string("Transaction failed")); - } - } - break; - } - - case CloseWindowCB: - break; - - case OpenWindow: { - auto packet = std::static_pointer_cast<PacketOpenWindow>(ptr); - - LOG(INFO) << "Open new window " << packet->WindowTitle << ": " << packet->WindowId; - break; - } - - case WindowItems: { - auto packet = std::static_pointer_cast<PacketWindowItems>(ptr); - if (packet->WindowId == 0) { - playerInventory.WindowId = 0; - playerInventory.slots = packet->SlotData; - } - break; - } - - case WindowProperty: - break; - - case SetSlot: { - auto packet = std::static_pointer_cast<PacketSetSlot>(ptr); - if (packet->WindowId == 0) { - playerInventory.slots[packet->Slot] = packet->SlotData; - } - 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; - PUSH_EVENT("Disconnected", packet->Reason); - break; - } - - case EntityStatus: - break; - case Explosion: - break; - - case UnloadChunk: { - auto packet = std::static_pointer_cast<PacketUnloadChunk>(ptr); - world.ParseChunkData(packet); - 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); - Entity entity; - entity.entityId = packet->EntityId; - entity.width = 0.6; - entity.height = 1.8; - world.AddEntity(entity); - player = world.GetEntityPtr(entity.entityId); - - 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; - PUSH_EVENT("PlayerConnected", 0); - break; - } - - case Map: - break; - - case EntityRelativeMove: { - auto packet = std::static_pointer_cast<PacketEntityRelativeMove>(ptr); - Entity &entity = world.GetEntity(packet->EntityId); - entity.pos = entity.pos + Entity::DecodeDeltaPos(packet->DeltaX, packet->DeltaY, packet->DeltaZ); - if (entity.entityId != 0) - LOG(INFO) << "M: " << packet->EntityId; - break; - } - - case EntityLookAndRelativeMove: { - auto packet = std::static_pointer_cast<PacketEntityLookAndRelativeMove>(ptr); - Entity &entity = world.GetEntity(packet->EntityId); - entity.pos = entity.pos + Entity::DecodeDeltaPos(packet->DeltaX, packet->DeltaY, packet->DeltaZ); - entity.pitch = packet->Pitch / 256.0; - entity.yaw = packet->Yaw / 256.0; - break; - } - - case EntityLook: { - auto packet = std::static_pointer_cast<PacketEntityLook>(ptr); - Entity &entity = world.GetEntity(packet->EntityId); - entity.pitch = packet->Pitch / 256.0; - entity.yaw = packet->Yaw / 256.0; - //LOG(INFO) << "L: " << packet->EntityId; - break; - } - - case EntityCB: - 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) { - player->pitch += packet->Pitch; - } else { - player->pitch = packet->Pitch; - } - - if ((packet->Flags & 0x08) != 0) { - player->yaw += packet->Yaw; - } else { - player->yaw = packet->Yaw; - } - - if ((packet->Flags & 0x01) != 0) { - player->pos.x += packet->X; - } else { - player->pos.x = packet->X; - } - - if ((packet->Flags & 0x02) != 0) { - player->pos.y += packet->Y; - } else { - player->pos.y = packet->Y; - } - - if ((packet->Flags & 0x04) != 0) { - player->pos.z += packet->Z; - } else { - player->pos.z = packet->Z; - } - - PUSH_EVENT("PlayerPosChanged", player->pos); - LOG(INFO) << "PlayerPos is " << player->pos << "\t\tAngle: " << player->yaw << "," << player->pitch;; - - if (!g_IsGameStarted) { - LOG(INFO) << "Game is started"; - PUSH_EVENT("RemoveLoadingScreen", 0); - } - - g_IsGameStarted = true; - - auto packetResponse = std::make_shared<PacketTeleportConfirm>(packet->TeleportId); - auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0); - - PUSH_EVENT("SendPacket",std::static_pointer_cast<Packet>(packetResponse)); - PUSH_EVENT("SendPacket",std::static_pointer_cast<Packet>(packetPerformRespawn)); - break; - } - - case UseBed: - break; - case UnlockRecipes: - break; - - case DestroyEntities: { - auto packet = std::static_pointer_cast<PacketDestroyEntities>(ptr); - for (unsigned int entityId : packet->EntityIds) { - world.DeleteEntity(entityId); - } - 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: { - auto packet = std::static_pointer_cast<PacketEntityVelocity>(ptr); - Entity &entity = world.GetEntity(packet->EntityId); - entity.vel = Entity::DecodeVelocity(packet->VelocityX, packet->VelocityY, packet->VelocityZ); - 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); - PUSH_EVENT("SendPacket",std::static_pointer_cast<Packet>(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.x << " " << g_SpawnPosition.y << " " - << g_SpawnPosition.z; - break; - } - - case TimeUpdate: { - auto packet = std::static_pointer_cast<PacketTimeUpdate>(ptr); - doDaylightCycle = TimeOfDay != packet->TimeOfDay; - WorldAge = packet->WorldAge; - TimeOfDay = packet->TimeOfDay; - interpolatedTimeOfDay = TimeOfDay; - break; - } - - case Title: - break; - case SoundEffect: - break; - case PlayerListHeaderAndFooter: - break; - case CollectItem: - break; - - case EntityTeleport: { - auto packet = std::static_pointer_cast<PacketEntityTeleport>(ptr); - Entity &entity = world.GetEntity(packet->EntityId); - entity.pos = VectorF(packet->X, packet->Y, packet->Z); - entity.pitch = packet->Pitch / 256.0; - entity.yaw = packet->Yaw / 256.0; - break; - } - - case Advancements: - break; - case EntityProperties: - break; - case EntityEffect: - break; - } - - while (!playerInventory.pendingTransactions.empty()) { - auto packet = std::make_shared<PacketClickWindow>(playerInventory.pendingTransactions.front()); - playerInventory.pendingTransactions.pop(); - PUSH_EVENT("SendPacket",std::static_pointer_cast<Packet>(packet)); - } + switch ((PacketNamePlayCB)ptr->GetPacketId()) { + case SpawnObject: { + auto packet = std::static_pointer_cast<PacketSpawnObject>(ptr); + Entity entity = CreateObject(static_cast<ObjectType>(packet->Type)); + entity.entityId = packet->EntityId; + entity.pos = VectorF(packet->X, packet->Y, packet->Z); + entity.uuid = packet->ObjectUuid; + entity.vel = Entity::DecodeVelocity(packet->VelocityX, packet->VelocityY, packet->VelocityZ); + entity.yaw = packet->Yaw / 256.0; + entity.pitch = packet->Pitch / 256.0; + entity.renderColor = glm::vec3(0, 1, 0); + world.AddEntity(entity); + PUSH_EVENT("EntityChanged", entity.entityId); + break; + } + + case SpawnExperienceOrb: + break; + + case SpawnGlobalEntity: + break; + + case SpawnMob: { + auto packet = std::static_pointer_cast<PacketSpawnMob>(ptr); + Entity entity; + entity.entityId = packet->EntityId; + entity.pos = VectorF(packet->X, packet->Y, packet->Z); + entity.uuid = packet->EntityUuid; + entity.vel = Entity::DecodeVelocity(packet->VelocityX, packet->VelocityY, packet->VelocityZ); + entity.yaw = packet->Yaw / 256.0; + entity.pitch = packet->Pitch / 256.0; + entity.renderColor = glm::vec3(0, 0, 1); + world.AddEntity(entity); + PUSH_EVENT("EntityChanged", entity.entityId); + break; + } + + case SpawnPainting: + break; + + case SpawnPlayer: { + auto packet = std::static_pointer_cast<PacketSpawnPlayer>(ptr); + Entity entity; + entity.entityId = packet->EntityId; + entity.pos = VectorF(packet->X, packet->Y, packet->Z); + entity.uuid = packet->PlayerUuid; + entity.yaw = packet->Yaw / 256.0; + entity.pitch = packet->Pitch / 256.0; + entity.renderColor = glm::vec3(1, 0, 0); + entity.height = 1.8; + entity.width = 0.6; + world.AddEntity(entity); + PUSH_EVENT("EntityChanged", entity.entityId); + break; + } + case AnimationCB: + break; + case Statistics: + break; + case BlockBreakAnimation: + break; + case UpdateBlockEntity: + break; + case BlockAction: + break; + + case BlockChange: { + auto packet = std::static_pointer_cast<PacketBlockChange>(ptr); + world.ParseChunkData(packet); + break; + } + + case BossBar: + break; + case ServerDifficulty: + break; + case TabCompleteCB: + break; + + case ChatMessageCB: { + auto packet = std::static_pointer_cast<PacketChatMessageCB>(ptr); + LOG(INFO) << "Message (" << int(packet->Position) << "): " << packet->JsonData.text; + PUSH_EVENT("ChatMessageReceived", std::make_tuple(packet->JsonData, packet->Position)); + break; + } + + case MultiBlockChange: { + auto packet = std::static_pointer_cast<PacketMultiBlockChange>(ptr); + world.ParseChunkData(packet); + break; + } + + case ConfirmTransactionCB: { + auto packet = std::static_pointer_cast<PacketConfirmTransactionCB>(ptr); + if (packet->WindowId == 0) { + try { + playerInventory.ConfirmTransaction(*packet); + } + catch (std::exception &e) { + PUSH_EVENT("Disconnected", std::string("Transaction failed")); + } + } + break; + } + + case CloseWindowCB: + break; + + case OpenWindow: { + auto packet = std::static_pointer_cast<PacketOpenWindow>(ptr); + + LOG(INFO) << "Open new window " << packet->WindowTitle << ": " << packet->WindowId; + break; + } + + case WindowItems: { + auto packet = std::static_pointer_cast<PacketWindowItems>(ptr); + if (packet->WindowId == 0) { + playerInventory.WindowId = 0; + playerInventory.slots = packet->SlotData; + } + break; + } + + case WindowProperty: + break; + + case SetSlot: { + auto packet = std::static_pointer_cast<PacketSetSlot>(ptr); + if (packet->WindowId == 0) { + playerInventory.slots[packet->Slot] = packet->SlotData; + } + 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; + PUSH_EVENT("Disconnected", packet->Reason); + break; + } + + case EntityStatus: + break; + case Explosion: + break; + + case UnloadChunk: { + auto packet = std::static_pointer_cast<PacketUnloadChunk>(ptr); + world.ParseChunkData(packet); + 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); + Entity entity; + entity.entityId = packet->EntityId; + entity.width = 0.6; + entity.height = 1.8; + world.AddEntity(entity); + player = world.GetEntityPtr(entity.entityId); + + playerStatus.eid = packet->EntityId; + gameStatus.gamemode = (packet->Gamemode & 0b11111011); + gameStatus.dimension = packet->Dimension; + gameStatus.difficulty = packet->Difficulty; + gameStatus.maxPlayers = packet->MaxPlayers; + gameStatus.levelType = packet->LevelType; + gameStatus.reducedDebugInfo = packet->ReducedDebugInfo; + LOG(INFO) << "Gamemode is " << gameStatus.gamemode << ", Difficulty is " << (int)gameStatus.difficulty + << ", Level Type is " << gameStatus.levelType; + PUSH_EVENT("PlayerConnected", 0); + break; + } + + case Map: + break; + + case EntityRelativeMove: { + auto packet = std::static_pointer_cast<PacketEntityRelativeMove>(ptr); + Entity &entity = world.GetEntity(packet->EntityId); + entity.pos = entity.pos + Entity::DecodeDeltaPos(packet->DeltaX, packet->DeltaY, packet->DeltaZ); + if (entity.entityId != 0) + LOG(INFO) << "M: " << packet->EntityId; + break; + } + + case EntityLookAndRelativeMove: { + auto packet = std::static_pointer_cast<PacketEntityLookAndRelativeMove>(ptr); + Entity &entity = world.GetEntity(packet->EntityId); + entity.pos = entity.pos + Entity::DecodeDeltaPos(packet->DeltaX, packet->DeltaY, packet->DeltaZ); + entity.pitch = packet->Pitch / 256.0; + entity.yaw = packet->Yaw / 256.0; + break; + } + + case EntityLook: { + auto packet = std::static_pointer_cast<PacketEntityLook>(ptr); + Entity &entity = world.GetEntity(packet->EntityId); + entity.pitch = packet->Pitch / 256.0; + entity.yaw = packet->Yaw / 256.0; + //LOG(INFO) << "L: " << packet->EntityId; + break; + } + + case EntityCB: + 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) { + player->pitch += packet->Pitch; + } + else { + player->pitch = packet->Pitch; + } + + if ((packet->Flags & 0x08) != 0) { + player->yaw += packet->Yaw; + } + else { + player->yaw = packet->Yaw; + } + + if ((packet->Flags & 0x01) != 0) { + player->pos.x += packet->X; + } + else { + player->pos.x = packet->X; + } + + if ((packet->Flags & 0x02) != 0) { + player->pos.y += packet->Y; + } + else { + player->pos.y = packet->Y; + } + + if ((packet->Flags & 0x04) != 0) { + player->pos.z += packet->Z; + } + else { + player->pos.z = packet->Z; + } + + PUSH_EVENT("PlayerPosChanged", player->pos); + LOG(INFO) << "PlayerPos is " << player->pos << "\t\tAngle: " << player->yaw << "," << player->pitch;; + + if (!gameStatus.isGameStarted) { + LOG(INFO) << "Game is started"; + PUSH_EVENT("RemoveLoadingScreen", 0); + } + + gameStatus.isGameStarted = true; + + auto packetResponse = std::make_shared<PacketTeleportConfirm>(packet->TeleportId); + auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0); + + PUSH_EVENT("SendPacket", std::static_pointer_cast<Packet>(packetResponse)); + PUSH_EVENT("SendPacket", std::static_pointer_cast<Packet>(packetPerformRespawn)); + break; + } + + case UseBed: + break; + case UnlockRecipes: + break; + + case DestroyEntities: { + auto packet = std::static_pointer_cast<PacketDestroyEntities>(ptr); + for (unsigned int entityId : packet->EntityIds) { + world.DeleteEntity(entityId); + } + 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: { + auto packet = std::static_pointer_cast<PacketEntityVelocity>(ptr); + Entity &entity = world.GetEntity(packet->EntityId); + entity.vel = Entity::DecodeVelocity(packet->VelocityX, packet->VelocityY, packet->VelocityZ); + break; + } + + case EntityEquipment: + break; + case SetExperience: + break; + + case UpdateHealth: { + auto packet = std::static_pointer_cast<PacketUpdateHealth>(ptr); + playerStatus.health = packet->Health; + if (playerStatus.health <= 0) { + LOG(INFO) << "Player is dead. Respawning..."; + auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0); + PUSH_EVENT("SendPacket", std::static_pointer_cast<Packet>(packetPerformRespawn)); + } + break; + } + + case ScoreboardObjective: + break; + case SetPassengers: + break; + case Teams: + break; + case UpdateScore: + break; + + case SpawnPosition: { + auto packet = std::static_pointer_cast<PacketSpawnPosition>(ptr); + gameStatus.spawnPosition = packet->Location; + LOG(INFO) << "Spawn position is " << gameStatus.spawnPosition; + break; + } + + case TimeUpdate: { + auto packet = std::static_pointer_cast<PacketTimeUpdate>(ptr); + timeStatus.doDaylightCycle = timeStatus.timeOfDay != packet->TimeOfDay; + timeStatus.worldAge = packet->WorldAge; + timeStatus.timeOfDay = packet->TimeOfDay; + timeStatus.interpolatedTimeOfDay = timeStatus.timeOfDay; + break; + } + + case Title: + break; + case SoundEffect: + break; + case PlayerListHeaderAndFooter: + break; + case CollectItem: + break; + + case EntityTeleport: { + auto packet = std::static_pointer_cast<PacketEntityTeleport>(ptr); + Entity &entity = world.GetEntity(packet->EntityId); + entity.pos = VectorF(packet->X, packet->Y, packet->Z); + entity.pitch = packet->Pitch / 256.0; + entity.yaw = packet->Yaw / 256.0; + break; + } + + case Advancements: + break; + case EntityProperties: + break; + case EntityEffect: + break; + } + + while (!playerInventory.pendingTransactions.empty()) { + auto packet = std::make_shared<PacketClickWindow>(playerInventory.pendingTransactions.front()); + playerInventory.pendingTransactions.pop(); + PUSH_EVENT("SendPacket", std::static_pointer_cast<Packet>(packet)); + } } -void GameState::HandleMovement(GameState::Direction direction, float deltaTime) { - if (!g_IsGameStarted) - return; - const double playerSpeed = 43; - - float velocity = playerSpeed * deltaTime; - - double playerYaw = Entity::DecodeYaw(player->yaw); - double playerPitch = Entity::DecodePitch(player->pitch); - - glm::vec3 front, right, worldUp, up; - worldUp = glm::vec3(0.0f, 1.0f, 0.0f); - front.x = cos(glm::radians(playerYaw)) * cos(glm::radians(playerPitch)); - front.y = player->isFlying ? sin(glm::radians(playerPitch)): 0; - front.z = sin(glm::radians(playerYaw)) * cos(glm::radians(playerPitch)); - front = glm::normalize(front); - right = glm::normalize(glm::cross(front, worldUp)); - up = glm::normalize(glm::cross(right, front)); - - glm::vec3 vel = player->vel.glm(); - switch (direction) { - case FORWARD: { - vel += front * velocity; - break; - } - - case BACKWARD: { - vel -= front * velocity; - break; - } - - case RIGHT: { - vel += right * velocity; - break; - } - - case LEFT: { - vel -= right * velocity; - break; - } - - case JUMP: - if (player->onGround && !player->isFlying) { - vel.y += 10; - player->onGround = false; - } else +void GameState::HandleMovement(GameState::MoveType direction, float deltaTime) { + if (!gameStatus.isGameStarted) + return; + + const double playerSpeed = 43; + + float velocity = playerSpeed * deltaTime; + + double playerYaw = Entity::DecodeYaw(player->yaw); + double playerPitch = Entity::DecodePitch(player->pitch); + + glm::vec3 front, right, worldUp, up; + worldUp = glm::vec3(0.0f, 1.0f, 0.0f); + front.x = cos(glm::radians(playerYaw)) * cos(glm::radians(playerPitch)); + front.y = player->isFlying ? sin(glm::radians(playerPitch)) : 0; + front.z = sin(glm::radians(playerYaw)) * cos(glm::radians(playerPitch)); + front = glm::normalize(front); + right = glm::normalize(glm::cross(front, worldUp)); + up = glm::normalize(glm::cross(right, front)); + + glm::vec3 vel = player->vel.glm(); + switch (direction) { + case FORWARD: { + vel += front * velocity; + break; + } + + case BACKWARD: { + vel -= front * velocity; + break; + } + + case RIGHT: { + vel += right * velocity; + break; + } + + case LEFT: { + vel -= right * velocity; + break; + } + + case JUMP: + if (player->onGround && !player->isFlying) { + vel.y += 10; + player->onGround = false; + } + else if (player->isFlying) { vel += up * velocity; } - break; - } - player->vel = VectorF(vel.x, vel.y, vel.z); + break; + } + player->vel = VectorF(vel.x, vel.y, vel.z); } void GameState::HandleRotation(double yaw, double pitch) { - if (!g_IsGameStarted) - return; - double playerYaw = Entity::DecodeYaw(player->yaw); - double playerPitch = Entity::DecodePitch(player->pitch); - playerYaw += yaw; - playerPitch += pitch; - if (playerPitch > 89.0) - playerPitch = 89.0; - if (playerPitch < -89.0) - playerPitch = -89.0; - player->yaw = Entity::EncodeYaw(playerYaw); - player->pitch = Entity::EncodePitch(playerPitch); + if (!gameStatus.isGameStarted) + return; + + double playerYaw = Entity::DecodeYaw(player->yaw); + double playerPitch = Entity::DecodePitch(player->pitch); + playerYaw += yaw; + playerPitch += pitch; + if (playerPitch > 89.0) + playerPitch = 89.0; + if (playerPitch < -89.0) + playerPitch = -89.0; + player->yaw = Entity::EncodeYaw(playerYaw); + player->pitch = Entity::EncodePitch(playerPitch); } glm::mat4 GameState::GetViewMatrix() { - double playerYaw = Entity::DecodeYaw(player->yaw); - double playerPitch = Entity::DecodePitch(player->pitch); - glm::vec3 front, right, worldUp, up; - worldUp = glm::vec3(0.0f, 1.0f, 0.0f); - front.x = cos(glm::radians(playerYaw)) * cos(glm::radians(playerPitch)); - front.y = sin(glm::radians(playerPitch)); - front.z = sin(glm::radians(playerYaw)) * cos(glm::radians(playerPitch)); - front = glm::normalize(front); - right = glm::normalize(glm::cross(front, worldUp)); - up = glm::normalize(glm::cross(right, front)); - - glm::vec3 eyePos = player->pos.glm(); - eyePos += player->EyeOffset.glm(); - return glm::lookAt(eyePos, eyePos + front, up); + double playerYaw = Entity::DecodeYaw(player->yaw); + double playerPitch = Entity::DecodePitch(player->pitch); + glm::vec3 front, right, worldUp, up; + worldUp = glm::vec3(0.0f, 1.0f, 0.0f); + front.x = cos(glm::radians(playerYaw)) * cos(glm::radians(playerPitch)); + front.y = sin(glm::radians(playerPitch)); + front.z = sin(glm::radians(playerYaw)) * cos(glm::radians(playerPitch)); + front = glm::normalize(front); + right = glm::normalize(glm::cross(front, worldUp)); + up = glm::normalize(glm::cross(right, front)); + + glm::vec3 eyePos = player->pos.glm(); + eyePos += player->EyeOffset.glm(); + return glm::lookAt(eyePos, eyePos + front, up); } // TODO: it should actually be something like this: @@ -567,20 +577,20 @@ glm::mat4 GameState::GetViewMatrix() { // send_packet(packet_type=start_digging_packet) // delay(time=selected_block_dig_time, action=finish_digging) void GameState::StartDigging() { - if (!isBlockSelected) - return; + if (!selectionStatus.isBlockSelected) + return; - auto packetStart = std::make_shared<PacketPlayerDigging>(0,selectedBlock,1); - auto packet = std::static_pointer_cast<Packet>(packetStart); - PUSH_EVENT("SendPacket",packet); + auto packetStart = std::make_shared<PacketPlayerDigging>(0, selectionStatus.selectedBlock, 1); + auto packet = std::static_pointer_cast<Packet>(packetStart); + PUSH_EVENT("SendPacket", packet); - FinishDigging(); + FinishDigging(); } void GameState::FinishDigging() { - auto packetFinish = std::make_shared<PacketPlayerDigging>(2,selectedBlock,1); - auto packet = std::static_pointer_cast<Packet>(packetFinish); - PUSH_EVENT("SendPacket",packet); + auto packetFinish = std::make_shared<PacketPlayerDigging>(2, selectionStatus.selectedBlock, 1); + auto packet = std::static_pointer_cast<Packet>(packetFinish); + PUSH_EVENT("SendPacket", packet); } // TODO: it should actually be something like this: @@ -589,48 +599,48 @@ void GameState::FinishDigging() { // send_packet(packet_type=start_digging_packet) // remove_delayed_action(finish_digging) void GameState::CancelDigging() { - auto packetCancel = std::make_shared<PacketPlayerDigging>(1,selectedBlock,1); - auto packet = std::static_pointer_cast<Packet>(packetCancel); - PUSH_EVENT("SendPacket", packet); + auto packetCancel = std::make_shared<PacketPlayerDigging>(1, selectionStatus.selectedBlock, 1); + auto packet = std::static_pointer_cast<Packet>(packetCancel); + PUSH_EVENT("SendPacket", packet); } BlockFacing detectHitFace(VectorF raycastHit, Vector selectedBlock) { - auto vec = VectorF(selectedBlock.x + .5, selectedBlock.y + .5, selectedBlock.z +.5) - raycastHit; - - // TODO: move these vectors to Vector.hpp - static const auto vecUp = VectorF(0, 1, 0); - static const auto vecRight = VectorF(1, 0, 0); - static const auto vecForward = VectorF(0, 0, -1); - - const double up = vec.cosBetween(vecUp); - const double down = -up; - const double right = vec.cosBetween(vecRight); - const double left = -right; - const double forward = vec.cosBetween(vecForward); - const double backward = -forward; - - const double min_cos = _min(up, down, right, left, forward, backward); - if (min_cos == down) - return BlockFacing::Bottom; - else if (min_cos == up) - return BlockFacing::Top; - else if (min_cos == forward) - return BlockFacing::North; - else if (min_cos == backward) - return BlockFacing::South; - else if (min_cos == left) - return BlockFacing::West; - else return BlockFacing::East; + auto vec = VectorF(selectedBlock.x + .5, selectedBlock.y + .5, selectedBlock.z + .5) - raycastHit; + + // TODO: move these vectors to Vector.hpp + static const auto vecUp = VectorF(0, 1, 0); + static const auto vecRight = VectorF(1, 0, 0); + static const auto vecForward = VectorF(0, 0, -1); + + const double up = vec.cosBetween(vecUp); + const double down = -up; + const double right = vec.cosBetween(vecRight); + const double left = -right; + const double forward = vec.cosBetween(vecForward); + const double backward = -forward; + + const double min_cos = _min(up, down, right, left, forward, backward); + if (min_cos == down) + return BlockFacing::Bottom; + else if (min_cos == up) + return BlockFacing::Top; + else if (min_cos == forward) + return BlockFacing::North; + else if (min_cos == backward) + return BlockFacing::South; + else if (min_cos == left) + return BlockFacing::West; + else return BlockFacing::East; } void GameState::PlaceBlock() { - if (!isBlockSelected) - return; + if (!selectionStatus.isBlockSelected) + return; - BlockFacing face = detectHitFace(raycastHit, selectedBlock); - auto packetPlace = std::make_shared<PacketPlayerBlockPlacement>( - selectedBlock, (unsigned char) face, 0, 0, 0, 0); + BlockFacing face = detectHitFace(selectionStatus.raycastHit, selectionStatus.selectedBlock); + auto packetPlace = std::make_shared<PacketPlayerBlockPlacement>( + selectionStatus.selectedBlock, (unsigned char)face, 0, 0, 0, 0); - auto packet = std::static_pointer_cast<Packet>(packetPlace); - PUSH_EVENT("SendPacket", packet); + auto packet = std::static_pointer_cast<Packet>(packetPlace); + PUSH_EVENT("SendPacket", packet); }
\ No newline at end of file diff --git a/src/GameState.hpp b/src/GameState.hpp index e96af29..8318c8a 100644 --- a/src/GameState.hpp +++ b/src/GameState.hpp @@ -1,73 +1,122 @@ #pragma once -#include <mutex> -#include <queue> #include <memory> +#include <string> +#include <vector> +#include <mutex> #include <glm/mat4x4.hpp> +#include "Vector.hpp" #include "World.hpp" #include "Window.hpp" class Packet; -class NetworkClient; class Entity; +struct TimeStatus { + double interpolatedTimeOfDay = 0; + long long worldAge = 0; + long long timeOfDay = 0; + bool doDaylightCycle = true; +}; + +struct GameStatus { + std::string levelType; + Vector spawnPosition; + int gamemode = 0; + int dimension = 0; + unsigned char difficulty = 0; + unsigned char maxPlayers = 0; + bool isGameStarted = false; + bool reducedDebugInfo = false; +}; + +struct PlayerStatus { + std::string uid; + std::string name; + float flyingSpeed = 0; + float fovModifier = 0; + float health = 0; + int eid = 0; + bool invulnerable = false; + bool flying = false; + bool allowFlying = false; + bool creativeMode = false; +}; + +struct SelectionStatus { + VectorF raycastHit; + Vector selectedBlock; + float distanceToSelectedBlock; + bool isBlockSelected; +}; + class GameState { -public: + Entity* player = nullptr; - GameState() = default; + World world; + + TimeStatus timeStatus; - ~GameState() = default; + GameStatus gameStatus; + + PlayerStatus playerStatus; + + SelectionStatus selectionStatus; + + Window playerInventory; + + std::vector<Window> openedWindows; +public: void Update(float deltaTime); void UpdatePacket(std::shared_ptr<Packet> ptr); - enum Direction { - FORWARD, BACKWARD, LEFT, RIGHT, JUMP - }; void StartDigging(); + void FinishDigging(); + void CancelDigging(); + void PlaceBlock(); - void HandleMovement(GameState::Direction direction, float deltaTime); + + enum MoveType { + FORWARD, BACKWARD, LEFT, RIGHT, JUMP + }; + + void HandleMovement(GameState::MoveType direction, float deltaTime); + void HandleRotation(double yaw, double pitch); + glm::mat4 GetViewMatrix(); - Entity* player; - - World world; - - std::string g_PlayerUuid = ""; - std::string g_PlayerName = ""; - bool g_IsGameStarted = false; - int g_PlayerEid = 0; - int g_Gamemode = 0; - int g_Dimension = 0; - unsigned char g_Difficulty = 0; - unsigned char g_MaxPlayers = 0; - std::string g_LevelType = ""; - bool g_ReducedDebugInfo = false; - Vector g_SpawnPosition; - 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_PlayerHealth = 0; - - long long WorldAge = 0; - long long TimeOfDay = 0; - - Window playerInventory; - std::vector<Window> openedWindows; - - bool isBlockSelected; - Vector selectedBlock; - float distanceToSelectedBlock; - VectorF raycastHit; - - double interpolatedTimeOfDay; - bool doDaylightCycle = true; + + inline Entity *GetPlayer() { + return player; + } + + inline const World &GetWorld() const { + return world; + } + + inline const TimeStatus &GetTimeStatus() const { + return timeStatus; + } + + inline const GameStatus &GetGameStatus() const { + return gameStatus; + } + + inline const PlayerStatus &GetPlayerStatus() const { + return playerStatus; + } + + inline const SelectionStatus &GetSelectionStatus() const { + return selectionStatus; + } + + inline const Window &GetInventory() const { + 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<NetworkClient> nc; std::unique_ptr<GameState> gs; +std::shared_ptr<GameState> gsReadOnly; std::unique_ptr<Render> 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<GameState>(*gs.get()); + gsCopyMutex.unlock(); + timer.Update(); } } @@ -212,8 +218,9 @@ void GlobalState::Exec() { render.reset(); } -GameState *GlobalState::GetGameState() { - return gs.get(); +std::shared_ptr<GameState> GlobalState::GetGameState() { + std::lock_guard<std::mutex> 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 <memory> + class NetworkClient; class GameState; class Render; @@ -15,7 +17,7 @@ enum class State { }; struct GlobalState { - static GameState *GetGameState(); + static std::shared_ptr<GameState> GetGameState(); static Render *GetRender(); static void Exec(); static State GetState(); diff --git a/src/Render.cpp b/src/Render.cpp index 41f2c7e..cf108e4 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(); @@ -382,6 +385,10 @@ void Render::RenderGui() { ImGui::Text("FPS: %.1f (%.3fms)", ImGui::GetIO().Framerate, 1000.0f / ImGui::GetIO().Framerate); float gameTime = DebugInfo::gameThreadTime / 100.0f; if (world) { + Entity *playerPtr = world->GameStatePtr()->GetPlayer(); + SelectionStatus selectionStatus = world->GameStatePtr()->GetSelectionStatus(); + const World *worldPtr = &world->GameStatePtr()->GetWorld(); + ImGui::Text("TPS: %.1f (%.2fms)", 1000.0f / gameTime, gameTime); ImGui::Text("Sections loaded: %d", (int) DebugInfo::totalSections); ImGui::Text( @@ -392,52 +399,56 @@ void Render::RenderGui() { "Culled sections: %d", (int) DebugInfo::renderSections - world->culledSections); + ImGui::Text( + "Rendered faces: %d", + (int)DebugInfo::renderFaces); + ImGui::Text( "Player pos: %.1f %.1f %.1f OnGround=%d", - world->GameStatePtr()->player->pos.x, - world->GameStatePtr()->player->pos.y, - world->GameStatePtr()->player->pos.z, - world->GameStatePtr()->player->onGround); + playerPtr->pos.x, + playerPtr->pos.y, + playerPtr->pos.z, + playerPtr->onGround); ImGui::Text( "Player block pos: %d %d %d in %d %d %d", - (int)(world->GameStatePtr()->player->pos.x - std::floor(world->GameStatePtr()->player->pos.x / 16.0) * 16), - (int)(world->GameStatePtr()->player->pos.y - std::floor(world->GameStatePtr()->player->pos.y / 16.0) * 16), - (int)(world->GameStatePtr()->player->pos.z - std::floor(world->GameStatePtr()->player->pos.z / 16.0) * 16), + (int)(playerPtr->pos.x - std::floor(playerPtr->pos.x / 16.0) * 16), + (int)(playerPtr->pos.y - std::floor(playerPtr->pos.y / 16.0) * 16), + (int)(playerPtr->pos.z - std::floor(playerPtr->pos.z / 16.0) * 16), - (int)std::floor(world->GameStatePtr()->player->pos.x / 16.0), - (int)std::floor(world->GameStatePtr()->player->pos.y / 16.0), - (int)std::floor(world->GameStatePtr()->player->pos.z / 16.0)); + (int)std::floor(playerPtr->pos.x / 16.0), + (int)std::floor(playerPtr->pos.y / 16.0), + (int)std::floor(playerPtr->pos.z / 16.0)); ImGui::Text( "Player vel: %.1f %.1f %.1f", - world->GameStatePtr()->player->vel.x, - world->GameStatePtr()->player->vel.y, - world->GameStatePtr()->player->vel.z); + playerPtr->vel.x, + playerPtr->vel.y, + playerPtr->vel.z); ImGui::Text( "Player health: %.1f/%.1f", - world->GameStatePtr()->g_PlayerHealth, 20.0f); + world->GameStatePtr()->GetPlayerStatus().health, 20.0f); ImGui::Text( "Selected block: %d %d %d : %.1f", - world->GameStatePtr()->selectedBlock.x, - world->GameStatePtr()->selectedBlock.y, - world->GameStatePtr()->selectedBlock.z, - world->GameStatePtr()->distanceToSelectedBlock); + selectionStatus.selectedBlock.x, + selectionStatus.selectedBlock.y, + selectionStatus.selectedBlock.z, + selectionStatus.distanceToSelectedBlock); ImGui::Text("Selected block light: %d (%d)", - world->GameStatePtr()->world.GetBlockLight(world->GameStatePtr()->selectedBlock), - world->GameStatePtr()->world.GetBlockSkyLight(world->GameStatePtr()->selectedBlock)); + worldPtr->GetBlockLight(selectionStatus.selectedBlock), + worldPtr->GetBlockSkyLight(selectionStatus.selectedBlock)); ImGui::Text("Selected block id: %d:%d (%s)", - world->GameStatePtr()->world.GetBlockId(world->GameStatePtr()->selectedBlock).id, - world->GameStatePtr()->world.GetBlockId(world->GameStatePtr()->selectedBlock).state, - AssetManager::GetAssetNameByBlockId(BlockId{ world->GameStatePtr()->world.GetBlockId(world->GameStatePtr()->selectedBlock).id,0 }).c_str()); + worldPtr->GetBlockId(selectionStatus.selectedBlock).id, + worldPtr->GetBlockId(selectionStatus.selectedBlock).state, + AssetManager::GetAssetNameByBlockId(BlockId{ worldPtr->GetBlockId(selectionStatus.selectedBlock).id,0 }).c_str()); ImGui::Text("Selected block variant: %s:%s", - TransformBlockIdToBlockStateName(world->GameStatePtr()->world.GetBlockId(world->GameStatePtr()->selectedBlock)).first.c_str(), - TransformBlockIdToBlockStateName(world->GameStatePtr()->world.GetBlockId(world->GameStatePtr()->selectedBlock)).second.c_str()); + TransformBlockIdToBlockStateName(worldPtr->GetBlockId(selectionStatus.selectedBlock)).first.c_str(), + TransformBlockIdToBlockStateName(worldPtr->GetBlockId(selectionStatus.selectedBlock)).second.c_str()); } ImGui::End(); @@ -499,58 +510,58 @@ void Render::RenderGui() { }; ImGui::SetNextWindowPosCenter(); ImGui::Begin("Inventory", 0, windowFlags); - Window& inventory = world->GameStatePtr()->playerInventory; + const Window& inventory = world->GameStatePtr()->GetInventory(); //Hand and drop slots if (renderSlot(inventory.handSlot, -1)) { } ImGui::SameLine(); if (ImGui::Button("Drop")) { - inventory.MakeClick(-1, true, true); + //inventory.MakeClick(-1, true, true); } ImGui::SameLine(); ImGui::Text("Hand slot and drop mode"); ImGui::Separator(); //Crafting if (renderSlot(inventory.slots[1], 1)) { - inventory.MakeClick(1, true); + //inventory.MakeClick(1, true); } ImGui::SameLine(); if (renderSlot(inventory.slots[2], 2)) { - inventory.MakeClick(2, true); + //inventory.MakeClick(2, true); } //Crafting result ImGui::SameLine(); ImGui::Text("Result"); ImGui::SameLine(); if (renderSlot(inventory.slots[0], 0)) { - inventory.MakeClick(0, true); + //inventory.MakeClick(0, true); } //Crafting second line if (renderSlot(inventory.slots[3], 3)) { - inventory.MakeClick(3, true); + //inventory.MakeClick(3, true); } ImGui::SameLine(); if (renderSlot(inventory.slots[4], 4)) { - inventory.MakeClick(4, true); + //inventory.MakeClick(4, true); } ImGui::Separator(); //Armor and offhand for (int i = 5; i < 8 + 1; i++) { if (renderSlot(inventory.slots[i], i)) { - inventory.MakeClick(i, true); + //inventory.MakeClick(i, true); } ImGui::SameLine(); } if (renderSlot(inventory.slots[45], 45)) { - inventory.MakeClick(45, true); + //inventory.MakeClick(45, true); } ImGui::SameLine(); ImGui::Text("Armor and offhand"); ImGui::Separator(); for (int i = 36; i < 44 + 1; i++) { if (renderSlot(inventory.slots[i], i)) { - inventory.MakeClick(i, true); + //inventory.MakeClick(i, true); } ImGui::SameLine(); } @@ -559,21 +570,21 @@ void Render::RenderGui() { ImGui::Text("Main inventory"); for (int i = 9; i < 17 + 1; i++) { if (renderSlot(inventory.slots[i], i)) { - inventory.MakeClick(i, true); + //inventory.MakeClick(i, true); } ImGui::SameLine(); } ImGui::Text(""); for (int i = 18; i < 26 + 1; i++) { if (renderSlot(inventory.slots[i], i)) { - inventory.MakeClick(i, true); + //inventory.MakeClick(i, true); } ImGui::SameLine(); } ImGui::Text(""); for (int i = 27; i < 35 + 1; i++) { if (renderSlot(inventory.slots[i], i)) { - inventory.MakeClick(i, true); + //inventory.MakeClick(i, true); } ImGui::SameLine(); } @@ -615,7 +626,7 @@ void Render::RenderGui() { if (fieldSensetivity != sensetivity) sensetivity = fieldSensetivity; - world->GameStatePtr()->player->isFlying = fieldFlight; + world->GameStatePtr()->GetPlayer()->isFlying = fieldFlight; isWireframe = fieldWireframe; timer.SetDelayLength(std::chrono::duration<double, std::milli>(1.0 / fieldTargetFps * 1000.0)); @@ -671,7 +682,7 @@ void Render::InitEvents() { renderWorld = true; GlobalState::SetState(State::Playing); glClearColor(0, 0, 0, 1.0f); - world->GameStatePtr()->player->isFlying = this->fieldFlight; + world->GameStatePtr()->GetPlayer()->isFlying = this->fieldFlight; PUSH_EVENT("SetMinLightLevel", fieldBrightness); }); diff --git a/src/RendererEntity.cpp b/src/RendererEntity.cpp index a1c9566..25403be 100644 --- a/src/RendererEntity.cpp +++ b/src/RendererEntity.cpp @@ -4,9 +4,10 @@ #include <glm/gtc/type_ptr.hpp> #include "Entity.hpp" -#include "World.hpp" +#include "GameState.hpp" #include "Renderer.hpp" #include "AssetManager.hpp" +#include "GlobalState.hpp" const GLfloat vertices[] = { -0.5f, 0.5f, 0.5f, @@ -114,18 +115,17 @@ GLuint RendererEntity::GetVao(){ return Vao; } -RendererEntity::RendererEntity(World *ptr, unsigned int id) +RendererEntity::RendererEntity(unsigned int id) { - world = ptr; entityId = id; } RendererEntity::~RendererEntity() { } -void RendererEntity::Render(RenderState & renderState) { +void RendererEntity::Render(RenderState& renderState, const World *world) { glm::mat4 model = glm::mat4(1.0); - Entity& entity = world->GetEntity(entityId); + const 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 e2e8bf1..346f9fb 100644 --- a/src/RendererEntity.hpp +++ b/src/RendererEntity.hpp @@ -2,17 +2,16 @@ #include <GL/glew.h> -class World; class RenderState; +class World; class RendererEntity { unsigned int entityId; - World *world; public: - RendererEntity(World *ptr, unsigned int id); + RendererEntity(unsigned int id); ~RendererEntity(); - void Render(RenderState& renderState); + void Render(RenderState& renderState, const World *world); static GLuint GetVao(); }; diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp index 75859e9..e0a28a4 100644 --- a/src/RendererWorld.cpp +++ b/src/RendererWorld.cpp @@ -52,13 +52,13 @@ void RendererWorld::ParseQueueUpdate() { vec.y -= 4500; } - parsing[id].data.section = gs->world.GetSection(vec); - parsing[id].data.north = gs->world.GetSection(vec + Vector(0, 0, 1)); - parsing[id].data.south = gs->world.GetSection(vec + Vector(0, 0, -1)); - parsing[id].data.west = gs->world.GetSection(vec + Vector(1, 0, 0)); - parsing[id].data.east = gs->world.GetSection(vec + Vector(-1, 0, 0)); - parsing[id].data.bottom = gs->world.GetSection(vec + Vector(0, -1, 0)); - parsing[id].data.top = gs->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; @@ -86,7 +86,7 @@ void RendererWorld::ParseQeueueRemoveUnnecessary() { if (std::find(elements.begin(), elements.end(), vec) != elements.end()) continue; - const Section& section = gs->world.GetSection(vec); + const Section& section = gs->GetWorld().GetSection(vec); bool skip = false; @@ -112,10 +112,10 @@ void RendererWorld::ParseQeueueRemoveUnnecessary() { } void RendererWorld::UpdateAllSections(VectorF playerPos) { - Vector playerChunk(std::floor(gs->player->pos.x / 16), 0, std::floor(gs->player->pos.z / 16)); + Vector playerChunk(std::floor(gs->GetPlayer()->pos.x / 16), 0, std::floor(gs->GetPlayer()->pos.z / 16)); std::vector<Vector> suitableChunks; - auto chunks = gs->world.GetSectionsList(); + auto chunks = gs->GetWorld().GetSectionsList(); for (auto& it : chunks) { double distance = (Vector(it.x, 0, it.z) - playerChunk).GetLength(); if (distance > MaxRenderingDistance) @@ -134,7 +134,7 @@ void RendererWorld::UpdateAllSections(VectorF playerPos) { PUSH_EVENT("DeleteSectionRender", it); } - playerChunk.y = std::floor(gs->player->pos.y / 16.0); + playerChunk.y = std::floor(gs->GetPlayer()->pos.y / 16.0); std::sort(suitableChunks.begin(), suitableChunks.end(), [playerChunk](Vector lhs, Vector rhs) { double leftLengthToPlayer = (playerChunk - lhs).GetLength(); double rightLengthToPlayer = (playerChunk - rhs).GetLength(); @@ -146,7 +146,7 @@ void RendererWorld::UpdateAllSections(VectorF playerPos) { } } -RendererWorld::RendererWorld(GameState* ptr) { +RendererWorld::RendererWorld(std::shared_ptr<GameState> ptr) { gs = ptr; MaxRenderingDistance = 2; numOfWorkers = _max(1, (signed int) std::thread::hardware_concurrency() - 2); @@ -184,9 +184,9 @@ RendererWorld::RendererWorld(GameState* ptr) { listener->RegisterHandler("EntityChanged", [this](const Event& eventData) { auto data = eventData.get<unsigned int>(); - for (unsigned int entityId : gs->world.GetEntitiesList()) { + for (unsigned int entityId : gs->GetWorld().GetEntitiesList()) { if (entityId == data) { - entities.push_back(RendererEntity(&gs->world, entityId)); + entities.push_back(RendererEntity(entityId)); } } }); @@ -196,7 +196,7 @@ RendererWorld::RendererWorld(GameState* ptr) { if (vec == Vector()) return; - Vector playerChunk(std::floor(gs->player->pos.x / 16), 0, std::floor(gs->player->pos.z / 16)); + Vector playerChunk(std::floor(gs->GetPlayer()->pos.x / 16), 0, std::floor(gs->GetPlayer()->pos.z / 16)); double distanceToChunk = (Vector(vec.x, 0, vec.z) - playerChunk).GetLength(); if (MaxRenderingDistance != 1000 && distanceToChunk > MaxRenderingDistance) { @@ -213,7 +213,7 @@ RendererWorld::RendererWorld(GameState* ptr) { if (vec == Vector()) return; - Vector playerChunk(std::floor(gs->player->pos.x / 16), 0, std::floor(gs->player->pos.z / 16)); + Vector playerChunk(std::floor(gs->GetPlayer()->pos.x / 16), 0, std::floor(gs->GetPlayer()->pos.z / 16)); double distanceToChunk = (Vector(vec.x, 0, vec.z) - playerChunk).GetLength(); if (MaxRenderingDistance != 1000 && distanceToChunk > MaxRenderingDistance) { @@ -228,7 +228,7 @@ RendererWorld::RendererWorld(GameState* ptr) { }); listener->RegisterHandler("UpdateSectionsRender", [this](const Event&) { - UpdateAllSections(gs->player->pos); + UpdateAllSections(gs->GetPlayer()->pos); }); listener->RegisterHandler("PlayerPosChanged", [this](const Event& eventData) { @@ -287,11 +287,11 @@ void RendererWorld::Render(RenderState & renderState) { renderState.SetActiveVao(RendererEntity::GetVao()); for (auto& it : entities) { - it.Render(renderState); + it.Render(renderState, &gs->GetWorld()); } //Render selected block - Vector selectedBlock = gs->selectedBlock; + Vector selectedBlock = gs->GetSelectionStatus().selectedBlock; if (selectedBlock != Vector()) { glLineWidth(2.0f); { @@ -309,7 +309,7 @@ void RendererWorld::Render(RenderState & renderState) { //Render raycast hit const bool renderHit = false; if (renderHit) { - VectorF hit = gs->raycastHit; + VectorF hit = gs->GetSelectionStatus().raycastHit; glLineWidth(2.0f); { glm::mat4 model; @@ -329,16 +329,16 @@ void RendererWorld::Render(RenderState & renderState) { glCheckError(); //Render sky - renderState.TimeOfDay = gs->TimeOfDay; + renderState.TimeOfDay = gs->GetTimeStatus().timeOfDay; Shader *skyShader = AssetManager::GetAsset<AssetShader>("/altcraft/shaders/sky")->shader.get(); skyShader->Activate(); skyShader->SetUniform("projection", projection); skyShader->SetUniform("view", view); glm::mat4 model = glm::mat4(1.0); - model = glm::translate(model, gs->player->pos.glm()); + model = glm::translate(model, gs->GetPlayer()->pos.glm()); const float scale = 1000000.0f; model = glm::scale(model, glm::vec3(scale, scale, scale)); - float shift = gs->interpolatedTimeOfDay / 24000.0f; + float shift = gs->GetTimeStatus().interpolatedTimeOfDay / 24000.0f; if (shift < 0) shift *= -1.0f; model = glm::rotate(model, glm::radians(90.0f), glm::vec3(0, 1.0f, 0.0f)); @@ -355,7 +355,7 @@ void RendererWorld::Render(RenderState & renderState) { const float moonriseLength = moonriseMax - moonriseMin; float mixLevel = 0; - float dayTime = gs->interpolatedTimeOfDay; + float dayTime = gs->GetTimeStatus().interpolatedTimeOfDay; if (dayTime < 0) dayTime *= -1; while (dayTime > 24000) @@ -386,6 +386,7 @@ void RendererWorld::Render(RenderState & renderState) { Frustum frustum(projView); size_t culledSections = sections.size(); + unsigned int renderedFaces = 0; for (auto& section : sections) { glm::vec3 point{ section.second.GetPosition().x * 16 + 8, @@ -400,8 +401,10 @@ void RendererWorld::Render(RenderState & renderState) { continue; } section.second.Render(renderState); + renderedFaces += section.second.numOfFaces; } this->culledSections = culledSections; + DebugInfo::renderFaces = renderedFaces; glCheckError(); } @@ -445,5 +448,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<GameState> gs; std::unique_ptr<EventListener> 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<GameState> ptr); ~RendererWorld(); void Render(RenderState& renderState); @@ -63,4 +63,8 @@ public: GameState *GameStatePtr(); int culledSections = 0; + + inline void UpdateGameState(std::shared_ptr<GameState> 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<unsigned sh std::copy(skyData.begin(), skyData.end(), sky); hash = -1; + CalculateHash(); } BlockId Section::GetBlockId(Vector pos) const { @@ -109,6 +110,7 @@ unsigned char Section::GetBlockSkyLight(Vector pos) const void Section::SetBlockId(Vector pos, BlockId value) { overrideList[pos] = value; hash = -1; + CalculateHash(); } Vector Section::GetPosition() const { diff --git a/src/World.cpp b/src/World.cpp index 9a4bfd1..da0a33b 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -3,7 +3,6 @@ #include <bitset> #include <glm/glm.hpp> -#include "Section.hpp" #include "Event.hpp" #include "DebugInfo.hpp" #include "Packet.hpp" @@ -15,16 +14,16 @@ void World::ParseChunkData(std::shared_ptr<PacketChunkData> 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<Section>(ParseSection(&chunkData, chunkPosition)); if (packet->GroundUpContinuous) { - if (!sections.insert(std::make_pair(chunkPosition, std::make_unique<Section>(section))).second) { + if (!sections.insert(std::make_pair(chunkPosition, section)).second) { LOG(ERROR) << "New chunk not created " << chunkPosition << " potential memory leak"; } UpdateSectionsList(); } else { - std::swap(*sections.at(chunkPosition).get(), section); + std::swap(sections.at(chunkPosition), section); } PUSH_EVENT("ChunkChanged", chunkPosition); @@ -58,13 +57,7 @@ Section World::ParseSection(StreamInput *data, Vector position) { std::move(blockLight), std::move(skyLight)); } -World::~World() { -} - -World::World() { -} - -bool World::isPlayerCollides(double X, double Y, double Z) { +bool World::isPlayerCollides(double X, double Y, double Z) const { Vector PlayerChunk(floor(X / 16.0), floor(Y / 16.0), floor(Z / 16.0)); if (sections.find(PlayerChunk) == sections.end() || sections.find(PlayerChunk - Vector(0, 1, 0)) == sections.end()) @@ -118,28 +111,26 @@ bool World::isPlayerCollides(double X, double Y, double Z) { return false; } -std::vector<Vector> World::GetSectionsList() { - sectionsListMutex.lock(); +std::vector<Vector> World::GetSectionsList() const { auto vec = sectionsList; - sectionsListMutex.unlock(); return vec; } static Section fallbackSection; -const Section &World::GetSection(Vector sectionPos) { +const Section &World::GetSection(Vector sectionPos) const { auto result = sections.find(sectionPos); if (result == sections.end()) { //LOG(ERROR) << "Accessed not loaded section " << sectionPos; return fallbackSection; } else { - return *result->second.get(); + return *result->second; } } // TODO: skip liquid blocks -RaycastResult World::Raycast(glm::vec3 position, glm::vec3 direction) { +RaycastResult World::Raycast(glm::vec3 position, glm::vec3 direction) const { const float maxLen = 5.0; const float step = 0.01; glm::vec3 pos = glm::vec3(0.0); @@ -199,7 +190,6 @@ void World::UpdatePhysics(float delta) { return { false }; }; - entitiesMutex.lock(); for (auto& it : entities) { if (it.isFlying) { VectorF newPos = it.pos + VectorF(it.vel.x, it.vel.y, it.vel.z) * delta; @@ -247,49 +237,50 @@ void World::UpdatePhysics(float delta) { it.vel = it.vel + resistForce; } } - entitiesMutex.unlock(); DebugInfo::totalSections = sections.size(); } Entity& World::GetEntity(unsigned int EntityId){ - entitiesMutex.lock(); for (auto& it : entities) { if (it.entityId == EntityId) { - entitiesMutex.unlock(); return it; } } - entitiesMutex.unlock(); static Entity fallback; return fallback; } -std::vector<unsigned int> World::GetEntitiesList() { - entitiesMutex.lock(); +const Entity &World::GetEntity(unsigned int EntityId) const { + for (auto& it : entities) { + if (it.entityId == EntityId) { + return it; + } + } + + static Entity fallback; + return fallback; +} + +std::vector<unsigned int> World::GetEntitiesList() const { std::vector<unsigned int> ret; for (auto& it : entities) { ret.push_back(it.entityId); } - entitiesMutex.unlock(); return ret; } void World::AddEntity(Entity entity) { - entitiesMutex.lock(); for (auto& it : entities) { if (it.entityId == entity.entityId) { LOG(ERROR) << "Adding already existing entity: " << entity.entityId; - entitiesMutex.unlock(); return; } } entities.push_back(entity); - entitiesMutex.unlock(); } void World::DeleteEntity(unsigned int EntityId) { - entitiesMutex.lock(); auto it = entities.begin(); for (; it != entities.end(); ++it) { if (it->entityId == EntityId) { @@ -298,7 +289,6 @@ void World::DeleteEntity(unsigned int EntityId) { } if (it != entities.end()) entities.erase(it); - entitiesMutex.unlock(); } void World::ParseChunkData(std::shared_ptr<PacketBlockChange> packet) { @@ -333,7 +323,7 @@ void World::ParseChunkData(std::shared_ptr<PacketMultiBlockChange> packet) { } void World::ParseChunkData(std::shared_ptr<PacketUnloadChunk> packet) { - std::vector<std::map<Vector, std::unique_ptr<Section>>::iterator> toRemove; + std::vector<std::map<Vector, std::shared_ptr<Section>>::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); @@ -346,20 +336,18 @@ void World::ParseChunkData(std::shared_ptr<PacketUnloadChunk> packet) { } void World::UpdateSectionsList() { - sectionsListMutex.lock(); sectionsList.clear(); for (auto& it : sections) { sectionsList.push_back(it.first); } - sectionsListMutex.unlock(); } -BlockId World::GetBlockId(Vector pos) { +BlockId World::GetBlockId(Vector pos) const { Vector sectionPos(std::floor(pos.x / 16.0), std::floor(pos.y / 16.0), std::floor(pos.z / 16.0)); - Section* section = GetSectionPtr(sectionPos); + const Section* section = GetSectionPtr(sectionPos); return !section ? BlockId{0, 0} : section->GetBlockId(pos - (sectionPos * 16)); } @@ -368,8 +356,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<Section>(*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)); @@ -393,42 +382,38 @@ void World::SetBlockSkyLight(Vector pos, unsigned char light) { } -Section *World::GetSectionPtr(Vector position) { +const Section *World::GetSectionPtr(Vector position) const { auto it = sections.find(position); if (it == sections.end()) return nullptr; - return it->second.get(); + return it->second.get(); } Entity* World::GetEntityPtr(unsigned int EntityId) { - entitiesMutex.lock(); for (auto& it : entities) { if (it.entityId == EntityId) { - entitiesMutex.unlock(); return ⁢ } } - entitiesMutex.unlock(); return nullptr; } -unsigned char World::GetBlockLight(Vector pos) -{ +unsigned char World::GetBlockLight(Vector pos) const { Vector sectionPos(std::floor(pos.x / 16.0), std::floor(pos.y / 16.0), std::floor(pos.z / 16.0)); Vector blockPos = pos - (sectionPos * 16); - Section* section = GetSectionPtr(sectionPos); - Section* yp = GetSectionPtr(sectionPos + Vector(0, 1, 0)); - Section* yn = GetSectionPtr(sectionPos + Vector(0, -1, 0)); - Section* xp = GetSectionPtr(sectionPos + Vector(1, 0, 0)); - Section* xn = GetSectionPtr(sectionPos + Vector(-1, 0, 0)); - Section* zp = GetSectionPtr(sectionPos + Vector(0, 0, 1)); - Section* zn = GetSectionPtr(sectionPos + Vector(0, 0, -1)); + const Section* section = GetSectionPtr(sectionPos); + const Section* yp = GetSectionPtr(sectionPos + Vector(0, 1, 0)); + const Section* yn = GetSectionPtr(sectionPos + Vector(0, -1, 0)); + const Section* xp = GetSectionPtr(sectionPos + Vector(1, 0, 0)); + const Section* xn = GetSectionPtr(sectionPos + Vector(-1, 0, 0)); + const Section* zp = GetSectionPtr(sectionPos + Vector(0, 0, 1)); + const Section* zn = GetSectionPtr(sectionPos + Vector(0, 0, -1)); if (!section) return 0; @@ -436,8 +421,7 @@ unsigned char World::GetBlockLight(Vector pos) return GetBlockLight(blockPos, section, xp, xn, yp, yn, zp, zn); } -unsigned char World::GetBlockLight(const Vector &blockPos, const Section *section, const Section *xp, const Section *xn, const Section *yp, const Section *yn, const Section *zp, const Section *zn) -{ +unsigned char World::GetBlockLight(const Vector &blockPos, const Section *section, const Section *xp, const Section *xn, const Section *yp, const Section *yn, const Section *zp, const Section *zn) const { static const Vector directions[] = { Vector(0,0,0), Vector(1,0,0), @@ -475,21 +459,20 @@ unsigned char World::GetBlockLight(const Vector &blockPos, const Section *sectio return value; } -unsigned char World::GetBlockSkyLight(Vector pos) -{ +unsigned char World::GetBlockSkyLight(Vector pos) const { Vector sectionPos( std::floor(pos.x / 16.0), std::floor(pos.y / 16.0), std::floor(pos.z / 16.0)); Vector blockPos = pos - (sectionPos * 16); - Section* section = GetSectionPtr(sectionPos); - Section* yp = GetSectionPtr(sectionPos + Vector(0, 1, 0)); - Section* yn = GetSectionPtr(sectionPos + Vector(0, -1, 0)); - Section* xp = GetSectionPtr(sectionPos + Vector(1, 0, 0)); - Section* xn = GetSectionPtr(sectionPos + Vector(-1, 0, 0)); - Section* zp = GetSectionPtr(sectionPos + Vector(0, 0, 1)); - Section* zn = GetSectionPtr(sectionPos + Vector(0, 0, -1)); + const Section* section = GetSectionPtr(sectionPos); + const Section* yp = GetSectionPtr(sectionPos + Vector(0, 1, 0)); + const Section* yn = GetSectionPtr(sectionPos + Vector(0, -1, 0)); + const Section* xp = GetSectionPtr(sectionPos + Vector(1, 0, 0)); + const Section* xn = GetSectionPtr(sectionPos + Vector(-1, 0, 0)); + const Section* zp = GetSectionPtr(sectionPos + Vector(0, 0, 1)); + const Section* zn = GetSectionPtr(sectionPos + Vector(0, 0, -1)); if (!section) return 0; @@ -497,8 +480,7 @@ unsigned char World::GetBlockSkyLight(Vector pos) return GetBlockSkyLight(blockPos, section, xp, xn, yp, yn, zp, zn); } -unsigned char World::GetBlockSkyLight(const Vector &blockPos, const Section *section, const Section *xp, const Section *xn, const Section *yp, const Section *yn, const Section *zp, const Section *zn) -{ +unsigned char World::GetBlockSkyLight(const Vector &blockPos, const Section *section, const Section *xp, const Section *xn, const Section *yp, const Section *yn, const Section *zp, const Section *zn) const { static const Vector directions[] = { Vector(0,0,0), Vector(1,0,0), diff --git a/src/World.hpp b/src/World.hpp index 165e73d..6c9a615 100644 --- a/src/World.hpp +++ b/src/World.hpp @@ -11,8 +11,8 @@ #include "Entity.hpp" #include "Block.hpp" #include "Vector.hpp" +#include "Section.hpp" -class Section; class PacketChunkData; class PacketBlockChange; class PacketMultiBlockChange; @@ -28,24 +28,17 @@ struct RaycastResult { class World { int dimension = 0; - std::map<Vector, std::unique_ptr<Section>> sections; + std::map<Vector, std::shared_ptr<Section>> sections; Section ParseSection(StreamInput *data, Vector position); std::list<Entity> entities; - std::mutex entitiesMutex; - std::vector<Vector> sectionsList; - std::mutex sectionsListMutex; - void UpdateSectionsList(); public: - World(); - - ~World(); void ParseChunkData(std::shared_ptr<PacketChunkData> packet); @@ -55,13 +48,13 @@ public: void ParseChunkData(std::shared_ptr<PacketUnloadChunk> packet); - bool isPlayerCollides(double X, double Y, double Z); + bool isPlayerCollides(double X, double Y, double Z) const; - std::vector<Vector> GetSectionsList(); + std::vector<Vector> GetSectionsList() const; - const Section &GetSection(Vector sectionPos); + const Section &GetSection(Vector sectionPos) const; - RaycastResult Raycast(glm::vec3 position, glm::vec3 direction); + RaycastResult Raycast(glm::vec3 position, glm::vec3 direction) const; void UpdatePhysics(float delta); @@ -69,13 +62,15 @@ public: Entity* GetEntityPtr(unsigned int EntityId); - std::vector<unsigned int> GetEntitiesList(); + const Entity& GetEntity(unsigned int EntityId) const; + + std::vector<unsigned int> GetEntitiesList() const; void AddEntity(Entity entity); void DeleteEntity(unsigned int EntityId); - BlockId GetBlockId(Vector pos); + BlockId GetBlockId(Vector pos) const; void SetBlockId(Vector pos, BlockId block); @@ -83,13 +78,13 @@ public: void SetBlockSkyLight(Vector pos, unsigned char light); - Section *GetSectionPtr(Vector position); + const Section *GetSectionPtr(Vector position) const; - unsigned char GetBlockLight(Vector pos); + unsigned char GetBlockLight(Vector pos) const; - unsigned char GetBlockLight(const Vector &blockPos, const Section *section, const Section *xp, const Section *xn, const Section *yp, const Section *yn, const Section *zp, const Section *zn); + unsigned char GetBlockLight(const Vector &blockPos, const Section *section, const Section *xp, const Section *xn, const Section *yp, const Section *yn, const Section *zp, const Section *zn) const; - unsigned char GetBlockSkyLight(Vector pos); + unsigned char GetBlockSkyLight(Vector pos) const; - unsigned char GetBlockSkyLight(const Vector &blockPos, const Section *section, const Section *xp, const Section *xn, const Section *yp, const Section *yn, const Section *zp, const Section *zn); + unsigned char GetBlockSkyLight(const Vector &blockPos, const Section *section, const Section *xp, const Section *xn, const Section *yp, const Section *yn, const Section *zp, const Section *zn) const; };
\ No newline at end of file |