Skip to content

Commit 1d3315f

Browse files
committed
docs: Update README.md
1 parent 4c270aa commit 1d3315f

File tree

2 files changed

+162
-61
lines changed

2 files changed

+162
-61
lines changed

README.md

Lines changed: 75 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ handles the rest.
3030
**What it does:**
3131

3232
- Automatically creates and destroys sessions on player join/quit (for lifecycle sessions)
33-
- Routes PMMP events to the correct player's session using `#[SessionEventHandler]` attributes — no listener classes to write
33+
- Routes PMMP events to the correct player's session using `#[SessionEventHandler]` attributes — no listener classes to
34+
write
3435
- Supports ordered session progression via `SessionSequence` for multi-step flows like tutorials
3536
- Prevents duplicate PMMP listener registration across multiple session types via a global registry
3637
- Provides a generic, type-safe `SessionManager<T>` for clean plugin architecture
@@ -76,11 +77,15 @@ class SessionManager~T extends Session~ {
7677
-array sessions
7778
-list eventBindingList
7879
+getSession(playerOrId) T?
80+
+getSessionOrThrow(playerOrId) T
81+
+getOrCreateSession(player) T?
7982
+createSession(player, ...args) T?
8083
+getAllSessions() list~T~
8184
+removeSession(session, reason) void
8285
+terminateAll(reason) int
8386
+getSessionClass() class-string
87+
+onSessionCreated(callback) self
88+
+onSessionTerminated(callback) self
8489
}
8590
8691
class SequenceSessionManager {
@@ -112,13 +117,21 @@ class SessionEventListener {
112117
+hasDispatchers() bool
113118
}
114119
115-
class SessionEventDispatcher {
116-
+SessionManager sessionManager
120+
class BaseSessionEventDispatcher {
121+
<<abstract>>
122+
+string eventKey
117123
+string eventClass
118124
+int priority
119125
+bool handleCancelled
120126
+string methodName
121-
+string eventKey
127+
+dispatch(event, player) void
128+
}
129+
130+
class SessionMethodDispatcher {
131+
+dispatch(event, player) void
132+
}
133+
134+
class ManagerMethodDispatcher {
122135
+dispatch(event, player) void
123136
}
124137
@@ -137,8 +150,10 @@ SequenceSessionManager --> SequenceSession : manages
137150
SessionManager --> Session : manages
138151
SessionManager --> SessionEventListenerRegistry : registers via
139152
SessionEventListenerRegistry --> SessionEventListener : owns one per eventKey
140-
SessionEventListener --> SessionEventDispatcher : dispatches to
141-
SessionEventDispatcher ..> SessionEventHandler : created from
153+
SessionEventListener --> BaseSessionEventDispatcher : dispatches to
154+
BaseSessionEventDispatcher <|-- SessionMethodDispatcher
155+
BaseSessionEventDispatcher <|-- ManagerMethodDispatcher
156+
SessionMethodDispatcher ..> SessionEventHandler : created from
142157
```
143158

144159
### Event flow
@@ -147,9 +162,9 @@ SessionEventDispatcher ..> SessionEventHandler : created from
147162
PMMP fires event
148163
→ SessionEventListener::onEvent()
149164
→ [cancelled mid-dispatch? stop if handleCancelled=false]
150-
SessionEventDispatcher::dispatch()
151-
→ SessionManager::getSession(player)
152-
Session::{methodName}(event)
165+
BaseSessionEventDispatcher::dispatch()
166+
├─ SessionMethodDispatcher → SessionManager::getSession(player) → Session::{methodName}(event)
167+
└─ ManagerMethodDispatcherSessionManager::{methodName}(event)
153168
```
154169

155170
---
@@ -197,9 +212,17 @@ All session classes passed to `SessionSequence` must extend `SequenceSession` an
197212

198213
Central orchestrator for one session type. On construction:
199214

200-
1. Scans the session class for `#[SessionEventHandler]` attributes
201-
2. Registers the resulting dispatchers with `SessionEventListenerRegistry`
202-
3. Registers join/quit lifecycle listeners (if `LifecycleSession`)
215+
1. Collects lifecycle dispatchers for `PlayerJoinEvent` / `PlayerQuitEvent` (if `LifecycleSession`)
216+
2. Scans the session class for `#[SessionEventHandler]` attributes
217+
3. Registers all collected dispatchers with `SessionEventListenerRegistry`
218+
219+
**Key methods:**
220+
221+
- `getSession(Player|int)` — Returns the active session or null.
222+
- `getSessionOrThrow(Player|int)` — Returns the active session or throws if none exists.
223+
- `getOrCreateSession(Player)` — Returns the active session or creates one if none exists.
224+
- `onSessionCreated(Closure)` — Registers a callback invoked after a session is created and started.
225+
- `onSessionTerminated(Closure)` — Registers a callback invoked after a session is terminated and removed.
203226

204227
### `#[SessionEventHandler]` (attribute)
205228

@@ -208,18 +231,24 @@ events. The method must be `public` and accept exactly one non-nullable `Event`
208231

209232
### `SessionEventListenerRegistry` (singleton)
210233

211-
Ensures only one PMMP listener exists per unique `(eventClass, priority, handleCancelled)` combination — the **eventKey**.
212-
Multiple session types subscribing to the same event share a single PMMP listener.
234+
Ensures only one PMMP listener exists per unique `(eventClass, priority, handleCancelled)` combination — the **eventKey
235+
**.
236+
Multiple session types subscribing to the same event share a single PMMP listener. This applies to both
237+
session event handlers and lifecycle events (`PlayerJoinEvent`, `PlayerQuitEvent`).
213238

214239
### `SessionEventListener` (class)
215240

216-
The actual PMMP-registered listener for one eventKey. Holds a list of `SessionEventDispatcher` instances and routes
217-
each fired event to the correct player's session. Respects cancellation state mid-dispatch.
241+
The actual PMMP-registered listener for one eventKey. Holds a list of `BaseSessionEventDispatcher` instances and routes
242+
each fired event to them in registration order. Respects cancellation state mid-dispatch.
243+
244+
### `BaseSessionEventDispatcher` (abstract class)
218245

219-
### `SessionEventDispatcher` (class)
246+
Base class for all event dispatchers. Holds the listener configuration (`eventKey`, `eventClass`, `priority`,
247+
`handleCancelled`, `methodName`) and defines the `dispatch()` contract. Two concrete subclasses are provided:
220248

221-
Represents one `#[SessionEventHandler]` binding. Holds its event configuration (`eventKey`), the target
222-
`SessionManager`, and the method name to invoke. Called by `SessionEventListener` on each event.
249+
- `SessionMethodDispatcher` — Looks up the player's active session and invokes the bound method on it.
250+
- `ManagerMethodDispatcher` — Invokes the bound method directly on the `SessionManager` instance. Used internally for
251+
lifecycle event handling.
223252

224253
### `SessionTerminateReasons` (interface)
225254

@@ -240,11 +269,14 @@ src/kim/present/utils/session/
240269
├── SessionSequence.php
241270
├── SessionTerminateReasons.php
242271
└── listener/
243-
├── SessionEventDispatcher.php
244272
├── SessionEventListener.php
245273
├── SessionEventListenerRegistry.php
246-
└── attribute/
247-
└── SessionEventHandler.php
274+
├── attribute/
275+
│ └── SessionEventHandler.php
276+
└── dispatcher/
277+
├── BaseSessionEventDispatcher.php
278+
├── SessionMethodDispatcher.php
279+
└── ManagerMethodDispatcher.php
248280
```
249281

250282
---
@@ -309,6 +341,14 @@ final class MyPlugin extends PluginBase{
309341

310342
protected function onEnable() : void{
311343
$this->sessionManager = new SessionManager($this, WorldEditSession::class);
344+
345+
$this->sessionManager
346+
->onSessionCreated(function(WorldEditSession $session) : void{
347+
// e.g. log session start
348+
})
349+
->onSessionTerminated(function(WorldEditSession $session, string $reason) : void{
350+
// e.g. persist state to DB
351+
});
312352
}
313353

314354
protected function onDisable() : void{
@@ -323,9 +363,15 @@ final class MyPlugin extends PluginBase{
323363
// Create a session on demand (for non-lifecycle sessions)
324364
$session = $this->sessionManager->createSession($player);
325365

326-
// Retrieve a session
366+
// Retrieve a session (returns null if none exists)
327367
$session = $this->sessionManager->getSession($player);
328368

369+
// Retrieve a session or throw if none exists
370+
$session = $this->sessionManager->getSessionOrThrow($player);
371+
372+
// Retrieve a session or create one if none exists
373+
$session = $this->sessionManager->getOrCreateSession($player);
374+
329375
// Remove a specific session
330376
$this->sessionManager->removeSession($player, SessionTerminateReasons::MANUAL);
331377

@@ -458,9 +504,15 @@ Distributed under the **MIT License**. See [LICENSE][license-url] for more infor
458504
---
459505

460506
[poggit-ci-badge]: https://poggit.pmmp.io/ci.shield/presentkim-pm/session-utils/session-utils?style=for-the-badge
507+
461508
[stars-badge]: https://img.shields.io/github/stars/presentkim-pm/session-utils.svg?style=for-the-badge
509+
462510
[license-badge]: https://img.shields.io/github/license/presentkim-pm/session-utils.svg?style=for-the-badge
511+
463512
[poggit-ci-url]: https://poggit.pmmp.io/ci/presentkim-pm/session-utils/session-utils
513+
464514
[stars-url]: https://github.com/presentkim-pm/session-utils/stargazers
515+
465516
[issues-url]: https://github.com/presentkim-pm/session-utils/issues
517+
466518
[license-url]: https://github.com/presentkim-pm/session-utils/blob/main/LICENSE

0 commit comments

Comments
 (0)