Skip to content

Commit 9f2f45e

Browse files
Add EventType enum and add values for all dragonfly events. Separate events into player_events.proto and world_events.proto (#7)
* refactor: add event types instead of string. add enum containing all events * generate proto
1 parent 14a8ef2 commit 9f2f45e

35 files changed

Lines changed: 3278 additions & 1517 deletions

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,11 @@ try {
126126
$sub = new \DF\Plugin\PluginToHost();
127127
$sub->setPluginId($pluginId);
128128
$subscribe = new \DF\Plugin\EventSubscribe();
129-
$subscribe->setEvents(['PLAYER_JOIN', 'COMMAND', 'BLOCK_BREAK']);
129+
$subscribe->setEvents([
130+
\DF\Plugin\EventType::PLAYER_JOIN,
131+
\DF\Plugin\EventType::COMMAND,
132+
\DF\Plugin\EventType::PLAYER_BLOCK_BREAK,
133+
]);
130134
$sub->setSubscribe($subscribe);
131135
$stream->write($sub);
132136
continue;
@@ -136,7 +140,7 @@ try {
136140
$event = $message->getEvent();
137141

138142
// Handle /mine command
139-
if ($event->getType() === 'COMMAND' && $event->hasCommand()) {
143+
if ($event->getType() === \DF\Plugin\EventType::COMMAND && $event->hasCommand()) {
140144
$cmd = $event->getCommand();
141145
if ($cmd->getCommand() === 'mine') {
142146
// Send message to player

docs/plugin-architecture.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,13 @@ plugins:
9797

9898
## 4. Event Routing
9999

100-
The manager sends events to plugins based on their subscriptions. Current events include:
100+
The manager sends events to plugins based on their subscriptions. Current events include values from the
101+
`EventType` enum, such as:
101102

102103
* `PLAYER_JOIN` / `PLAYER_QUIT`
103104
* `CHAT`
104105
* `COMMAND`
105-
* `BLOCK_BREAK`
106+
* `PLAYER_BLOCK_BREAK`
106107
* `WORLD_CLOSE`
107108

108109
Events carry minimal data required for action correlation (player UUID, name, coordinates). Plugins can correlate
@@ -147,7 +148,7 @@ respect Dragonfly’s threading model.
147148
* `api_version`
148149
* Optional command registrations (shown in `/help`).
149150
3. Dragonfly identifies the plugin by `plugin_id` and sends `HostHello(api_version="v1")`.
150-
4. Plugin sends `EventSubscribe` listing uppercase event names (`["PLAYER_JOIN", "COMMAND"]`).
151+
4. Plugin sends `EventSubscribe` listing `EventType` values (for example, `[EventType.PLAYER_JOIN, EventType.COMMAND]`).
151152
5. Stream enters steady state: host pushes events; plugin sends actions/logs as needed.
152153

153154
## 8. Backpressure & Fault Handling

examples/plugins/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,13 @@ Host ←→ Plugin (EventStream)
127127
128128
### 4. Example Event Types
129129
130+
Values come from the `EventType` enum:
131+
130132
- `PLAYER_JOIN` - Player connected
131133
- `PLAYER_QUIT` - Player disconnected
132134
- `CHAT` - Player sent chat message
133135
- `COMMAND` - Player executed command
134-
- `BLOCK_BREAK` - Player broke a block
136+
- `PLAYER_BLOCK_BREAK` - Player broke a block
135137
- `WORLD_CLOSE` - World is closing
136138
137139
### 5. Example Actions

examples/plugins/php/src/HelloPlugin.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Df\Plugin\CommandSpec;
1515
use Df\Plugin\EventResult;
1616
use Df\Plugin\EventSubscribe;
17+
use Df\Plugin\EventType;
1718
use Df\Plugin\PluginClient;
1819
use Df\Plugin\PluginHello;
1920
use Df\Plugin\PluginToHost;
@@ -51,7 +52,11 @@
5152
$subscribeMsg = new PluginToHost();
5253
$subscribeMsg->setPluginId($pluginId);
5354
$subscribe = new EventSubscribe();
54-
$subscribe->setEvents(['PLAYER_JOIN', 'COMMAND', 'CHAT']);
55+
$subscribe->setEvents([
56+
EventType::PLAYER_JOIN,
57+
EventType::COMMAND,
58+
EventType::CHAT,
59+
]);
5560
$subscribeMsg->setSubscribe($subscribe);
5661
$call->write($subscribeMsg);
5762

@@ -76,12 +81,12 @@
7681
$event = $message->getEvent();
7782
$eventId = $event->getEventId();
7883

79-
if ($event->getType() === 'PLAYER_JOIN' && $event->hasPlayerJoin()) {
84+
if ($event->getType() === EventType::PLAYER_JOIN && $event->hasPlayerJoin()) {
8085
acknowledgeEvent($call, $pluginId, $eventId);
8186
continue;
8287
}
8388

84-
if ($event->getType() === 'CHAT' && $event->hasChat()) {
89+
if ($event->getType() === EventType::CHAT && $event->hasChat()) {
8590
$chat = $event->getChat();
8691
$text = $chat->getMessage();
8792

@@ -101,7 +106,7 @@
101106
continue;
102107
}
103108

104-
if ($event->getType() === 'COMMAND' && $event->hasCommand()) {
109+
if ($event->getType() === EventType::COMMAND && $event->hasCommand()) {
105110
$commandEvent = $event->getCommand();
106111
if ($commandEvent->getRaw() === '/cheers') {
107112
$action = new Action();

examples/plugins/typescript/src/index.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
HostToPlugin,
77
PluginToHost,
88
GameMode,
9+
EventType,
910
} from '@dragonfly/proto';
1011

1112
const pluginId = process.env.DF_PLUGIN_ID || 'typescript-plugin';
@@ -46,7 +47,7 @@ function handleEvent(
4647
event: NonNullable<HostToPlugin['event']>
4748
) {
4849
switch (event.type) {
49-
case 'PLAYER_JOIN': {
50+
case EventType.PLAYER_JOIN: {
5051
const player = event.playerJoin;
5152
if (!player) break;
5253

@@ -72,7 +73,7 @@ function handleEvent(
7273
break;
7374
}
7475

75-
case 'PLAYER_QUIT': {
76+
case EventType.PLAYER_QUIT: {
7677
const player = event.playerQuit;
7778
if (!player) break;
7879
console.log(`[ts] player left ${player.name}`);
@@ -89,7 +90,7 @@ function handleEvent(
8990
break;
9091
}
9192

92-
case 'COMMAND': {
93+
case EventType.COMMAND: {
9394
const cmd = event.command;
9495
if (!cmd) break;
9596

@@ -228,7 +229,7 @@ function handleEvent(
228229
break;
229230
}
230231

231-
case 'CHAT': {
232+
case EventType.CHAT: {
232233
const chat = event.chat;
233234
if (!chat) break;
234235

@@ -292,7 +293,7 @@ function handleEvent(
292293
break;
293294
}
294295

295-
case 'BLOCK_BREAK': {
296+
case EventType.PLAYER_BLOCK_BREAK: {
296297
const blockBreak = event.blockBreak;
297298
if (!blockBreak) break;
298299

@@ -328,7 +329,7 @@ function handleEvent(
328329
}
329330

330331
default:
331-
console.log('[ts] unhandled event type:', event.type);
332+
console.log('[ts] unhandled event type:', EventType[event.type] ?? event.type);
332333
}
333334
}
334335

@@ -371,7 +372,13 @@ call.write(helloMessage);
371372
const initialSubscribe: PluginToHost = {
372373
pluginId,
373374
subscribe: {
374-
events: ['PLAYER_JOIN', 'PLAYER_QUIT', 'COMMAND', 'CHAT', 'BLOCK_BREAK'],
375+
events: [
376+
EventType.PLAYER_JOIN,
377+
EventType.PLAYER_QUIT,
378+
EventType.COMMAND,
379+
EventType.CHAT,
380+
EventType.PLAYER_BLOCK_BREAK,
381+
],
375382
},
376383
};
377384
call.write(initialSubscribe);

plugin/adapters/handlers/world.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func (h *WorldHandler) HandleClose(tx *world.Tx) {
2727
}
2828
evt := &pb.EventEnvelope{
2929
EventId: h.broadcaster.GenerateEventID(),
30-
Type: "WORLD_CLOSE",
30+
Type: pb.EventType_WORLD_CLOSE,
3131
Payload: &pb.EventEnvelope_WorldClose{
3232
WorldClose: &pb.WorldCloseEvent{},
3333
},

plugin/adapters/plugin/emitter.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ func (m *Emitter) detachPlayer(p *player.Player) {
220220
func (m *Emitter) EmitPlayerJoin(p *player.Player) {
221221
evt := &pb.EventEnvelope{
222222
EventId: m.generateEventID(),
223-
Type: "PLAYER_JOIN",
223+
Type: pb.EventType_PLAYER_JOIN,
224224
Payload: &pb.EventEnvelope_PlayerJoin{
225225
PlayerJoin: &pb.PlayerJoinEvent{
226226
PlayerUuid: p.UUID().String(),
@@ -234,7 +234,7 @@ func (m *Emitter) EmitPlayerJoin(p *player.Player) {
234234
func (m *Emitter) EmitPlayerQuit(p *player.Player) {
235235
evt := &pb.EventEnvelope{
236236
EventId: m.generateEventID(),
237-
Type: "PLAYER_QUIT",
237+
Type: pb.EventType_PLAYER_QUIT,
238238
Payload: &pb.EventEnvelope_PlayerQuit{
239239
PlayerQuit: &pb.PlayerQuitEvent{
240240
PlayerUuid: p.UUID().String(),
@@ -251,7 +251,7 @@ func (m *Emitter) EmitChat(ctx *player.Context, p *player.Player, msg *string) {
251251
}
252252
evt := &pb.EventEnvelope{
253253
EventId: m.generateEventID(),
254-
Type: "CHAT",
254+
Type: pb.EventType_CHAT,
255255
Payload: &pb.EventEnvelope_Chat{
256256
Chat: &pb.ChatEvent{
257257
PlayerUuid: p.UUID().String(),
@@ -285,7 +285,7 @@ func (m *Emitter) EmitCommand(ctx *player.Context, p *player.Player, cmdName str
285285
}
286286
evt := &pb.EventEnvelope{
287287
EventId: m.generateEventID(),
288-
Type: "COMMAND",
288+
Type: pb.EventType_COMMAND,
289289
Payload: &pb.EventEnvelope_Command{
290290
Command: &pb.CommandEvent{
291291
PlayerUuid: p.UUID().String(),
@@ -308,7 +308,7 @@ func (m *Emitter) EmitCommand(ctx *player.Context, p *player.Player, cmdName str
308308
func (m *Emitter) EmitBlockBreak(ctx *player.Context, p *player.Player, pos cube.Pos, drops *[]item.Stack, xp *int, worldDim string) {
309309
evt := &pb.EventEnvelope{
310310
EventId: m.generateEventID(),
311-
Type: "BLOCK_BREAK",
311+
Type: pb.EventType_PLAYER_BLOCK_BREAK,
312312
Payload: &pb.EventEnvelope_BlockBreak{
313313
BlockBreak: &pb.BlockBreakEvent{
314314
PlayerUuid: p.UUID().String(),
@@ -351,7 +351,7 @@ func (m *Emitter) dispatchEvent(envelope *pb.EventEnvelope, expectResult bool) [
351351
if envelope == nil {
352352
return nil
353353
}
354-
eventType := strings.ToUpper(envelope.Type)
354+
eventType := envelope.Type
355355
m.mu.RLock()
356356
procs := make([]*pluginProcess, 0, len(m.plugins))
357357
for _, proc := range m.plugins {
@@ -385,14 +385,14 @@ func (m *Emitter) dispatchEvent(envelope *pb.EventEnvelope, expectResult bool) [
385385
res, err := proc.waitEventResult(waitCh, eventResponseTimeout)
386386
if err != nil {
387387
if errors.Is(err, context.DeadlineExceeded) {
388-
proc.log.Warn("plugin did not respond to event", "event_id", envelope.EventId, "type", envelope.Type)
388+
proc.log.Warn("plugin did not respond to event", "event_id", envelope.EventId, "type", envelope.Type.String())
389389
}
390390
proc.discardEventResult(envelope.EventId)
391391
continue
392392
}
393393
if res != nil {
394394
results = append(results, res)
395-
if envelope.Type == "CHAT" {
395+
if envelope.Type == pb.EventType_CHAT {
396396
if chatEvt := envelope.GetChat(); chatEvt != nil {
397397
if chatMut := res.GetChat(); chatMut != nil {
398398
chatEvt.Message = chatMut.Message

plugin/adapters/plugin/process.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"log/slog"
1010
"os"
1111
"os/exec"
12-
"strings"
1312
"sync"
1413
"sync/atomic"
1514
"time"
@@ -226,25 +225,27 @@ func (p *pluginProcess) recvLoop() {
226225
}
227226
}
228227

229-
func (p *pluginProcess) HasSubscription(event string) bool {
228+
func (p *pluginProcess) HasSubscription(event pb.EventType) bool {
230229
if !p.ready.Load() {
231230
return false
232231
}
233-
if _, ok := p.subscriptions.Load("*"); ok {
232+
if _, ok := p.subscriptions.Load(pb.EventType_EVENT_TYPE_ALL); ok {
234233
return true
235234
}
236-
_, ok := p.subscriptions.Load(strings.ToUpper(event))
235+
if event == pb.EventType_EVENT_TYPE_UNSPECIFIED {
236+
return false
237+
}
238+
_, ok := p.subscriptions.Load(event)
237239
return ok
238240
}
239241

240-
func (p *pluginProcess) updateSubscriptions(events []string) {
242+
func (p *pluginProcess) updateSubscriptions(events []pb.EventType) {
241243
p.subscriptions.Range(func(key, value any) bool {
242244
p.subscriptions.Delete(key)
243245
return true
244246
})
245247
for _, evt := range events {
246-
evt = strings.ToUpper(strings.TrimSpace(evt))
247-
if evt == "" {
248+
if evt == pb.EventType_EVENT_TYPE_UNSPECIFIED {
248249
continue
249250
}
250251
p.subscriptions.Store(evt, struct{}{})

plugin/ports/ports.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type PluginManager interface {
1818
type PluginProcess interface {
1919
Start(ctx context.Context) error
2020
Stop()
21-
HasSubscription(eventType string) bool
21+
HasSubscription(eventType pb.EventType) bool
2222
Queue(msg *pb.HostToPlugin)
2323
}
2424

proto/generated/php/Df/Plugin/BlockBreakEvent.php

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)