omegga 1.8.1 → 1.9.0
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/CHANGELOG.md +12 -0
- package/README.md +3 -1
- package/dist/omegga/matchers/index.js +3 -1
- package/dist/omegga/matchers/index.js.map +1 -1
- package/dist/omegga/matchers/wire.js +27 -0
- package/dist/omegga/matchers/wire.js.map +1 -0
- package/dist/omegga/server.js +112 -70
- package/dist/omegga/server.js.map +1 -1
- package/dist/plugin.js.map +1 -1
- package/dist/util/brdb.js +38 -585
- package/dist/util/brdb.js.map +1 -1
- package/dist/util/index.js +50 -3
- package/dist/util/index.js.map +1 -1
- package/dist/util/uuid.js +2 -4
- package/dist/util/uuid.js.map +1 -1
- package/package.json +3 -3
- package/templates/safe-ts/omegga.d.ts +2439 -38
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@
|
|
|
4
4
|
|
|
5
5
|
- Future features go here
|
|
6
6
|
|
|
7
|
+
## 1.9.0 - 2026-07-05
|
|
8
|
+
|
|
9
|
+
Wire graph log events and a brs-js 3.0.0 upgrade for native brdb/brz reading.
|
|
10
|
+
|
|
11
|
+
- Plugins: Add `wirelog` event, emitted for each `[Wire Graph]` console log with the raw text
|
|
12
|
+
- Plugins: Add `wirecmd:command` event, emitted when a `[Wire Graph]` log starts with a command word (lowercased) followed by space-separated args
|
|
13
|
+
- Update brs-js to 3.2.1 and expose brdb/brz features on `OMEGGA_UTIL.brdb`
|
|
14
|
+
- World revisions are now read directly from the `.brdb` file instead of the game console, so `getWorldRevisions` no longer requires the server to be running
|
|
15
|
+
- Plugins: Add `OMEGGA_UTIL.Sqlite` for opening sqlite files (or brdb files)
|
|
16
|
+
- Plugins: `loadSaveData`/`loadSaveDataOnPlayer`/`getSaveData` are back using `brs-js` 3
|
|
17
|
+
- Fix `clearRegion`, `clearAllBricks`, `loadSaveData`, `getSaveData`, in safe plugins
|
|
18
|
+
|
|
7
19
|
## 1.8.1 - 2026-07-03
|
|
8
20
|
|
|
9
21
|
Prefab support for EA3, replacing the removed `.brs` bricks commands.
|
package/README.md
CHANGED
|
@@ -891,7 +891,9 @@ Register custom `/commands` by returning `{registeredCommands: ['foo', 'bar']}`
|
|
|
891
891
|
| `event:NAME` | [>player from click<, ...args] | Runs when an interact component has `event:NAME: arg1,arg2,arg\,3, | |
|
|
892
892
|
| `mapchange` | \[{map}\] | Runs when the map changes | |
|
|
893
893
|
| `autorestart` | [autorestart config] | Runs server has an autorestart scheduled | |
|
|
894
|
-
| `minigamejoin` | {player: {name, id}; minigameName: string} | Runs when a player joins a minigame. Note that minigameName is not unique between minigames. minigameName will be null if player leaves all minigames. This will run before `join`
|
|
894
|
+
| `minigamejoin` | {player: {name, id}; minigameName: string} | **Deprecated as of EA3.** Runs when a player joins a minigame. Note that minigameName is not unique between minigames. minigameName will be null if player leaves all minigames. This will run before `join` | |
|
|
895
|
+
| `wirelog` | [raw string] | Runs when a `[Wire Graph]` log line is emitted. `raw` is the text after the `[Wire Graph] ` prefix | |
|
|
896
|
+
| `wirecmd:command` | [...args] | Runs when a `[Wire Graph]` log starts with `command args`. `command` is lowercased; args are the remaining space-separated words | |
|
|
895
897
|
|
|
896
898
|
### Folder Structure
|
|
897
899
|
|
|
@@ -11,6 +11,7 @@ const init = require("./init.js");
|
|
|
11
11
|
const mapChange = require("./mapChange.js");
|
|
12
12
|
const interact = require("./interact.js");
|
|
13
13
|
const minigameJoin = require("./minigameJoin.js");
|
|
14
|
+
const wire = require("./wire.js");
|
|
14
15
|
const MATCHERS = [
|
|
15
16
|
join.default,
|
|
16
17
|
leave.default,
|
|
@@ -22,7 +23,8 @@ const MATCHERS = [
|
|
|
22
23
|
init.default,
|
|
23
24
|
mapChange.default,
|
|
24
25
|
interact.default,
|
|
25
|
-
minigameJoin.default
|
|
26
|
+
minigameJoin.default,
|
|
27
|
+
wire.default
|
|
26
28
|
];
|
|
27
29
|
exports.default = MATCHERS;
|
|
28
30
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/omegga/matchers/index.ts"],"sourcesContent":["import { MatchGenerator } from './types';\n\nimport join from './join';\n// 'join' event => { name, id, state, controller }\n\nimport leave from './leave';\n// 'leave' event => { name, id, state, controller }\n\nimport chat from './chat';\n// 'chat' event => name, message; 'chatcmd:command' event => name, [...args]\n// 'kick' event => name, kicker, reason\n\nimport command from './command';\n// 'cmd:command' event => name, args (string)\n\nimport auth from './auth';\n// assigns host, 'host' event, 'start' event, 'unauthorized' event\n\nimport exit from './exit';\n// 'exit' event\n\nimport version from './version';\n// 'version' event, check game version\n\nimport init from './init';\n// watch loginit for any funny business\n\nimport mapChange from './mapChange';\n// 'mapchange' event\n\n// interaction event\nimport interact from './interact';\n\n// minigame join event\nimport minigameJoin from './minigameJoin';\n\nexport default [\n join,\n leave,\n chat,\n command,\n auth,\n exit,\n version,\n init,\n mapChange,\n interact,\n minigameJoin,\n] as MatchGenerator<any>[];\n"],"names":["join","leave","chat","command","auth","exit","version","init","mapChange","interact","minigameJoin"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/omegga/matchers/index.ts"],"sourcesContent":["import { MatchGenerator } from './types';\n\nimport join from './join';\n// 'join' event => { name, id, state, controller }\n\nimport leave from './leave';\n// 'leave' event => { name, id, state, controller }\n\nimport chat from './chat';\n// 'chat' event => name, message; 'chatcmd:command' event => name, [...args]\n// 'kick' event => name, kicker, reason\n\nimport command from './command';\n// 'cmd:command' event => name, args (string)\n\nimport auth from './auth';\n// assigns host, 'host' event, 'start' event, 'unauthorized' event\n\nimport exit from './exit';\n// 'exit' event\n\nimport version from './version';\n// 'version' event, check game version\n\nimport init from './init';\n// watch loginit for any funny business\n\nimport mapChange from './mapChange';\n// 'mapchange' event\n\n// interaction event\nimport interact from './interact';\n\n// minigame join event\nimport minigameJoin from './minigameJoin';\n\nimport wire from './wire';\n// 'wirelog' event => raw; 'wirecmd:command' event => [...args]\n\nexport default [\n join,\n leave,\n chat,\n command,\n auth,\n exit,\n version,\n init,\n mapChange,\n interact,\n minigameJoin,\n wire,\n] as MatchGenerator<any>[];\n"],"names":["join","leave","chat","command","auth","exit","version","init","mapChange","interact","minigameJoin","wire"],"mappings":";;;;;;;;;;;;;;AAuCA,MAAA,WAAe;AAAA,EACbA,KAAAA;AAAAA,EACAC,MAAAA;AAAAA,EACAC,KAAAA;AAAAA,EACAC,QAAAA;AAAAA,EACAC,KAAAA;AAAAA,EACAC,KAAAA;AAAAA,EACAC,QAAAA;AAAAA,EACAC,KAAAA;AAAAA,EACAC,UAAAA;AAAAA,EACAC,SAAAA;AAAAA,EACAC,aAAAA;AAAAA,EACAC,KAAAA;AACF;;"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
|
+
const wire = (omegga) => {
|
|
4
|
+
const wireRegExp = /^\[Wire Graph\] (?<raw>.*)$/;
|
|
5
|
+
return {
|
|
6
|
+
// listen for wire graph messages
|
|
7
|
+
pattern(_line, logMatch) {
|
|
8
|
+
if (!logMatch) return;
|
|
9
|
+
const { generator, data } = logMatch.groups;
|
|
10
|
+
if (generator !== "LogBrickadia") return;
|
|
11
|
+
const match = data.match(wireRegExp);
|
|
12
|
+
if (!match) return;
|
|
13
|
+
return { raw: match.groups.raw };
|
|
14
|
+
},
|
|
15
|
+
// when there's a match, emit the wire log event
|
|
16
|
+
callback({ raw }) {
|
|
17
|
+
omegga.emit("wirelog", raw);
|
|
18
|
+
const [cmd, ...args] = raw.split(" ");
|
|
19
|
+
if (cmd.length > 0) {
|
|
20
|
+
omegga.emit("wirecmd:" + cmd.toLowerCase(), ...args);
|
|
21
|
+
omegga.emit("wirecmd", cmd.toLowerCase(), ...args);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
exports.default = wire;
|
|
27
|
+
//# sourceMappingURL=wire.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wire.js","sources":["../../../src/omegga/matchers/wire.ts"],"sourcesContent":["import { MatchGenerator } from './types';\n\nconst wire: MatchGenerator<{ raw: string }> = omegga => {\n // pattern to match wire graph log messages\n // e.g. `LogBrickadia: [Wire Graph] test`\n const wireRegExp = /^\\[Wire Graph\\] (?<raw>.*)$/;\n\n return {\n // listen for wire graph messages\n pattern(_line, logMatch) {\n // line is not generic console log\n if (!logMatch) return;\n\n const { generator, data } = logMatch.groups;\n // check if log is a brickadia log\n if (generator !== 'LogBrickadia') return;\n\n // match the wire graph log pattern\n const match = data.match(wireRegExp);\n if (!match) return;\n\n return { raw: match.groups.raw };\n },\n // when there's a match, emit the wire log event\n callback({ raw }) {\n omegga.emit('wirelog', raw);\n\n // wire command parsing, emit `wirecmd:test` when `test ...` is logged\n const [cmd, ...args] = raw.split(' ');\n if (cmd.length > 0) {\n omegga.emit('wirecmd:' + cmd.toLowerCase(), ...args);\n omegga.emit('wirecmd', cmd.toLowerCase(), ...args);\n }\n },\n };\n};\n\nexport default wire;\n"],"names":[],"mappings":";;AAEA,MAAM,OAAwC,CAAA,WAAU;AAGtD,QAAM,aAAa;AAEnB,SAAO;AAAA;AAAA,IAEL,QAAQ,OAAO,UAAU;AAEvB,UAAI,CAAC,SAAU;AAEf,YAAM,EAAE,WAAW,KAAA,IAAS,SAAS;AAErC,UAAI,cAAc,eAAgB;AAGlC,YAAM,QAAQ,KAAK,MAAM,UAAU;AACnC,UAAI,CAAC,MAAO;AAEZ,aAAO,EAAE,KAAK,MAAM,OAAO,IAAA;AAAA,IAC7B;AAAA;AAAA,IAEA,SAAS,EAAE,OAAO;AAChB,aAAO,KAAK,WAAW,GAAG;AAG1B,YAAM,CAAC,KAAK,GAAG,IAAI,IAAI,IAAI,MAAM,GAAG;AACpC,UAAI,IAAI,SAAS,GAAG;AAClB,eAAO,KAAK,aAAa,IAAI,YAAA,GAAe,GAAG,IAAI;AACnD,eAAO,KAAK,WAAW,IAAI,YAAA,GAAe,GAAG,IAAI;AAAA,MACnD;AAAA,IACF;AAAA,EAAA;AAEJ;;"}
|
package/dist/omegga/server.js
CHANGED
|
@@ -4,6 +4,7 @@ const logger = require("../logger.js");
|
|
|
4
4
|
const softconfig = require("../softconfig.js");
|
|
5
5
|
const version = require("../version.js");
|
|
6
6
|
const index$2 = require("../util/index.js");
|
|
7
|
+
const brdb = require("../util/brdb.js");
|
|
7
8
|
const file = require("../util/file.js");
|
|
8
9
|
const index = require("../webserver/backend/index.js");
|
|
9
10
|
const brs = require("brs-js");
|
|
@@ -18,6 +19,25 @@ const plugin = require("./plugin.js");
|
|
|
18
19
|
const wrapper = require("./wrapper.js");
|
|
19
20
|
const MISSING_CMD = '"Command not found. Type <color=\\"ffff00\\">/help</> for a list of commands or <color=\\"ffff00\\">/plugins</> for plugin information."';
|
|
20
21
|
const WHOLE_WORLD_EXTENT = 1e9;
|
|
22
|
+
function brsRemoved(version2) {
|
|
23
|
+
return version2 > 0 && version2 >= commands.PREFAB_VERSION;
|
|
24
|
+
}
|
|
25
|
+
function warnRemoved(version2, method, since, release, replacement) {
|
|
26
|
+
if (!(version2 > 0 && version2 >= since)) return false;
|
|
27
|
+
logger.default.warnp(
|
|
28
|
+
`omegga.${method}() uses a console command removed in Brickadia ${release}. This call has no effect - use ${replacement} instead.`
|
|
29
|
+
);
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
function writeTempPrefab(omegga, saveData) {
|
|
33
|
+
const ref = omegga._tempSavePrefix + Date.now() + "_" + omegga._tempCounter.save++;
|
|
34
|
+
const file$1 = path.join(omegga.prefabPath, ref + ".brz");
|
|
35
|
+
if (!file$1.startsWith(omegga.prefabPath))
|
|
36
|
+
throw "prefab file not in Saved/Prefabs directory";
|
|
37
|
+
file.mkdir(omegga.prefabPath);
|
|
38
|
+
fs.writeFileSync(file$1, new Uint8Array(brs.writeBrzLegacy(saveData)));
|
|
39
|
+
return { ref, file: file$1 };
|
|
40
|
+
}
|
|
21
41
|
class Omegga extends wrapper.default {
|
|
22
42
|
/**
|
|
23
43
|
* Omegga instance
|
|
@@ -446,30 +466,6 @@ class Omegga extends wrapper.default {
|
|
|
446
466
|
const presetPath = path.join(this.presetPath, "Environment");
|
|
447
467
|
return fs.existsSync(presetPath) ? glob.sync(presetPath + "/**/*.bp").map((f) => path.basename(f).replace(/\.bp$/, "")) : [];
|
|
448
468
|
}
|
|
449
|
-
/**
|
|
450
|
-
* Whether the running game version has removed the legacy .brs bricks console
|
|
451
|
-
* commands (Bricks.Save/Load/ClearAll/ClearRegion, World.LoadAdditive) in
|
|
452
|
-
* favor of the prefab (`br.Prefab.*`) and world (`br.World.Clear*`) commands.
|
|
453
|
-
* Removed at Brickadia CL{@link PREFAB_VERSION}.
|
|
454
|
-
*/
|
|
455
|
-
#brsRemoved() {
|
|
456
|
-
return this.version > 0 && this.version >= commands.PREFAB_VERSION;
|
|
457
|
-
}
|
|
458
|
-
/**
|
|
459
|
-
* Warn that a method backed by a removed console command is a no-op on the
|
|
460
|
-
* running game version, and return whether the caller should bail.
|
|
461
|
-
* @param method the omegga method being called (for the message)
|
|
462
|
-
* @param since CL version the underlying command was removed at
|
|
463
|
-
* @param release human release name for that version (e.g. `EA2`, `EA3`)
|
|
464
|
-
* @param replacement suggested replacement method/API
|
|
465
|
-
*/
|
|
466
|
-
#warnRemoved(method, since, release, replacement) {
|
|
467
|
-
if (!(this.version > 0 && this.version >= since)) return false;
|
|
468
|
-
logger.default.warnp(
|
|
469
|
-
`omegga.${method}() uses a console command removed in Brickadia ${release}. This call has no effect - use ${replacement} instead.`
|
|
470
|
-
);
|
|
471
|
-
return true;
|
|
472
|
-
}
|
|
473
469
|
clearBricks(target, quiet = false) {
|
|
474
470
|
if (typeof target === "object" && target.id) target = target.id;
|
|
475
471
|
else if (typeof target === "string" && !index$2.uuid.match(target)) {
|
|
@@ -489,7 +485,7 @@ class Omegga extends wrapper.default {
|
|
|
489
485
|
}
|
|
490
486
|
const center = region.center.join(" ");
|
|
491
487
|
const extent = region.extent.join(" ");
|
|
492
|
-
if (
|
|
488
|
+
if (brsRemoved(this.version)) {
|
|
493
489
|
const bricks = options?.bricks ?? true ? 1 : 0;
|
|
494
490
|
const entities = options?.entities ?? false ? 1 : 0;
|
|
495
491
|
this.writeln(
|
|
@@ -507,7 +503,7 @@ class Omegga extends wrapper.default {
|
|
|
507
503
|
bricks = true,
|
|
508
504
|
entities = false
|
|
509
505
|
} = typeof options === "boolean" ? { quiet: options } : options;
|
|
510
|
-
if (
|
|
506
|
+
if (brsRemoved(this.version)) {
|
|
511
507
|
this.writeln(
|
|
512
508
|
`${this.Console.World.ClearAll} ${bricks ? 1 : 0} ${entities ? 1 : 0} ${quiet ? 1 : 0}`
|
|
513
509
|
);
|
|
@@ -516,7 +512,13 @@ class Omegga extends wrapper.default {
|
|
|
516
512
|
this.writeln(`${this.Console.Bricks.ClearAll} ${quiet ? 1 : ""}`);
|
|
517
513
|
}
|
|
518
514
|
saveBricks(saveName, region) {
|
|
519
|
-
if (
|
|
515
|
+
if (warnRemoved(
|
|
516
|
+
this.version,
|
|
517
|
+
"saveBricks",
|
|
518
|
+
commands.PREFAB_VERSION,
|
|
519
|
+
"EA3",
|
|
520
|
+
"savePrefab"
|
|
521
|
+
))
|
|
520
522
|
return;
|
|
521
523
|
if (!saveName) return;
|
|
522
524
|
if (!(saveName.startsWith('"') && saveName.endsWith('"')))
|
|
@@ -530,7 +532,8 @@ class Omegga extends wrapper.default {
|
|
|
530
532
|
else this.writeln(`${this.Console.Bricks.Save} ${saveName}`);
|
|
531
533
|
}
|
|
532
534
|
async saveBricksAsync(saveName, region) {
|
|
533
|
-
if (
|
|
535
|
+
if (warnRemoved(
|
|
536
|
+
this.version,
|
|
534
537
|
"saveBricksAsync",
|
|
535
538
|
commands.PREFAB_VERSION,
|
|
536
539
|
"EA3",
|
|
@@ -563,7 +566,13 @@ class Omegga extends wrapper.default {
|
|
|
563
566
|
correctPalette = false,
|
|
564
567
|
correctCustom = false
|
|
565
568
|
} = {}) {
|
|
566
|
-
if (
|
|
569
|
+
if (warnRemoved(
|
|
570
|
+
this.version,
|
|
571
|
+
"loadBricks",
|
|
572
|
+
commands.PREFAB_VERSION,
|
|
573
|
+
"EA3",
|
|
574
|
+
"loadPrefab"
|
|
575
|
+
))
|
|
567
576
|
return;
|
|
568
577
|
if (!(saveName.startsWith('"') && saveName.endsWith('"')))
|
|
569
578
|
saveName = `"${saveName}"`;
|
|
@@ -578,7 +587,8 @@ class Omegga extends wrapper.default {
|
|
|
578
587
|
correctPalette = false,
|
|
579
588
|
correctCustom = false
|
|
580
589
|
} = {}) {
|
|
581
|
-
if (
|
|
590
|
+
if (warnRemoved(
|
|
591
|
+
this.version,
|
|
582
592
|
"loadBricksOnPlayer",
|
|
583
593
|
commands.EA2_VERSION,
|
|
584
594
|
"EA2",
|
|
@@ -617,42 +627,12 @@ class Omegga extends wrapper.default {
|
|
|
617
627
|
return fs.existsSync(file2) ? file2 : void 0;
|
|
618
628
|
}
|
|
619
629
|
async getWorldRevisions(worldName) {
|
|
620
|
-
if (!this.started || this.starting || this.stopping) {
|
|
621
|
-
throw new Error("Server is not started");
|
|
622
|
-
}
|
|
623
630
|
worldName = worldName.replace(/\.brdb$/i, "");
|
|
624
|
-
|
|
631
|
+
const path2 = this.getWorldPath(worldName);
|
|
632
|
+
if (!worldName || !path2) {
|
|
625
633
|
throw new Error(`World "${worldName}" does not exist`);
|
|
626
634
|
}
|
|
627
|
-
|
|
628
|
-
const revisionsRaw = await this.watchLogChunk(
|
|
629
|
-
`${this.Console.World.ListRevisions} "${worldName}"`,
|
|
630
|
-
/^LogBRBundleManager: (There are (?<numRevisions>\d+) revisions|Revision (?<revision>\d+) - (?<date>[\d.-]+): (?<note>.+))$/,
|
|
631
|
-
{
|
|
632
|
-
last: (match) => Number(match.groups.reverse) === numRevisions,
|
|
633
|
-
first: (match) => {
|
|
634
|
-
if (match.groups?.numRevisions !== void 0) {
|
|
635
|
-
numRevisions = Number(match.groups.numRevisions);
|
|
636
|
-
return true;
|
|
637
|
-
}
|
|
638
|
-
return false;
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
);
|
|
642
|
-
if (!revisionsRaw) return [];
|
|
643
|
-
return revisionsRaw.map((match) => {
|
|
644
|
-
if (match.groups?.numRevisions !== void 0) {
|
|
645
|
-
return null;
|
|
646
|
-
}
|
|
647
|
-
const revision = match.groups.revision ? Number(match.groups.revision) : 0;
|
|
648
|
-
const dateStr = match.groups.date.replace(
|
|
649
|
-
/(\d{4})\.(\d{2})\.(\d{2})-(\d{2})\.(\d{2})\.(\d{2})/,
|
|
650
|
-
"$1-$2-$3T$4:$5:$6Z"
|
|
651
|
-
);
|
|
652
|
-
const date = new Date(dateStr);
|
|
653
|
-
const note = match.groups.note || "";
|
|
654
|
-
return { index: revision, date, note };
|
|
655
|
-
}).filter(Boolean);
|
|
635
|
+
return brdb.readBrdbRevisions(path2) ?? [];
|
|
656
636
|
}
|
|
657
637
|
async loadWorld(worldName) {
|
|
658
638
|
worldName = worldName.replace(/\.brdb$/i, "");
|
|
@@ -799,8 +779,14 @@ class Omegga extends wrapper.default {
|
|
|
799
779
|
correctPalette = false,
|
|
800
780
|
correctCustom = false
|
|
801
781
|
} = {}) {
|
|
802
|
-
if (this
|
|
782
|
+
if (brsRemoved(this.version)) {
|
|
783
|
+
const { ref, file: file2 } = writeTempPrefab(this, saveData);
|
|
784
|
+
this.loadPrefab(ref, { offX, offY, offZ });
|
|
785
|
+
setTimeout(() => {
|
|
786
|
+
if (fs.existsSync(file2)) fs.unlinkSync(file2);
|
|
787
|
+
}, 5e3);
|
|
803
788
|
return;
|
|
789
|
+
}
|
|
804
790
|
const saveFile = this._tempSavePrefix + Date.now() + "_" + this._tempCounter.save++;
|
|
805
791
|
this.writeSaveData(saveFile, saveData);
|
|
806
792
|
await this.watchLogChunk(
|
|
@@ -825,15 +811,24 @@ class Omegga extends wrapper.default {
|
|
|
825
811
|
correctPalette = false,
|
|
826
812
|
correctCustom = false
|
|
827
813
|
} = {}) {
|
|
828
|
-
|
|
814
|
+
player = typeof player === "string" ? this.getPlayer(player) : player;
|
|
815
|
+
if (!player) return;
|
|
816
|
+
if (brsRemoved(this.version)) {
|
|
817
|
+
const { ref, file: file2 } = writeTempPrefab(this, saveData);
|
|
818
|
+
this.givePrefabToPlayer(ref, player);
|
|
819
|
+
setTimeout(() => {
|
|
820
|
+
if (fs.existsSync(file2)) fs.unlinkSync(file2);
|
|
821
|
+
}, 5e3);
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
if (warnRemoved(
|
|
825
|
+
this.version,
|
|
829
826
|
"loadSaveDataOnPlayer",
|
|
830
827
|
commands.EA2_VERSION,
|
|
831
828
|
"EA2",
|
|
832
829
|
"loadPrefabOnPlayer"
|
|
833
830
|
))
|
|
834
831
|
return;
|
|
835
|
-
player = typeof player === "string" ? this.getPlayer(player) : player;
|
|
836
|
-
if (!player) return;
|
|
837
832
|
const saveFile = this._tempSavePrefix + Date.now() + "_" + this._tempCounter.save++;
|
|
838
833
|
this.writeSaveData(saveFile, saveData);
|
|
839
834
|
await this.watchLogChunk(
|
|
@@ -852,8 +847,54 @@ class Omegga extends wrapper.default {
|
|
|
852
847
|
}
|
|
853
848
|
}
|
|
854
849
|
async getSaveData(region) {
|
|
855
|
-
if (this
|
|
856
|
-
|
|
850
|
+
if (brsRemoved(this.version)) {
|
|
851
|
+
const ref = this._tempSavePrefix + Date.now() + "_" + this._tempCounter.save++;
|
|
852
|
+
const file2 = await this.savePrefabAsync(ref, { region });
|
|
853
|
+
if (!file2) return void 0;
|
|
854
|
+
try {
|
|
855
|
+
const MAIN_GRID = 1;
|
|
856
|
+
const reader = brs.WorldReader.from(new Uint8Array(fs.readFileSync(file2)));
|
|
857
|
+
const bricks = [...reader.bricks(MAIN_GRID)].map((b) => ({
|
|
858
|
+
...b,
|
|
859
|
+
physical_index: 0,
|
|
860
|
+
components: {}
|
|
861
|
+
}));
|
|
862
|
+
let brickOffset = 0;
|
|
863
|
+
for (const chunk of reader.brickChunkIndex(MAIN_GRID)) {
|
|
864
|
+
if (chunk.numComponents > 0) {
|
|
865
|
+
const { components } = reader.componentChunk(
|
|
866
|
+
MAIN_GRID,
|
|
867
|
+
chunk.index
|
|
868
|
+
);
|
|
869
|
+
for (const c of components) {
|
|
870
|
+
const brick = bricks[brickOffset + c.brickIndex];
|
|
871
|
+
if (brick) brick.components[c.typeName] = c.data ?? {};
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
brickOffset += chunk.numBricks;
|
|
875
|
+
}
|
|
876
|
+
return {
|
|
877
|
+
version: 10,
|
|
878
|
+
map: this.currentMap ?? "Unknown",
|
|
879
|
+
author: { id: this.host?.id ?? "", name: this.host?.name ?? "" },
|
|
880
|
+
host: { id: this.host?.id ?? "", name: this.host?.name ?? "" },
|
|
881
|
+
description: "",
|
|
882
|
+
brick_count: bricks.length,
|
|
883
|
+
mods: [],
|
|
884
|
+
brick_assets: reader.brickAssets(),
|
|
885
|
+
colors: [],
|
|
886
|
+
materials: reader.materials(),
|
|
887
|
+
physical_materials: [],
|
|
888
|
+
brick_owners: reader.brickOwners(),
|
|
889
|
+
game_version: this.version,
|
|
890
|
+
save_time: new Uint8Array(),
|
|
891
|
+
bricks,
|
|
892
|
+
components: {}
|
|
893
|
+
};
|
|
894
|
+
} finally {
|
|
895
|
+
if (fs.existsSync(file2)) fs.unlinkSync(file2);
|
|
896
|
+
}
|
|
897
|
+
}
|
|
857
898
|
const saveFile = this._tempSavePrefix + Date.now() + "_" + this._tempCounter.save++;
|
|
858
899
|
await this.saveBricksAsync(saveFile, region);
|
|
859
900
|
const savePath = this.getSavePath(saveFile);
|
|
@@ -881,8 +922,9 @@ class Omegga extends wrapper.default {
|
|
|
881
922
|
overrideUserId = ""
|
|
882
923
|
} = {}) {
|
|
883
924
|
if (!path2) return;
|
|
925
|
+
const rootPart = rootEntityPersistentIndex >= 0 ? ` ${rootEntityPersistentIndex} ${mirrorAxes}${overrideUserId ? ` "${overrideUserId}"` : ""}` : "";
|
|
884
926
|
this.writeln(
|
|
885
|
-
`${this.Console.Prefab.Load} "${path2}" ${offX} ${offY} ${offZ} ${atOriginalPosition ? 1 : 0} ${orientation}
|
|
927
|
+
`${this.Console.Prefab.Load} "${path2}" ${offX} ${offY} ${offZ} ${atOriginalPosition ? 1 : 0} ${orientation}${rootPart}`
|
|
886
928
|
);
|
|
887
929
|
}
|
|
888
930
|
/**
|