diff --git a/client/source/hud/BlockCursor.cpp b/client/source/hud/BlockCursor.cpp index 6e9dddb1b..3b7f1c083 100644 --- a/client/source/hud/BlockCursor.cpp +++ b/client/source/hud/BlockCursor.cpp @@ -50,7 +50,7 @@ BlockCursor::BlockCursor(ClientPlayer &player, ClientWorld &world, ClientCommand void BlockCursor::onEvent(const SDL_Event &event, const Hotbar &hotbar) { if (event.type == SDL_MOUSEBUTTONDOWN && m_selectedBlock.w != -1) { if (event.button.button == SDL_BUTTON_LEFT) { - m_animationStart = gk::GameClock::getTicks(); + m_animationStart = gk::GameClock::getInstance().getTicks(); m_currentTool = &m_player.inventory().getStack(hotbar.cursorPos(), 0); } else if (event.button.button == SDL_BUTTON_RIGHT) { @@ -133,24 +133,26 @@ void BlockCursor::update(const Hotbar &hotbar) { // m_selectedBlock.w = -1; // } + u32 ticks = gk::GameClock::getInstance().getTicks(); + if (selectedBlockChanged) - m_animationStart = (m_animationStart) ? gk::GameClock::getTicks() : 0; + m_animationStart = (m_animationStart) ? ticks : 0; const ItemStack ¤tStack = m_player.inventory().getStack(hotbar.cursorPos(), 0); float timeToBreak = 0; if (m_animationStart) { if (m_currentTool->item().id() != currentStack.item().id()) { - m_animationStart = gk::GameClock::getTicks(); + m_animationStart = ticks; m_currentTool = ¤tStack; } else { timeToBreak = m_currentBlock->timeToBreak(currentStack.item().harvestCapability(), currentStack.item().miningSpeed()); - if (gk::GameClock::getTicks() > m_animationStart + timeToBreak * 1000) { + if (ticks > m_animationStart + timeToBreak * 1000) { ItemStack itemDrop = m_currentBlock->getItemDrop(); m_player.inventory().addStack(itemDrop.item().stringID(), itemDrop.amount()); m_world.setBlock(m_selectedBlock.x, m_selectedBlock.y, m_selectedBlock.z, 0); - m_animationStart = gk::GameClock::getTicks(); + m_animationStart = ticks; m_client.sendPlayerDigBlock(m_selectedBlock); m_client.sendPlayerInvUpdate(); @@ -167,7 +169,7 @@ void BlockCursor::update(const Hotbar &hotbar) { if (m_animationStart && m_currentBlock) updateAnimationVertexBuffer(*m_currentBlock, orientation, - (gk::GameClock::getTicks() - m_animationStart) / (timeToBreak * 100)); + (ticks - m_animationStart) / (timeToBreak * 100)); } using namespace BlockGeometry; diff --git a/client/source/hud/HUD.cpp b/client/source/hud/HUD.cpp index d33475c78..c46d202ab 100644 --- a/client/source/hud/HUD.cpp +++ b/client/source/hud/HUD.cpp @@ -84,7 +84,7 @@ void HUD::update() { m_hotbar.update(); if (Config::isFpsCounterEnabled) - m_fpsText.setText(std::to_string(gk::GameClock::getFpsAverage()) + " FPS"); + m_fpsText.setText(std::to_string(gk::GameClock::getInstance().getFpsAverage()) + " FPS"); m_blockCursor.update(m_hotbar); diff --git a/client/source/network/Client.cpp b/client/source/network/Client.cpp index 7b1b40384..89bdf8e3d 100644 --- a/client/source/network/Client.cpp +++ b/client/source/network/Client.cpp @@ -91,7 +91,7 @@ void Client::sendKeyState() { gk::InputHandler *inputHandler = gk::GamePad::getInputHandler(); if (inputHandler) { sf::Packet packet; - packet << Network::Command::KeyState << gk::GameClock::getTicks() << m_id; + packet << Network::Command::KeyState << gk::GameClock::getInstance().getTicks() << m_id; for (auto &it : inputHandler->keysPressed()) { packet << static_cast(it.first) << it.second; } diff --git a/client/source/states/GameState.cpp b/client/source/states/GameState.cpp index 000d8d97c..4bb674b86 100644 --- a/client/source/states/GameState.cpp +++ b/client/source/states/GameState.cpp @@ -145,7 +145,7 @@ void GameState::update() { m_hud.update(); - if (gk::GameClock::getTicks() % 100 < 10) { + if (gk::GameClock::getInstance().getTicks() % 100 < 10) { m_clientCommandHandler.sendPlayerPosUpdate(); } @@ -171,7 +171,7 @@ void GameState::onGuiScaleChanged(const GuiScaleChangedEvent &event) { void GameState::draw(gk::RenderTarget &target, gk::RenderStates states) const { // FIXME: This uniform is not used anymore since water/leaves effects are disabled // gk::Shader::bind(&m_shader); - // m_shader.setUniform("u_time", gk::GameClock::getTicks()); + // m_shader.setUniform("u_time", gk::GameClock::getInstance().getTicks()); // gk::Shader::bind(nullptr); states.shader = &m_shader; diff --git a/client/source/states/TitleScreenState.cpp b/client/source/states/TitleScreenState.cpp index b90d8dab3..fe77a968e 100644 --- a/client/source/states/TitleScreenState.cpp +++ b/client/source/states/TitleScreenState.cpp @@ -71,6 +71,7 @@ void TitleScreenState::centerBackground() { void TitleScreenState::init() { m_eventHandler->addListener(&TitleScreenState::onGuiScaleChanged, this); + m_eventHandler->addListener(&TitleScreenState::onServerOnlineEvent, this); } void TitleScreenState::onEvent(const SDL_Event &event) { @@ -86,23 +87,27 @@ void TitleScreenState::onEvent(const SDL_Event &event) { } void TitleScreenState::update() { + if (m_isServerOnline) { + auto &game = m_stateStack->push(); + game.setSingleplayer(true); + game.connect("localhost", m_port); + + m_stateStack->push(game, m_showLoadingState, this); + } } void TitleScreenState::startSingleplayer(bool showLoadingState) { + m_showLoadingState = showLoadingState; + + if (m_thread.joinable()) + m_thread.join(); + m_thread = std::thread([this] () { - ServerApplication app; + ServerApplication app{*m_eventHandler}; app.setSingleplayer(true); app.setPort(m_port); app.run(); }); - - std::this_thread::sleep_for(std::chrono::milliseconds(200)); - - auto &game = m_stateStack->push(); - game.setSingleplayer(true); - game.connect("localhost", m_port); - - m_stateStack->push(game, showLoadingState, this); } void TitleScreenState::startMultiplayer(const std::string &host) { @@ -118,7 +123,13 @@ void TitleScreenState::onGuiScaleChanged(const GuiScaleChangedEvent &event) { m_menuWidget.onGuiScaleChanged(event); } +void TitleScreenState::onServerOnlineEvent(const ServerOnlineEvent &event) { + m_isServerOnline = event.isOnline; +} + void TitleScreenState::draw(gk::RenderTarget &target, gk::RenderStates states) const { + if (m_isServerOnline) return; + prepareDraw(target, states); target.draw(m_background, states); diff --git a/client/source/states/TitleScreenState.hpp b/client/source/states/TitleScreenState.hpp index 866a359f6..ae001d6d1 100644 --- a/client/source/states/TitleScreenState.hpp +++ b/client/source/states/TitleScreenState.hpp @@ -33,6 +33,7 @@ #include "MenuWidget.hpp" struct GuiScaleChangedEvent; +struct ServerOnlineEvent; class TitleScreenState : public InterfaceState { public: @@ -52,6 +53,7 @@ class TitleScreenState : public InterfaceState { private: void onGuiScaleChanged(const GuiScaleChangedEvent &event); + void onServerOnlineEvent(const ServerOnlineEvent &event); void draw(gk::RenderTarget &target, gk::RenderStates states) const override; @@ -62,6 +64,9 @@ class TitleScreenState : public InterfaceState { std::thread m_thread; u16 m_port = 4242; + + bool m_showLoadingState = false; + bool m_isServerOnline = false; }; #endif // TITLESCREENSTATE_HPP_ diff --git a/server/source/core/ServerApplication.cpp b/server/source/core/ServerApplication.cpp index 1c3c52b71..14a1e4fef 100644 --- a/server/source/core/ServerApplication.cpp +++ b/server/source/core/ServerApplication.cpp @@ -33,11 +33,17 @@ namespace fs = ghc::filesystem; ServerApplication::ServerApplication(int argc, char **argv) : m_argumentParser(argc, argv) { - std::srand(std::time(nullptr)); - BlockGeometry::initOrientation(); +} + +ServerApplication::ServerApplication(gk::EventHandler &eventHandler) { + m_eventHandler = &eventHandler; } void ServerApplication::init() { + std::srand(std::time(nullptr)); + + BlockGeometry::initOrientation(); + m_argumentParser.addArgument("port", {"-p", "--port", true}); m_argumentParser.addArgument("working_dir", {"-w", "--working-dir", true}); @@ -68,6 +74,9 @@ void ServerApplication::init() { m_scriptEngine.luaCore().setRegistry(&m_registry); std::cout << "Server is running on localhost:" << m_port << std::endl; + + if (m_eventHandler) + m_eventHandler->emplaceEvent(true); } int ServerApplication::run(bool isProtected) { @@ -77,6 +86,9 @@ int ServerApplication::run(bool isProtected) { mainLoop(); } catch(const gk::Exception &e) { + if (m_eventHandler) + m_eventHandler->emplaceEvent(false); + std::cerr << "Fatal error " << e.what() << std::endl; return 1; } @@ -92,7 +104,7 @@ int ServerApplication::run(bool isProtected) { void ServerApplication::update() { m_worldController.update(); - if (gk::GameClock::getTicks() % 100 < 10) { + if (m_clock.getTicks() % 100 < 10) { for (auto &it : m_players) { m_serverCommandHandler.sendPlayerPosUpdate(it.first); } diff --git a/server/source/core/ServerApplication.hpp b/server/source/core/ServerApplication.hpp index fa0202c92..47eb9bd4b 100644 --- a/server/source/core/ServerApplication.hpp +++ b/server/source/core/ServerApplication.hpp @@ -29,6 +29,7 @@ #include #include +#include #include "LuaCore.hpp" #include "Registry.hpp" @@ -38,9 +39,14 @@ #include "ServerPlayer.hpp" #include "WorldController.hpp" +struct ServerOnlineEvent { + bool isOnline; +}; + class ServerApplication { public: ServerApplication(int argc = 0, char **argv = nullptr); + ServerApplication(gk::EventHandler &eventHandler); void init(); @@ -57,6 +63,7 @@ class ServerApplication { gk::ArgumentParser m_argumentParser; gk::GameClock m_clock; + gk::EventHandler *m_eventHandler = nullptr; ScriptEngine m_scriptEngine; @@ -64,7 +71,7 @@ class ServerApplication { u16 m_port = 4242; - WorldController m_worldController{m_registry}; + WorldController m_worldController{m_registry, m_clock}; std::unordered_map m_players; Server m_server; diff --git a/server/source/world/ServerWorld.cpp b/server/source/world/ServerWorld.cpp index 0df9b8096..1de54d490 100644 --- a/server/source/world/ServerWorld.cpp +++ b/server/source/world/ServerWorld.cpp @@ -34,8 +34,8 @@ #include "ServerWorld.hpp" void ServerWorld::update() { - if (m_lastTick < gk::GameClock::getTicks() / 50) { - m_lastTick = gk::GameClock::getTicks() / 50; + if (m_lastTick < m_clock.getTicks() / 50) { + m_lastTick = m_clock.getTicks() / 50; for (auto &it : m_chunks) { it.second->tick(*this, *m_server); diff --git a/server/source/world/ServerWorld.hpp b/server/source/world/ServerWorld.hpp index e9988c83e..a24adb2e1 100644 --- a/server/source/world/ServerWorld.hpp +++ b/server/source/world/ServerWorld.hpp @@ -33,6 +33,10 @@ #include "TerrainGenerator.hpp" #include "World.hpp" +namespace gk { + class GameClock; +} + class ClientInfo; class Dimension; class ServerCommandHandler; @@ -42,8 +46,8 @@ class ServerWorld : public World { using ChunkMap = std::unordered_map>; public: - ServerWorld(const Dimension &dimension) - : m_dimension(dimension), m_terrainGenerator(dimension) {} + ServerWorld(const Dimension &dimension, gk::GameClock &clock) + : m_dimension(dimension), m_terrainGenerator(dimension), m_clock(clock) {} void update(); @@ -73,6 +77,8 @@ class ServerWorld : public World { TerrainGenerator m_terrainGenerator; ServerCommandHandler *m_server = nullptr; + + gk::GameClock &m_clock; }; #endif // SERVERWORLD_HPP_ diff --git a/server/source/world/WorldController.cpp b/server/source/world/WorldController.cpp index 637f50a77..a4d9727d9 100644 --- a/server/source/world/WorldController.cpp +++ b/server/source/world/WorldController.cpp @@ -29,7 +29,7 @@ void WorldController::init() { for (const Dimension &dimension : m_registry.dimensions()) { - m_worldList.emplace_back(dimension); + m_worldList.emplace_back(dimension, m_clock); m_worldList.back().setServer(m_server); } } diff --git a/server/source/world/WorldController.hpp b/server/source/world/WorldController.hpp index ea72e4c81..027444863 100644 --- a/server/source/world/WorldController.hpp +++ b/server/source/world/WorldController.hpp @@ -31,11 +31,15 @@ #include "ServerWorld.hpp" +namespace gk { + class GameClock; +} + class Registry; class WorldController { public: - WorldController(Registry ®istry) : m_registry(registry) {} + WorldController(Registry ®istry, gk::GameClock &clock) : m_registry(registry), m_clock(clock) {} void init(); @@ -50,6 +54,8 @@ class WorldController { Registry &m_registry; + gk::GameClock &m_clock; + ServerCommandHandler *m_server = nullptr; };