pushLevel function
Future<Map<String, Object?> >
pushLevel(
- String vmService,
- String document, {
- String? base,
- ConnectVmService connect = connectVmService,
Sends document to the game whose VM service is at vmService, to the
isolate that answers ext.flutter3d.level.apply.
With a base — the level the game is believed to be playing — what goes
first is the patch from it to document (ext.flutter3d.level.patch),
and the whole document only when the game answers that the patch is
stale, when it predates patches, or when the patch would be no shorter.
The answer then carries fellBack, the game's reason.
Throws when no isolate there has registered it: a game that never called
registerLevelExtension cannot take a level, and saying so is better
than a silence the person reads as "sent".
Implementation
Future<Map<String, Object?>> pushLevel(
String vmService,
String document, {
String? base,
ConnectVmService connect = connectVmService,
}) async {
const method = 'ext.flutter3d.level.apply';
const patchMethod = 'ext.flutter3d.level.patch';
final service = await connect(vmService);
try {
final vm = await service.getVM();
for (final ref in vm.isolates ?? const <IsolateRef>[]) {
final isolate = await service.getIsolate(ref.id!);
final rpcs = isolate.extensionRPCs ?? const <String>[];
if (!rpcs.contains(method)) continue;
final patch = base == null || !rpcs.contains(patchMethod)
? null
: levelPatchArguments(base, document);
final String? fellBack;
if (patch != null) {
try {
final response = await service.callServiceExtension(
patchMethod,
isolateId: ref.id,
args: patch,
);
return response.json ?? const <String, Object?>{};
} on RPCError catch (error) {
if (error.code != LevelPatch.staleCode) rethrow;
fellBack = error.details ?? error.message;
}
} else {
fellBack = null;
}
final response = await service.callServiceExtension(
method,
isolateId: ref.id,
args: levelApplyArguments(document),
);
return <String, Object?>{...?response.json, 'fellBack': ?fellBack};
}
throw StateError(
'the running game does not take levels: nothing registered $method',
);
} finally {
await service.dispose();
}
}