WaterBlock tiling to match T2/Torque, improve CLAUDE.md

This commit is contained in:
Brian Beck 2025-12-11 22:07:29 -08:00
parent bcf4f4a1a5
commit aeda3ca8d5
940 changed files with 1207 additions and 337 deletions

View file

@ -75,18 +75,32 @@ export interface RunServerResult {
export function runServer(options: RunServerOptions): RunServerResult {
const { missionName, missionType, runtimeOptions, onMissionLoadDone } =
options;
const { signal, fileSystem } = runtimeOptions ?? {};
const {
signal,
fileSystem,
globals = {},
preloadScripts = [],
} = runtimeOptions ?? {};
// server.cs has a loop that calls `findFirstFile("scripts/*Game.cs")` and
// runs `exec()` on each resulting glob match. Since we can't statically
// analyze dynamic exec paths, we need to preload all game scripts in the same
// way (so they're available when exec() is called). We could assume that we
// only need some (like DefaultGame.cs and the one for our game type), but
// sometimes map authors bundle a custom script that they don't exec() in the
// .mis file, instead preferring to give it a "*Game.cs" name so it's loaded
// automatically.
const gameScripts = fileSystem.findFiles("scripts/*Game.cs");
const runtime = createRuntime({
...runtimeOptions,
globals: {
...runtimeOptions?.globals,
...globals,
"$Host::Map": missionName,
"$Host::MissionType": missionType,
},
preloadScripts: [...preloadScripts, ...gameScripts],
});
const gameTypeName = `${missionType}Game`;
const gameTypeScript = `scripts/${gameTypeName}.cs`;
const ready = (async function createServer() {
try {
@ -94,29 +108,6 @@ export function runServer(options: RunServerOptions): RunServerResult {
const serverScript = await runtime.loadFromPath("scripts/server.cs");
signal?.throwIfAborted();
// server.cs has a glob loop that does: findFirstFile("scripts/*Game.cs")
// and then exec()s each result dynamically. Since we can't statically
// analyze dynamic exec paths, we need to either preload all game scripts
// in the same way (so they're available when exec() is called) or just
// exec() the ones we know we need...
//
// To load them all, do:
// if (fileSystem) {
// const gameScripts = fileSystem.findFiles("scripts/*Game.cs");
// await Promise.all(
// gameScripts.map((path) => runtime.loadFromPath(path)),
// );
// signal?.throwIfAborted();
// }
await runtime.loadFromPath("scripts/DefaultGame.cs");
signal?.throwIfAborted();
try {
await runtime.loadFromPath(gameTypeScript);
} catch (err) {
// It's OK if that one fails. Not every game type needs its own script.
}
signal?.throwIfAborted();
// Also preload the mission file (another dynamic exec path)
await runtime.loadFromPath(`missions/${missionName}.mis`);
signal?.throwIfAborted();