diff --git a/index.html b/index.html
index 6cfadf55..2691fc1d 100644
--- a/index.html
+++ b/index.html
@@ -24,13 +24,16 @@
diff --git a/public/assets/minecraft/models/block/block.json b/public/assets/minecraft/models/block/block.json
index 3ca539e9..aebc4bef 100644
--- a/public/assets/minecraft/models/block/block.json
+++ b/public/assets/minecraft/models/block/block.json
@@ -1 +1,124 @@
-{"gui_light":"side","display":{"gui":{"rotation":[30,225,0],"translation":[0,0,0],"scale":[0.625,0.625,0.625]},"ground":{"rotation":[0,0,0],"translation":[0,3,0],"scale":[0.25,0.25,0.25]},"fixed":{"rotation":[0,0,0],"translation":[0,0,0],"scale":[0.5,0.5,0.5]},"on_shelf":{"rotation":[0,180,0],"translation":[0,0,0],"scale":[1,1,1]},"thirdperson_righthand":{"rotation":[75,45,0],"translation":[0,2.5,0],"scale":[0.375,0.375,0.375]},"firstperson_righthand":{"rotation":[0,45,0],"translation":[0,0,0],"scale":[0.4,0.4,0.4]},"firstperson_lefthand":{"rotation":[0,225,0],"translation":[0,0,0],"scale":[0.4,0.4,0.4]}}}
\ No newline at end of file
+{
+ "gui_light": "side",
+ "display": {
+ "gui": {
+ "rotation": [
+ 30,
+ 225,
+ 0
+ ],
+ "translation": [
+ 0,
+ 0,
+ 0
+ ],
+ "scale": [
+ 0.625,
+ 0.625,
+ 0.625
+ ]
+ },
+ "ground": {
+ "rotation": [
+ 0,
+ 0,
+ 0
+ ],
+ "translation": [
+ 0,
+ 3,
+ 0
+ ],
+ "scale": [
+ 0.25,
+ 0.25,
+ 0.25
+ ]
+ },
+ "fixed": {
+ "rotation": [
+ 0,
+ 0,
+ 0
+ ],
+ "translation": [
+ 0,
+ 0,
+ 0
+ ],
+ "scale": [
+ 0.5,
+ 0.5,
+ 0.5
+ ]
+ },
+ "on_shelf": {
+ "rotation": [
+ 0,
+ 180,
+ 0
+ ],
+ "translation": [
+ 0,
+ 0,
+ 0
+ ],
+ "scale": [
+ 1,
+ 1,
+ 1
+ ]
+ },
+ "thirdperson_righthand": {
+ "rotation": [
+ 75,
+ 45,
+ 0
+ ],
+ "translation": [
+ 0,
+ 2.5,
+ 0
+ ],
+ "scale": [
+ 0.375,
+ 0.375,
+ 0.375
+ ]
+ },
+ "firstperson_righthand": {
+ "rotation": [
+ 0,
+ 45,
+ 0
+ ],
+ "translation": [
+ 0,
+ 0,
+ 0
+ ],
+ "scale": [
+ 0.4,
+ 0.4,
+ 0.4
+ ]
+ },
+ "firstperson_lefthand": {
+ "rotation": [
+ 0,
+ 225,
+ 0
+ ],
+ "translation": [
+ 0,
+ 0,
+ 0
+ ],
+ "scale": [
+ 0.4,
+ 0.4,
+ 0.4
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/public/assets/minecraft/models/block/cube.json b/public/assets/minecraft/models/block/cube.json
index 7b512042..e8ed7953 100644
--- a/public/assets/minecraft/models/block/cube.json
+++ b/public/assets/minecraft/models/block/cube.json
@@ -1 +1,43 @@
-{"parent":"block/block","elements":[{"from":[0,0,0],"to":[16,16,16],"faces":{"down":{"texture":"#down","cullface":"down"},"up":{"texture":"#up","cullface":"up"},"north":{"texture":"#north","cullface":"north"},"south":{"texture":"#south","cullface":"south"},"west":{"texture":"#west","cullface":"west"},"east":{"texture":"#east","cullface":"east"}}}]}
\ No newline at end of file
+{
+ "parent": "block/block",
+ "elements": [
+ {
+ "from": [
+ 0,
+ 0,
+ 0
+ ],
+ "to": [
+ 16,
+ 16,
+ 16
+ ],
+ "faces": {
+ "down": {
+ "texture": "#down",
+ "cullface": "down"
+ },
+ "up": {
+ "texture": "#up",
+ "cullface": "up"
+ },
+ "north": {
+ "texture": "#north",
+ "cullface": "north"
+ },
+ "south": {
+ "texture": "#south",
+ "cullface": "south"
+ },
+ "west": {
+ "texture": "#west",
+ "cullface": "west"
+ },
+ "east": {
+ "texture": "#east",
+ "cullface": "east"
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/public/assets/minecraft/models/block/cube_all.json b/public/assets/minecraft/models/block/cube_all.json
index a638b497..aaa6adbc 100644
--- a/public/assets/minecraft/models/block/cube_all.json
+++ b/public/assets/minecraft/models/block/cube_all.json
@@ -1 +1,12 @@
-{"parent":"block/cube","textures":{"particle":"#all","down":"#all","up":"#all","north":"#all","east":"#all","south":"#all","west":"#all"}}
\ No newline at end of file
+{
+ "parent": "block/cube",
+ "textures": {
+ "particle": "#all",
+ "down": "#all",
+ "up": "#all",
+ "north": "#all",
+ "east": "#all",
+ "south": "#all",
+ "west": "#all"
+ }
+}
\ No newline at end of file
diff --git a/public/assets/minecraft/models/block/smooth_stone.json b/public/assets/minecraft/models/block/smooth_stone.json
index 4f01b2d8..54595f0c 100644
--- a/public/assets/minecraft/models/block/smooth_stone.json
+++ b/public/assets/minecraft/models/block/smooth_stone.json
@@ -1 +1,6 @@
-{"parent":"minecraft:block/cube_all","textures":{"all":"minecraft:block/smooth_stone"}}
\ No newline at end of file
+{
+ "parent": "minecraft:block/cube_all",
+ "textures": {
+ "all": "minecraft:block/smooth_stone"
+ }
+}
\ No newline at end of file
diff --git a/src/blockstate.js b/src/blockstate.js
index 21d1a4ac..abf334b8 100644
--- a/src/blockstate.js
+++ b/src/blockstate.js
@@ -174,13 +174,16 @@ export class BlockstateResolver {
this.pending.delete(id);
if (this.onResolve) {
- this.onResolve(id, resolver);
+ this.onResolve(id);
}
})
.catch(reason => {
this.resolvers.set(id, this.resolvers.get(':invalid'));
this.pending.delete(id);
- console.log(`failed to resolve blockstate ${id}: ${reason}`);
+ console.warn(`failed to resolve blockstate ${id}: ${reason}`);
+ if (this.onResolve) {
+ this.onResolve(id);
+ }
}));
}
@@ -189,7 +192,26 @@ export class BlockstateResolver {
resolve(id, pos, state) {
const resolver = this.getResolver(id);
- const hash = pos[0] * 3.236 + pos[1] * 4.854 + pos[2] * 8.090;
+
+ // Read the 3 floats directly as 32-bit integers
+ let buffer = new Float32Array([pos[0], pos[1], pos[2]]).buffer;
+ let uview = new Uint32Array(buffer);
+
+ // Mix using large primes
+ let hash = Math.imul(uview[0], 73856093) ^
+ Math.imul(uview[1], 19349663) ^
+ Math.imul(uview[2], 83492791);
+
+ // Avalanche step: Force high bits to mix into low bits (fixes the % 8 issue)
+ hash ^= hash >>> 16;
+ hash = Math.imul(hash, 0x85ebca6b);
+ hash ^= hash >>> 13;
+ hash = Math.imul(hash, 0xc2b2ae35);
+ hash ^= hash >>> 16;
+
+ // Ensure unsigned 32-bit int
+ hash >>>= 0;
+
return resolver(state, hash);
}
}
\ No newline at end of file
diff --git a/src/minerama.js b/src/minerama.js
index 87773834..8cbf6bed 100644
--- a/src/minerama.js
+++ b/src/minerama.js
@@ -1,4 +1,5 @@
import {BlockstateResolver} from "./blockstate";
+import {ModelResolver} from "./model";
export class Renderer {
constructor() {
@@ -12,26 +13,38 @@ export class Renderer {
async function parse(src) {
const lines = src.replace(/#.*?(?:\n|$)/, '\n').trim().split(/(?:\n[ \t]*)+/);
- let count = 0;
- const res = new BlockstateResolver();
+ const bres = new BlockstateResolver();
+ const mres = new ModelResolver();
function ff() {
+ const drawList = new Map();
+
for (const line of lines) {
const args = line.split(/[ \t]+/);
const cmd = args[0].toLowerCase();
if (cmd === 'p') {
- const id = args[1];
- const hash = count;
- count += 1;
-
- console.log(id, JSON.stringify(res.getResolver(id)({}, hash)));
+ const pos = [args[1], args[2], args[3]];
+ const id = args[4];
+ const state = Object.fromEntries(args.slice(5).map(it => it.split('=')));
+ for (const part of bres.resolve(id, pos, state)) {
+ drawList.set(part.model, null);
+ }
}
}
+
+ for (const id of drawList.keys()) {
+ const data = mres.get(id);
+ console.log(id, data);
+ }
}
- res.onResolve = (id, fn) => {
- console.log('resolved', id, 'to', fn)
+ bres.onResolve = (id) => {
+ console.log('resolved blockstate', id)
+ ff()
+ }
+ mres.onResolve = (id) => {
+ console.log('resolved model', id)
ff()
}
diff --git a/src/model.js b/src/model.js
new file mode 100644
index 00000000..41afbcf8
--- /dev/null
+++ b/src/model.js
@@ -0,0 +1,58 @@
+export class ModelResolver {
+ constructor() {
+ this.models = new Map();
+ this.pending = new Map();
+
+ this.onResolve = undefined;
+
+ const cuboid = {
+ "from": [0, 0, 0],
+ "to": [0, 0, 0],
+ "faces": {
+ "down": {"texture": "#all"},
+ "up": {"texture": "#all"},
+ "north": {"texture": "#all"},
+ "south": {"texture": "#all"},
+ "west": {"texture": "#all"},
+ "east": {"texture": "#all"}
+ }
+ };
+
+ this.models.set(':pending', {"textures": {"all": ":pending"}, "elements": [cuboid]});
+ this.models.set(':missing', {"textures": {"all": ":missing"}, "elements": [cuboid]});
+ }
+
+ get(id) {
+ id = id.includes(":") ? id : `minecraft:${id}`;
+
+ if (this.models.has(id)) {
+ return this.models.get(id);
+ }
+
+ if (!this.pending.has(id)) {
+ const [space, name] = id.split(':');
+ const url = `/assets/${space}/models/${name}.json`;
+
+ this.pending.set(id, fetch(url)
+ .then(res => res.json())
+ .then(data => {
+ this.models.set(id, data)
+ this.pending.delete(id)
+
+ if (this.onResolve) {
+ this.onResolve(id);
+ }
+ })
+ .catch(reason => {
+ this.models.set(id, this.models.get(':invalid'));
+ this.pending.delete(id);
+ console.log(`failed to resolve model ${id}: ${reason}`)
+ if (this.onResolve) {
+ this.onResolve(id);
+ }
+ }));
+ }
+
+ return this.models.get(':pending');
+ }
+}
\ No newline at end of file