mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 02:43:44 +00:00
feat: worlds starting up on the dashboard; the prestarted worlds are a setting
The dashboard shows worlds master has launched but that aren't connected yet (Starting) and those shutting down, on the main page's world list and in /api/worlds (state: starting|stopping), without a shutdown button. Master's server list now carries each world's state (appended after the UGC fields, one byte per world) and master pushes the list to the dashboard whenever a world is launched, becomes ready, is told to shut down or goes away, instead of the dashboard only seeing it on its 30 second poll. Starting worlds are kept apart from the running ones, so counts, events and shutdown requests still only see running worlds. prestart_worlds (masterconfig.ini, zone ids) lists the worlds master starts when prestart_servers is on, instead of the hardcoded character select (0) and Venture Explorer (1000), which stay the default when it is missing or empty. It is on the Settings page as a zone list (restart only), shown when prestart_servers is on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -88,6 +88,38 @@ SystemAddress ugcServerMasterPeerSysAddr;
|
||||
uint32_t ugcServerPid = 0;
|
||||
|
||||
namespace {
|
||||
// Every server for the dashboard: auth, chat, the UGC server and the worlds, including those launched but not
|
||||
// connected yet (starting) and those shutting down
|
||||
MasterPackets::ServerListResponse BuildServerList() {
|
||||
using eState = MasterPackets::ServerListResponse::eState;
|
||||
MasterPackets::ServerListResponse response;
|
||||
response.authOnline = authServerMasterPeerSysAddr != UNASSIGNED_SYSTEM_ADDRESS ? 1 : 0;
|
||||
response.chatOnline = chatServerMasterPeerSysAddr != UNASSIGNED_SYSTEM_ADDRESS ? 1 : 0;
|
||||
response.ugcEnabled = Game::config->GetValue("enable_ugc_server") == "1" ? 1 : 0;
|
||||
response.ugcOnline = ugcServerMasterPeerSysAddr != UNASSIGNED_SYSTEM_ADDRESS ? 1 : 0;
|
||||
response.ugcPid = ugcServerPid;
|
||||
if (!Game::im) return response;
|
||||
for (const auto& inst : Game::im->GetInstances()) {
|
||||
if (!inst || inst->GetShutdownComplete()) continue;
|
||||
auto& entry = response.instances.emplace_back();
|
||||
entry.mapID = inst->GetMapID();
|
||||
entry.instanceID = inst->GetInstanceID();
|
||||
entry.cloneID = inst->GetCloneID();
|
||||
entry.players = static_cast<uint32_t>(inst->GetCurrentClientCount());
|
||||
entry.ip = LUString(inst->GetIP());
|
||||
entry.port = inst->GetPort();
|
||||
entry.isPrivate = inst->GetIsPrivate() ? 1 : 0;
|
||||
entry.state = inst->GetIsShuttingDown() ? eState::STOPPING : inst->GetIsReady() ? eState::READY : eState::STARTING;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
// Tells the dashboard at once when a world is launched, connects or goes away (it also asks every 30 seconds)
|
||||
void PushServerListToDashboard() {
|
||||
if (dashboardServerMasterPeerSysAddr == UNASSIGNED_SYSTEM_ADDRESS) return;
|
||||
MasterPackets::SendTo(dashboardServerMasterPeerSysAddr, BuildServerList());
|
||||
}
|
||||
|
||||
// Dashboard player actions waiting for world servers to answer
|
||||
struct PendingPlayerAction {
|
||||
ePlayerAction action{};
|
||||
@@ -418,6 +450,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
//Create additional objects here:
|
||||
Game::im = new InstanceManager(Game::server->GetIP());
|
||||
Game::im->SetOnInstancesChanged(PushServerListToDashboard);
|
||||
|
||||
//Get CDClient initial information
|
||||
try {
|
||||
@@ -442,8 +475,17 @@ int main(int argc, char** argv) {
|
||||
if (Game::config->GetValue("prestart_servers") != "0") {
|
||||
StartChatServer();
|
||||
|
||||
Game::im->GetInstance(0, false, 0);
|
||||
Game::im->GetInstance(1000, false, 0);
|
||||
// The worlds started with master (prestart_worlds, zone ids; missing or empty: character select and Venture Explorer)
|
||||
for (auto part : GeneralUtils::SplitString(Game::config->GetValue("prestart_worlds", "0,1000"), ',')) {
|
||||
std::erase_if(part, [](const char c) { return std::isspace(static_cast<unsigned char>(c)); });
|
||||
if (part.empty()) continue;
|
||||
const auto zoneId = GeneralUtils::TryParse<LWOMAPID>(part);
|
||||
if (!zoneId) {
|
||||
LOG("prestart_worlds: '%s' isn't a zone id; skipped", part.c_str());
|
||||
continue;
|
||||
}
|
||||
Game::im->GetInstance(*zoneId, false, 0);
|
||||
}
|
||||
StartAuthServer();
|
||||
}
|
||||
|
||||
@@ -804,6 +846,7 @@ namespace {
|
||||
|
||||
LOG("Got shutdown response from zone %i clone %i instance %i port %i", instance->GetMapID(), instance->GetCloneID(), instance->GetInstanceID(), instance->GetPort());
|
||||
instance->SetIsShuttingDown(true);
|
||||
PushServerListToDashboard();
|
||||
}
|
||||
|
||||
void OnShutdownUniverse(const ShutdownUniverse& request, const SystemAddress& sysAddr) {
|
||||
@@ -937,25 +980,7 @@ namespace {
|
||||
void OnRequestServerList(const RequestServerList& request, const SystemAddress& sysAddr) {
|
||||
LOG("Dashboard requested server list");
|
||||
|
||||
ServerListResponse response;
|
||||
response.authOnline = authServerMasterPeerSysAddr != UNASSIGNED_SYSTEM_ADDRESS ? 1 : 0;
|
||||
response.chatOnline = chatServerMasterPeerSysAddr != UNASSIGNED_SYSTEM_ADDRESS ? 1 : 0;
|
||||
response.ugcEnabled = Game::config->GetValue("enable_ugc_server") == "1" ? 1 : 0;
|
||||
response.ugcOnline = ugcServerMasterPeerSysAddr != UNASSIGNED_SYSTEM_ADDRESS ? 1 : 0;
|
||||
response.ugcPid = ugcServerPid;
|
||||
|
||||
for (const auto& inst : Game::im->GetInstances()) {
|
||||
if (!inst || !inst->GetIsReady() || inst->GetIsShuttingDown()) continue;
|
||||
auto& entry = response.instances.emplace_back();
|
||||
entry.mapID = inst->GetMapID();
|
||||
entry.instanceID = inst->GetInstanceID();
|
||||
entry.cloneID = inst->GetCloneID();
|
||||
entry.players = static_cast<uint32_t>(inst->GetCurrentClientCount());
|
||||
entry.ip = LUString(inst->GetIP());
|
||||
entry.port = inst->GetPort();
|
||||
entry.isPrivate = inst->GetIsPrivate() ? 1 : 0;
|
||||
}
|
||||
|
||||
const auto response = BuildServerList();
|
||||
MasterPackets::SendTo(sysAddr, response);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user