### Summary
- Adds [Code Generated Events](https://github.com/modernuo/CodeGeneratedEvents)
- Removes EventSink.PlayerDeath
- Adds `PlayerDeathEvent` and `CreatureDeathEvent` using code generated events
> [!Important]
> **Developer Note**
> Use `[OnEvent(nameof(PlayerMobile.PlayerDeathEvent))]` instead of `EventSink.PlayerDeath` delegate
> Check this commit for examples of how to use this.
> [!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.
### Summary
- Fixes the name `Vegies` to `Veggies`
- Adds feeding leather to goats
- Adds metal for Lava Lizards
- Fixes Bone Helm being classified as plate instead of bone.
- Fixes wooden shields not classified as wood.
### Note
On OSI, the preferred foods on the animal lore gump doesn't contain all possible favorite food categories. Furthermore, the one listed is not necessarily always the "first" in the list of possible categories. We aren't going to try and fix that since it isn't important.
### Summary
* Fixes syntax compile error when THREADGUARD is enabled.
* Removes `int packetLength` from incoming packet handles since they aren't needed.
### Developer Notes
Incoming packet handler `SpanReader` is now properly scoped to that packet by length.
### Summary
The BitArray class will be optimized over the next several years for various platforms/hardware and maintaining a duplicate for serialization is not practical. Removing the custom implementation. Recommend against using BitArray for serialization unless it is absolutely necessary.
### Summary
Eliminates `IPooledEnumerable<NetState>` and `eable.Free()` from `Map` for clients. This drastically simplifies code that iterates in range, for example:
```cs
foreach (var m in m.GetClientsInRange(5))
{
}
```
The code above no longer requires an eable and calling `Free()`.
### Summary
Eliminates `IPooledEnumerable<T>` and `eable.Free()` from `Map` for mobiles. This drastically simplifies code that iterates in range, for example:
```cs
foreach (var m in m.GetMobilesInRange(5))
{
}
```
The code above no longer requires an eable and calling `Free()`.
- [X] Fixed several locations where an NPC that was damaged would cause a server crash.
- [X] Removed an unnecessary allocation in guard fake calls (NPCs calling guards on you)
- [X] Fixes damage precision loss in Poison Strike Spell
- [X] BogThing no longer attempts to "search" for boglings to eat when it is at full health
### Summary
Eliminates `IPooledEnumerable<T>` and `eable.Free()` from `Map` for items. This drastically simplifies code that iterates in range, for example:
```cs
foreach (var item in m.GetItemsInRange(5))
{
}
```
The code above no longer requires an eable and calling `Free()`.
### Summary
- Adds the following configurations:
```json
"stats.statMax": "125",
"stats.gainChanceMultiplier": 1.0,
"stats.primaryStatGainChance": 0.75,
"stats.gainDelay": "00:10:00",
"stats.petGainDelay": "00:05:00",
"stats.usePub45StatGain": "False"
```
- Adds Pub 45 stat gain rate for UOML+.
- Reduces the gain delay for legacy stat gain from 15 minutes to 10 minutes.
- Legacy gain no longer requires a gain in skill to gain in a stat.
## Breaking Changes
Incoming packet registration signature has changed to:
```cs
delegate* void OnReceiveCallback(NetState state, SpanReader reader, int packetLength);
IncomingPackets.Register(int packetID, int length, bool ingame, OnReceiveCallback onReceive);
```
For example, an incoming packet handler signature would now look like this:
```cs
public static void SomeIncomingPacket(NetState state, SpanReader reader, int packetLength)
{
// Parse the data
}
```
## Summary
Updates the network Pipe class to use a mirrored memory technique. This technique involves mapping the same physical memory to two contiguous virtual memory spaces so the byte buffer appears duplicated. This allows writing to a double-sized array to wrap around without the need for the `CircularBuffer` classes.
In practice this allows us to use `Span<byte>` as if the buffer was a regular array.
### Bug Fixes
- [X] Fixes bad fixed length string parsing
### Summary
- [X] Fixed a bug where entity persistence was serialized out of order, causing world corruption.
- [X] Fixed LastSerialized not being utilized properly and dangling references still becoming an issue.
- [X] Added a new `GenericEntityPersistence<T>` type to encapsulate `ISerializable` serialization.
- [X] Removing the custom logic and moved Items, Mobiles, Guilds, and Accounts to GenericEntityPersistence.
- [X] Changed serialization to use the singleton pattern to reduce calling methods from stored variables.
## MAJOR CHANGE (API BREAKING)
Moved the virtues to it's own system _VirtueSystem_. This should make it easier to extend or remove the virtue system. Virtues will be saved to a new folder called _Virtues_.
### Motivation
The motivation was also two-fold, performance/stability, and to fix bugs.
First, virtues is the second system (first is murders), that has a pre-world-save check on _every mobile in the game_ to atrophy virtue stats. This is taxing since it freexes the world and makes world saves take longer. Every mobile had Gain/Loss dates for each virtue, whether they needed them or not. Most players don't even use the virtue system, so this will increase performance considerably.
Second, when I tried to optimize/refactor the code, I found several bugs that needed to be fixed.
### Major API Changes
- [X] The properties on players related to virtues are gone. Use `pm.GetVirtues()?.<PropertyName>` instead.
- [X] Virtues were removed from non-player Mobiles.
- [X] `pm.JusticeProtectors` was removed. Use `JusticeVirtue.GetProtector()` or `JusticeVirtue.GetProtected()` instead.
### Screenshots
<img width="221" alt="Props-1" src="https://github.com/modernuo/ModernUO/assets/3953314/5c09cb83-b8d5-44a2-b899-a7ed7cd736ac">
<img width="220" alt="props-2" src="https://github.com/modernuo/ModernUO/assets/3953314/aeade4d3-8df0-47bd-955a-a864d0946cf7">
### Summary
- [X] Moves AntiMacro to it's own system.
- [X] Removes antimacro from PlayerMobile.
- [X] Adds `LastExpiration` to antimacro to easily clear out all antimacro tracking when a player logs out, or during world save.
- [X] Optimizes the code somewhat.
**Only one functional change**
* Fixes a bug in LogFactory where `Warning` is being logged as `Information`
Non-functional changes:
* Updates/Fixes copyright headers
* Removes namespace scopes for core files.
View with [whitespace off](https://github.com/modernuo/ModernUO/pull/1187/files?w=1).
- [X] Fixes NPE from account tags.
- [X] Fixes bad skill check due to missing cast to double.
- [X] Fixes water elemental duration.
- [X] Standardizes spell summon duration by expansion.
* Removes scaled speed by dex for monsters
* Changes scaled speed by dex for pets (HS+ expansion) to be 400ms -> 100ms between 50 -> 200 dex
* Removes speed changes that were broken for various mobs
* Combines "Legacy" speed and renames the class to `NPCSpeeds`
* Creates speed "classes" (slow, medium, fast, very fast)
* Introduces a new overridable property `SpeedClass`. Register a new speed class using `NPCSpeeds.Register()` and then set the speed class to bulk/mass apply speeds.
Order of speed determination:
1. SpeedMod
2. SpeedClass property (not null)
3. SpeedClass entry in Data\npc-speeds.json for that type
4. "Fast" (200ms Active, 400ms Passive)
- [X] Removes several `ToList()` uses with `PooledRefQueue`
- [X] Adds a `PeekRandom` to PooledRefQueue
- [X] Updates EV/BS so they dispel each other in a more efficient manner.
- [X] Fixes Firebomb so it works like a normal firefield.
- [X] Fixes field spells so they aren't unnecessarily using a Point3D ref more than necessary.
- [X] Removes extra allocation in campfire by using reverse loop.
- [X] Removes other LINQ calls that aren't needed.
Fixes an issue with DropReq where an old client was sending in 14 bytes, but the server was expecting 15 bytes.
To fix this we introduced a new packet handler, `ContainerGridPacketHandler` and changed the code to determine the length of the packet dynamically using `GetLength(NetState)`.
Also fixed throttling so dropped packets are properly skipped.