Skip to content

Commit 83f18bc

Browse files
committed
Finish basic game mode support
1 parent 22b161a commit 83f18bc

File tree

14 files changed

+175
-59
lines changed

14 files changed

+175
-59
lines changed

api/lib/src/models/config.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,5 +152,6 @@ final class SetonixConfig with SetonixConfigMappable {
152152
whitelistEnabled: other.whitelistEnabled ?? whitelistEnabled,
153153
apiEndpoint: other.apiEndpoint ?? apiEndpoint,
154154
endpointSecret: other.endpointSecret ?? endpointSecret,
155+
gameMode: other.gameMode ?? gameMode,
155156
);
156157
}

api/lib/src/models/data.dart

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,19 @@ class SetonixData extends ArchiveData<SetonixData> {
3838
: identifier = identifier ?? createPackIdentifier(data),
3939
super.fromBytes();
4040

41-
factory SetonixData.fromMode(ItemLocation? location, GameMode? mode) {
41+
factory SetonixData.fromMode(
42+
PackItem<GameMode>? mode, {
43+
Set<String> packs = const {},
44+
}) {
45+
if (mode == null) return SetonixData.empty();
4246
var data = SetonixData.empty().setInfo(
4347
GameInfo(
44-
packs: [?location?.namespace],
45-
script: location,
46-
teams: mode?.teams ?? const {},
48+
packs: {...packs, mode.namespace}.toList(),
49+
gameMode: mode.location,
50+
teams: mode.item.teams,
4751
),
4852
);
49-
for (final entry
50-
in mode?.tables.entries ??
51-
Iterable<MapEntry<String, GameTable>>.empty()) {
53+
for (final entry in mode.item.tables.entries) {
5254
data = data.setTable(entry.value, entry.key);
5355
}
5456
return data;
@@ -413,6 +415,6 @@ final class PackItem<T> {
413415
String get namespace => location.namespace;
414416
String get id => location.id;
415417

416-
PackItem<E> withItem<E>(E backgroundTranslation) =>
417-
PackItem(pack: pack, location: location, item: backgroundTranslation);
418+
PackItem<E> withItem<E>(E item) =>
419+
PackItem(pack: pack, location: location, item: item);
418420
}

api/lib/src/models/info.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ part 'info.mapper.dart';
88
class GameInfo with GameInfoMappable {
99
final Map<String, GameTeam> teams;
1010
final List<String> packs;
11-
final ItemLocation? script;
11+
final ItemLocation? gameMode;
1212

13-
const GameInfo({this.teams = const {}, this.packs = const [], this.script});
13+
const GameInfo({this.teams = const {}, this.packs = const [], this.gameMode});
1414
}
1515

1616
@MappableEnum()

api/lib/src/models/info.mapper.dart

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

app/lib/bloc/world/bloc.dart

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,8 @@ class WorldBloc extends Bloc<PlayableWorldEvent, ClientWorldState> {
159159
);
160160
});
161161
if (!state.multiplayer.isClient) {
162-
_loadScript(state.world.info.script);
162+
final mode = state.world.info.gameMode;
163+
if (mode != null) _loadGameMode(mode);
163164
}
164165
}
165166

@@ -227,10 +228,20 @@ class WorldBloc extends Bloc<PlayableWorldEvent, ClientWorldState> {
227228
}
228229
}
229230

230-
Future<void> _loadScript(ItemLocation? location) async {
231+
Future<void> _loadGameMode(ItemLocation? location) async {
231232
try {
232233
if (location == null) return;
233-
pluginSystem.loadLuaPluginFromLocation(state.assetManager, location);
234+
final gameMode = state.assetManager
235+
.getPack(location.namespace)
236+
?.getMode(location.id);
237+
if (gameMode == null) return;
238+
final script = gameMode.script;
239+
if (script != null && script.isNotEmpty) {
240+
pluginSystem.loadLuaPluginFromLocation(
241+
state.assetManager,
242+
ItemLocation(location.namespace, script),
243+
);
244+
}
234245
// ignore: empty_catches
235246
} catch (e) {}
236247
}

app/pack/modes/hello.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"script": "hello.lua"
3+
}

app/pack/scripts/hello.lua

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
print("Hello from Lua script!")
2+
3+
Events.CellHideChanged.Connect(function()
4+
print("cell hide changed")
5+
end)

plugin/lib/src/plugin.dart

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,13 @@ final class PluginSystem {
3838
String name,
3939
FutureOr<SetonixPlugin> Function(PluginServerInterface) pluginBuilder,
4040
) async {
41+
unregisterPlugin(name);
4142
final pluginServer = _PluginServerInterfaceImpl(server, name);
4243
final plugin = await pluginBuilder(pluginServer);
4344
return _plugins[name] = plugin;
4445
}
4546

46-
Future<SetonixPlugin> registerLuauPlugin(
47-
String name,
48-
String code, {
49-
void Function(String)? onPrint,
50-
}) {
47+
Future<SetonixPlugin> registerLuauPlugin(String name, String code) {
5148
if (!_nativeEnabled) throw Exception('Native not enabled');
5249
return registerPlugin(
5350
name,
@@ -72,30 +69,22 @@ final class PluginSystem {
7269
.getPack(location.namespace)
7370
?.getScript(location.id);
7471
if (data == null) return;
75-
loadLuaPlugin(assetManager, data, name);
76-
}
77-
78-
void loadLuaPlugin(
79-
AssetManager assetManager,
80-
String script, [
81-
String name = 'game',
82-
]) {
83-
unregisterPlugin(name);
84-
final location = ItemLocation.fromString(script);
85-
final data = assetManager
86-
.getPack(location.namespace)
87-
?.getScript(location.id);
88-
if (data == null) return;
89-
registerLuauPlugin(name, data, onPrint: (e) => server.print(e, name));
72+
registerLuauPlugin(name, data);
9073
}
9174

9275
bool get _nativeEnabled => RustLib.instance.initialized;
9376

77+
Iterable<String> get plugins => _plugins.keys;
78+
9479
void dispose([bool disposeNative = true]) {
95-
List<String>.from(_plugins.keys).forEach(unregisterPlugin);
80+
unregisterAll();
9681
if (disposeNative) disposePluginSystem();
9782
}
9883

84+
void unregisterAll() {
85+
List<String>.from(_plugins.keys).forEach(unregisterPlugin);
86+
}
87+
9988
void fire(Event event) {
10089
for (final plugin in _plugins.values) {
10190
plugin.eventSystem.fire(event);

server/lib/src/bloc.dart

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ Future<ServerProcessed> _computeEvent(
1616
);
1717
}
1818

19+
const scriptSuffix = '.lua';
20+
1921
class WorldBloc extends Bloc<PlayableWorldEvent, WorldState>
2022
with ServerInterface {
2123
final SetonixServer server;
@@ -52,14 +54,14 @@ class WorldBloc extends Bloc<PlayableWorldEvent, WorldState>
5254
processed.responses.forEach(process);
5355
if (event is WorldInitialized) {
5456
server.log(
55-
"World initialized${(event.info?.script != null) ? " with script ${event.info?.script}" : ""}",
57+
"World initialized${(event.info?.gameMode != null) ? " with script ${event.info?.gameMode}" : ""}",
5658
level: LogLevel.info,
5759
);
5860
_serverPlugin = await _pluginSystem.registerPlugin(
5961
'',
6062
SetonixPlugin.new,
6163
);
62-
await _loadScripts((newState ?? state).info.script);
64+
await _loadScripts((newState ?? state).info.gameMode);
6365
}
6466
if (newState == null) return;
6567
emit(newState);
@@ -79,11 +81,19 @@ class WorldBloc extends Bloc<PlayableWorldEvent, WorldState>
7981
}
8082
}
8183

82-
Future<void> _loadScripts(ItemLocation? location) async {
84+
Future<void> _loadGameMode(ItemLocation location) async {
85+
final mode = assetManager.getPack(location.namespace)?.getMode(location.id);
86+
if (mode == null) return;
87+
final script = mode.script;
88+
if (script == null) return;
89+
final scriptLocation = ItemLocation.fromString(script, location.namespace);
90+
pluginSystem.loadLuaPluginFromLocation(assetManager, scriptLocation);
91+
}
92+
93+
Future<void> _loadScripts(ItemLocation? mode) async {
94+
pluginSystem.unregisterAll();
8395
try {
84-
if (location != null) {
85-
pluginSystem.loadLuaPluginFromLocation(assetManager, location);
86-
}
96+
if (mode != null) await _loadGameMode(mode);
8797
} catch (e) {
8898
server.log('Error loading script: $e', level: LogLevel.error);
8999
}
@@ -94,16 +104,19 @@ class WorldBloc extends Bloc<PlayableWorldEvent, WorldState>
94104
}
95105
final scriptFiles = (await scriptsFolder.list().toList())
96106
.whereType<File>()
97-
.where((file) => file.path.endsWith('.lua'));
107+
.where((file) => file.path.endsWith(scriptSuffix));
98108
server.log(
99109
"Found ${scriptFiles.length} script file(s)",
100110
level: LogLevel.info,
101111
);
102112
for (final file in scriptFiles) {
103113
try {
104114
final code = await file.readAsString();
105-
final relativePath = file.path.substring(scriptsFolder.path.length + 1);
106-
pluginSystem.registerLuauPlugin(relativePath, code);
115+
final relativePath = file.path.substring(
116+
scriptsFolder.path.length + 1,
117+
file.path.length - scriptSuffix.length,
118+
);
119+
await pluginSystem.registerLuauPlugin(relativePath, code);
107120
} catch (e) {
108121
server.log(
109122
'Error loading script from ${file.path}: $e',
@@ -114,7 +127,7 @@ class WorldBloc extends Bloc<PlayableWorldEvent, WorldState>
114127
}
115128

116129
Future<void> init() async {
117-
await _loadScripts(state.info.script);
130+
await _loadScripts(state.info.gameMode);
118131
}
119132

120133
Future<void> resetWorld([ItemLocation? mode]) async {
@@ -124,7 +137,7 @@ class WorldBloc extends Bloc<PlayableWorldEvent, WorldState>
124137

125138
Future<void> save({bool force = false}) async {
126139
var file = File(
127-
worldName == defaultWorldName ? 'world.stnx' : 'worlds/$worldName.stnx',
140+
'${worldName == defaultWorldName ? SetonixServer.defaultWorldName : '${SetonixServer.worldDirectory}/$worldName'}${SetonixServer.worldSuffix}',
128141
);
129142
if (!await file.exists()) {
130143
await file.create(recursive: true);

server/lib/src/config.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ class ConfigManager {
1010
SetonixConfig _argsConfig = SetonixConfig();
1111

1212
ConfigManager({SetonixConfig? argsConfig, SetonixConfig? envConfig})
13-
: _envConfig = envConfig ?? SetonixConfig.fromEnvironment();
13+
: _envConfig = (envConfig ?? SetonixConfig.fromEnvironment()).merge(
14+
argsConfig ?? SetonixConfig(),
15+
);
1416

1517
SetonixConfig _mergeConfig() {
1618
return _config.merge(_envConfig).merge(_argsConfig);

0 commit comments

Comments
 (0)