feat: master coordinates moving an instance's players (replace, merge)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-26 08:40:52 -05:00
parent daad87a661
commit db93405252
6 changed files with 415 additions and 3 deletions

View File

@@ -34,6 +34,7 @@
#include "AuthPackets.h"
#include "Game.h"
#include "InstanceManager.h"
#include "MigrationCoordinator.h"
#include "MasterPackets.h"
#include "FdbToSqlite.h"
#include "BitStreamUtils.h"
@@ -372,6 +373,16 @@ int main(int argc, char** argv) {
return EXIT_FAILURE;
}
// Instance migration progress goes to every world, where the GM who asked for it hears about it
MigrationCoordinator::SetReporter([](const MigrationStatus& status) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, ServiceType::MASTER, MessageType::Master::MIGRATE_STATUS);
status.Serialize(bitStream);
for (const auto& instance : Game::im->GetInstances()) {
if (instance && instance->GetIsReady() && !instance->GetShutdownComplete()) Game::server->Send(bitStream, instance->GetSysAddr(), false);
}
});
//Depending on the config, start up servers:
if (Game::config->GetValue("prestart_servers") != "0") {
StartChatServer();
@@ -403,6 +414,8 @@ int main(int argc, char** argv) {
packet = nullptr;
}
MigrationCoordinator::Update();
//Push our log every 15s:
if (framesSinceLastFlush >= logFlushTime) {
Game::logger->Flush();
@@ -493,6 +506,7 @@ void HandlePacket(Packet* packet) {
Game::im->GetInstanceBySysAddr(packet->systemAddress);
if (instance) {
LOG("Actually disconnected from zone %i clone %i instance %i port %i", instance->GetMapID(), instance->GetCloneID(), instance->GetInstanceID(), instance->GetPort());
MigrationCoordinator::OnInstanceGone(*instance);
Game::im->RemoveInstance(instance); //Delete the old
}
@@ -514,6 +528,7 @@ void HandlePacket(Packet* packet) {
Game::im->GetInstanceBySysAddr(packet->systemAddress);
if (instance) {
LWOZONEID zoneID = instance->GetZoneID(); //Get the zoneID so we can recreate a server
MigrationCoordinator::OnInstanceGone(*instance);
Game::im->RemoveInstance(instance); //Delete the old
}
@@ -834,6 +849,33 @@ void HandlePacket(Packet* packet) {
break;
}
case MessageType::Master::INSTANCE_MIGRATE: {
// Only servers connected to master can send this (a world, for a GM's /replaceinstance or /mergeinstance)
CINSTREAM_SKIP_HEADER;
InstanceMigrationRequest request;
if (!request.Deserialize(inStream)) break;
if (shutdownSequenceStarted) {
LOG("Shutdown sequence has been started. Not starting instance migration %u.", request.requestId);
break;
}
MigrationCoordinator::Start(request);
break;
}
case MessageType::Master::MIGRATE_STATUS: {
CINSTREAM_SKIP_HEADER;
MigrationStatus status;
if (status.Deserialize(inStream)) MigrationCoordinator::HandleStatus(packet->systemAddress, status);
break;
}
case MessageType::Master::MIGRATE_PLAYER_STATE: {
CINSTREAM_SKIP_HEADER;
CarriedPlayerState state;
if (state.Deserialize(inStream)) MigrationCoordinator::HandleCarriedState(packet->systemAddress, state, packet->data, packet->length);
break;
}
default:
LOG("Unknown master packet ID from server: %i", packet->data[3]);
}