mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 10:53:44 +00:00
feat(net): CDCLIENT_RELOAD master message
Appended at the end of MessageType::Master (46); the pin test is updated. With names it tells a server which fdb copy and CDServer.sqlite to switch to; without them it asks master to check the client's fdb now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -89,5 +89,10 @@ namespace MessageType {
|
||||
PROFILE_REQUEST,
|
||||
// Any server -> master -> dashboard: a profiling session started, failed or finished with its scope tree
|
||||
PROFILE_RESULT,
|
||||
|
||||
// CDClient reload (see CDClientReload.h, docs/CDClientFdb.md)
|
||||
// Master -> every server: the client's cdclient.fdb changed; switch to the named copy and CDServer.sqlite.
|
||||
// World or dashboard -> master (no names): check the client's fdb now
|
||||
CDCLIENT_RELOAD,
|
||||
};
|
||||
}
|
||||
|
||||
50
dNet/master/CDClientReload.h
Normal file
50
dNet/master/CDClientReload.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#ifndef __CDCLIENTRELOAD__H__
|
||||
#define __CDCLIENTRELOAD__H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "BitStream.h"
|
||||
#include "BitStreamUtils.h"
|
||||
#include "InstanceMigration.h"
|
||||
#include "MessageType/Master.h"
|
||||
#include "dCommonVars.h"
|
||||
|
||||
/**
|
||||
* CDCLIENT_RELOAD payload.
|
||||
*
|
||||
* Master -> every server: the client's cdclient.fdb changed. fdb and sqlite name the new copy and its CDServer.sqlite
|
||||
* in resServer (FdbSnapshot.h); each server switches to them between frames.
|
||||
*
|
||||
* World or dashboard -> master, with no names: check the client's fdb now (a GM's /reloadcdclient or the dashboard).
|
||||
* requesterId is the character who asked (told the result in chat), 0 for the dashboard.
|
||||
*/
|
||||
struct CDClientReload : public LUBitStream {
|
||||
CDClientReload() : LUBitStream(ServiceType::MASTER, MessageType::Master::CDCLIENT_RELOAD) {}
|
||||
|
||||
static constexpr uint16_t MAX_NAME = 64;
|
||||
|
||||
LWOOBJID requesterId{};
|
||||
std::string fdb;
|
||||
std::string sqlite;
|
||||
|
||||
[[nodiscard]] bool IsRequest() const { return fdb.empty(); }
|
||||
|
||||
void Serialize(RakNet::BitStream& stream) const override {
|
||||
stream.Write(requesterId);
|
||||
InstanceMigration::WriteText(stream, fdb, MAX_NAME);
|
||||
InstanceMigration::WriteText(stream, sqlite, MAX_NAME);
|
||||
}
|
||||
|
||||
bool Deserialize(RakNet::BitStream& stream) override {
|
||||
if (!stream.Read(requesterId)) return false;
|
||||
if (!InstanceMigration::ReadText(stream, fdb, MAX_NAME) || !InstanceMigration::ReadText(stream, sqlite, MAX_NAME)) return false;
|
||||
// Names in resServer only
|
||||
for (const auto* name : { &fdb, &sqlite }) {
|
||||
if (name->find_first_of("/\\") != std::string::npos || *name == "..") return false;
|
||||
}
|
||||
return fdb.empty() == sqlite.empty();
|
||||
}
|
||||
};
|
||||
|
||||
#endif //!__CDCLIENTRELOAD__H__
|
||||
@@ -1763,7 +1763,7 @@ static_assert(static_cast<int64_t>(MessageType::Game::CAN_ITEMS_BE_REFORGED) ==
|
||||
static_assert(static_cast<int64_t>(MessageType::Game::NOTIFY_CLIENT_RAIL_START_FAILED) == 1771);
|
||||
static_assert(static_cast<int64_t>(MessageType::Game::GET_IS_ON_RAIL) == 1772);
|
||||
|
||||
// MessageType::Master: 43 enumerators
|
||||
// MessageType::Master: 44 enumerators
|
||||
static_assert(static_cast<int64_t>(MessageType::Master::REQUEST_ZONE_TRANSFER) == 1);
|
||||
static_assert(static_cast<int64_t>(MessageType::Master::REQUEST_ZONE_TRANSFER_RESPONSE) == 2);
|
||||
static_assert(static_cast<int64_t>(MessageType::Master::SERVER_INFO) == 3);
|
||||
@@ -1809,6 +1809,7 @@ static_assert(static_cast<int64_t>(MessageType::Master::CHAT_HANDOFF) == 42);
|
||||
static_assert(static_cast<int64_t>(MessageType::Master::CHAT_SERVER_READY) == 43);
|
||||
static_assert(static_cast<int64_t>(MessageType::Master::PROFILE_REQUEST) == 44);
|
||||
static_assert(static_cast<int64_t>(MessageType::Master::PROFILE_RESULT) == 45);
|
||||
static_assert(static_cast<int64_t>(MessageType::Master::CDCLIENT_RELOAD) == 46);
|
||||
|
||||
// MessageType::Server: 3 enumerators
|
||||
static_assert(static_cast<int64_t>(MessageType::Server::VERSION_CONFIRM) == 0);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "MasterPackets.h"
|
||||
#include "master/CDClientReload.h"
|
||||
#include "master/DashboardMessages.h"
|
||||
#include "master/DataChanged.h"
|
||||
#include "master/InstanceMigration.h"
|
||||
@@ -522,3 +523,27 @@ TEST(MasterPacketsTests, UgcModelsMadeBytes) {
|
||||
truncated.Write<LWOOBJID>(1);
|
||||
EXPECT_FALSE(read.Deserialize(truncated));
|
||||
}
|
||||
|
||||
TEST(MasterPacketsTests, CDClientReload) {
|
||||
CDClientReload reload;
|
||||
reload.fdb = "cdclient-0123456789abcdef.fdb";
|
||||
reload.sqlite = "CDServer-0123456789abcdef.sqlite";
|
||||
ExpectHeaderThenSerialize(reload, MessageType::Master::CDCLIENT_RELOAD);
|
||||
EXPECT_FALSE(reload.IsRequest());
|
||||
|
||||
CDClientReload request;
|
||||
request.requesterId = 42;
|
||||
ExpectHeaderThenSerialize(request, MessageType::Master::CDCLIENT_RELOAD);
|
||||
EXPECT_TRUE(request.IsRequest());
|
||||
|
||||
// A name that leaves resServer, or only one of the two names, is refused
|
||||
for (const auto& [fdb, sqlite] : std::vector<std::pair<std::string, std::string>>{ { "../cdclient.fdb", "CDServer.sqlite" }, { "cdclient-1.fdb", "" } }) {
|
||||
CDClientReload bad;
|
||||
bad.fdb = fdb;
|
||||
bad.sqlite = sqlite;
|
||||
RakNet::BitStream stream;
|
||||
bad.Serialize(stream);
|
||||
CDClientReload read;
|
||||
EXPECT_FALSE(read.Deserialize(stream)) << fdb;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user