Skip to content

Commit d9fdd71

Browse files
committed
fix: fix a few minor bugs
1 parent 14161a2 commit d9fdd71

File tree

5 files changed

+85
-46
lines changed

5 files changed

+85
-46
lines changed

scripts/generateTransparentList.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ async function doTheFilter() {
1919
const transparent = data
2020
.filter(bl => bl.material.opaque === false || bl.id.includes('door'))
2121
.map(bl => bl.id.replace('minecraft:', ''));
22+
23+
// MC has renamed this to short_grass; it's common enough to special case for old schematics.
24+
transparent.push('grass');
25+
2226
await Promise.all([
2327
writeFile(
2428
new URL('../src/renderer/nonOccluding.json', import.meta.url),

src/renderer/model/loader.ts

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -208,21 +208,20 @@ export function getModelLoader(resourceLoader: ResourceLoader): ModelLoader {
208208
const weightedRandomIndex = (
209209
options: BlockModelData['models'][number]['options']
210210
) => {
211-
const weights = [];
212-
211+
let totalWeight = 0;
213212
for (let i = 0; i < options.length; i++) {
214-
weights[i] = options[i].weight + (weights[i - 1] || 0);
213+
totalWeight += options[i].weight;
215214
}
216215

217-
const random = Math.random() * weights[weights.length - 1];
218-
219-
for (let i = 0; i < weights.length; i++) {
220-
if (weights[i] > random) {
216+
let random = Math.random() * totalWeight;
217+
for (let i = 0; i < options.length; i++) {
218+
random -= options[i].weight;
219+
if (random < 0) {
221220
return i;
222221
}
223222
}
224223

225-
return weights.length - 1;
224+
return options.length - 1;
226225
};
227226

228227
let name = data.name;
@@ -242,9 +241,17 @@ export function getModelLoader(resourceLoader: ResourceLoader): ModelLoader {
242241
scene: Scene
243242
) => {
244243
if (modelCache.has(data.name)) {
245-
return modelCache
246-
.get(data.name)
247-
.map((mesh, i) => mesh.createInstance(`${data.name}-${i}`));
244+
const cachedGroup = modelCache.get(data.name);
245+
const instances = new Array<InstancedMesh>(cachedGroup.length);
246+
const instanceNamePrefix = `${data.name}-`;
247+
248+
for (let i = 0; i < cachedGroup.length; i++) {
249+
instances[i] = cachedGroup[i].createInstance(
250+
instanceNamePrefix + i
251+
);
252+
}
253+
254+
return instances;
248255
}
249256

250257
const group: Mesh[] = [];
@@ -490,7 +497,13 @@ export function getModelLoader(resourceLoader: ResourceLoader): ModelLoader {
490497
mesh.isVisible = false;
491498
}
492499
modelCache.set(data.name, group);
493-
return group.map((mesh, i) => mesh.createInstance(`${data.name}-${i}`));
500+
501+
const instances = new Array<InstancedMesh>(group.length);
502+
const instanceNamePrefix = `${data.name}-`;
503+
for (let i = 0; i < group.length; i++) {
504+
instances[i] = group[i].createInstance(instanceNamePrefix + i);
505+
}
506+
return instances;
494507
};
495508

496509
return {

src/renderer/renderer.ts

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,26 @@ const CASSETTE_DECK_URL = `https://services.enginehub.org/cassette-deck/minecraf
3030
const URL_1_13 =
3131
'https://launcher.mojang.com/v1/objects/c0b970952cdd279912da384cdbfc0c26e6c6090b/client.jar';
3232

33+
function blockKey(block: Block): string {
34+
const props = block.properties ?? {};
35+
const keys = Object.keys(props);
36+
if (keys.length === 0) {
37+
return block.type;
38+
}
39+
40+
keys.sort();
41+
let out = block.type + '[';
42+
for (let i = 0; i < keys.length; i++) {
43+
const key = keys[i];
44+
if (i > 0) {
45+
out += ',';
46+
}
47+
out += key + '=' + String(props[key]);
48+
}
49+
out += ']';
50+
return out;
51+
}
52+
3353
async function getClientJarUrlDefault({
3454
dataVersion,
3555
corsBypassUrl,
@@ -88,9 +108,8 @@ export async function renderSchematic(
88108

89109
scene.ambientColor = new Color3(0.5, 0.5, 0.5);
90110
if (backgroundColor !== 'transparent') {
91-
scene.clearColor = Color4.FromHexString(
92-
`#${backgroundColor.toString(16)}FF`
93-
);
111+
const hex = backgroundColor.toString(16).padStart(6, '0');
112+
scene.clearColor = Color4.FromHexString(`#${hex}FF`);
94113
} else {
95114
scene.clearColor = new Color4(0, 0, 0, 0);
96115
}
@@ -142,7 +161,7 @@ export async function renderSchematic(
142161
]);
143162
const modelLoader = getModelLoader(resourceLoader);
144163

145-
const blockModelLookup: Map<Block, BlockModelData> = new Map();
164+
const blockModelLookup: Map<string, BlockModelData> = new Map();
146165

147166
for (const block of loadedSchematic.blockTypes) {
148167
if (INVISIBLE_BLOCKS.has(block.type)) {
@@ -159,11 +178,17 @@ export async function renderSchematic(
159178
continue;
160179
}
161180

162-
blockModelLookup.set(block, blockModelData);
181+
blockModelLookup.set(blockKey(block), blockModelData);
163182
}
164183

165184
Mesh.INSTANCEDMESH_SORT_TRANSPARENT = true;
166185

186+
const worldXBase = -worldWidth / 2 + 0.5;
187+
const worldYBase = -worldHeight / 2 + 0.5;
188+
const worldZBase = -worldLength / 2 + 0.5;
189+
190+
const neighborPos = { x: 0, y: 0, z: 0 };
191+
167192
scene.blockMaterialDirtyMechanism = true;
168193
for (const pos of loadedSchematic) {
169194
const { x, y, z } = pos;
@@ -173,7 +198,7 @@ export async function renderSchematic(
173198
continue;
174199
}
175200

176-
const modelData = blockModelLookup.get(block);
201+
const modelData = blockModelLookup.get(blockKey(block));
177202
if (!modelData) {
178203
continue;
179204
}
@@ -182,11 +207,10 @@ export async function renderSchematic(
182207

183208
for (const face of POSSIBLE_FACES) {
184209
const faceOffset = faceToFacingVector(face);
185-
const offBlock = loadedSchematic.getBlock({
186-
x: x + faceOffset[0],
187-
y: y + faceOffset[1],
188-
z: z + faceOffset[2],
189-
});
210+
neighborPos.x = x + faceOffset[0];
211+
neighborPos.y = y + faceOffset[1];
212+
neighborPos.z = z + faceOffset[2];
213+
const offBlock = loadedSchematic.getBlock(neighborPos);
190214

191215
if (!offBlock || NON_OCCLUDING_BLOCKS.has(offBlock.type)) {
192216
anyVisible = true;
@@ -206,12 +230,10 @@ export async function renderSchematic(
206230
continue;
207231
}
208232

209-
mesh.position.x += -worldWidth / 2 + x + 0.5;
210-
mesh.position.y += -worldHeight / 2 + y + 0.5;
211-
mesh.position.z += -worldLength / 2 + z + 0.5;
233+
mesh.position.x += worldXBase + x;
234+
mesh.position.y += worldYBase + y;
235+
mesh.position.z += worldZBase + z;
212236
mesh.freezeWorldMatrix();
213-
214-
scene.addMesh(mesh);
215237
}
216238
}
217239
scene.blockMaterialDirtyMechanism = false;
@@ -254,8 +276,10 @@ export async function renderSchematic(
254276
engine.setSize(width, height);
255277
},
256278
destroy() {
257-
engine.dispose();
258279
hasDestroyed = true;
280+
engine.stopRenderLoop(render);
281+
scene.dispose();
282+
engine.dispose();
259283
},
260284
render,
261285
getEngine(): Engine {

0 commit comments

Comments
 (0)