@crowdedkingdoms/crowdyjs 17.13.0-dev.1 → 17.14.0-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATION.md +72 -1
- package/README.md +72 -7
- package/dist/crowdy-studio/controller.d.ts +38 -11
- package/dist/crowdy-studio/controller.d.ts.map +1 -1
- package/dist/crowdy-studio/controller.js +237 -46
- package/dist/crowdy-studio/dom-shell.d.ts.map +1 -1
- package/dist/crowdy-studio/dom-shell.js +3 -1
- package/dist/crowdy-studio/embed/hud-layer.d.ts +2 -1
- package/dist/crowdy-studio/embed/hud-layer.d.ts.map +1 -1
- package/dist/crowdy-studio/embed/panel.d.ts +7 -6
- package/dist/crowdy-studio/embed/panel.d.ts.map +1 -1
- package/dist/crowdy-studio/starter-projects.d.ts +8 -0
- package/dist/crowdy-studio/starter-projects.d.ts.map +1 -1
- package/dist/crowdy-studio/starter-projects.js +79 -5
- package/dist/domains/exec.d.ts +162 -15
- package/dist/domains/exec.d.ts.map +1 -1
- package/dist/domains/exec.js +180 -18
- package/dist/domains/marketplace.d.ts +15 -3
- package/dist/domains/marketplace.d.ts.map +1 -1
- package/dist/domains/marketplace.js +17 -3
- package/dist/generated/graphql.d.ts +349 -0
- package/dist/generated/graphql.d.ts.map +1 -1
- package/dist/generated/graphql.js +17 -8
- package/dist/grid-mods/exec-client-halves.d.ts +140 -0
- package/dist/grid-mods/exec-client-halves.d.ts.map +1 -0
- package/dist/grid-mods/exec-client-halves.js +341 -0
- package/dist/grid-mods/grid-host-calls.d.ts +3 -1
- package/dist/grid-mods/grid-host-calls.d.ts.map +1 -1
- package/dist/grid-mods/grid-host-calls.js +3 -1
- package/dist/grid-mods/index.d.ts +1 -0
- package/dist/grid-mods/index.d.ts.map +1 -1
- package/dist/grid-mods/index.js +1 -0
- package/dist/grid-mods/mod-runtime.d.ts +10 -2
- package/dist/grid-mods/mod-runtime.d.ts.map +1 -1
- package/dist/grid-mods/mod-runtime.js +2 -0
- package/dist/grid-scope.d.ts +1 -0
- package/dist/grid-scope.d.ts.map +1 -1
- package/dist/grid-scope.js +1 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/kit/npcs.d.ts.map +1 -1
- package/dist/kit/social.d.ts.map +1 -1
- package/dist/live-coding/rust-analysis.js +13 -1
- package/dist/player-runtime/glue-runtime.d.ts +19 -6
- package/dist/player-runtime/glue-runtime.d.ts.map +1 -1
- package/dist/player-runtime/glue-runtime.js +40 -16
- package/dist/player-runtime/player-code-broker.d.ts +29 -0
- package/dist/player-runtime/player-code-broker.d.ts.map +1 -1
- package/dist/player-runtime/player-code-broker.js +41 -8
- package/dist/player-runtime/player-glue-worker.d.ts +2 -1
- package/dist/player-runtime/player-glue-worker.d.ts.map +1 -1
- package/dist/player-runtime/player-glue-worker.js +3 -1
- package/dist/stores/actors.d.ts +12 -2
- package/dist/stores/actors.d.ts.map +1 -1
- package/dist/stores/actors.js +43 -18
- package/dist/stores/chunks.d.ts +12 -0
- package/dist/stores/chunks.d.ts.map +1 -1
- package/dist/stores/chunks.js +112 -39
- package/dist/stores/durable.d.ts.map +1 -1
- package/dist/stores/durable.js +2 -1
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PlayerCodeBroker, } from '../player-runtime/player-code-broker.js';
|
|
2
|
+
import { CrowdyError, CrowdyGraphQLError } from '../errors.js';
|
|
2
3
|
import { digestCanonicalJson, sha256Digest, } from '../player-host/json-schema.js';
|
|
3
4
|
import { parseRustcDiagnostics } from './diagnostics.js';
|
|
4
5
|
import { githubNewRepositoryUrl, githubRepositorySlug } from './github/new-repo.js';
|
|
@@ -204,6 +205,7 @@ export class CrowdyStudioController {
|
|
|
204
205
|
...options,
|
|
205
206
|
...this.scope(),
|
|
206
207
|
...(modStarter ? { modStarter } : {}),
|
|
208
|
+
engine: this.state.serverEngine,
|
|
207
209
|
});
|
|
208
210
|
const project = await this.options.projectProvider.createProject(input);
|
|
209
211
|
this.installProject(project);
|
|
@@ -982,8 +984,10 @@ export class CrowdyStudioController {
|
|
|
982
984
|
message: `Submitting ${name}`,
|
|
983
985
|
},
|
|
984
986
|
});
|
|
985
|
-
if (
|
|
986
|
-
return
|
|
987
|
+
if (this.mods) {
|
|
988
|
+
return target === 'SERVER'
|
|
989
|
+
? this.buildMod(name, files, operation)
|
|
990
|
+
: this.buildClientHalf(name, files, operation);
|
|
987
991
|
}
|
|
988
992
|
// The server resolves the source from the project itself: the saved
|
|
989
993
|
// files at the project revision, or — for a GITHUB project — the rust at
|
|
@@ -1041,34 +1045,69 @@ export class CrowdyStudioController {
|
|
|
1041
1045
|
*/
|
|
1042
1046
|
async buildMod(name, files, operation) {
|
|
1043
1047
|
const mods = this.mods;
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1048
|
+
const problem = modNameProblem(this.requireProject());
|
|
1049
|
+
if (problem)
|
|
1050
|
+
throw new Error(problem);
|
|
1047
1051
|
const { appId, gridId } = this.scope();
|
|
1048
1052
|
const queued = await mods.modBuild(appId, {
|
|
1049
|
-
name:
|
|
1050
|
-
files: files
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
+
name: crateName(name),
|
|
1054
|
+
files: crateFiles(files),
|
|
1055
|
+
});
|
|
1056
|
+
this.checkOperation(operation);
|
|
1057
|
+
const built = await this.awaitModBuild('SERVER', name, queued.buildId, operation);
|
|
1058
|
+
if (!built)
|
|
1059
|
+
return null;
|
|
1060
|
+
const mod = await mods.modDeploy(appId, gridId, name, built.buildId);
|
|
1061
|
+
this.checkOperation(operation);
|
|
1062
|
+
return { target: 'SERVER', name, versionId: String(mod.version) };
|
|
1063
|
+
}
|
|
1064
|
+
/**
|
|
1065
|
+
* The CLIENT target as a ck-exec mod's CLIENT half: the project's `crowdy-client-sdk` crate,
|
|
1066
|
+
* built on the platform (`modClientBuild`, a build of `kind` `client`). It is attached to the
|
|
1067
|
+
* project's mod when the project runs ({@link attachClientHalf}).
|
|
1068
|
+
*/
|
|
1069
|
+
async buildClientHalf(name, files, operation) {
|
|
1070
|
+
const problem = modNameProblem(this.requireProject());
|
|
1071
|
+
if (problem)
|
|
1072
|
+
throw new Error(problem);
|
|
1073
|
+
const cargo = files.find((file) => file.path === 'Cargo.toml')?.content ?? '';
|
|
1074
|
+
if (/^\s*crowdy-compute-sdk\s*=/m.test(cargo)) {
|
|
1075
|
+
this.recordBuild('CLIENT', LEGACY_CLIENT_CRATE);
|
|
1076
|
+
this.update({
|
|
1077
|
+
runtime: {
|
|
1078
|
+
phase: 'COMPILE_FAILED',
|
|
1079
|
+
target: 'CLIENT',
|
|
1080
|
+
message: `${name} is a legacy player compute crate; a CLIENT half builds on crowdy-client-sdk`,
|
|
1081
|
+
},
|
|
1082
|
+
});
|
|
1083
|
+
return null;
|
|
1084
|
+
}
|
|
1085
|
+
const queued = await this.mods.modClientBuild(this.options.appId, {
|
|
1086
|
+
name: crateName(name),
|
|
1087
|
+
files: crateFiles(files),
|
|
1053
1088
|
});
|
|
1054
1089
|
this.checkOperation(operation);
|
|
1090
|
+
const built = await this.awaitModBuild('CLIENT', name, queued.buildId, operation);
|
|
1091
|
+
return built ? { target: 'CLIENT', name, versionId: built.buildId } : null;
|
|
1092
|
+
}
|
|
1093
|
+
/** Polls a mod build, a mod's or a CLIENT half's, recording its log; null when it did not succeed. */
|
|
1094
|
+
async awaitModBuild(target, name, buildId, operation) {
|
|
1095
|
+
const mods = this.mods;
|
|
1055
1096
|
const limit = this.options.compilePollLimit ?? 60;
|
|
1056
1097
|
const pollMs = this.options.compilePollMs ?? 1500;
|
|
1057
1098
|
for (let attempt = 0; attempt < limit; attempt++) {
|
|
1058
|
-
const b = await mods.modBuildStatus(appId,
|
|
1099
|
+
const b = await mods.modBuildStatus(this.options.appId, buildId);
|
|
1059
1100
|
this.checkOperation(operation);
|
|
1060
1101
|
if (b.status === 'succeeded') {
|
|
1061
|
-
this.recordBuild(
|
|
1062
|
-
|
|
1063
|
-
this.checkOperation(operation);
|
|
1064
|
-
return { target: 'SERVER', name, versionId: String(mod.version) };
|
|
1102
|
+
this.recordBuild(target, b.log ?? '');
|
|
1103
|
+
return b;
|
|
1065
1104
|
}
|
|
1066
1105
|
if (b.status === 'failed') {
|
|
1067
|
-
this.recordBuild(
|
|
1106
|
+
this.recordBuild(target, b.log ?? 'Compilation failed without output');
|
|
1068
1107
|
this.update({
|
|
1069
1108
|
runtime: {
|
|
1070
1109
|
phase: 'COMPILE_FAILED',
|
|
1071
|
-
target
|
|
1110
|
+
target,
|
|
1072
1111
|
message: `${name} failed to compile`,
|
|
1073
1112
|
},
|
|
1074
1113
|
});
|
|
@@ -1078,12 +1117,106 @@ export class CrowdyStudioController {
|
|
|
1078
1117
|
this.checkOperation(operation);
|
|
1079
1118
|
}
|
|
1080
1119
|
const timeout = `Compilation timed out after ${limit} polls`;
|
|
1081
|
-
this.recordBuild(
|
|
1120
|
+
this.recordBuild(target, timeout);
|
|
1082
1121
|
this.update({
|
|
1083
|
-
runtime: { phase: 'COMPILE_FAILED', target
|
|
1122
|
+
runtime: { phase: 'COMPILE_FAILED', target, message: timeout },
|
|
1084
1123
|
});
|
|
1085
1124
|
return null;
|
|
1086
1125
|
}
|
|
1126
|
+
/**
|
|
1127
|
+
* Attaches a built CLIENT half to the project's mod, consents to it as its author (the API
|
|
1128
|
+
* serves a CLIENT half only to a player who consented or trusts its author, the author too) and
|
|
1129
|
+
* fetches the served module for this browser's preview. A CLIENT-only project first makes sure
|
|
1130
|
+
* the mod it rides is the player's and switched on.
|
|
1131
|
+
*/
|
|
1132
|
+
async attachClientHalf(compiled, operation) {
|
|
1133
|
+
const mods = this.mods;
|
|
1134
|
+
const { appId, gridId } = this.scope();
|
|
1135
|
+
const project = this.requireProject();
|
|
1136
|
+
const modName = projectModName(project);
|
|
1137
|
+
if (!projectTargets(project.kind).includes('SERVER')) {
|
|
1138
|
+
await this.ensureClientOnlyMod(modName, operation);
|
|
1139
|
+
}
|
|
1140
|
+
this.update({
|
|
1141
|
+
runtime: { phase: 'ENABLING', target: 'CLIENT', message: `Attaching ${compiled.name} to ${modName}` },
|
|
1142
|
+
});
|
|
1143
|
+
const attached = await mods.modClientDeploy(appId, gridId, modName, compiled.versionId);
|
|
1144
|
+
this.checkOperation(operation);
|
|
1145
|
+
await mods.consentClientMod(appId, attached.modId, attached.capabilityHash);
|
|
1146
|
+
this.checkOperation(operation);
|
|
1147
|
+
this.recordNote('CLIENT', `Attached to mod '${modName}' as CLIENT version ${attached.clientVersion} (capabilities ` +
|
|
1148
|
+
`${attached.capabilityHash}; ticks every ${attached.tickIntervalMs} ms). Visitors of grid ` +
|
|
1149
|
+
`${gridId} run it once they consent to it or trust you; you consented to it as its author.`);
|
|
1150
|
+
let artifact;
|
|
1151
|
+
try {
|
|
1152
|
+
artifact = await mods.modClientArtifactBytes(appId, attached.modId);
|
|
1153
|
+
}
|
|
1154
|
+
catch (error) {
|
|
1155
|
+
if (error instanceof CrowdyGraphQLError && error.code === 'NOT_FOUND') {
|
|
1156
|
+
throw new CrowdyError({
|
|
1157
|
+
message: `${compiled.name} is attached to mod '${modName}', but its preview did not load: the ` +
|
|
1158
|
+
'API serves a CLIENT half only while its mod is switched on and not held, to a player ' +
|
|
1159
|
+
`with run_client_code who stands in grid ${gridId}`,
|
|
1160
|
+
cause: error,
|
|
1161
|
+
});
|
|
1162
|
+
}
|
|
1163
|
+
if (error instanceof CrowdyGraphQLError && error.code === 'RATE_LIMITED') {
|
|
1164
|
+
throw new CrowdyError({
|
|
1165
|
+
message: `${compiled.name} is attached to mod '${modName}', but its preview was fetched too ` +
|
|
1166
|
+
'often (12 a minute); deploy again in a minute',
|
|
1167
|
+
cause: error,
|
|
1168
|
+
});
|
|
1169
|
+
}
|
|
1170
|
+
throw error;
|
|
1171
|
+
}
|
|
1172
|
+
this.checkOperation(operation);
|
|
1173
|
+
if (artifact.digest !== attached.digest || artifact.clientVersion !== attached.clientVersion) {
|
|
1174
|
+
throw new Error('The served CLIENT half is not the one just attached; deploy again');
|
|
1175
|
+
}
|
|
1176
|
+
return artifact;
|
|
1177
|
+
}
|
|
1178
|
+
/**
|
|
1179
|
+
* A CLIENT half rides a mod: without a mod of this name running as the player on the grid,
|
|
1180
|
+
* the mod starter's server half is deployed under it first, and the log says so. The mod is
|
|
1181
|
+
* switched on, since only a running mod's CLIENT half is served.
|
|
1182
|
+
*/
|
|
1183
|
+
async ensureClientOnlyMod(name, operation) {
|
|
1184
|
+
const mods = this.mods;
|
|
1185
|
+
const { appId, gridId } = this.scope();
|
|
1186
|
+
const mine = (await mods.myMods(appId)).find((mod) => String(mod.gridId) === gridId && mod.name === name);
|
|
1187
|
+
this.checkOperation(operation);
|
|
1188
|
+
if (!mine) {
|
|
1189
|
+
if (!this.canTarget('SERVER', 'write') || !this.canTarget('SERVER', 'run')) {
|
|
1190
|
+
throw new Error(`A CLIENT half rides a mod, and grid ${gridId} has no mod '${name}' of yours; deploying one needs SERVER write and run permissions here`);
|
|
1191
|
+
}
|
|
1192
|
+
this.update({
|
|
1193
|
+
runtime: { phase: 'COMPILING', target: 'SERVER', message: `Deploying the mod starter as ${name}` },
|
|
1194
|
+
});
|
|
1195
|
+
const starter = await mods.modStarter(appId);
|
|
1196
|
+
this.checkOperation(operation);
|
|
1197
|
+
const queued = await mods.modBuild(appId, { name: crateName(name), files: starter.files });
|
|
1198
|
+
this.checkOperation(operation);
|
|
1199
|
+
const built = await this.awaitModBuild('SERVER', name, queued.buildId, operation);
|
|
1200
|
+
if (!built) {
|
|
1201
|
+
throw new Error(`The mod starter did not build, so the CLIENT half has no mod '${name}' to ride`);
|
|
1202
|
+
}
|
|
1203
|
+
await mods.modDeploy(appId, gridId, name, built.buildId);
|
|
1204
|
+
this.checkOperation(operation);
|
|
1205
|
+
this.recordNote('SERVER', `Grid ${gridId} had no mod '${name}' of yours, and a CLIENT half rides a mod: deployed the ` +
|
|
1206
|
+
`ck-exec mod starter (${starter.crate}) as '${name}', its server half.`);
|
|
1207
|
+
}
|
|
1208
|
+
if (!mine?.enabled) {
|
|
1209
|
+
await mods.modSetEnabled(appId, gridId, name, true);
|
|
1210
|
+
this.checkOperation(operation);
|
|
1211
|
+
if (mine)
|
|
1212
|
+
this.recordNote('SERVER', `Switched mod '${name}' on, so its CLIENT half is served.`);
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
recordNote(target, note) {
|
|
1216
|
+
this.update({
|
|
1217
|
+
buildOutput: [this.state.buildOutput, `## ${target}\n${note}`].filter(Boolean).join('\n\n'),
|
|
1218
|
+
});
|
|
1219
|
+
}
|
|
1087
1220
|
recordBuild(target, log) {
|
|
1088
1221
|
const section = `## ${target}\n${log || 'Compiled successfully.'}`;
|
|
1089
1222
|
const authoritativeDiagnostics = [
|
|
@@ -1122,28 +1255,47 @@ export class CrowdyStudioController {
|
|
|
1122
1255
|
throw new Error(`${compiled.name} compiled successfully, but run_client_code is unavailable on this grid`);
|
|
1123
1256
|
}
|
|
1124
1257
|
const runtime = this.clientRuntimeOptions();
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1258
|
+
let brokerOptions;
|
|
1259
|
+
let bytes;
|
|
1260
|
+
if (this.mods) {
|
|
1261
|
+
const half = await this.attachClientHalf(compiled, operation);
|
|
1262
|
+
bytes = half.bytes;
|
|
1263
|
+
brokerOptions = {
|
|
1264
|
+
...runtime,
|
|
1265
|
+
engine: 'ck-exec',
|
|
1266
|
+
moduleName: half.name,
|
|
1267
|
+
artifactHash: half.digest,
|
|
1268
|
+
fuelPerDispatch: half.fuelPerDispatch,
|
|
1269
|
+
consentedHostCalls: half.capabilitySummary.hostFunctions,
|
|
1270
|
+
onPresentation: this.options.onPresentation,
|
|
1271
|
+
tickIntervalMs: this.options.clientTickIntervalMs ?? half.tickIntervalMs,
|
|
1272
|
+
};
|
|
1273
|
+
}
|
|
1274
|
+
else {
|
|
1275
|
+
const artifact = await this.options.playerCompute.artifactBytes({
|
|
1276
|
+
...this.scope(),
|
|
1277
|
+
name: compiled.name,
|
|
1278
|
+
versionId: compiled.versionId,
|
|
1279
|
+
});
|
|
1280
|
+
this.checkOperation(operation);
|
|
1281
|
+
if (artifact.versionId !== compiled.versionId ||
|
|
1282
|
+
!artifact.artifactHash ||
|
|
1283
|
+
artifact.bytes.byteLength === 0) {
|
|
1284
|
+
throw new Error('Client artifact did not match the compiled project version');
|
|
1285
|
+
}
|
|
1286
|
+
bytes = artifact.bytes;
|
|
1287
|
+
brokerOptions = {
|
|
1288
|
+
...runtime,
|
|
1289
|
+
artifactHash: artifact.artifactHash,
|
|
1290
|
+
fuelPerDispatch: artifact.fuelPerDispatch,
|
|
1291
|
+
onPresentation: this.options.onPresentation,
|
|
1292
|
+
tickIntervalMs: this.options.clientTickIntervalMs ??
|
|
1293
|
+
parseClientTickIntervalMs(this.requireProject().files.find((file) => file.target === 'CLIENT' && file.path === 'Cargo.toml')?.content),
|
|
1294
|
+
};
|
|
1295
|
+
}
|
|
1144
1296
|
const broker = this.options.brokerFactory?.(brokerOptions) ??
|
|
1145
1297
|
new PlayerCodeBroker(brokerOptions);
|
|
1146
|
-
await broker.start(
|
|
1298
|
+
await broker.start(bytes);
|
|
1147
1299
|
this.checkOperation(operation);
|
|
1148
1300
|
const previous = this.broker;
|
|
1149
1301
|
this.broker = broker;
|
|
@@ -1170,10 +1322,12 @@ export class CrowdyStudioController {
|
|
|
1170
1322
|
this.broker = null;
|
|
1171
1323
|
}
|
|
1172
1324
|
}
|
|
1173
|
-
|
|
1325
|
+
// On ck-exec a CLIENT-only project's CLIENT half rides a mod too: switched off, it is no
|
|
1326
|
+
// longer served to visitors.
|
|
1327
|
+
if (projectTargets(project.kind).includes('SERVER') || this.mods) {
|
|
1174
1328
|
serverStopped = false;
|
|
1175
1329
|
try {
|
|
1176
|
-
await this.setServerEnabled(moduleNameFor(project, 'SERVER'), false);
|
|
1330
|
+
await this.setServerEnabled(this.mods ? projectModName(project) : moduleNameFor(project, 'SERVER'), false);
|
|
1177
1331
|
serverStopped = true;
|
|
1178
1332
|
}
|
|
1179
1333
|
catch (error) {
|
|
@@ -1289,12 +1443,13 @@ export class CrowdyStudioController {
|
|
|
1289
1443
|
this.update({ runs: [] });
|
|
1290
1444
|
return;
|
|
1291
1445
|
}
|
|
1292
|
-
const
|
|
1293
|
-
|
|
1446
|
+
const modName = projectModNameOrNull(this.state.project);
|
|
1447
|
+
const lines = modName
|
|
1448
|
+
? await this.mods.modLogs(this.options.appId, this.options.gridId, modName, {
|
|
1294
1449
|
limit: 50,
|
|
1295
1450
|
})
|
|
1296
1451
|
: [];
|
|
1297
|
-
this.update({ logs: lines.map((line) => modLogRow(
|
|
1452
|
+
this.update({ logs: lines.map((line) => modLogRow(modName, line)) });
|
|
1298
1453
|
return;
|
|
1299
1454
|
}
|
|
1300
1455
|
if (surface === 'runs') {
|
|
@@ -1318,10 +1473,9 @@ export class CrowdyStudioController {
|
|
|
1318
1473
|
});
|
|
1319
1474
|
return;
|
|
1320
1475
|
}
|
|
1321
|
-
// Player compute's units and compile quota
|
|
1322
|
-
const legacyUsage = !this.mods || projectTargets(this.state.project.kind).includes('CLIENT');
|
|
1476
|
+
// Player compute's units and compile quota, which nothing spends on ck-exec.
|
|
1323
1477
|
const [usage, wallet] = await Promise.all([
|
|
1324
|
-
|
|
1478
|
+
!this.mods
|
|
1325
1479
|
? this.options.playerCompute.usage({ appId: this.options.appId })
|
|
1326
1480
|
: Promise.resolve(null),
|
|
1327
1481
|
this.options.playerWallet?.balance() ?? Promise.resolve(null),
|
|
@@ -1593,6 +1747,43 @@ function isModCrateFile(path) {
|
|
|
1593
1747
|
path === 'README.md' ||
|
|
1594
1748
|
(path.startsWith('src/') && path.endsWith('.rs')));
|
|
1595
1749
|
}
|
|
1750
|
+
function crateFiles(files) {
|
|
1751
|
+
return files
|
|
1752
|
+
.filter((file) => isModCrateFile(file.path))
|
|
1753
|
+
.map((file) => ({ path: file.path, content: file.content }));
|
|
1754
|
+
}
|
|
1755
|
+
/** A build's crate name for a module: its own when it is one, else `mod-<name>`. */
|
|
1756
|
+
function crateName(name) {
|
|
1757
|
+
return CRATE_NAME.test(name) ? name : `mod-${name}`;
|
|
1758
|
+
}
|
|
1759
|
+
/**
|
|
1760
|
+
* The mod a ck-exec project runs as: its SERVER module's name, or for a CLIENT-only project the
|
|
1761
|
+
* CLIENT module's, which names the mod its CLIENT half rides.
|
|
1762
|
+
*/
|
|
1763
|
+
function projectModName(project) {
|
|
1764
|
+
return moduleNameFor(project, projectTargets(project.kind).includes('SERVER') ? 'SERVER' : 'CLIENT');
|
|
1765
|
+
}
|
|
1766
|
+
function projectModNameOrNull(project) {
|
|
1767
|
+
try {
|
|
1768
|
+
return projectModName(project);
|
|
1769
|
+
}
|
|
1770
|
+
catch {
|
|
1771
|
+
return null;
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1774
|
+
/** Why a ck-exec project's mod name cannot be a mod's, or null. */
|
|
1775
|
+
function modNameProblem(project) {
|
|
1776
|
+
const name = projectModName(project);
|
|
1777
|
+
if (MOD_NAME.test(name))
|
|
1778
|
+
return null;
|
|
1779
|
+
return projectTargets(project.kind).includes('SERVER')
|
|
1780
|
+
? `The server module name '${name}' must be 1-48 lowercase letters, digits, - or _ to run as a mod`
|
|
1781
|
+
: `The CLIENT module name '${name}' names the mod its CLIENT half rides, so it must be 1-48 lowercase letters, digits, - or _`;
|
|
1782
|
+
}
|
|
1783
|
+
const LEGACY_CLIENT_CRATE = 'This CLIENT crate depends on crowdy-compute-sdk, legacy player compute. On ck-exec a CLIENT ' +
|
|
1784
|
+
'target is a mod\u2019s CLIENT half, one crowdy-client-sdk crate: in Cargo.toml replace the ' +
|
|
1785
|
+
'crowdy-compute-sdk line with crowdy-client-sdk = "0.1.0", and in src/ use crowdy_client_sdk ' +
|
|
1786
|
+
'in place of crowdy_compute_sdk. Its host calls are the same, less the Game Model and sessions.';
|
|
1596
1787
|
function modLogRow(moduleName, line) {
|
|
1597
1788
|
const level = LOG_LEVELS[line.level] ?? 'debug';
|
|
1598
1789
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom-shell.d.ts","sourceRoot":"","sources":["../../src/crowdy-studio/dom-shell.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"dom-shell.d.ts","sourceRoot":"","sources":["../../src/crowdy-studio/dom-shell.ts"],"names":[],"mappings":"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"}
|
|
@@ -903,7 +903,9 @@ export class CrowdyStudioDomShell {
|
|
|
903
903
|
setInputUnlessFocused(this.clientModuleName, project.metadata.clientModuleName ?? '');
|
|
904
904
|
this.serverModuleName.disabled = !projectTargets(project.kind).includes('SERVER');
|
|
905
905
|
this.clientModuleName.disabled = !projectTargets(project.kind).includes('CLIENT');
|
|
906
|
-
|
|
906
|
+
// A mod has no pairing: its CLIENT half rides it.
|
|
907
|
+
this.pairing.disabled =
|
|
908
|
+
project.kind !== 'FULL_STACK' || state.serverEngine === 'ck-exec';
|
|
907
909
|
this.pairing.value = project.metadata.pairingPreference;
|
|
908
910
|
}
|
|
909
911
|
renderProblems(state) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A persistent, game-owned HUD layer for
|
|
2
|
+
* A persistent, game-owned HUD layer for CLIENT mods (ck-exec CLIENT halves
|
|
3
|
+
* and legacy player-compute CLIENT modules). A
|
|
3
4
|
* running client mod never touches the game DOM; it emits `hud_set` payloads
|
|
4
5
|
* that the broker forwards here. This layer lives outside the studio panel so
|
|
5
6
|
* a mod's HUD survives panel re-renders and keeps rendering after the coding
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hud-layer.d.ts","sourceRoot":"","sources":["../../../src/crowdy-studio/embed/hud-layer.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"hud-layer.d.ts","sourceRoot":"","sources":["../../../src/crowdy-studio/embed/hud-layer.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,oBAAoB;IACnC,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,IAAI,CAA+B;IAC3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2C;IACnE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;IAE3D,OAAO,CAAC,UAAU;IAUlB,+DAA+D;IAC/D,GAAG,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI;IAKtC,oEAAoE;IACpE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI5B,KAAK,IAAI,IAAI;IAKb;;;;OAIG;IACH,YAAY,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI;IAShE,OAAO,IAAI,IAAI;IAQf,OAAO,CAAC,MAAM;IAYd,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,SAAS;IAajB,mEAAmE;IACnE,OAAO,CAAC,QAAQ;CAQjB"}
|
|
@@ -19,7 +19,7 @@ export interface CrowdyStudioEmbedServices {
|
|
|
19
19
|
playerWallet?: CrowdyStudioPlayerWallet;
|
|
20
20
|
/** GitHub repository loop; omission hides the card. `CrowdyClient` provides it. */
|
|
21
21
|
crowdyStudioGitHub?: CrowdyStudioGitHubTransport;
|
|
22
|
-
/** ck-exec, the default
|
|
22
|
+
/** ck-exec, the default engine for both targets when present. `CrowdyClient` provides it. */
|
|
23
23
|
exec?: CrowdyStudioMods;
|
|
24
24
|
}
|
|
25
25
|
export interface CrowdyStudioEmbedTargetPermission {
|
|
@@ -70,11 +70,12 @@ export interface CrowdyStudioEmbedOptions {
|
|
|
70
70
|
*/
|
|
71
71
|
github?: CrowdyStudioGitHubTransport;
|
|
72
72
|
/**
|
|
73
|
-
* What runs the
|
|
74
|
-
* `
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
73
|
+
* What runs the project: a ck-exec mod on the grid, built from the project's `ckx-sdk`
|
|
74
|
+
* crate, with the CLIENT target as its `crowdy-client-sdk` CLIENT half (`client.exec`), or
|
|
75
|
+
* legacy player compute for both targets, which the platform is switching off. Defaults to
|
|
76
|
+
* `'ck-exec'` when the client has `exec` (every `CrowdyClient` does), else
|
|
77
|
+
* `'player-compute'`. Pass `'player-compute'` to stay on the legacy engine until 18.0
|
|
78
|
+
* removes it.
|
|
78
79
|
*/
|
|
79
80
|
serverEngine?: CrowdyStudioServerEngine;
|
|
80
81
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../../src/crowdy-studio/embed/panel.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC9B,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,KAAK,EACV,sBAAsB,EACtB,gBAAgB,EAChB,yBAAyB,EACzB,wBAAwB,EACxB,wBAAwB,EACzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,KAAK,EACV,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,EACvB,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAKL,KAAK,4BAA4B,EAClC,MAAM,WAAW,CAAC;AAEnB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAO1D,MAAM,MAAM,4BAA4B,GAAG,QAAQ,GAAG,YAAY,CAAC;AAEnE;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC,YAAY,EAAE,2BAA2B,CAAC;IAC1C,aAAa,EAAE,yBAAyB,CAAC;IACzC,YAAY,CAAC,EAAE,wBAAwB,CAAC;IACxC,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,2BAA2B,CAAC;IACjD,
|
|
1
|
+
{"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../../src/crowdy-studio/embed/panel.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CrowdyStudioServerEngine } from './controller.js';
|
|
1
2
|
import { type CreateCrowdyStudioProjectInput, type CrowdyStudioProjectKind } from './models.js';
|
|
2
3
|
/** ck-exec's mod starter crate (`client.exec.modStarter(appId)`). */
|
|
3
4
|
export interface CrowdyStudioModStarter {
|
|
@@ -19,6 +20,13 @@ export interface CrowdyStudioNewProjectOptions {
|
|
|
19
20
|
* client pairing, so a full-stack project records `NONE`.
|
|
20
21
|
*/
|
|
21
22
|
modStarter?: CrowdyStudioModStarter;
|
|
23
|
+
/**
|
|
24
|
+
* `'ck-exec'`: the project is a ck-exec mod. Its SERVER target starts from `modStarter`
|
|
25
|
+
* (required with one), its CLIENT target from a `crowdy-client-sdk` crate, the mod's CLIENT
|
|
26
|
+
* half, and both module names fit a mod's. Default `'player-compute'`, where the CLIENT target
|
|
27
|
+
* is a legacy compute SDK crate.
|
|
28
|
+
*/
|
|
29
|
+
engine?: CrowdyStudioServerEngine;
|
|
22
30
|
}
|
|
23
31
|
/** Create a compile-oriented starter without introducing a raw JSON source map. */
|
|
24
32
|
export declare function createCrowdyStudioStarterProject(options: CrowdyStudioNewProjectOptions): CreateCrowdyStudioProjectInput;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"starter-projects.d.ts","sourceRoot":"","sources":["../../src/crowdy-studio/starter-projects.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,8BAA8B,EAEnC,KAAK,uBAAuB,EAG7B,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"starter-projects.d.ts","sourceRoot":"","sources":["../../src/crowdy-studio/starter-projects.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAEL,KAAK,8BAA8B,EAEnC,KAAK,uBAAuB,EAG7B,MAAM,aAAa,CAAC;AASrB,qEAAqE;AACrE,MAAM,WAAW,sBAAsB;IACrC,sDAAsD;IACtD,KAAK,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACrD;AAED,MAAM,WAAW,6BAA6B;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,uBAAuB,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,UAAU,CAAC,EAAE,sBAAsB,CAAC;IACpC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,wBAAwB,CAAC;CACnC;AAED,mFAAmF;AACnF,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,6BAA6B,GACrC,8BAA8B,CAqChC"}
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import { projectTargets, } from './models.js';
|
|
2
2
|
const SDK_VERSION = '0.1.8';
|
|
3
|
+
/** crowdy-client-sdk, what a ck-exec mod's CLIENT half builds on; the build points it at the platform's copy. */
|
|
4
|
+
const CLIENT_SDK_VERSION = '0.1.0';
|
|
3
5
|
/** A mod's name is at most 48 characters, and the SERVER module name is `<base>-server`. */
|
|
4
6
|
const MOD_BASE_MAX = 48 - '-server'.length;
|
|
5
7
|
/** Create a compile-oriented starter without introducing a raw JSON source map. */
|
|
6
8
|
export function createCrowdyStudioStarterProject(options) {
|
|
7
9
|
const mod = options.modStarter;
|
|
8
|
-
const
|
|
10
|
+
const exec = options.engine === 'ck-exec';
|
|
9
11
|
const targets = projectTargets(options.kind);
|
|
12
|
+
if (exec && targets.includes('SERVER') && !mod) {
|
|
13
|
+
throw new Error('A ck-exec SERVER target starts from the mod starter (client.exec.modStarter)');
|
|
14
|
+
}
|
|
15
|
+
const base = mod || exec ? modModuleBase(options.name) : moduleName(options.name);
|
|
10
16
|
const metadata = {
|
|
11
17
|
name: options.name.trim() || 'Untitled mod',
|
|
12
18
|
...(options.description?.trim()
|
|
@@ -18,7 +24,7 @@ export function createCrowdyStudioStarterProject(options) {
|
|
|
18
24
|
...(targets.includes('CLIENT')
|
|
19
25
|
? { clientModuleName: `${base}-client` }
|
|
20
26
|
: {}),
|
|
21
|
-
pairingPreference: options.kind === 'FULL_STACK' && !mod ? 'REQUIRED' : 'NONE',
|
|
27
|
+
pairingPreference: options.kind === 'FULL_STACK' && !mod && !exec ? 'REQUIRED' : 'NONE',
|
|
22
28
|
};
|
|
23
29
|
return {
|
|
24
30
|
appId: options.appId,
|
|
@@ -29,9 +35,77 @@ export function createCrowdyStudioStarterProject(options) {
|
|
|
29
35
|
? mod
|
|
30
36
|
? modStarterFiles(mod, metadata.serverModuleName)
|
|
31
37
|
: starterFiles(target, metadata.serverModuleName)
|
|
32
|
-
:
|
|
38
|
+
: exec
|
|
39
|
+
? clientHalfStarterFiles(metadata.clientModuleName)
|
|
40
|
+
: starterFiles(target, metadata.clientModuleName)),
|
|
33
41
|
};
|
|
34
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* A ck-exec mod's CLIENT half: one `crowdy-client-sdk` crate within the build's rules (only
|
|
45
|
+
* `[package]`, `[lib]` as a cdylib, the SDK and serde dependencies, and
|
|
46
|
+
* `[package.metadata.crowdy] tick_interval_ms`).
|
|
47
|
+
*/
|
|
48
|
+
function clientHalfStarterFiles(name) {
|
|
49
|
+
return [
|
|
50
|
+
{
|
|
51
|
+
target: 'CLIENT',
|
|
52
|
+
path: 'Cargo.toml',
|
|
53
|
+
content: `[package]
|
|
54
|
+
name = "${name}"
|
|
55
|
+
version = "0.1.0"
|
|
56
|
+
edition = "2021"
|
|
57
|
+
|
|
58
|
+
[lib]
|
|
59
|
+
crate-type = ["cdylib"]
|
|
60
|
+
|
|
61
|
+
# How often visitors' browsers call tick (clamped 16–1000 ms).
|
|
62
|
+
# 1000 = HUD/text. 50 = physics minigames (pool). 16 = shooters, if a tick stays cheap.
|
|
63
|
+
[package.metadata.crowdy]
|
|
64
|
+
tick_interval_ms = 1000
|
|
65
|
+
|
|
66
|
+
[dependencies]
|
|
67
|
+
crowdy-client-sdk = "${CLIENT_SDK_VERSION}"
|
|
68
|
+
serde_json = "1"
|
|
69
|
+
`,
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
target: 'CLIENT',
|
|
73
|
+
path: 'src/lib.rs',
|
|
74
|
+
content: `use crowdy_client_sdk as crowdy;
|
|
75
|
+
|
|
76
|
+
fn init() {
|
|
77
|
+
// Runs once in each visitor's browser, after they consent to this CLIENT half
|
|
78
|
+
// (or trust you) and while they stand in this grid.
|
|
79
|
+
crowdy::log(1, "ready");
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
fn tick(_dt_ms: u32) {
|
|
83
|
+
// Every tick_interval_ms (Cargo.toml). The state blob lasts as long as the page's worker.
|
|
84
|
+
let ticks = u32::from_le_bytes(crowdy::state_get().try_into().unwrap_or([0; 4])).wrapping_add(1);
|
|
85
|
+
crowdy::state_set(&ticks.to_le_bytes());
|
|
86
|
+
// Host calls cross the page's broker as the visiting player, inside this grid: the HUD and
|
|
87
|
+
// overlay, chunk and actor reads, voxel writes, spatial and channel sends, grid events.
|
|
88
|
+
// Type "crowdy::api::" for the rest. The page's DOM and tokens are never reachable.
|
|
89
|
+
let _ = crowdy::api::hud_set(serde_json::json!({ "text": format!("Ticks here: {ticks}") }));
|
|
90
|
+
//
|
|
91
|
+
// Mouse (holodeck canvas only; Studio chrome is omitted). Drain every tick:
|
|
92
|
+
// let data = crowdy::api::pointer_clicks().unwrap_or(serde_json::json!({}));
|
|
93
|
+
// data["clicks"] = [{ "t": "down"|"up", "button": 0, "atMs", "heldMs", "nx", "ny" }]
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
fn invoke(payload: &[u8]) -> Vec<u8> {
|
|
97
|
+
payload.to_vec()
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
fn event(_payload: &[u8]) {
|
|
101
|
+
// Grid events from the other CLIENT halves on this page (crowdy::api::emit_event).
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
crowdy::register_module!(init: init, tick: tick, invoke: invoke, event: event);
|
|
105
|
+
`,
|
|
106
|
+
},
|
|
107
|
+
];
|
|
108
|
+
}
|
|
35
109
|
function modStarterFiles(starter, name) {
|
|
36
110
|
const paths = new Set(starter.files.map((file) => file.path));
|
|
37
111
|
if (!paths.has('Cargo.toml') || !paths.has('src/lib.rs')) {
|
|
@@ -66,8 +140,8 @@ function renamePackage(manifest, name) {
|
|
|
66
140
|
.join('\n');
|
|
67
141
|
}
|
|
68
142
|
/**
|
|
69
|
-
* A mod module base: short enough for `<base>-server` to be
|
|
70
|
-
* letter, as a build's crate names must.
|
|
143
|
+
* A mod module base: short enough for `<base>-server` and `<base>-client` to be mod names, and
|
|
144
|
+
* starting with a letter, as a build's crate names must.
|
|
71
145
|
*/
|
|
72
146
|
function modModuleBase(value) {
|
|
73
147
|
const slug = slugModuleName(value);
|