Initial plugin registry: unreal + hello-exbyte
This commit is contained in:
9
README.md
Normal file
9
README.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Exbyte Depot — official plugin registry
|
||||||
|
|
||||||
|
`registry.json` lists official plugins for **Exbyte Depot**. The client fetches it,
|
||||||
|
shows available plugins, and installs them into the user's local plugins folder.
|
||||||
|
Plugins marked `"autoInstall": true` are installed automatically on first run
|
||||||
|
(e.g. **Unreal Engine Tools**).
|
||||||
|
|
||||||
|
Each plugin lives under `plugins/<id>/` (a `plugin.json` manifest + a JS entry).
|
||||||
|
See the app's `PLUGINS.md` for the SDK.
|
||||||
57
plugins/hello-exbyte/index.js
Normal file
57
plugins/hello-exbyte/index.js
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// Hello Exbyte — example plugin.
|
||||||
|
// A plugin is a plain ES module that exports `activate(host)`. The host is the
|
||||||
|
// only way the plugin touches the app; what it can reach is gated by the
|
||||||
|
// "permissions" in plugin.json.
|
||||||
|
|
||||||
|
export function activate(host) {
|
||||||
|
host.log("activating", host.plugin.id, "v", host.version);
|
||||||
|
|
||||||
|
// 1) A menu action (appears under the Actions menu).
|
||||||
|
host.ui.addMenuItem("Say hello 👋", () => {
|
||||||
|
const me = host.info()?.userName || "there";
|
||||||
|
host.flash(`Hello, ${me}! (from the Hello Exbyte plugin)`);
|
||||||
|
host.notify("Hello Exbyte", "The example plugin says hi.");
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2) A file context-menu item (right-click a file in Changes).
|
||||||
|
host.ui.addFileContextItem("Copy depot path (plugin)", (file) => {
|
||||||
|
if (file.depotFile) {
|
||||||
|
host.clipboard.write(file.depotFile);
|
||||||
|
host.flash("Copied: " + file.depotFile);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3) A view — a per-workspace notepad, persisted with host.storage.
|
||||||
|
// Opens from the Actions menu (listed by its title).
|
||||||
|
host.ui.addView({
|
||||||
|
id: "notes",
|
||||||
|
title: "Workspace Notes",
|
||||||
|
render: (el) => {
|
||||||
|
const key = "notes:" + (host.info()?.clientName || "default");
|
||||||
|
const ta = document.createElement("textarea");
|
||||||
|
ta.value = host.storage.get(key) || "";
|
||||||
|
ta.placeholder = "Jot notes for this workspace… (saved locally, per workspace)";
|
||||||
|
ta.style.cssText =
|
||||||
|
"width:100%;height:320px;box-sizing:border-box;resize:vertical;" +
|
||||||
|
"background:var(--input-bg,#111);color:var(--txt,#eee);" +
|
||||||
|
"border:1px solid var(--border,#333);border-radius:10px;padding:12px;" +
|
||||||
|
"font:13px/1.6 system-ui;outline:none";
|
||||||
|
ta.addEventListener("input", () => host.storage.set(key, ta.value));
|
||||||
|
el.appendChild(ta);
|
||||||
|
// optional cleanup returned to the host:
|
||||||
|
return () => host.storage.set(key, ta.value);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 4) A submit guard — blocks (with a confirm) files that look like WIP.
|
||||||
|
// This is the same hook point a reference-integrity guard would use.
|
||||||
|
host.ui.addSubmitHook((files) => {
|
||||||
|
const wip = files.filter((f) => /(^|\/)(wip|temp|scratch)[^/]*$/i.test(f.depotFile || ""));
|
||||||
|
if (wip.length) {
|
||||||
|
return { ok: false, message: `${wip.length} file(s) look like work-in-progress (wip / temp / scratch).` };
|
||||||
|
}
|
||||||
|
return { ok: true };
|
||||||
|
});
|
||||||
|
|
||||||
|
host.log("activated");
|
||||||
|
}
|
||||||
11
plugins/hello-exbyte/plugin.json
Normal file
11
plugins/hello-exbyte/plugin.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"id": "hello-exbyte",
|
||||||
|
"name": "Hello Exbyte",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"author": "Exbyte Studios",
|
||||||
|
"description": "Example plugin — a menu action, a per-workspace notes panel, a file context item, and a submit guard. Copy it as a starting point.",
|
||||||
|
"entry": "index.js",
|
||||||
|
"minAppVersion": "0.3.5",
|
||||||
|
"permissions": ["p4:read", "notify"],
|
||||||
|
"contributes": { "menu": true, "views": ["notes"], "fileContext": true, "submitHooks": true }
|
||||||
|
}
|
||||||
46
plugins/unreal/index.js
Normal file
46
plugins/unreal/index.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Unreal Engine Tools — official plugin.
|
||||||
|
// The core app keeps the build engine (UnrealBuildTool / MSBuild), the build
|
||||||
|
// overlay and the log reader; this plugin is just the Unreal-facing surface:
|
||||||
|
// a "Build Solution" action and a live Unreal-log view. Reached through the
|
||||||
|
// permission-gated `host.ue` bridge.
|
||||||
|
|
||||||
|
export function activate(host) {
|
||||||
|
const ue = host.ue;
|
||||||
|
if (!ue) { host.log("no ue bridge — plugin.json needs the \"ue\" permission"); return; }
|
||||||
|
|
||||||
|
// Build the game target (UnrealBuildTool for the game module, MSBuild for plain C++).
|
||||||
|
host.ui.addMenuItem("🔨 Build Solution (Unreal)", () => {
|
||||||
|
if (!ue.hasProject()) { host.flash("No Unreal project in the current working folder.", true); return; }
|
||||||
|
ue.build(); // triggers the core build flow + overlay
|
||||||
|
});
|
||||||
|
|
||||||
|
// Live Unreal editor log (tails Saved/Logs). Opens from the Actions menu.
|
||||||
|
host.ui.addView({
|
||||||
|
id: "unreal-log",
|
||||||
|
title: "Unreal Log",
|
||||||
|
render: (el) => {
|
||||||
|
el.style.cssText = "display:flex;flex-direction:column;height:100%;min-height:340px";
|
||||||
|
const pre = document.createElement("pre");
|
||||||
|
pre.style.cssText =
|
||||||
|
"flex:1;margin:0;overflow:auto;white-space:pre-wrap;word-break:break-word;" +
|
||||||
|
"font:11.5px/1.6 var(--mono,ui-monospace,monospace);color:var(--muted,#9a9aa8)";
|
||||||
|
el.appendChild(pre);
|
||||||
|
let alive = true;
|
||||||
|
async function tick() {
|
||||||
|
if (!alive) return;
|
||||||
|
try {
|
||||||
|
if (!ue.hasProject()) { pre.textContent = "No Unreal project in the current working folder."; return; }
|
||||||
|
const atBottom = pre.scrollTop + pre.clientHeight >= pre.scrollHeight - 30;
|
||||||
|
const txt = await ue.readLog(200000);
|
||||||
|
pre.textContent = txt || "No Unreal log yet. It appears when the editor writes to Saved/Logs (i.e. while Unreal is running).";
|
||||||
|
if (atBottom) pre.scrollTop = pre.scrollHeight;
|
||||||
|
} catch (e) { pre.textContent = String(e); }
|
||||||
|
}
|
||||||
|
tick();
|
||||||
|
const id = setInterval(tick, 1500);
|
||||||
|
return () => { alive = false; clearInterval(id); };
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
host.log("Unreal Engine Tools activated");
|
||||||
|
}
|
||||||
12
plugins/unreal/plugin.json
Normal file
12
plugins/unreal/plugin.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"id": "unreal",
|
||||||
|
"name": "Unreal Engine Tools",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"author": "Exbyte Studios",
|
||||||
|
"description": "Build the game (.sln / UnrealBuildTool) and tail the Unreal editor log. Enable this on Unreal Engine projects.",
|
||||||
|
"entry": "index.js",
|
||||||
|
"minAppVersion": "0.3.6",
|
||||||
|
"permissions": ["ue"],
|
||||||
|
"defaultEnabled": true,
|
||||||
|
"contributes": { "menu": true, "views": ["unreal-log"] }
|
||||||
|
}
|
||||||
32
registry.json
Normal file
32
registry.json
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"schema": "exbyte-depot-plugin-registry/1",
|
||||||
|
"updated": "2026-07-09",
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"id": "unreal",
|
||||||
|
"name": "Unreal Engine Tools",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"author": "Exbyte Studios",
|
||||||
|
"description": "Build the game (.sln / UnrealBuildTool) and tail the Unreal editor log. For Unreal Engine projects.",
|
||||||
|
"permissions": ["ue"],
|
||||||
|
"minAppVersion": "0.3.6",
|
||||||
|
"official": true,
|
||||||
|
"autoInstall": true,
|
||||||
|
"files": ["plugin.json", "index.js"],
|
||||||
|
"baseUrl": "https://gitea.exbytestudios.com/ExbytePublicServices/exbyte-depot-plugins/raw/branch/main/plugins/unreal/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hello-exbyte",
|
||||||
|
"name": "Hello Exbyte",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"author": "Exbyte Studios",
|
||||||
|
"description": "Example plugin — menu action, per-workspace notes, file context item, submit guard. A starting point for your own.",
|
||||||
|
"permissions": ["p4:read", "notify"],
|
||||||
|
"minAppVersion": "0.3.5",
|
||||||
|
"official": true,
|
||||||
|
"autoInstall": false,
|
||||||
|
"files": ["plugin.json", "index.js"],
|
||||||
|
"baseUrl": "https://gitea.exbytestudios.com/ExbytePublicServices/exbyte-depot-plugins/raw/branch/main/plugins/hello-exbyte/"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user