1
- import 'dart:async' ;
2
1
import 'dart:convert' ;
3
2
import 'dart:io' ;
4
3
@@ -12,49 +11,41 @@ typedef PluginProcessCallback = void Function(String, WorldEvent, [bool force]);
12
11
typedef PluginSendEventCallback = void Function (
13
12
NetworkerPacket <PlayableWorldEvent > packet, String ? worldName);
14
13
14
+ mixin ServerInterface {
15
+ void process (WorldEvent event, {bool force = false , required String plugin});
16
+ void sendEvent (PlayableWorldEvent event,
17
+ {Channel target = kAnyChannel, required String plugin});
18
+
19
+ WorldState get state;
20
+ List <int > get players;
21
+ }
22
+
15
23
final class PluginSystem {
16
- final Map <
17
- String ,
18
- (
19
- SetonixPlugin ,
20
- StreamSubscription <ProcessMessage >,
21
- StreamSubscription <SentEvent >
22
- )> _plugins = {};
23
- final PluginProcessCallback _onProcess;
24
- final PluginSendEventCallback _onSendEvent;
25
- final WorldState Function () stateGetter;
26
- final List <int > Function () playersGetter;
24
+ final ServerInterface server;
25
+ final Map <String , SetonixPlugin > _plugins = {};
27
26
28
27
PluginSystem ({
29
- required PluginProcessCallback onProcess,
30
- required PluginSendEventCallback onSendEvent,
31
- required this .stateGetter,
32
- required this .playersGetter,
33
- }) : _onProcess = onProcess,
34
- _onSendEvent = onSendEvent;
35
-
36
- void registerPlugin (String name, SetonixPlugin plugin) {
37
- final processSub = plugin.onProcess
38
- .listen ((message) => _onProcess (name, message.event, message.force));
39
- final sendSub = plugin.onSendEvent
40
- .listen ((event) => _onSendEvent (event.event, event.worldName));
41
- _plugins[name] = (plugin, processSub, sendSub);
28
+ required this .server,
29
+ });
30
+
31
+ SetonixPlugin registerPlugin (String name,
32
+ SetonixPlugin Function (PluginServerInterface ) pluginBuilder) {
33
+ final pluginServer = _PluginServerInterfaceImpl (server, name);
34
+ final plugin = pluginBuilder (pluginServer);
35
+ return _plugins[name] = plugin;
42
36
}
43
37
44
38
SetonixPlugin registerLuauPlugin (String name, String code,
45
39
{void Function (String )? onPrint}) {
46
40
if (! _nativeEnabled) throw Exception ('Native not enabled' );
47
- final plugin = RustSetonixPlugin . build (
48
- (c) => LuauPlugin (code : code, callback : c), this );
49
- registerPlugin (name, plugin);
50
- return plugin ;
41
+ return registerPlugin (
42
+ name,
43
+ (pluginServer) => RustSetonixPlugin . build (
44
+ (c) => LuauPlugin (code : code, callback : c), pluginServer)) ;
51
45
}
52
46
53
47
void unregisterPlugin (String name) {
54
- final data = _plugins.remove (name);
55
- data? .$1.dispose ();
56
- data? .$2.cancel ();
57
- data? .$3.cancel ();
48
+ _plugins.remove (name);
58
49
}
59
50
60
51
void loadLuaPlugin (AssetManager assetManager, String script,
@@ -76,95 +67,104 @@ final class PluginSystem {
76
67
77
68
void fire (Event event) {
78
69
for (final plugin in _plugins.values) {
79
- plugin.$1. eventSystem.fire (event);
70
+ plugin.eventSystem.fire (event);
80
71
}
81
72
}
82
73
83
74
GameProperty runPing (HttpRequest request, GameProperty property) {
84
75
var result = property;
85
76
for (final plugin in _plugins.values) {
86
- result = plugin.$1. eventSystem.runPing (request, result);
77
+ result = plugin.eventSystem.runPing (request, result);
87
78
}
88
79
return result;
89
80
}
90
81
91
82
void runLeaveCallback (Channel channel, ConnectionInfo info) {
92
83
for (final plugin in _plugins.values) {
93
- plugin.$1. eventSystem.runLeaveCallback (channel, info);
84
+ plugin.eventSystem.runLeaveCallback (channel, info);
94
85
}
95
86
}
96
87
}
97
88
89
+ abstract class PluginServerInterface {
90
+ void process (WorldEvent event, {bool force = false });
91
+ void sendEvent (PlayableWorldEvent event, {Channel target = kAnyChannel});
92
+ WorldState get state;
93
+ List <int > get players;
94
+ }
95
+
96
+ class _PluginServerInterfaceImpl implements PluginServerInterface {
97
+ final ServerInterface server;
98
+ final String pluginName;
99
+
100
+ _PluginServerInterfaceImpl (this .server, this .pluginName);
101
+
102
+ @override
103
+ void process (WorldEvent event, {bool force = false }) {
104
+ server.process (event, force: force, plugin: pluginName);
105
+ }
106
+
107
+ @override
108
+ void sendEvent (PlayableWorldEvent event, {Channel target = kAnyChannel}) {
109
+ server.sendEvent (event, target: target, plugin: pluginName);
110
+ }
111
+
112
+ @override
113
+ WorldState get state => server.state;
114
+
115
+ @override
116
+ List <int > get players => server.players;
117
+ }
118
+
98
119
final class ProcessMessage {
99
120
final WorldEvent event;
100
121
final bool force;
101
122
102
123
ProcessMessage (this .event, this .force);
103
124
}
104
125
105
- final class SentEvent {
106
- final NetworkerPacket <PlayableWorldEvent > event;
107
- final String ? worldName;
108
-
109
- SentEvent (this .event, [this .worldName]);
110
- }
111
-
112
126
class SetonixPlugin {
127
+ final PluginServerInterface server;
113
128
final EventSystem eventSystem = EventSystem ();
114
- final StreamController <ProcessMessage > _onProcessController =
115
- StreamController .broadcast ();
116
- final StreamController <SentEvent > _onSendEventController =
117
- StreamController .broadcast ();
118
129
119
- Stream <ProcessMessage > get onProcess => _onProcessController.stream;
120
- Stream <SentEvent > get onSendEvent => _onSendEventController.stream;
121
-
122
- void process (WorldEvent event, {bool force = false }) =>
123
- _onProcessController.add (ProcessMessage (event, force));
124
-
125
- void sendEvent (PlayableWorldEvent event,
126
- {Channel target = kAnyChannel, String ? worldName}) =>
127
- _onSendEventController
128
- .add (SentEvent (NetworkerPacket (event, target), worldName));
130
+ SetonixPlugin (this .server);
129
131
130
132
void dispose () {
131
133
eventSystem.dispose ();
132
- _onProcessController.close ();
133
- _onSendEventController.close ();
134
134
}
135
135
}
136
136
137
137
final class RustSetonixPlugin extends SetonixPlugin {
138
138
final RustPlugin plugin;
139
139
140
- RustSetonixPlugin ._(this .plugin);
140
+ RustSetonixPlugin ._(super .server, this .plugin);
141
141
142
142
factory RustSetonixPlugin .build (
143
143
RustPlugin Function (PluginCallback ) builder,
144
- PluginSystem pluginSystem , {
144
+ PluginServerInterface server , {
145
145
void Function (String )? onPrint,
146
146
}) {
147
147
final callback = PluginCallback .default_ ();
148
148
final plugin = builder (callback);
149
- final instance = RustSetonixPlugin ._(plugin);
149
+ final instance = RustSetonixPlugin ._(server, plugin);
150
150
if (onPrint != null ) {
151
151
callback.changeOnPrint (onPrint: onPrint);
152
152
}
153
153
callback.changeProcessEvent (processEvent: (eventSerizalized, force) {
154
154
final event = WorldEventMapper .fromJson (eventSerizalized);
155
- instance .process (event, force: force ?? false );
155
+ server .process (event, force: force ?? false );
156
156
});
157
157
callback.changeSendEvent (sendEvent: (eventSerizalized, target) {
158
158
final event = PlayableWorldEventMapper .fromJson (eventSerizalized);
159
- instance .sendEvent (event, target: target ?? kAnyChannel);
159
+ server .sendEvent (event, target: target ?? kAnyChannel);
160
160
});
161
161
callback.changeStateFieldAccess (stateFieldAccess: (field) {
162
- final state = pluginSystem. stateGetter () ;
162
+ final state = server.state ;
163
163
return switch (field) {
164
164
StateFieldAccess .info => state.info.toJson (),
165
165
StateFieldAccess .table => state.table.toJson (),
166
166
StateFieldAccess .tableName => jsonEncode (state.tableName),
167
- StateFieldAccess .players => jsonEncode (pluginSystem. playersGetter () ),
167
+ StateFieldAccess .players => jsonEncode (server.players ),
168
168
StateFieldAccess .teamMembers => jsonEncode (state.teamMembers),
169
169
};
170
170
});
0 commit comments