Skip to content

Commit b1fba4c

Browse files
committed
use xml format for editor actions
1 parent 3b01434 commit b1fba4c

3 files changed

Lines changed: 65 additions & 11 deletions

File tree

editor/client/ui/bottom-tabs.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,15 @@ export class BottomTabs implements InspectorUIWidget {
116116

117117
// @ts-expect-error Global
118118
(game as ClientGame).on(NewRecommendedActions, e => {
119-
if (e.plan) {
119+
if (Array.isArray(e.plan) && e.plan.length > 0) {
120120
aiSuggestionsPopup.setPlan(e.plan);
121121
recommendedActionsTab.classList.remove("hidden");
122122
loadingActionsTab.classList.add("hidden");
123+
} else if (Array.isArray(e.plan) && e.plan.length === 0) {
124+
aiSuggestionsPopup.setPlan([]);
125+
aiSuggestionsPopup.hide();
126+
recommendedActionsTab.classList.add("hidden");
127+
loadingActionsTab.classList.add("hidden");
123128
} else if (e.plan === "fail") {
124129
recommendedActionsTab.classList.add("hidden");
125130
loadingActionsTab.classList.add("hidden");

multiplayer/server-host/edit-watcher.ts

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { GameSession } from "./session.ts";
55
export async function watchForEditChanges(session: GameSession) {
66
const instance = session.parent;
77
const worldDir = instance.info.worldDirectory;
8-
const editorActionsPath = `${worldDir}/editorActions.json`;
8+
const editorActionsPath = `${worldDir}/editorActions.xml`;
99

1010
["src", "instructions"].forEach(dir =>
1111
Deno.mkdirSync(`${worldDir}/${dir}`, { recursive: true }),
@@ -43,13 +43,42 @@ export async function watchForEditChanges(session: GameSession) {
4343
if (!event.paths.includes(editorActionsPath)) continue;
4444
if (event.kind === "create" || event.kind === "modify") {
4545
await processEditorActionsFile(session, editorActionsPath);
46+
} else if (event.kind === "remove") {
47+
session.broadcastPacket({
48+
t: "EditorActions",
49+
actions: [],
50+
});
4651
}
4752
}
4853
};
4954

5055
await Promise.all([watchScriptChanges(), watchEditorActions()]);
5156
}
5257

58+
function parseEditorActionsXml(
59+
content: string,
60+
): Array<{ editDescription: string; editCode: string }> {
61+
const actions: Array<{ editDescription: string; editCode: string }> = [];
62+
const editorBlockRegex = /<editor>([\s\S]*?)<\/editor>/g;
63+
64+
let match;
65+
while ((match = editorBlockRegex.exec(content)) !== null) {
66+
const block = match[1];
67+
68+
const descMatch = /<editDescription>([\s\S]*?)<\/editDescription>/.exec(block);
69+
const codeMatch = /<editCode>([\s\S]*?)<\/editCode>/.exec(block);
70+
71+
if (descMatch && codeMatch) {
72+
actions.push({
73+
editDescription: descMatch[1].trim(),
74+
editCode: codeMatch[1].trim(),
75+
});
76+
}
77+
}
78+
79+
return actions;
80+
}
81+
5382
async function processEditorActionsFile(session: GameSession, filePath: string) {
5483
await new Promise(resolve => setTimeout(resolve, 50));
5584

@@ -58,17 +87,13 @@ async function processEditorActionsFile(session: GameSession, filePath: string)
5887
if (!stat) return;
5988

6089
const content = await Deno.readTextFile(filePath);
61-
if (!content.trim()) return;
62-
63-
const actions = JSON.parse(content);
64-
if (!Array.isArray(actions) || actions.length === 0) return;
90+
const actions = parseEditorActionsXml(content);
6591

6692
session.broadcastPacket({
6793
t: "EditorActions",
6894
actions: actions,
6995
});
7096
} catch (error) {
7197
if (error instanceof Deno.errors.NotFound) return;
72-
if (error instanceof SyntaxError && error.message.includes("JSON")) return;
7398
}
7499
}

multiplayer/server-host/web/routes/script-editing.ts

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,30 @@ export const serveScriptEditingAPI = (router: Router) => {
603603
),
604604
);
605605

606+
const parseEditorActionsXml = (
607+
content: string,
608+
): Array<{ editDescription: string; editCode: string }> => {
609+
const actions: Array<{ editDescription: string; editCode: string }> = [];
610+
const editorBlockRegex = /<editor>([\s\S]*?)<\/editor>/g;
611+
612+
let match;
613+
while ((match = editorBlockRegex.exec(content)) !== null) {
614+
const block = match[1];
615+
616+
const descMatch = /<editDescription>([\s\S]*?)<\/editDescription>/.exec(block);
617+
const codeMatch = /<editCode>([\s\S]*?)<\/editCode>/.exec(block);
618+
619+
if (descMatch && codeMatch) {
620+
actions.push({
621+
editDescription: descMatch[1].trim(),
622+
editCode: codeMatch[1].trim(),
623+
});
624+
}
625+
}
626+
627+
return actions;
628+
};
629+
606630
router.get("/api/v1/edit/:instance_id/:world_name/editor-actions", async ctx => {
607631
const worldId = `${ctx.params.instance_id}/${ctx.params.world_name}`;
608632
const instance = [...instances.values()].find(inst => inst.info.worldId === worldId);
@@ -613,12 +637,12 @@ export const serveScriptEditingAPI = (router: Router) => {
613637
return;
614638
}
615639

616-
const editorActionsPath = path.join(instance.info.worldDirectory, "editorActions.json");
640+
const editorActionsPath = path.join(instance.info.worldDirectory, "editorActions.xml");
617641

618642
try {
619643
const content = await Deno.readTextFile(editorActionsPath);
620-
const actions = JSON.parse(content);
621-
ctx.response.body = { payload: Array.isArray(actions) ? actions : [] };
644+
const actions = parseEditorActionsXml(content);
645+
ctx.response.body = { payload: actions };
622646
} catch (error) {
623647
if (error instanceof Deno.errors.NotFound) {
624648
ctx.response.body = { payload: [] };
@@ -639,7 +663,7 @@ export const serveScriptEditingAPI = (router: Router) => {
639663
return;
640664
}
641665

642-
const editorActionsPath = path.join(instance.info.worldDirectory, "editorActions.json");
666+
const editorActionsPath = path.join(instance.info.worldDirectory, "editorActions.xml");
643667

644668
try {
645669
await Deno.remove(editorActionsPath);

0 commit comments

Comments
 (0)