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
Kamron Batman
c14f361de1
fix: Moves containers/bods/traps/etc to serialization generator ( #2310 )
2026-01-07 21:55:55 -08:00
Guyute
b612c443df
fix: Migrate BOD gumps to DynamicGump ( #1926 )
2024-08-13 08:13:20 -07:00
Kamron Batman
8282b00ca2
feat: Moves gumps out of the core ( #1916 )
...
> [!Important]
> **Developer Note**
> This code change will **completely move gumps out of the core**
### Summary
- Adds `GetGumps()` convenience which exposes methods to Find/Close/Send multiple gumps. This helper is a performance improvement by eliminating the Dictionary<Player, List> lookup for gumps.
2024-08-09 19:07:32 -07:00
Kamron Batman
b74b47159f
fix: Fixes localization corner cases with OPL ( #1050 )
...
## Changes
- [X] Adds OPL convenience methods
- `opl.Add(cliloc, value)` and `opl.Add(value)` - value as an integer or string works just like `opl.Add(cliloc, $"{value}")`
- `opl.AddLocalized(cliloc, clilocValue)` - works the same as `opl.Add(cliloc, $"#{clilocValue}");`
- [X] Simplifies basic `list.Add()` situations
- [X] Changes cliloc as an argument so it works with custom IPropertyList implementations (HTML)
- [X] Fixes plants so they support the old localization and new (changed in 7.0.12.0+)
- [X] Exposes more methods to override for Item to make creating custom OPL possible.
## Important Notes
* Using a ternary as an argument, like this `opl.Add(number, showType ? $"{type}\t{value}" : $"{value}");` _will not use the correct string interpolation_. This means if you use a custom PropertyList (for HTML or some other purpose), the property list won't be localized properly.
* All localization values must be interpolated, even if they are literal strings, or integers. Example: `opl.Add(number, $"{"Charges"}\t{m_Charges}");` is correct. Using the following: `$"Charges\t{m_Charges}"` will not work for custom PropertyList implementations!
2022-06-12 21:17:42 -07:00
Kamron Batman
ecbee17690
fix: Optimizes OPL using string interpolation ( #1041 )
...
## Breaking Changes (New API)
ObjectPropertyList supports the following API:
```cs
list.Add(500000);
list.Add(500001, stringArgument);
list.Add("Some text");
list.Add($"Some text with {argument}");
list.Add(500002, $"{arg1}\t{arg2}");
```
## Notes
1. All API uses that require a formatter like this:
```cs
list.Add(500002, "{0}\t{1}", arg1, arg2);
```
Should be changed to use string interpolation, for example:
```cs
list.Add(500002, $"{arg1}\t{arg2}");
```
2. The following paradigm should no longer be used:
```cs
list.Add(1061170, prop.ToString()); // strength requirement ~1_val~
```
The new string interpolation API will avoid having to convert the argument to a string before writing it to the packet. Instead use the following:
```cs
list.Add(1061170, $"{prop}"); // strength requirement ~1_val~
```
### Benchmarks
```cs
| Method | Mean | Error | StdDev | Gen 0 | Allocated |
|------------------------------- |---------:|--------:|--------:|-------:|----------:|
| BenchmarkOldOPL | 241.0 ns | 0.56 ns | 0.47 ns | 0.0105 | 88 B |
| BenchmarkStringInterpolatedOPL | 199.9 ns | 2.44 ns | 2.39 ns | - | - |
```
### Changes
- [X] Removes crash in STArray.Return when array is null.
- [X] Fixes NPE in OPL when entity is null. Serial in packet will be 0 when entity is null.
- [X] Fixes NPE in AosAttributes when Parent is null.
- [X] Changes OPL to use string interpolation.
- [X] Introduces `IPropertyList` to allow extending PropertyList for other uses.
2022-06-02 10:09:53 -07:00
Kamron Batman
54d728a322
fix: Updates serialization to use v2.0 ( #998 )
...
- [X] Deletes serialization annotations
- [X] Updates to ModernUO.Serialization.Annotations nuget
- [X] Updates serializer to v2.0
- [X] Changes all `Serializable()` to `SerializationGenerator()`
- [X] Updates to schema generator v2.0
2022-04-17 08:02:15 -07:00
Kamron Batman
2c8097f707
fix(codegen): Fixes various code gen issues. Adds better embedded serialization support ( #688 )
...
* Adds save flag support (see `ElvenGlasses` for an example)
* Updates AOSAttributes so they are code genned
* Fixes embedded object support by adding an `IRawSerializable`
* Fixes various inconsistencies in serializing with codegen
2021-08-17 02:43:52 -07:00
Kamron Batman
510d2e006b
fix(codegen): Fixes bulk order deed hue and codegens ( #647 )
...
- [X] Codegens some Bulk Order stuff
- [X] Fixes deserializing with a class that requires the parent as a constructor argument
Closes #641
Closes #623
2021-06-11 19:51:03 -07:00
Kamron Batman
b4b1b0b122
fix(core): Converts more packets and switches to Moq ( #415 )
...
- [X] Switches testing to moq for mocking
- [X] Converts race changer packets
- [X] Renames some more folders and misc cleanup
2021-01-16 22:09:05 -08:00