From d1243729736140359affb0dd9d6131c0d8bab5ed Mon Sep 17 00:00:00 2001 From: Aaron Kimbrell Date: Tue, 10 Nov 2026 18:25:53 -0600 Subject: [PATCH] feat(config): zone_override_dir and the limits of edited zone files World, master and chat servers read files under maps/ through the override folder named by zone_override_dir (empty: off). The settings for who may send zone files and how large a set may be are in sharedconfig.ini and the settings catalog. Co-Authored-By: Claude Fable 5.2 --- dChatServer/ChatServer.cpp | 3 +++ dDashboardServer/routes/SettingsCatalog.cpp | 10 ++++++++++ dMasterServer/MasterServer.cpp | 3 +++ dWorldServer/WorldServer.cpp | 3 +++ resources/sharedconfig.ini | 16 ++++++++++++++++ 5 files changed, 35 insertions(+) diff --git a/dChatServer/ChatServer.cpp b/dChatServer/ChatServer.cpp index 64269705b..092a2d0f7 100644 --- a/dChatServer/ChatServer.cpp +++ b/dChatServer/ChatServer.cpp @@ -18,6 +18,7 @@ #include "MessageType/Master.h" #include "Diagnostics.h" #include "AssetManager.h" +#include "ZoneOverrideStore.h" #include "BinaryPathFinder.h" #include "ServiceType.h" #include "PlayerContainer.h" @@ -92,6 +93,8 @@ int main(int argc, char** argv) { } Game::assetManager = new AssetManager(clientPath); + // Edited zone files are read in place of the client's (docs/ZonePublish.md) + Game::assetManager->SetOverrideDir(ZoneOverrideStore::RootFromSetting(Game::config->GetValue("zone_override_dir"))); } catch (std::runtime_error& ex) { LOG("Got an error while setting up assets: %s", ex.what()); delete Game::logger; diff --git a/dDashboardServer/routes/SettingsCatalog.cpp b/dDashboardServer/routes/SettingsCatalog.cpp index 1cab6d944..9c83fec66 100644 --- a/dDashboardServer/routes/SettingsCatalog.cpp +++ b/dDashboardServer/routes/SettingsCatalog.cpp @@ -152,6 +152,16 @@ namespace { c.Add(Unit(Int(MASTER, "live_update_service_timeout", "Server restart timeout", "How long auth, chat, the UGC server or the dashboard may take to stop or come back before master starts it again (3 tries).", "30", 10, 600), "seconds")); c.Add(Bool(MASTER, "live_update_run_migrations", "Run database migrations", "Run the new build's database migrations first. The running servers must cope with the new schema until they are replaced.", true)); + c.AddSection("Edited zone files", "Zone files sent by an external level editor through the dashboard's API (docs/ZonePublish.md): they are kept in their own folder and read in place of the client's, which are never written."); + c.Add(Format(Text(SHARED, "zone_override_dir", "Override folder", "A file under maps/ is read from this folder's maps/ when it is there, and from the client otherwise. Also holds the sets being checked and the replaced sets. Relative to the server binaries unless absolute. Empty turns the feature off.", "", true), eFormat::PATH)); + c.Add(Int(SHARED, "zone_publish_gm_level", "Level to send zone files", "The lowest GM level that may send, restore or clear a zone's edited files. The account also has to hold the zone's lock, and its API key needs the zones.publish permission.", "9", 1, 9)); + c.Add(Int(SHARED, "zone_lock_admin_gm_level", "Level to manage zone locks", "The lowest GM level that may take any zone's lock without being one of its editors, take a lock away from its holder, and assign editors.", "9", 1, 9)); + c.Add(Unit(Int(SHARED, "zone_publish_max_file_mb", "Largest file", "The largest single file of a set.", "64", 1, 1024), "MiB")); + c.Add(Unit(Int(SHARED, "zone_publish_max_total_mb", "Largest set", "The largest set, all its files together.", "256", 1, 4096), "MiB")); + c.Add(Int(SHARED, "zone_publish_max_files", "Files in a set", "The most files one set can have.", "128", 1, 1024)); + c.Add(Int(SHARED, "zone_publish_max_objects", "Objects in a set", "The most objects the scenes of one set can place, all together.", "100000", 1, 10000000)); + c.Add(Int(SHARED, "zone_publish_max_backups", "Replaced sets kept", "How many of a zone's replaced sets are kept to go back to; older ones are deleted.", "20", 0, 1000)); + c.AddSection("Game client"); c.Add(Format(Text(SHARED, "client_location", "Client folder", "The folder with res/, or the one with client/ and versions/.", "", true), eFormat::PATH)); c.Add(Int(SHARED, "client_net_version", "Network version", "Clients reporting another version are refused. 171022 for the retail client, 171023 for Darkflame Universe clients.", "171022", 0, std::nullopt, true)); diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index e9f48e91e..9d8ede971 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -29,6 +29,7 @@ #include "Logger.h" #include "dServer.h" #include "AssetManager.h" +#include "ZoneOverrideStore.h" #include "BinaryPathFinder.h" #include "ServiceType.h" #include "MessageType/Master.h" @@ -313,6 +314,8 @@ int main(int argc, char** argv) { } Game::assetManager = new AssetManager(clientPath); + // Edited zone files are read in place of the client's (docs/ZonePublish.md) + Game::assetManager->SetOverrideDir(ZoneOverrideStore::RootFromSetting(Game::config->GetValue("zone_override_dir"))); } catch (std::runtime_error& ex) { LOG("Got an error while setting up assets: %s", ex.what()); LOG("Is the provided client_location in Windows Onedrive? If so, remove it from Onedrive."); diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index 7efe90371..de581f770 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -88,6 +88,7 @@ #include "PropertyManagementComponent.h" #include "EditMode.h" #include "AssetManager.h" +#include "ZoneOverrideStore.h" #include "LevelProgressionComponent.h" #include "eBlueprintSaveResponseType.h" #include "Amf3.h" @@ -289,6 +290,8 @@ int main(int argc, char** argv) { clientPath = BinaryPathFinder::GetBinaryDir() / clientPath; } Game::assetManager = new AssetManager(clientPath); + // Edited zone files are read in place of the client's (docs/ZonePublish.md) + Game::assetManager->SetOverrideDir(ZoneOverrideStore::RootFromSetting(Game::config->GetValue("zone_override_dir"))); } catch (const std::exception& ex) { LOG("Got an error while setting up assets: %s", ex.what()); diff --git a/resources/sharedconfig.ini b/resources/sharedconfig.ini index 534d9341d..db8a78cfe 100644 --- a/resources/sharedconfig.ini +++ b/resources/sharedconfig.ini @@ -130,3 +130,19 @@ replay_sandbox=0 # Live database (sandbox): Set by the capture tool in replay sandboxes: the real server's SQLite file, which a sandbox # refuses to open. Read when the server starts. replay_live_sqlite_path= + +# Edited zone files (docs/ZonePublish.md). A folder for zone files sent by an external level editor: a file under +# maps/ is read from /maps/... when it is there, and from the client otherwise. The client's own +# files are never written. Relative to the servers' folder unless absolute. Empty = off. +zone_override_dir= +# The lowest GM level that may send, restore or clear a zone's edited files (the account also has to hold the zone's lock) +zone_publish_gm_level=9 +# The lowest GM level that may take any zone's lock without being one of its editors, take a lock away, and assign editors +zone_lock_admin_gm_level=9 +# Limits of one set of edited zone files: megabytes per file, megabytes and files per set, objects in its scenes +zone_publish_max_file_mb=64 +zone_publish_max_total_mb=256 +zone_publish_max_files=128 +zone_publish_max_objects=100000 +# How many replaced sets are kept per zone to go back to +zone_publish_max_backups=20