diff --git a/include/TServer.h b/include/TServer.h index 3202c9e..d620dcc 100644 --- a/include/TServer.h +++ b/include/TServer.h @@ -53,7 +53,10 @@ public: io_context& IoCtx() { return mIoCtxPoller.IoCtx(); } + uint64_t GetServerTimeMS() const { return std::chrono::duration_cast(std::chrono::steady_clock::now() - TimeSyncStart).count();} + double GetServerTime() const { return std::chrono::duration(std::chrono::steady_clock::now() - TimeSyncStart).count(); } private: + std::chrono::time_point TimeSyncStart; TIoPollThread mIoCtxPoller; TClientSet mClients; mutable RWMutex mClientsMutex; diff --git a/src/TLuaEngine.cpp b/src/TLuaEngine.cpp index f92ff3c..027bd45 100644 --- a/src/TLuaEngine.cpp +++ b/src/TLuaEngine.cpp @@ -1012,6 +1012,14 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, TLuaStateI } MPTable.set_function("Get", &LuaAPI::MP::Get); + MPTable.set_function("GetServerTimeMS", [this](const sol::this_state ts) { + return make_object(sol::state_view(ts), this->mEngine->Server().GetServerTimeMS()); + }); + + MPTable.set_function("GetServerTime", [this](const sol::this_state ts) { + return make_object(sol::state_view(ts), this->mEngine->Server().GetServerTime()); + }); + auto UtilTable = StateView.create_named_table("Util"); UtilTable.set_function("LogDebug", [this](sol::variadic_args args) { std::string ToPrint = ""; diff --git a/src/TServer.cpp b/src/TServer.cpp index f4b0a45..ef0e27b 100644 --- a/src/TServer.cpp +++ b/src/TServer.cpp @@ -123,6 +123,12 @@ TEST_CASE("GetPidVid") { TServer::TServer(const std::vector& Arguments) { beammp_info("BeamMP Server v" + Application::ServerVersionString()); Application::SetSubsystemStatus("Server", Application::Status::Starting); + std::mt19937_64 TimeSyncRandomDevice(std::random_device{}()); + + TimeSyncStart = std::chrono::steady_clock::now() + - std::chrono::duration_cast( + std::chrono::duration(std::uniform_real_distribution(0.0, 2592000.0)(TimeSyncRandomDevice)) + ); Application::SetSubsystemStatus("Server", Application::Status::Good); } @@ -210,6 +216,24 @@ void TServer::GlobalParser(const std::weak_ptr& Client, std::vector ServerTime(sizeof(uint64_t)); + std::memcpy(ServerTime.data(), &Time, sizeof(uint64_t)); + + auto Data = Packet; + + beammp_debugf("Sending server time {} to client '{}' ({}), client time: {}", Time, LockedClient->GetName(), LockedClient->GetID(), reinterpret_cast(Data.data())); + + Data.insert(Data.end(), ServerTime.begin(), ServerTime.end()); + + if (!Network.Respond(*LockedClient, Data, true)) { + Network.DisconnectClient(*LockedClient, "Failed to send time"); + } + } + return; case 'H': // initial connection if (udp) { beammp_debugf("Received 'H' packet over UDP from client '{}' ({}), ignoring it", LockedClient->GetName(), LockedClient->GetID());