revert(master): the edit mode flag on a private instance

This reverts commit 4cf0909d. Nothing starts an edit mode instance any more. Its two
fixes that had nothing to do with edit mode come back in the next commit.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-11-10 18:37:23 -06:00
parent 3526ee2eb0
commit 37cc844562
12 changed files with 14 additions and 68 deletions

View File

@@ -387,7 +387,7 @@ const InstancePtr& InstanceManager::FindInstanceWithPrivate(LWOMAPID mapID, LWOI
return g_Empty;
}
const InstancePtr& InstanceManager::CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID cloneID, const std::string& password, const bool editMode) {
const InstancePtr& InstanceManager::CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID cloneID, const std::string& password) {
const auto& instance = FindPrivateInstance(password);
if (instance != nullptr) {
@@ -408,10 +408,9 @@ const InstancePtr& InstanceManager::CreatePrivateInstance(LWOMAPID mapID, LWOCLO
uint32_t port = GetFreePort();
auto newInstance = make_unique<Instance>(mExternalIP, port, mapID, ++m_LastInstanceID, cloneID, maxPlayers, maxPlayers, true, password);
newInstance->SetIsEditMode(editMode);
//Start the actual process:
StartWorldServer(mapID, port, m_LastInstanceID, maxPlayers, cloneID, editMode);
StartWorldServer(mapID, port, m_LastInstanceID, maxPlayers, cloneID);
m_Instances.push_back(std::move(newInstance));
if (m_OnInstancesChanged) m_OnInstancesChanged();

View File

@@ -58,10 +58,6 @@ public:
bool GetIsPrivate() const { return m_IsPrivate; }
const std::string& GetPassword() const { return m_Password; }
// A GM's edit mode instance (docs/EditMode.md): private, and its world server constructs none of the zone's
// objects. Its replacement (a reload, a live update) is in edit mode too
bool GetIsEditMode() const { return m_IsEditMode; }
void SetIsEditMode(bool value) { m_IsEditMode = value; }
bool GetIsReady() const { return m_Ready; }
void SetIsReady(bool value) { m_Ready = value; }
@@ -160,7 +156,6 @@ private:
bool m_IsPrivate{};
std::string m_Password{};
bool m_IsEditMode{};
bool m_Shutdown{};
@@ -199,8 +194,7 @@ public:
const InstancePtr& FindInstance(LWOMAPID mapID, LWOINSTANCEID instanceID);
const InstancePtr& FindInstanceWithPrivate(LWOMAPID mapID, LWOINSTANCEID instanceID);
// editMode: a GM's edit mode instance. An instance that has the password already is returned as it is
const InstancePtr& CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID cloneID, const std::string& password, bool editMode = false);
const InstancePtr& CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID cloneID, const std::string& password);
const InstancePtr& FindPrivateInstance(const std::string& password);
void SetIsShuttingDown(bool value) { this->m_IsShuttingDown = value; };
void PruneUnreadyInstances();

View File

@@ -896,12 +896,12 @@ namespace {
void OnCreatePrivateZone(const CreatePrivateZone& request, const SystemAddress& sysAddr) {
// Passwords were cut to 50 characters when read
const auto& newInst = Game::im->CreatePrivateInstance(request.zoneID, request.cloneID, request.password.c_str(), request.editMode != 0);
const auto& newInst = Game::im->CreatePrivateInstance(request.zoneID, request.cloneID, request.password.c_str());
if (!newInst) {
LOG("No private zone was created for map %i/%i", request.zoneID, request.cloneID);
return;
}
LOG("Creating private zone %i/%i/%i%s", newInst->GetMapID(), newInst->GetCloneID(), newInst->GetInstanceID(), newInst->GetIsEditMode() ? " in edit mode" : "");
LOG("Creating private zone %i/%i/%i", newInst->GetMapID(), newInst->GetCloneID(), newInst->GetInstanceID());
}
void OnRequestPrivateZone(const RequestPrivateZone& request, const SystemAddress& sysAddr) {
@@ -918,12 +918,6 @@ namespace {
return;
}
// Still starting (asked for right after it was created): answered when its world server is ready
if (!instance->GetIsReady()) {
instance->GetPendingRequests().push_back({ requestID, static_cast<bool>(mythranShift), sysAddr, {} });
return;
}
const auto& zone = instance->GetZoneID();
RequestZoneTransferResponse response;

View File

@@ -171,11 +171,11 @@ void MigrationCoordinator::SetObserver(std::function<void(const MigrationStatus&
namespace {
// The new instance (REPLACE): a fresh world server from the binary on disk now, so an update takes effect. A private
// instance's replacement gets the same password and edit mode; the source is draining already, so the password finds the new one.
// instance's replacement gets the same password; the source is draining already, so the password finds the new one.
Instance* StartTarget(Instance& source) {
if (source.GetIsPrivate()) {
source.SetIsDraining(true);
const auto& started = Game::im->CreatePrivateInstance(source.GetMapID(), source.GetCloneID(), source.GetPassword(), source.GetIsEditMode());
const auto& started = Game::im->CreatePrivateInstance(source.GetMapID(), source.GetCloneID(), source.GetPassword());
return started ? started.get() : nullptr;
}
const auto& started = Game::im->StartNewInstance(source.GetMapID(), source.GetCloneID());

View File

@@ -192,13 +192,13 @@ uint32_t StartUgcServer() {
return ugc_pid;
}
uint32_t StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInstanceID, int maxPlayers, LWOCLONEID cloneID, const bool editMode) {
uint32_t StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInstanceID, int maxPlayers, LWOCLONEID cloneID) {
auto world_path = BinaryPathFinder::GetBinaryDir() / "WorldServer";
#ifdef _WIN32
world_path.replace_extension(".exe");
auto cmd = world_path.wstring() + L" -zone " + std::to_wstring(mapID) + L" -port " + std::to_wstring(port) +
L" -instance " + std::to_wstring(lastInstanceID) + L" -maxclients " + std::to_wstring(maxPlayers) +
L" -clone " + std::to_wstring(cloneID) + L" -editmode " + std::to_wstring(editMode ? 1 : 0);
L" -clone " + std::to_wstring(cloneID);
auto world_startup = startup;
auto world_info = PROCESS_INFORMATION{};
@@ -226,8 +226,7 @@ uint32_t StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInsta
"-port", std::to_string(port).c_str(),
"-instance", std::to_string(lastInstanceID).c_str(),
"-maxclients", std::to_string(maxPlayers).c_str(),
"-clone", std::to_string(cloneID).c_str(),
"-editmode", editMode ? "1" : "0", nullptr);
"-clone", std::to_string(cloneID).c_str(), nullptr);
// exec failed (e.g. the binary is being rebuilt): the child must not carry on as a second master
perror("exec");
_exit(127);

View File

@@ -5,4 +5,4 @@ uint32_t StartAuthServer();
uint32_t StartChatServer();
uint32_t StartDashboardServer();
uint32_t StartUgcServer();
uint32_t StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInstanceID, int maxPlayers, LWOCLONEID cloneID, bool editMode = false);
uint32_t StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInstanceID, int maxPlayers, LWOCLONEID cloneID);

View File

@@ -16,12 +16,7 @@ namespace {
uint32_t length{};
VALIDATE_READ(bitStream.Read(length));
value.resize(std::min(length, maxLength));
if (!value.empty() && !bitStream.ReadBits(reinterpret_cast<unsigned char*>(value.data()), BYTES_TO_BITS(value.size()), true)) return false;
const uint32_t rest = length - static_cast<uint32_t>(value.size());
if (rest == 0) return true;
if (BITS_TO_BYTES(bitStream.GetNumberOfUnreadBits()) < rest) return false;
bitStream.IgnoreBits(BYTES_TO_BITS(rest));
return true;
return value.empty() || bitStream.ReadBits(reinterpret_cast<unsigned char*>(value.data()), BYTES_TO_BITS(value.size()), true);
}
}
@@ -152,15 +147,12 @@ namespace MasterPackets {
bitStream.Write(zoneID);
bitStream.Write(cloneID);
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, password);
if (editMode != 0) bitStream.Write(editMode);
}
bool CreatePrivateZone::Deserialize(RakNet::BitStream& bitStream) {
VALIDATE_READ(bitStream.Read(zoneID));
VALIDATE_READ(bitStream.Read(cloneID));
VALIDATE_READ(ReadCappedString(bitStream, password, MAX_PASSWORD_LENGTH));
editMode = 0;
if (bitStream.GetNumberOfUnreadBits() >= 8) VALIDATE_READ(bitStream.Read(editMode));
return true;
}

View File

@@ -146,9 +146,6 @@ namespace MasterPackets {
uint32_t zoneID{};
uint32_t cloneID{};
std::string password; // u32 length, then 1 byte per character
// A GM's edit mode: the instance's world server constructs none of the zone's objects (docs/EditMode.md). Written
// only when set, so a plain private zone stays as it always was
uint8_t editMode{};
CreatePrivateZone() : LUBitStream(ServiceType::MASTER, MessageType::Master::CREATE_PRIVATE_ZONE) {}
void Serialize(RakNet::BitStream& bitStream) const override;

View File

@@ -1009,7 +1009,6 @@ json ToJson(const MasterPackets::CreatePrivateZone& m) {
json j = json::object();
j["zoneID"] = ToJson(m.zoneID);
j["cloneID"] = ToJson(m.cloneID);
j["editMode"] = ToJson(m.editMode);
return j;
}
json ToJson(const MasterPackets::RequestPrivateZone& m) {

View File

@@ -35,12 +35,11 @@ void ZoneInstanceManager::HandleRequestZoneTransferResponse(const MasterPackets:
}
}
void ZoneInstanceManager::CreatePrivateZone(dServer* server, uint32_t zoneID, uint32_t zoneClone, const std::string& password, const bool editMode) {
void ZoneInstanceManager::CreatePrivateZone(dServer* server, uint32_t zoneID, uint32_t zoneClone, const std::string& password) {
MasterPackets::CreatePrivateZone request;
request.zoneID = zoneID;
request.cloneID = zoneClone;
request.password = password;
request.editMode = editMode ? 1 : 0;
MasterPackets::SendToMaster(request, server);
}

View File

@@ -62,8 +62,7 @@ public:
*/
void HandleRequestZoneTransferResponse(const MasterPackets::RequestZoneTransferResponse& response);
// editMode: a GM's edit mode instance, whose world server constructs none of the zone's objects
void CreatePrivateZone(dServer* server, uint32_t zoneID, uint32_t zoneClone, const std::string& password, bool editMode = false);
void CreatePrivateZone(dServer* server, uint32_t zoneID, uint32_t zoneClone, const std::string& password);
void RequestPrivateZone(dServer* server, bool mythranShift, const std::string& password, TransferCallback callback);
};

View File

@@ -237,32 +237,6 @@ TEST(MasterPacketsTests, PrivateZonesMatchLegacy) {
}
}
// The edit mode flag of a private zone: one more byte, only when set, and read after a password of any length
TEST(MasterPacketsTests, CreatePrivateZoneEditMode) {
for (const auto& password : g_Strings) {
MasterPackets::CreatePrivateZone plain;
plain.zoneID = 1100;
plain.password = password;
MasterPackets::CreatePrivateZone edit = plain;
edit.editMode = 1;
RakNet::BitStream plainStream; LoadPayload(plainStream, plain);
RakNet::BitStream editStream; LoadPayload(editStream, edit);
EXPECT_EQ(editStream.GetNumberOfUnreadBits(), plainStream.GetNumberOfUnreadBits() + 8);
MasterPackets::CreatePrivateZone readPlain;
readPlain.editMode = 1;
ASSERT_TRUE(readPlain.Deserialize(plainStream));
EXPECT_EQ(readPlain.editMode, 0);
MasterPackets::CreatePrivateZone readEdit;
ASSERT_TRUE(readEdit.Deserialize(editStream));
EXPECT_EQ(readEdit.editMode, 1);
EXPECT_EQ(readEdit.zoneID, 1100u);
EXPECT_EQ(readEdit.password, password.substr(0, MasterPackets::CreatePrivateZone::MAX_PASSWORD_LENGTH));
}
}
TEST(MasterPacketsTests, WorldStateMatchesLegacy) {
for (const LWOMAPID zone : { static_cast<LWOMAPID>(0), static_cast<LWOMAPID>(1100), static_cast<LWOMAPID>(0xFFFF) }) {
for (const LWOINSTANCEID instance : { static_cast<LWOINSTANCEID>(0), static_cast<LWOINSTANCEID>(3), static_cast<LWOINSTANCEID>(0xFFFF) }) {