Commit graph

4946 commits

Author SHA1 Message Date
sven-n
b3ab6fbe99
Merge pull request #871 from MUnique/claude/player-class-refactor-plan-aha5v2
Make map changes and the logout observable in the player state machine
2026-08-15 18:45:37 +02:00
sven-n
2849f9c012
Merge pull request #872 from MUnique/claude/player-components
Extract movement, persistence, summon and storages from the Player class
2026-08-15 18:43:33 +02:00
sven-n
af4fe2ea19
Merge pull request #866 from ze-dom/ragefighter_master_tree_finishup
Rage Fighter Master Tree Finishup
2026-08-15 18:42:14 +02:00
sven-n
066b14e57d
Merge pull request #873 from mrallanodreman/fix/reentrancy-map-change-guard
Prevent duplicate map entry on repeated F3 12 packet

Guards ClientReadyAfterMapChangeAsync against re-entry when CurrentMap is
already set. A repeated client-ready packet previously re-ran the handler,
adding the player and its summon to the area of interest a second time.

GameMap.AddAsync partially dedupes (no id regeneration, no double player
count), but calls AddObjectAsync unconditionally, and Bucket<T> neither
dedupes on add nor removes more than the first occurrence on remove, so
the duplicate entry outlived the player on the map.

Includes ClientReadyAfterMapChangeTests covering both halves of the
invariant: the player is added exactly once across two calls, and no entry
survives removal afterwards.
2026-08-15 18:40:28 +02:00
sven-n
0398c2dbdf
Merge pull request #878 from nolt/bot-logging-category
Give bots their own log category and quiet their per-tick logging
2026-08-15 18:35:06 +02:00
sven-n
e966ceb76f
Merge pull request #879 from nolt/feature/configurable-server-timezone
Add configurable server time zone for periodic event schedules
2026-08-15 18:35:01 +02:00
ze-dom
7116084de5 Refactored base skill check 2026-08-13 15:21:16 +01:00
nolt
b94b62f6a5 Add configurable server time zone for periodic event schedules
Periodic events (invasions, Blood Castle, Devil Square, Chaos Castle,
Happy Hour) match their timetable against DateTime.UtcNow, so the times
of day are effectively interpreted as UTC. There was no concept of a
server time zone, which forces admins to enter UTC times and makes the
schedule drift with daylight saving time.

This adds a SystemConfiguration.TimeZoneId (nullable string), resolved
once at startup and used by the scheduler to interpret the timetable.
When empty or unresolvable it falls back to UTC, so existing servers
keep their current behavior without any action.

- DataModel: SystemConfiguration.TimeZoneId + resources and an EF
  migration for the new nullable column.
- GameLogic: IGameContext.ServerTimeZone; PeriodicTaskConfiguration
  .IsItTimeToStart now interprets the timetable in that zone.
- Startup: resolve TimeZoneId (IANA or Windows id via ICU) with a UTC
  fallback and a warning, and flow it into each game server context.
- Admin Panel: the System page gets a "Server time zone" field which
  suggests the available system time zones (normalized to IANA) and
  validates the entered id, while still allowing a free-text value.
2026-08-13 10:51:48 +02:00
nolt
8cb4b907f2 Give bots their own log category and quiet their per-tick logging
Every Player subclass logged under the same MUnique.OpenMU.GameLogic.Player
category, because the logger was created with CreateLogger<Player>()
regardless of the runtime type. Bots are Players, so their output was
indistinguishable from a real player's and no log configuration could
silence one without the other.

Measured with 500 bots on a Season 6 server: 592 log lines per minute
right after startup and 293 in the steady state, and every single one of
them under MUnique.OpenMU.GameLogic.Player. BotNavigator alone accounted
for 74.6% of the volume, its hunting-ground line for 58.7%.

RuntimeCategoryLogger resolves the category from the owner's runtime type.
BotPlayer installs it for itself in its constructor, so bots now log under
MUnique.OpenMU.GameLogic.Bots.BotPlayer while real players - connected and
their offline MU Helper alike - keep the base Player logger and its
unchanged MUnique.OpenMU.GameLogic.Player category. Serilog's prefix-based
MinimumLevel.Override can now silence the bots on their own
(...GameLogic.Bots=Warning) or raise just them to Debug for a closer look.

On top of that, the 33 bot log entries which fire on a recurring per-bot
basis move from Information to Debug, so the default configuration stays
quiet: walking to a hunting ground, shopping trips, party churn, equipment
and progression milestones. The eight operator-facing events keep their
Information level - start, stop, purge, reset, account generation and the
population summary - as do all warnings and errors.

The same 500 bots now produce one log line per five minutes.
2026-08-12 15:02:21 +02:00
ze-dom
630fb6c3eb Added CopyMagicEffectValues method 2026-08-11 13:19:56 +01:00
Mr Allan Odreman
f4ac6fcdeb Address review: acknowledge respawn branch, log the duplicate, add tests
The comment implied CurrentMap is always null when this handler runs. The
IRespawnAfterDeathPlugIn branch of RespawnAtAsync is the exception: it assigns
CurrentMap and adds the player itself, so a trailing packet is redundant there
as well rather than merely duplicated.

A duplicate F3 12 is client behaviour the server cannot otherwise observe, so
it is now logged as a warning, matching how suspicious client input is handled
elsewhere in this file.

The tests cover both halves of the invariant: the player is only added to the
area of interest once, and no ghost entry survives removal from the map. Both
fail without the guard.
2026-08-10 16:56:58 -05:00
ze-dom
994c1d0ba2
Add summary documentation for ConfigureCastleSiegeRegistration 2026-08-10 21:09:00 +01:00
ze-dom
4889cac09e Merge branch 'ragefighter_master_tree_finishup' of https://github.com/ze-dom/OpenMU into ragefighter_master_tree_finishup
merging remote
2026-08-10 21:00:55 +01:00
ze-dom
5e34b9edf4 Added Claude suggestions 2026-08-10 20:54:57 +01:00
Mr Allan Odreman
443c22dbd6 Prevent duplicate map entry on repeated F3 12 packet
A repeated 'client ready after map change' (F3 12) packet re-runs
ClientReadyAfterMapChangeAsync, which adds the player and its summon to the
current map a second time.

During a regular map change CurrentMap is set to null and only reassigned in
this handler, so a non-null CurrentMap on entry means the handler already
completed for the current map change. Return early in that case.
2026-08-09 19:08:19 -05:00
Claude
4a754235e1
Extract movement, persistence, summon and storages from the player
Moves four cohesive subsystems into components which are owned by the
player, following the pattern of Walker, MagicEffectsList and
ObserverToWorldViewAdapter:

- PlayerMovement owns the walker, the move lock, the speed calculation
  and the validation of the walk requests of the client.
- PlayerPersistence owns the persistence lock, its reentrancy tracking
  and the progress save, including the documented lock invariants.
- PlayerSummon owns the summoned monster and its map handling.
- PlayerStorages owns inventory, shop, vault, temporary and backup
  storage, their creation and the restore of the temporary storage.

The public members of the player stay as they are and delegate, so no
call site changes. TemporaryStorage has no setter anymore, it was
private before and is only written by the storages component now.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V5grV5oveZNhhjK1mazM2B
2026-08-09 18:24:33 +00:00
Claude
7d75b5a426
Make map changes and the logout observable in the state machine
The declared ChangingMap state was never used and unreachable, so a warp
raised no state change at all: ClientReadyAfterMapChangeAsync advances to
EnteredWorld, which is not a possible transition of EnteredWorld itself,
so TryAdvanceToAsync just returned false.

WarpToAsync and RespawnAtAsync now advance to ChangingMap while the
client loads the map, which makes map changes observable through
IPlayerStateChangedPlugIn and cancelable through
IPlayerStateChangingPlugIn. As a consequence, the state guards of the
player actions reject actions while a map is loading.

The logout back to the character selection advances to Authenticated,
which was in no in-game state's possible transitions - it failed
silently and left the player in EnteredWorld without a selected
character. It only worked because the character list request accepts
EnteredWorld too; from an opened NPC dialog or from the dead state, the
player could not get back to the character selection at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V5grV5oveZNhhjK1mazM2B
2026-08-09 13:30:41 +00:00
sven-n
8919944d66
Merge pull request #870 from MUnique/claude/player-class-refactor-plan-aha5v2
Refactoring plan for the Player class, and its first step
2026-08-09 15:18:44 +02:00
Claude
a5e518786e
Extract pure helpers out of the Player class
First step of the refactoring plan: move logic which does not need any
private state of the player into extension classes of the same
namespace, so all call sites stay unchanged, and move the three nested
classes into their own files.

Moved to extension classes:
- messages and localization (PlayerMessageExtensions)
- money and vault money (PlayerMoneyExtensions)
- item requirements, item destruction and invalid item logging
  (PlayerItemExtensions)
- self defense queries, next to the state they read (SelfDefenseExtensions)
- the magic effect power-up creation (MagicEffectPowerUpExtensions)
- the invisibility effect (PlayerInvisibilityExtensions)

Moved to their own files: PlayerAppearanceData (formerly the nested
AppearanceDataAdapter), GameMasterMagicEffectDefinition and
TemporaryItemStorage.

TryAddMoney loses its virtual modifier - no type overrides it.

No behavior change: Player.cs shrinks by 486 lines and the only
additions to it are the two renamed type references.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V5grV5oveZNhhjK1mazM2B
2026-08-09 13:05:06 +00:00
sven-n
a7412572ce
Merge pull request #864 from eduardosmaniotto/chore/toast
chore: replace Bazored.Toast with custom Toast component
2026-08-09 14:53:57 +02:00
Claude
f869403bb9
Record the decisions on plugin deactivation and async signatures
Admins may deactivate any extracted plugin, so no "not deactivatable"
marker is introduced and the plan extracts more generously. Existing
plugin interfaces get async signatures instead of async sibling points;
IAttackableMovedPlugIn stays synchronous because it is raised from
property setters.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V5grV5oveZNhhjK1mazM2B
2026-08-09 10:47:50 +00:00
Claude
2d0cd6bee4
Reuse the player state plugin points in the refactoring plan
Instead of adding new plugin points for entering the world and changing
the map, the plan now uses the existing IPlayerStateChangedPlugIn and
IPlayerStateChangingPlugIn. Adds the state machine repair needed for
that: the declared ChangingMap state is currently unreachable, so warps
raise no state change at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V5grV5oveZNhhjK1mazM2B
2026-08-09 10:43:28 +00:00
Claude
d928319862
Add refactoring plan for the Player class
Documents how the responsibilities currently bundled in Player can be
extracted: new plugin points for game rules, component objects for
stateful subsystems, extension methods for pure helpers, plus the
infrastructure gaps (plugin ordering, per-player plugin state) that need
to be closed first.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V5grV5oveZNhhjK1mazM2B
2026-08-09 10:28:37 +00:00
ze-dom
6be9e37da3
Merge branch 'master' into ragefighter_master_tree_finishup 2026-08-07 22:18:15 +01:00
ze-dom
ba18da0c17 Applied C# analyzer suggestions 2026-08-07 22:13:12 +01:00
ze-dom
e9433cb042 Fixed aggregatetype 2026-08-07 21:53:29 +01:00
ze-dom
588b08e710 Fixed few issues 2026-08-07 20:56:05 +01:00
sven-n
5df288e907
Merge pull request #869 from Zylkien/castle-siege/725-npcs 2026-08-07 21:18:31 +02:00
Zylkien
31d76cf82b Resolve Castle Siege quality findings
Replace public monster-number constants with static read-only properties and update the corresponding switch matching. Remove the redundant namespace import while preserving the thread-safe Castle Siege player tracker.
2026-08-07 19:50:53 +02:00
Zylkien
b431a43d4d Address Castle Siege NPC review findings
Make Guardian Statue regeneration atomic, restore closed gates during mid-battle startup, and truncate movement at blocked terrain. Optimize Castle Siege player queries and broadcasts, configure structure repair costs, harden overlapping gate terrain restoration, centralize upgrade lookups, and add regression coverage.
2026-08-07 19:41:24 +02:00
Zylkien
f908adf8ef Address Castle Siege NPC quality findings
Replace public NPC number constants with static read-only properties and update the dependent matching logic.

Make Crown and switch timer callbacks task-returning and document the intentional no-op path for unspawned non-life upgrades.
2026-08-07 15:09:10 +02:00
Zylkien
ae3c9f87a8 Implement Castle Siege NPC lifecycle and management
Add Castle Siege gates, Guardian Statues, Crown, switches, levers, and battle-only machines with their runtime intelligence and event lifecycle.

Implement defense-structure purchase, repair, upgrade, persistence, packet views, validated gate operation, server-side terrain blocking, entrant synchronization, and focused regression coverage.
2026-08-07 14:48:32 +02:00
ze-dom
310a65388e Added update plugin 2026-08-07 12:38:10 +01:00
sven-n
a9732eca7c
Merge pull request #862 from Zylkien/castle-siege/723-registration
Implement Castle Siege registration and mark system
2026-08-07 08:59:51 +02:00
Zylkien
efda253106 Refine Castle Siege registration edge cases
Resolve alliance registrations directly through persistent alliance-master identities, including when the master has no online members.

Preserve customized Sign of Lord settings, tolerate configurations without the default item, document persistence-before-consumption semantics, and extend regression coverage.
2026-08-07 08:36:33 +02:00
Zylkien
875352df6b Address Castle Siege registration review
Rebase the registration flow on the merged Castle Siege packet definitions and address the review findings.

Preserve Sign of Lord items until mark persistence succeeds, expose the complete client result codes, replace guild-table scans with direct guild identity lookup, and make Sign of Lord registration configurable for new and existing databases. Add packet safeguards, plug-in metadata, documentation, migrations, and regression coverage.
2026-08-06 19:57:51 +02:00
ze-dom
b5d6d720b8 Added null default value 2026-08-06 17:41:23 +01:00
ze-dom
8115bd958d Added contingency for skill requirements with null skill entry 2026-08-06 17:35:09 +01:00
ze-dom
2768ab7ac9 Renamed stat 2026-08-06 17:17:03 +01:00
Zylkien
c45c7546b9 Implement Castle Siege registration and mark handling
Add guild and alliance registration, unregistration, registration-state queries, and Sign of Lord submission with persistence. Add B2 request handlers, client-compatible response packets and remote views, generated packet documentation, and regression tests for validation, restart recovery, inventory-slot translation, and serialization.

# Conflicts:
#	docs/Packets/ServerToClient.md
#	src/Network/Packets/ServerToClient/ConnectionExtensions.cs
#	src/Network/Packets/ServerToClient/ServerToClientPackets.cs
#	src/Network/Packets/ServerToClient/ServerToClientPackets.xml
#	src/Network/Packets/ServerToClient/ServerToClientPacketsRef.cs
2026-08-06 17:57:04 +02:00
ze-dom
141aea78a0 First commit 2026-08-06 15:52:16 +01:00
Eduardo
f8e0dc9947 replace Bazored.Toast with custom Toast component 2026-08-04 23:00:07 -03:00
sven-n
66fd5f2967
Merge pull request #863 from Zylkien/castle-siege/731-network-packets 2026-08-04 22:53:14 +02:00
Zylkien
2a2d4a6ae1 Refine Castle Siege packet definitions
Add client-verified Castle Siege packet enums, clarify tax value semantics, and normalize packet naming.

Mark unverified result semantics accordingly, regenerate packet APIs and documentation, and extend conformance tests for packed MuMain layouts and enum values.
2026-08-04 20:38:12 +02:00
Zylkien
42d997a683 Define and validate Castle Siege network packets
Add MuMain-compatible Castle Siege server-to-client packet definitions, correct gate-operation semantics, and define the Alliance removal guild name as a fixed eight-byte field. Regenerate packet structs, extensions, tests, and documentation, and add conformance tests covering sizes, offsets, endianness, and string widths.
2026-08-03 17:53:32 +02:00
sven-n
2a60ae96e1
Merge pull request #845 from Rhefew/feature/admin-log-viewer
feat(admin): live log viewer and searcher in log files page
2026-08-02 17:34:57 +02:00
sven-n
a1c4287186
Merge pull request #856 from ze-dom/summoner_master_tree_finishup
Summoner Master Tree Finishup
2026-08-02 17:27:49 +02:00
sven-n
7bd96126eb Update ServerToClientPacketTests.cs 2026-08-02 17:25:33 +02:00
sven-n
c6512d77bc
Merge pull request #861 from Zylkien/castle-siege/722-state-machine 2026-08-02 14:22:12 +02:00
Zylkien
049352e075 Harden Castle Siege persistence handling
Preserve persisted NPC states when the runtime snapshot is incomplete, update NPC rows in place, and separate loading from default-state creation. Add regression coverage for missing data, in-place updates, stale NPC removal, and incomplete snapshots.
2026-08-02 13:03:53 +02:00