summaryrefslogblamecommitdiffstats
path: root/src/gamestate/GameState.cpp
blob: 3f3469d5fbc7c7abaf1f37eb6188671d363bc44c (plain) (tree)
1
2
3
4
5
6
7
8
9
                        
 




                                                                                 

 


































































































































































































































































































































































































                                                                                                                                    
 
#include "GameState.hpp"

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(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;
}