安装python3.12及以上
rust
bash
sudo pacman -S curl base-devel git go-task nodejs npm pnpm unzip openssh wget jq
cargo install magoo
bash
rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
rustup target add wasm32-unknown-unknown --toolchain nightly
bash
curl -fsSL https://bun.sh/install | bash
source /home/Nightmare/.bash_profile
bash
git clone https://github.com/Pistonite/botw-ist.git --depth 1
bash
sudo pacman -Syu --needed base-devel cmake zlib
git clone https://github.com/Pistonight/symbotw.git
cd symbotw/
bash
nano packages/uking-relocate/Cargo.toml
替换
yoml
[dependencies.cu]
git = "https://github.com/Pistonight/cu"
package = "pistonite-cu"
features = ["cli", "fs"]
bash
cargo build --release -p uking-relocate
bash
sudo pacman -Syu ninja cmake ccache xdelta3 clang openssl pkgconf
修改taskfile.yml
yml
- task: itemsys-build:bsource
packages/blueflame-deps/scripts/gen-actors.ts
typescript
import { ActorDataMap } from "../../itemsys/src/generated/actor_data_map.ts"
import { getActorParam, getItemTypeAndUse, PouchItemType, PouchItemUse } from "../../itemsys/src/data"
packages/app/vite.config.ts
typescript
/// <reference types="vitest" />
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import { spawnSync } from "child_process";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import path from "path";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import fs from "fs";
import { type Plugin, defineConfig, type UserConfig } from "vite";
import serveStatic from "vite-plugin-serve-static";
import intwc from "@pistonite/vite-plugin-intwc";
import monodev from "mono-dev/vite";
import { createWriteStream } from "fs";
import { pipeline } from "stream";
import { promisify } from "util";
import { request } from "https";
const pipelineAsync = promisify(pipeline);
const downloadMissingAssets = (): Plugin => {
return {
name: "download-missing-assets",
apply: "serve",
configureServer(server) {
server.middlewares.use(async (req, _, next) => {
if (req.url?.startsWith("/static/itemsys/")) {
const filePath = req.url.replace("/static/itemsys/", "");
const localPath = path.join("..", "itemsys-build", "public", filePath);
// 检查本地文件是否存在
if (!fs.existsSync(localPath)) {
console.log(`File ${localPath} not found, downloading from remote...`);
try {
// 确保目录存在
const dir = path.dirname(localPath);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
// 从远程下载文件
const remoteUrl = `https://ist.pistonite.app/static/itemsys/${filePath}`;
console.log(`Downloading from: ${remoteUrl}`);
await new Promise((resolve, reject) => {
const req = request(remoteUrl, (res) => {
if (res.statusCode === 200) {
const writeStream = createWriteStream(localPath);
pipelineAsync(res, writeStream)
.then(() => {
console.log(`Successfully downloaded: ${filePath}`);
resolve({ success: true });
})
.catch(reject);
} else {
reject(
new Error(
`HTTP ${res.statusCode}: ${res.statusMessage}`,
),
);
}
});
req.on("error", reject);
req.end();
});
} catch (error) {
console.error(`Failed to download ${filePath}:`, error);
}
}
}
next();
});
},
};
};
const staticAssetHeader = (): Plugin => {
return {
name: "static-asset-header",
apply: "serve",
configureServer(server) {
server.middlewares.use((req, res, next) => {
if (req.url?.startsWith("/runtime/")) {
res.setHeader("Cross-Origin-Embedder-Policy", "require-corp");
res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
}
next();
});
},
};
};
// https://vitejs.dev/config/
export default defineConfig(({ command }) => {
const commit = spawnSync("git", ["rev-parse", "HEAD"], {
encoding: "utf-8",
}).stdout.trim();
console.log(`commit: ${commit}`);
const packageJson = JSON.parse(fs.readFileSync("../../package.json", "utf-8"));
const version = packageJson.version;
console.log(`version: ${version}`);
const monodevConfig = monodev({
https: command === "serve",
});
return monodevConfig<UserConfig>({
define: {
"import.meta.env.COMMIT": JSON.stringify(commit),
"import.meta.env.VERSION": JSON.stringify(version),
"import.meta.vitest": "undefined",
},
plugins: [
intwc({ basicLanguages: [] }),
staticAssetHeader(),
downloadMissingAssets(),
serveStatic([
{
pattern: /^\/runtime\/(.*)/,
resolve: ([_, capture]) => path.join("..", "runtime-wasm", "dist", capture),
},
{
pattern: /^\/static\/itemsys\/(.*)/,
resolve: ([_, capture]) => path.join("..", "itemsys-build", "public", capture),
},
]),
],
resolve: {
dedupe: ["botw-item-assets"],
},
server: {
port: 23172,
headers: {
"Cross-Origin-Embedder-Policy": "require-corp",
"Cross-Origin-Opener-Policy": "same-origin",
},
},
build: {
rollupOptions: {
input: {
index: "index.html",
popout: "popout.html",
},
},
},
test: {
includeSource: ["src/**/*.{js,ts}"],
environment: "jsdom",
},
});
});
packages/runtime-wasm/Taskfile.yml
yml
version: '3'
includes:
ecma:
taskfile: ../mono-dev/task/ecma.yaml
internal: true
cargo:
taskfile: ../mono-dev/task/cargo.yaml
internal: true
tasks:
build:
desc: Run wasm-bindgen and build the dev dist package
cmds:
- task: build-wasm
- task: build-dist
build-wasm-types:
cmds:
- $(which mkdir) -p node_modules/.wasm-out-type
- wasm-pack build -t no-modules --no-pack --no-opt --out-dir node_modules/.wasm-out-type
build-wasm:
cmds:
- task: cargo:wasm-pack-build
vars:
TARGET_DIR: ../../target
PACKAGE: skybook_runtime_wasm
WASM_PACK_ARGS: -t no-modules --no-pack
- $(which mkdir) -p node_modules/.wasm-out-type
- cp pkg/skybook_runtime_wasm.d.ts node_modules/.wasm-out-type
clean-dist:
cmds:
- rm -rf dist
build-dist:
vars:
BUILD_DIR: dist
SKYBOOK_JS: "{{.BUILD_DIR}}/skybook.js"
WORKER_JS: "{{.BUILD_DIR}}/worker.js"
SKYBOOK_WASM: "{{.BUILD_DIR}}/skybook.wasm"
cmds:
- $(which mkdir) -p {{.BUILD_DIR}}
- cp pkg/skybook_runtime_wasm_bg.wasm {{.SKYBOOK_WASM}}
- cp pkg/skybook_runtime_wasm.js {{.SKYBOOK_JS}}
- cmd: >
echo 'bundling worker';
cp pkg/skybook_runtime_wasm.js {{.WORKER_JS}};
echo 'self["__skybook_path_base"]="/runtime/skybook";' >> {{.WORKER_JS}};
echo 'self["__min"]=false;' >> {{.WORKER_JS}};
bun build src/main.ts >> {{.WORKER_JS}};
silent: true
build-dist-min:
desc: Clean and build the minified production package
vars:
BUILD_DIR: dist
COMMIT_SHORT:
sh: git rev-parse HEAD | cut -c1-8
SKYBOOK_MIN_JS: "{{.BUILD_DIR}}/skybook-{{.COMMIT_SHORT}}.min.js"
WORKER_MIN_JS: "{{.BUILD_DIR}}/worker-{{.COMMIT_SHORT}}.min.js"
SKYBOOK_WASM: "{{.BUILD_DIR}}/skybook-{{.COMMIT_SHORT}}.wasm"
cmds:
- $(which mkdir) -p {{.BUILD_DIR}}
- cp pkg/skybook_runtime_wasm_bg.wasm {{.SKYBOOK_WASM}}
- cmd: >
echo 'minifying wasm_bindgen module';
echo 'let wasm_bindgen;(function(){function __export(x){wasm_bindgen=x;};' > {{.SKYBOOK_MIN_JS}};
cp pkg/skybook_runtime_wasm.js {{.WORKER_MIN_JS}};
echo '__export(wasm_bindgen)' >> {{.WORKER_MIN_JS}};
bun build --minify {{.WORKER_MIN_JS}} >> {{.SKYBOOK_MIN_JS}};
echo '})();' >> {{.SKYBOOK_MIN_JS}};
silent: true
- cmd: >
echo 'bundling minified worker';
cp {{.SKYBOOK_MIN_JS}} {{.WORKER_MIN_JS}};
echo 'self["__skybook_path_base"]="/runtime/skybook-{{.COMMIT_SHORT}}";' >> {{.WORKER_MIN_JS}};
echo 'self["__min"]=true;' >> {{.WORKER_MIN_JS}};
bun build --minify src/main.ts >> {{.WORKER_MIN_JS}};
silent: true
check:
cmds:
- task: build-wasm-types
- task: cargo:clippy-all
- task: cargo:fmt-check
- task: ecma:mono-check
check-ts:
- task: ecma:mono-check
fix:
cmds:
- task: cargo:fmt-fix
- task: ecma:mono-fix
pull-dist:
desc: Download Runtime WASM for local development
vars:
ORIGIN: https://ist.pistonite.app
COMMIT:
sh: curl {{.ORIGIN}}/commit | cut -c1-8
cmds:
- $(which mkdir) -p dist
- wget -O dist/worker.js {{.ORIGIN}}/runtime/worker-{{.COMMIT}}.min.js
- wget -O dist/skybook.js {{.ORIGIN}}/runtime/skybook-{{.COMMIT}}.min.js
- wget -O dist/skybook.wasm {{.ORIGIN}}/runtime/skybook-{{.COMMIT}}.wasm
- cp dist/worker.js dist/worker-{{.COMMIT}}.min.js
- cp dist/skybook.js dist/skybook-{{.COMMIT}}.min.js
- cp dist/skybook.wasm dist/skybook-{{.COMMIT}}.wasm
clean:
desc: Clean the wasm artifacts that might help resolve build issues
cmds:
- rm -rf dist pkg