#include "GlobalState.hpp" #include "NetworkClient.hpp" #include "GameState.hpp" #include "Render.hpp" #include "DebugInfo.hpp" #include "Event.hpp" //Global game variables std::unique_ptr nc; std::unique_ptr gs; std::unique_ptr render; std::thread threadGs; bool isRunning; bool isPhysRunning; EventListener listener; bool isMoving[5] = { 0,0,0,0,0 }; std::thread threadPhys; State state; void PhysExec(); void InitEvents() { /* * Network Events */ listener.RegisterHandler(EventType::Exit, [](EventData eventData) { isRunning = false; }); listener.RegisterHandler(EventType::ConnectToServer, [](EventData eventData) { auto data = std::get(eventData); if (data.address == "" || data.port == 0) LOG(FATAL) << "NOT VALID CONNECT-TO-SERVER EVENT"; if (nc != nullptr) { LOG(ERROR) << "Already connected"; return; } LOG(INFO) << "Connecting to server"; EventAgregator::PushEvent(EventType::Connecting, ConnectingData{}); try { nc = std::make_unique(data.address, data.port, data.username); } catch (std::exception &e) { LOG(WARNING) << "Connection failed"; EventAgregator::PushEvent(EventType::ConnectionFailed, ConnectionFailedData{ e.what() }); return; } LOG(INFO) << "Connected to server"; EventAgregator::PushEvent(EventType::ConnectionSuccessfull, ConnectionSuccessfullData{}); }); listener.RegisterHandler(EventType::Disconnect, [](EventData eventData) { auto data = std::get(eventData); EventAgregator::PushEvent(EventType::Disconnected, DisconnectedData{ data.reason }); LOG(INFO) << "Disconnected: " << data.reason; nc.reset(); }); listener.RegisterHandler(EventType::NetworkClientException, [](EventData eventData) { auto data = std::get(eventData); EventAgregator::PushEvent(EventType::Disconnect, DisconnectData{ data.what }); }); /* * GameState Events */ listener.RegisterHandler(EventType::Exit, [](EventData eventData) { isRunning = false; }); listener.RegisterHandler(EventType::ConnectionSuccessfull, [](EventData eventData) { auto data = std::get(eventData); gs = std::make_unique(); isPhysRunning = true; threadPhys = std::thread(&PhysExec); }); listener.RegisterHandler(EventType::Disconnected, [](EventData eventData) { if (!gs) return; isPhysRunning = false; threadPhys.join(); gs.reset(); }); listener.RegisterHandler(EventType::SendChatMessage, [](EventData eventData) { nc->SendPacket(std::make_shared(std::get(eventData).message)); }); } void PhysExec() { EventListener listener; listener.RegisterHandler(EventType::KeyPressed, [](EventData eventData) { if (!gs) return; switch (std::get(eventData).key) { case SDL_SCANCODE_W: isMoving[GameState::FORWARD] = true; break; case SDL_SCANCODE_A: isMoving[GameState::LEFT] = true; break; case SDL_SCANCODE_S: isMoving[GameState::BACKWARD] = true; break; case SDL_SCANCODE_D: isMoving[GameState::RIGHT] = true; break; case SDL_SCANCODE_SPACE: isMoving[GameState::JUMP] = true; break; default: break; } }); listener.RegisterHandler(EventType::KeyReleased, [](EventData eventData) { if (!gs) return; switch (std::get(eventData).key) { case SDL_SCANCODE_W: isMoving[GameState::FORWARD] = false; break; case SDL_SCANCODE_A: isMoving[GameState::LEFT] = false; break; case SDL_SCANCODE_S: isMoving[GameState::BACKWARD] = false; break; case SDL_SCANCODE_D: isMoving[GameState::RIGHT] = false; break; case SDL_SCANCODE_SPACE: isMoving[GameState::JUMP] = false; break; default: break; } }); listener.RegisterHandler(EventType::MouseMoved, [](EventData eventData) { if (!gs) return; auto data = std::get(eventData); gs->HandleRotation(data.x, data.y); }); LoopExecutionTimeController timer(std::chrono::milliseconds(8)); while (isPhysRunning) { DebugInfo::gameThreadTime = timer.GetRealDeltaS() * 1000'00.0f; if (state == State::Playing) { if (isMoving[GameState::FORWARD]) gs->HandleMovement(GameState::FORWARD, timer.GetRealDeltaS()); if (isMoving[GameState::BACKWARD]) gs->HandleMovement(GameState::BACKWARD, timer.GetRealDeltaS()); if (isMoving[GameState::LEFT]) gs->HandleMovement(GameState::LEFT, timer.GetRealDeltaS()); if (isMoving[GameState::RIGHT]) gs->HandleMovement(GameState::RIGHT, timer.GetRealDeltaS()); if (isMoving[GameState::JUMP]) gs->HandleMovement(GameState::JUMP, timer.GetRealDeltaS()); } gs->Update(timer.GetRealDeltaS()); while (listener.IsEventsQueueIsNotEmpty()) listener.HandleEvent(); timer.Update(); } } void GsExec() { LoopExecutionTimeController timer(std::chrono::milliseconds(16)); while (isRunning) { try { while (nc && gs) { nc->UpdatePacket(); gs->UpdatePacket(nc.get()); while (listener.IsEventsQueueIsNotEmpty()) listener.HandleEvent(); } } catch (std::exception &e) { EventAgregator::PushEvent(EventType::NetworkClientException, NetworkClientExceptionData{ e.what() }); } while (listener.IsEventsQueueIsNotEmpty()) listener.HandleEvent(); timer.Update(); } if (isPhysRunning) { isPhysRunning = false; threadPhys.join(); } nc.reset(); gs.reset(); } void GlobalState::Exec() { render = std::make_unique(900, 480, "AltCraft"); isRunning = true; InitEvents(); threadGs = std::thread(&GsExec); render->ExecuteRenderLoop(); isRunning = false; threadGs.join(); render.reset(); } GameState *GlobalState::GetGameState() { return gs.get(); } Render *GlobalState::GetRender() { return render.get(); } State GlobalState::GetState() { return state; } void GlobalState::SetState(const State &newState) { if (newState != state) EventAgregator::PushEvent(EventType::StateUpdated, StateUpdatedData{}); state = newState; }