diff options
Diffstat (limited to 'src/gamestate/GameState.cpp')
-rw-r--r-- | src/gamestate/GameState.cpp | 518 |
1 files changed, 392 insertions, 126 deletions
diff --git a/src/gamestate/GameState.cpp b/src/gamestate/GameState.cpp index 5c5b9c4..3f3469d 100644 --- a/src/gamestate/GameState.cpp +++ b/src/gamestate/GameState.cpp @@ -1,131 +1,397 @@ #include "GameState.hpp" -GameState::GameState(NetworkClient *Net) : nc(Net) { - Packet *response = nc->GetPacket(); - if (response->GetId() != 0x02) { - LOG(ERROR) << "Response id is " << response->GetId(); - throw std::runtime_error("Response id is not 0x02"); - } - PacketParser::Parse(*response, Login); - g_PlayerUuid = response->GetField(0).GetString(); - g_PlayerName = response->GetField(1).GetString(); - delete response; - m_networkState = ConnectionState::Play; - LOG(INFO) << g_PlayerName << "'s UUID is " << g_PlayerUuid; +GameState::GameState(NetworkClient *Net, bool &quit) : nc(Net), isRunning(quit) { + 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() { - Packet *packetPtr; - - try { - packetPtr = nc->GetPacket(); - if (packetPtr == nullptr) - return; - PacketParser::Parse(*packetPtr, m_networkState); - } catch (std::exception &e) { - LOG(ERROR) << "Catched exception during packet pulling: " << e.what(); - return; - } - Packet &packet = *packetPtr; - nlohmann::json json; - - switch (packet.GetId()) { - case 0x23: - g_PlayerEid = packet.GetField(0).GetInt(); - g_Gamemode = (packet.GetField(1).GetUByte() & 0b11111011); - g_Dimension = packet.GetField(2).GetInt(); - g_Difficulty = packet.GetField(3).GetUByte(); - g_MaxPlayers = packet.GetField(4).GetUByte(); - g_LevelType = packet.GetField(5).GetString(); - g_ReducedDebugInfo = packet.GetField(6).GetBool(); - LOG(INFO) << "Gamemode is " << g_Gamemode << ", Difficulty is " << (int) g_Difficulty - << ", Level Type is " << g_LevelType; - break; - case 0x0D: - g_Difficulty = packet.GetField(0).GetUByte(); - LOG(INFO) << "Difficulty now is " << (int) g_Difficulty; - break; - case 0x43: - g_SpawnPosition = packet.GetField(0).GetPosition(); - LOG(INFO) << "Spawn position is " << g_SpawnPosition.GetX() << "," << g_SpawnPosition.GetY() << "," - << g_SpawnPosition.GetZ(); - break; - case 0x2B: - g_PlayerInvulnerable = (packet.GetField(0).GetByte() & 0x01) != 0; - g_PlayerFlying = (packet.GetField(0).GetByte() & 0x02) != 0; - g_PlayerAllowFlying = (packet.GetField(0).GetByte() & 0x04) != 0; - g_PlayerCreativeMode = (packet.GetField(0).GetByte() & 0x08) != 0; - g_PlayerFlyingSpeed = packet.GetField(1).GetFloat(); - g_PlayerFovModifier = packet.GetField(2).GetFloat(); - LOG(INFO) << "FOV modifier is " << g_PlayerFovModifier; - break; - case 0x2E: - if ((packet.GetField(5).GetByte() & 0x10) != 0) { - g_PlayerPitch += packet.GetField(4).GetFloat(); - } else { - g_PlayerPitch = packet.GetField(4).GetFloat(); - }; - - if ((packet.GetField(5).GetByte() & 0x08) != 0) { - g_PlayerYaw += packet.GetField(3).GetFloat(); - } else { - g_PlayerYaw = packet.GetField(3).GetFloat(); - } - - if ((packet.GetField(5).GetByte() & 0x01) != 0) { - g_PlayerX += packet.GetField(0).GetDouble(); - } else { - g_PlayerX = packet.GetField(0).GetDouble(); - } - - if ((packet.GetField(5).GetByte() & 0x02) != 0) { - g_PlayerY += packet.GetField(1).GetDouble(); - } else { - g_PlayerY = packet.GetField(1).GetDouble(); - } - - if ((packet.GetField(5).GetByte() & 0x04) != 0) { - g_PlayerZ += packet.GetField(2).GetDouble(); - } else { - g_PlayerZ = packet.GetField(2).GetDouble(); - } - - g_IsGameStarted = true; - nc->AddPacketToQueue(PacketBuilder::CPlay0x03(0)); - nc->AddPacketToQueue(PacketBuilder::CPlay0x00(packet.GetField(6).GetVarInt())); - LOG(INFO) << "Game is started!"; - LOG(INFO) << "PlayerPos is " << g_PlayerX << ", " << g_PlayerY << ", " << g_PlayerZ << "\tAngle: " - << g_PlayerYaw - << "," << g_PlayerPitch; - break; - case 0x1A: - json = nlohmann::json::parse(packet.GetField(0).GetString()); - LOG(INFO) << "Disconnect reason: " << json["text"].get<std::string>(); - throw 119; - break; - case 0x20: - world.ParseChunkData(packet); - break; - case 0x07: - LOG(INFO) << "Statistics: "; - for (int i = 0; i < packet.GetField(0).GetVarInt(); i++) { - LOG(INFO) << "\t" << packet.GetField(1).GetArray()[0].GetString() << ": " - << packet.GetField(1).GetArray()[1].GetVarInt(); - } - break; - default: - break; - } - if (g_IsGameStarted) { - std::chrono::steady_clock clock; - static auto timeOfPreviousSendedPpalPacket(clock.now()); - std::chrono::duration<double, std::milli> delta = clock.now() - timeOfPreviousSendedPpalPacket; - if (delta.count() >= 50) { - nc->AddPacketToQueue( - PacketBuilder::CPlay0x0D(g_PlayerX, g_PlayerY, g_PlayerZ, g_PlayerYaw, g_PlayerPitch, true)); - timeOfPreviousSendedPpalPacket = clock.now(); - } - } - - delete packetPtr; +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) { + nc->SendPacket(std::make_shared<PacketPlayerPositionAndLookSB>(g_PlayerX, g_PlayerY, g_PlayerZ, g_PlayerYaw, + g_PlayerPitch, g_OnGround)); + timeOfPreviousSendedPacket = clock.now(); + } + + const float gravity = -9.8f; + g_PlayerVelocityY += gravity * deltaTime; + + bool isCollides = world.isPlayerCollides(g_PlayerX, g_PlayerY + g_PlayerVelocityY * deltaTime, + g_PlayerZ); + if (!isCollides) { + g_PlayerY += g_PlayerVelocityY * deltaTime; + g_OnGround = false; + } else { + g_PlayerVelocityY = 0; + g_OnGround = true; + } + + isCollides = world.isPlayerCollides(g_PlayerX + g_PlayerVelocityX * deltaTime, g_PlayerY, + g_PlayerZ + g_PlayerVelocityZ * deltaTime); + if (!isCollides) { + g_PlayerX += g_PlayerVelocityX * deltaTime; + g_PlayerZ += g_PlayerVelocityZ * deltaTime; + } + + /*const float AirResistance = 10.0f; + if (std::abs(g_PlayerVelocityX) > 0.01) + g_PlayerVelocityX -= AirResistance * deltaTime * (g_PlayerVelocityX > 0 ? 1 : -1); + else + g_PlayerVelocityX = 0; + if (std::abs(g_PlayerVelocityZ) > 0.01) + g_PlayerVelocityZ -= AirResistance * deltaTime * (g_PlayerVelocityZ > 0 ? 1 : -1); + else + g_PlayerVelocityZ = 0;*/ + const float AirResistance = 10.0f; + glm::vec3 vel(g_PlayerVelocityX, 0, g_PlayerVelocityZ); + glm::vec3 resistForce = -vel * AirResistance * deltaTime; + vel += resistForce; + g_PlayerVelocityX = vel.x; + g_PlayerVelocityZ = vel.z; + } + + + //Packet handling + auto ptr = nc->ReceivePacket(); + if (ptr == nullptr) + return; + 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; + isRunning = false; + 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; + 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 & 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 & 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; + + g_IsGameStarted = true; + + 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<1) { + 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) { + const float PlayerSpeed = 40.0; + float velocity = PlayerSpeed * deltaTime; + glm::vec3 vel(g_PlayerVelocityX, g_PlayerVelocityY, g_PlayerVelocityZ); + glm::vec3 front(cos(glm::radians(this->Yaw())) * cos(glm::radians(this->Pitch())), 0, + sin(glm::radians(this->Yaw())) * cos(glm::radians(this->Pitch()))); + front = glm::normalize(front); + glm::vec3 right = glm::normalize(glm::cross(front, this->WorldUp)); + 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 (g_OnGround) + vel.y += 5; + break; + } + g_PlayerVelocityX = vel.x; + g_PlayerVelocityY = vel.y; + g_PlayerVelocityZ = vel.z; + const double MaxSpeed = 5.0; + /*if (g_PlayerVelocityX > MaxSpeed || g_PlayerVelocityX < -MaxSpeed) + g_PlayerVelocityX = MaxSpeed * (g_PlayerVelocityX > 0 ? 1 : -1); + if (g_PlayerVelocityZ > MaxSpeed || g_PlayerVelocityZ < -MaxSpeed) + g_PlayerVelocityZ = MaxSpeed * (g_PlayerVelocityZ > 0 ? 1 : -1);*/ + + + /*bool isCollides = world.isPlayerCollides(g_PlayerX, g_PlayerY, g_PlayerZ); + if (isCollides) { + SetPosition(previousPos); + return; + } + auto updatePacket = std::make_shared<PacketPlayerPosition>(g_PlayerX, g_PlayerY, g_PlayerZ, true); + nc->SendPacket(updatePacket);*/ +} + +void GameState::HandleRotation(double yaw, double pitch) { + this->SetYaw(Yaw() + yaw); + this->SetPitch(Pitch() + pitch); + if (this->Pitch() > 89.0f) + this->SetPitch(89.0f); + if (this->Pitch() < -89.0f) + this->SetPitch(-89.0f); + this->updateCameraVectors(); + + auto updatePacket = std::make_shared<PacketPlayerLook>(g_PlayerYaw, g_PlayerPitch, g_OnGround); + nc->SendPacket(updatePacket); +} + +glm::mat4 GameState::GetViewMatrix() { + return glm::lookAt(this->Position(), this->Position() + this->Front, this->Up); +} + +void GameState::updateCameraVectors() { + glm::vec3 front; + front.x = cos(glm::radians(this->Yaw())) * cos(glm::radians(this->Pitch())); + front.y = sin(glm::radians(this->Pitch())); + front.z = sin(glm::radians(this->Yaw())) * cos(glm::radians(this->Pitch())); + this->Front = glm::normalize(front); + this->Right = glm::normalize(glm::cross(this->Front, this->WorldUp)); + this->Up = glm::normalize(glm::cross(this->Right, this->Front)); +} + +float GameState::Yaw() { + return g_PlayerYaw + 90; +} + +float GameState::Pitch() { + return -g_PlayerPitch; +} + +void GameState::SetYaw(float yaw) { + g_PlayerYaw = yaw - 90; +} + +void GameState::SetPitch(float pitch) { + g_PlayerPitch = -pitch; +} + +glm::vec3 GameState::Position() { + return glm::vec3(g_PlayerX - 0.5, g_PlayerY + 1.12, g_PlayerZ - 0.5); +} + +void GameState::SetPosition(glm::vec3 Position) { + g_PlayerX = Position.x + 0.5; + g_PlayerY = Position.y - 1.12; + g_PlayerZ = Position.z + 0.5; } |