Atmosphäre-Tools, EZ-Tree-Fixes, i18n, AnimSet, Baum-Export

- blight-lang: TextResolver + EN/DE Sprachpakete (TextReference i18n)
- AnimSet: Clips + ActionMap in .animset.json zusammengeführt
- EZ-Tree: Branch-Parameter-Fixes (length/radius/children/force nicht senden,
  twist Grad→Radiant, leaves.size ×5); Ordner-ComboBox mit Auto-Refresh
- Logging beim Baum-Export in allen drei Generatoren (EZ-Tree, Blight, Palme)
- Atmosphäre-Tools: Emitter, Licht, Wasser, Sound-/Musikbereiche, Spiel-Starten
- AnimPreviewState, RetargetingSystem, AnimationLibrary (Animations-Editor)
- Terrain-Transparenz-Fix, Schatten-Fix, ThirdPersonCamera-Fix
- DayNightState, WeatherState, CloudsNode, JmeConsole
- MapIO v6, neue blight-common Modell-Klassen (GameCharacter, NPC, Quests…)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-02 23:12:46 +02:00
parent 1e0789461f
commit 50f496c864
121 changed files with 13277 additions and 806 deletions

1
tools/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
node_modules/

21
tools/dom_polyfill.cjs Normal file
View File

@@ -0,0 +1,21 @@
// Minimal DOM polyfill so Three.js TextureLoader doesn't crash in Node.js
global.document = {
createElementNS: (ns, name) => ({
style: {},
addEventListener: () => {},
removeEventListener: () => {},
dispatchEvent: () => {},
src: '',
onload: null,
onerror: null
}),
createElement: (name) => ({
style: {},
addEventListener: () => {},
removeEventListener: () => {},
src: '',
onload: null,
onerror: null
})
};
global.window = global;

123
tools/ez_tree_generate.mjs Normal file
View File

@@ -0,0 +1,123 @@
/**
* Headless ez-tree geometry generator.
* Usage: node --require ./dom_polyfill.cjs ez_tree_generate.mjs '<JSON>'
*
* Input JSON: { preset: "Oak Medium", params: { seed, type, bark, branch, leaves, trellis } }
* Output JSON: { branches: { positions, normals, uvs, indices }, leaves: { ... } }
*/
import { Tree, TreePreset } from '@dgreenheck/ez-tree';
const input = JSON.parse(process.argv[2] ?? '{}');
const presetName = input.preset ?? 'Oak Medium';
const params = input.params ?? {};
if (!TreePreset[presetName]) {
process.stderr.write('Unknown preset: ' + presetName + '\n');
process.exit(1);
}
const options = structuredClone(TreePreset[presetName]);
applyParams(options, params);
const tree = new Tree();
tree.options.copy(options);
try {
tree.generate();
} catch (e) {
// generate() may fail on DOM APIs for materials, but geometry arrays are
// already populated at that point — continue.
}
const branches = tree.branches;
const leaves = tree.leaves;
if (!branches || !leaves) {
process.stderr.write('Generation produced no geometry\n');
process.exit(1);
}
const leafNormals = leaves.normals?.length > 0
? leaves.normals
: computeFlatNormals(leaves.verts, leaves.indices);
const result = {
branches: {
positions: Array.from(branches.verts),
normals: Array.from(branches.normals),
uvs: Array.from(branches.uvs),
indices: Array.from(branches.indices),
},
leaves: {
positions: Array.from(leaves.verts),
normals: Array.from(leafNormals),
uvs: Array.from(leaves.uvs),
indices: Array.from(leaves.indices),
},
};
process.stdout.write(JSON.stringify(result));
// ── Parameter-Overrides ────────────────────────────────────────────────────
function applyParams(options, params) {
if (params.seed !== undefined) options.seed = params.seed;
if (params.type !== undefined) options.type = params.type;
if (params.bark) {
const b = params.bark;
if (b.tint !== undefined) options.bark.tint = b.tint;
if (b.flatShading !== undefined) options.bark.flatShading = b.flatShading;
if (b.textureScale) {
if (b.textureScale.x !== undefined) options.bark.textureScale.x = b.textureScale.x;
if (b.textureScale.y !== undefined) options.bark.textureScale.y = b.textureScale.y;
}
}
if (params.branch) {
const br = params.branch;
if (br.levels !== undefined) options.branch.levels = br.levels;
if (br.force) {
if (br.force.strength !== undefined)
options.branch.force.strength = br.force.strength;
if (br.force.direction) {
if (br.force.direction.x !== undefined) options.branch.force.direction.x = br.force.direction.x;
if (br.force.direction.y !== undefined) options.branch.force.direction.y = br.force.direction.y;
if (br.force.direction.z !== undefined) options.branch.force.direction.z = br.force.direction.z;
}
}
// Per-level maps: replace entirely when provided (Java sends the full map)
for (const key of ['angle','children','gnarliness','length','radius',
'sections','segments','start','taper','twist']) {
if (br[key] !== undefined) options.branch[key] = br[key];
}
}
if (params.leaves) {
Object.assign(options.leaves, params.leaves);
}
if (params.trellis) {
Object.assign(options.trellis, params.trellis);
}
}
// ── Helpers ────────────────────────────────────────────────────────────────
function computeFlatNormals(verts, indices) {
const normals = new Float32Array(verts.length);
for (let i = 0; i < indices.length; i += 3) {
const ia = indices[i] * 3, ib = indices[i + 1] * 3, ic = indices[i + 2] * 3;
const ax = verts[ib] - verts[ia], ay = verts[ib+1] - verts[ia+1], az = verts[ib+2] - verts[ia+2];
const bx = verts[ic] - verts[ia], by = verts[ic+1] - verts[ia+1], bz = verts[ic+2] - verts[ia+2];
const nx = ay*bz - az*by, ny = az*bx - ax*bz, nz = ax*by - ay*bx;
const len = Math.sqrt(nx*nx + ny*ny + nz*nz) || 1;
for (const idx of [ia, ib, ic]) {
normals[idx] += nx/len;
normals[idx+1] += ny/len;
normals[idx+2] += nz/len;
}
}
return Array.from(normals);
}

31
tools/package-lock.json generated Normal file
View File

@@ -0,0 +1,31 @@
{
"name": "blight-tools",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "blight-tools",
"version": "1.0.0",
"dependencies": {
"@dgreenheck/ez-tree": "^1.1.0",
"three": "^0.167.0"
}
},
"node_modules/@dgreenheck/ez-tree": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@dgreenheck/ez-tree/-/ez-tree-1.1.0.tgz",
"integrity": "sha512-6pvS6hD6B6h00dm0SnkgYeT4ABU5Y1Z9M44p1tXiV5C0eKrQy2sKECXshoaUv0qAOqYVL68w/PwadUxDFDiHUg==",
"license": "MIT",
"peerDependencies": {
"three": ">=0.167"
}
},
"node_modules/three": {
"version": "0.167.1",
"resolved": "https://registry.npmjs.org/three/-/three-0.167.1.tgz",
"integrity": "sha512-gYTLJA/UQip6J/tJvl91YYqlZF47+D/kxiWrbTon35ZHlXEN0VOo+Qke2walF1/x92v55H6enomymg4Dak52kw==",
"license": "MIT"
}
}
}

10
tools/package.json Normal file
View File

@@ -0,0 +1,10 @@
{
"name": "blight-tools",
"version": "1.0.0",
"type": "module",
"private": true,
"dependencies": {
"@dgreenheck/ez-tree": "^1.1.0",
"three": "^0.167.0"
}
}