ModernUO/Projects/Server
Kamron Batman b191498569
feat: Adds Feature Flag System (#2328)
## Feature Flag System

A runtime feature flag system for dynamically enabling/disabling game systems and blocking specific game elements
without server restarts.

### Overview

Two types of controls:

1. Feature Flags - Named boolean flags that gate entire systems (trading, PvP, vendors, housing, etc.)
2. Dynamic Blocks - Block specific gumps, items, skills, or spells by type

All changes are persisted to JSON, broadcast to online staff, and bypass-able by administrators.

### Predefined Flags
```
┌─────────────────┬──────────┬─────────────────────────────────────┐
│      Flag       │ Category │             Description             │
├─────────────────┼──────────┼─────────────────────────────────────┤
│ player_trading  │ Economy  │ Allow secure trades between players │
├─────────────────┼──────────┼─────────────────────────────────────┤
│ vendor_purchase │ Economy  │ Allow purchasing from NPC vendors   │
├─────────────────┼──────────┼─────────────────────────────────────┤
│ vendor_sell     │ Economy  │ Allow selling to NPC vendors        │
├─────────────────┼──────────┼─────────────────────────────────────┤
│ player_vendors  │ Economy  │ Allow player vendor interactions    │
├─────────────────┼──────────┼─────────────────────────────────────┤
│ bank_access     │ Economy  │ Allow bank box access               │
├─────────────────┼──────────┼─────────────────────────────────────┤
│ house_placement │ Housing  │ Allow new house placements          │
├─────────────────┼──────────┼─────────────────────────────────────┤
│ boat_placement  │ Housing  │ Allow new boat placements           │
├─────────────────┼──────────┼─────────────────────────────────────┤
│ bulk_orders     │ Crafting │ Allow bulk order deeds              │
├─────────────────┼──────────┼─────────────────────────────────────┤
│ pvp_combat      │ Combat   │ Allow player vs player combat       │
└─────────────────┴──────────┴─────────────────────────────────────┘
```

### Commands

#### Feature Flags
```
┌────────────────────────────────────────────────────┬───────────────────────┐
│                      Command                       │      Description      │
├────────────────────────────────────────────────────┼───────────────────────┤
│ [FeatureFlag <key> on|off|toggle|info              │ Manage a feature flag │
├────────────────────────────────────────────────────┼───────────────────────┤
│ [FF <key> on|off                                   │ Shorthand alias       │
├────────────────────────────────────────────────────┼───────────────────────┤
│ [FeatureFlag <key> create <category> <desc>        │ Create a custom flag  │
├────────────────────────────────────────────────────┼───────────────────────┤
│ [FeatureFlag <key> delete                          │ Delete a custom flag  │
├────────────────────────────────────────────────────┼───────────────────────┤
│ [FeatureList [flags|gumps|items|skills|spells|all] │ List all flags/blocks │
├────────────────────────────────────────────────────┼───────────────────────┤
│ [FeatureAdmin                                      │ Open the admin gump   │
└────────────────────────────────────────────────────┴───────────────────────┘
```

#### Gump Blocks
```
┌────────────────────────────────┬──────────────────────────────────────────────────────┐
│            Command             │                     Description                      │
├────────────────────────────────┼──────────────────────────────────────────────────────┤
│ [BlockGump <typeName> [reason] │ Block a gump type from displaying                    │
├────────────────────────────────┼──────────────────────────────────────────────────────┤
│ [UnblockGump <typeName>        │ Remove a gump block                                  │
├────────────────────────────────┼──────────────────────────────────────────────────────┤
│ [ListGumps [self]              │ List open gumps on a player (for finding type names) │
└────────────────────────────────┴──────────────────────────────────────────────────────┘
```

#### Item Blocks
```
┌────────────────────────────────────────────────┬───────────────────────────────┐
│                    Command                     │          Description          │
├────────────────────────────────────────────────┼───────────────────────────────┤
│ [BlockItemUse <typeName|target> [reason]       │ Block item use                │
├────────────────────────────────────────────────┼───────────────────────────────┤
│ [BlockItemEquip <typeName|target> [reason]     │ Block item equipping          │
├────────────────────────────────────────────────┼───────────────────────────────┤
│ [BlockItemContainer <typeName|target> [reason] │ Block container access        │
├────────────────────────────────────────────────┼───────────────────────────────┤
│ [UnblockItemUse <typeName>                     │ Remove use block              │
├────────────────────────────────────────────────┼───────────────────────────────┤
│ [UnblockItemEquip <typeName>                   │ Remove equip block            │
├────────────────────────────────────────────────┼───────────────────────────────┤
│ [UnblockItemContainer <typeName>               │ Remove container access block │
└────────────────────────────────────────────────┴───────────────────────────────┘
```
Item block commands create an entry if one doesn't exist, or flip the relevant flag on an existing entry. Unblock
commands only clear their specific flag -- the entry is removed when all flags (use/equip/container) are off.

#### Skill & Spell Blocks
```
┌──────────────────────────────────────┬──────────────────────┐
│               Command                │     Description      │
├──────────────────────────────────────┼──────────────────────┤
│ [BlockSkill <SkillName> [reason]     │ Block a skill        │
├──────────────────────────────────────┼──────────────────────┤
│ [UnblockSkill <SkillName>            │ Remove a skill block │
├──────────────────────────────────────┼──────────────────────┤
│ [BlockSpell <SpellTypeName> [reason] │ Block a spell        │
├──────────────────────────────────────┼──────────────────────┤
│ [UnblockSpell <SpellTypeName>        │ Remove a spell block │
└──────────────────────────────────────┴──────────────────────┘
```

### Architecture

- Static bool classes for hot-path checks (no dictionary lookups): ServerFeatureFlags (Server project) and
ContentFeatureFlags (UOContent)
- Synced automatically by FeatureFlagManager.SyncStaticFlag() when flags change
- Predefined flags loaded from Distribution/Configuration/FeatureFlags/default-flags.json
- Runtime state persisted to Configuration/FeatureFlags/*.json (flags, gump-blocks, item-blocks, skill-blocks,
spell-blocks)
- Admin gump with tabbed UI for managing all block types, per-entry PropertiesGump editing, and pagination
- All staff at AccessLevel.GameMaster+ bypass dynamic blocks; AccessLevel.Administrator+ bypass feature flags

### Hook Points

Hook: Player trading
Location: Mobile.OpenTrade
Mechanism: ServerFeatureFlags.PlayerTrading
────────────────────────────────────────
Hook: PvP combat
Location: Mobile.CanBeHarmful
Mechanism: ServerFeatureFlags.PvPCombat
────────────────────────────────────────
Hook: Bank access
Location: BankBox.Open()
Mechanism: ServerFeatureFlags.BankAccess
────────────────────────────────────────
Hook: Vendor buy/sell
Location: BaseVendor
Mechanism: ContentFeatureFlags.VendorPurchase/Sell
────────────────────────────────────────
Hook: Player vendors
Location: PlayerVendor
Mechanism: ContentFeatureFlags.PlayerVendors
────────────────────────────────────────
Hook: House placement
Location: HousePlacement.Check()
Mechanism: ContentFeatureFlags.HousePlacement (returns BadRegionTemp)
────────────────────────────────────────
Hook: Boat placement
Location: BaseBoatDeed.OnDoubleClick/OnPlacement
Mechanism: ContentFeatureFlags.BoatPlacement
────────────────────────────────────────
Hook: Bulk orders
Location: SmallBOD/LargeBOD
Mechanism: ContentFeatureFlags.BulkOrders
────────────────────────────────────────
Hook: Gump display
Location: GumpSystem.SendGump
Mechanism: FeatureFlagManager.IsGumpBlocked
────────────────────────────────────────
Hook: Item use
Location: PlayerMobile.AllowItemUse
Mechanism: FeatureFlagManager.IsItemUseBlocked
────────────────────────────────────────
Hook: Item equip
Location: PlayerMobile.CheckEquip
Mechanism: FeatureFlagManager.IsItemEquipBlocked
────────────────────────────────────────
Hook: Container access
Location: BaseContainer.DisplayTo
Mechanism: FeatureFlagManager.IsContainerAccessBlocked
────────────────────────────────────────
Hook: Skill use
Location: PlayerMobile.AllowSkillUse
Mechanism: FeatureFlagManager.IsSkillBlocked
────────────────────────────────────────
Hook: Spell casting
Location: Spell.Cast / Spellbook.CastSpellRequest
Mechanism: FeatureFlagManager.IsSpellBlocked
2026-02-07 12:02:57 -08:00
..
Buffers feat: Adds Latin1 text support (#2317) 2026-01-22 15:51:00 -08:00
Client chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
Collections feat: Adds Feature Flag System (#2328) 2026-02-07 12:02:57 -08:00
Comparers chore: Updates copyright (#1448) 2023-08-09 09:09:26 -07:00
Compression fix: Fixes libdeflate threading issue (#1813) 2024-06-02 15:02:47 -07:00
Configuration fix: Fixes idleCPU override (#2308) 2026-01-04 17:21:08 -08:00
Console fix: Console Input is disabled on Linux when no standard input is attached. (#1809) 2024-06-06 21:20:22 -07:00
ContextMenus fix: Moves ContextMenu out of core, streamlines code, fixes bugs (#1873) 2024-07-20 21:33:23 -07:00
Events feat: Upgrades networking to use io_uring. (#2315) 2026-02-01 16:02:32 -08:00
Exceptions chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
GarbageCollection chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
Geometry fix: Fixes zero height spawners and normalizes spawn bounds before use. (#2301) 2025-12-31 10:25:42 -08:00
Items feat: Adds Feature Flag System (#2328) 2026-02-07 12:02:57 -08:00
Json feat: Add spawn position caching and spiral scan optimization (#2295) 2025-12-28 02:40:21 -08:00
Localization chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
Maps refactor: Add BitMask256 utility for 256-bit bitmask operations (#2300) 2025-12-29 12:54:49 -08:00
Menus fix: Cleans up core code (#1187) 2022-10-10 21:47:08 -07:00
Migrations fix: Moves containers/bods/traps/etc to serialization generator (#2310) 2026-01-07 21:55:55 -08:00
Mobiles feat: Adds Feature Flag System (#2328) 2026-02-07 12:02:57 -08:00
Network fix: Fixes logout in new networking (#2326) 2026-02-04 22:42:18 -08:00
PropertyList chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
Random chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
Regions fix: Eliminates List allocations in various places. (#2158) 2025-11-16 18:33:53 -08:00
Serialization feat: Adds new decay system and SkipSerialization (#2311) 2026-01-08 11:43:51 -08:00
Targeting chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
Text feat: Adds Latin1 text support (#2317) 2026-01-22 15:51:00 -08:00
TileMatrix feat: Updates to .NET 9 (#1984) 2024-12-08 10:16:34 -08:00
Timer chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
TimeZones fix: Fixes order of execution with AutoSave and TZ (#1665) 2024-01-24 17:17:45 -08:00
Utilities feat: Upgrades networking to use io_uring. (#2315) 2026-02-01 16:02:32 -08:00
World feat: Adds Feature Flag System (#2328) 2026-02-07 12:02:57 -08:00
AssemblyHandler.cs chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
Attributes.cs fix: Fixes props for interfaces and adds account manipulation (#2179) 2025-05-09 15:39:47 -07:00
CityInfo.cs chore: Updates copyright (#1448) 2023-08-09 09:09:26 -07:00
Commands.cs fix: Fixes adding items with ambiguous type lookup (#2307) 2026-01-06 21:21:29 -08:00
Effects.cs chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
EntityFinalizationTracker.cs feat: Adds an Item/Mobile memory leak detector. Fixes minor leak in doors. (#2159) 2025-04-15 19:14:45 -07:00
EventLoopTasks.cs chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
ExpansionInfo.cs chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
FeatureFlags.cs feat: Adds Feature Flag System (#2328) 2026-02-07 12:02:57 -08:00
Guild.cs chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
HuePicker.cs fix: Cleans up core code (#1187) 2022-10-10 21:47:08 -07:00
IAccount.cs fix: Fixes looking up accounts that were renamed. (#2078) 2025-01-18 17:11:43 -08:00
IEntity.cs feat: Upgrades serialization v4 (Threaded Heap Serialization) (#1947) 2024-09-14 09:57:43 -07:00
Interfaces.cs feat: Add CanSpawnMobile overload with props Z-range support. (#2293) 2025-12-27 17:01:15 -08:00
IVirtualCheckGump.cs feat: Moves gumps out of the core (#1916) 2024-08-09 19:07:32 -07:00
KeywordList.cs fix: Cleans up core code (#1187) 2022-10-10 21:47:08 -07:00
Main.cs feat: Upgrades networking to use io_uring. (#2315) 2026-02-01 16:02:32 -08:00
MessageType.cs fix: Moves the rest of the Incoming packets (#1338) 2023-02-10 22:59:36 -08:00
Module.cs fix: Fixes sending packets and sidesteps a major issue with stackalloc and PGO in .NET 8 (#1607) 2023-11-21 12:18:20 -08:00
MultiData.cs chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
Party.cs fix: Cleans up core code (#1187) 2022-10-10 21:47:08 -07:00
Poison.cs fix: Adds ISpanParsable and fixes command conditionals (#1241) 2022-11-12 00:26:02 -08:00
Prompt.cs fix: Cleans up core code (#1187) 2022-10-10 21:47:08 -07:00
Race.cs fix: Fixes TryParse for Race (#1244) 2022-11-12 00:31:25 -08:00
SecureTrade.cs feat: Moves gumps out of the core (#1916) 2024-08-09 19:07:32 -07:00
Serial.cs feat: Updates to .NET 9 (#1984) 2024-12-08 10:16:34 -08:00
Server.csproj feat: Adds SerializableFieldChanged option (#2324) 2026-02-01 21:28:26 -08:00
Skills.cs chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
TileData.cs feat: Add CanSpawnMobile overload with props Z-range support. (#2293) 2025-12-27 17:01:15 -08:00
TileList.cs fix: Refactors getting static tiles to use enumerators (#1611) 2023-11-26 09:39:46 -08:00