minerender 2.1.0-alpha.60 → 2.1.0-alpha.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/index.d.mts +47 -13
- package/dist/browser/index.d.ts +47 -13
- package/dist/browser/index.js +443 -320
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.mjs +245 -122
- package/dist/browser/index.mjs.map +1 -1
- package/dist/bundle.js +177 -48
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +47 -13
- package/dist/node/index.d.ts +47 -13
- package/dist/node/index.js +445 -320
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +245 -122
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/bundle.js
CHANGED
|
@@ -33790,7 +33790,7 @@ var MineRender = (() => {
|
|
|
33790
33790
|
}
|
|
33791
33791
|
static async getItemModel(key) {
|
|
33792
33792
|
const itemKey = new AssetKey(key.namespace, key.path, "items", void 0, key.rootType, ".json", key.root);
|
|
33793
|
-
const model = await this.PERSISTENT_CACHE.getOrLoad(AssetLoader.persistentKey(itemKey.serialize())
|
|
33793
|
+
const model = await this.PERSISTENT_CACHE.getOrLoad(`item-v2:${AssetLoader.persistentKey(itemKey.serialize())}`, async () => {
|
|
33794
33794
|
const result = await AssetLoader.getFirst([itemKey, key], "json" /* JSON */);
|
|
33795
33795
|
if (!result) return void 0;
|
|
33796
33796
|
if (result.key.assetType !== "items") return { ...result.asset, key };
|
|
@@ -33799,7 +33799,7 @@ var MineRender = (() => {
|
|
|
33799
33799
|
modelKey.root = key.root;
|
|
33800
33800
|
const model2 = await this.getRaw(modelKey);
|
|
33801
33801
|
if (!model2) throw new Error(`Item ${key.toNamespacedString()} references missing model ${selected.model}`);
|
|
33802
|
-
return selected.special
|
|
33802
|
+
return { ...model2, ...selected.special && { special: selected.special }, ...selected.tints && { tints: selected.tints } };
|
|
33803
33803
|
});
|
|
33804
33804
|
return model ? { ...model, key: Object.assign(new AssetKey("", ""), model.key) } : void 0;
|
|
33805
33805
|
}
|
|
@@ -33810,7 +33810,7 @@ var MineRender = (() => {
|
|
|
33810
33810
|
}
|
|
33811
33811
|
switch (node.type.replace(/^minecraft:/, "")) {
|
|
33812
33812
|
case "model":
|
|
33813
|
-
if (typeof node.model === "string" && node.model) return { model: node.model };
|
|
33813
|
+
if (typeof node.model === "string" && node.model) return { model: node.model, tints: node.tints };
|
|
33814
33814
|
break;
|
|
33815
33815
|
case "special": {
|
|
33816
33816
|
if (!node.base || !node.model || typeof node.model !== "object") break;
|
|
@@ -78923,11 +78923,11 @@ ${key}` : key;
|
|
|
78923
78923
|
return { ...layers[names[0]], id: model.id, layers, ...model.transform && { transform: model.transform } };
|
|
78924
78924
|
}
|
|
78925
78925
|
/**
|
|
78926
|
-
*
|
|
78926
|
+
* Native and sampled vanilla clips by name, or undefined when the model or selected version has none.
|
|
78927
78927
|
*/
|
|
78928
78928
|
static async getAnimations(modelKey) {
|
|
78929
78929
|
const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
|
|
78930
|
-
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models/animations", ".json");
|
|
78930
|
+
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models/animations", ".json", isAssetKey(modelKey) ? modelKey.root : void 0);
|
|
78931
78931
|
const file = await Caching.entityAnimationCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
|
|
78932
78932
|
return file?.animations;
|
|
78933
78933
|
}
|
|
@@ -78977,7 +78977,7 @@ ${key}` : key;
|
|
|
78977
78977
|
let low = 0, high = keyframes.length;
|
|
78978
78978
|
while (low < high) {
|
|
78979
78979
|
const middle = low + high >>> 1;
|
|
78980
|
-
if (time
|
|
78980
|
+
if (time < keyframes[middle].time) high = middle;
|
|
78981
78981
|
else low = middle + 1;
|
|
78982
78982
|
}
|
|
78983
78983
|
const a4 = Math.max(0, low - 1);
|
|
@@ -79025,6 +79025,7 @@ ${key}` : key;
|
|
|
79025
79025
|
init_dirname();
|
|
79026
79026
|
init_buffer2();
|
|
79027
79027
|
init_process2();
|
|
79028
|
+
init_three_module();
|
|
79028
79029
|
init_EntityAnimation();
|
|
79029
79030
|
ZERO = [0, 0, 0];
|
|
79030
79031
|
EntityAnimationPlayer = class {
|
|
@@ -79041,25 +79042,45 @@ ${key}` : key;
|
|
|
79041
79042
|
return this._time;
|
|
79042
79043
|
}
|
|
79043
79044
|
/**
|
|
79044
|
-
* Starts an animation on
|
|
79045
|
-
*
|
|
79045
|
+
* Starts an animation on matching named parts. Supplied baked poses are the baseline for offsets;
|
|
79046
|
+
* without them, the current pose is used. Stopping restores the pose from before playback.
|
|
79046
79047
|
*/
|
|
79047
|
-
play(layers, animation, options = {}) {
|
|
79048
|
+
play(layers, animation, options = {}, poses) {
|
|
79048
79049
|
this.stop();
|
|
79049
79050
|
this._animation = animation;
|
|
79050
79051
|
this._time = options.time ?? 0;
|
|
79051
79052
|
this.loop = options.loop ?? animation.loop;
|
|
79052
79053
|
this.speed = options.speed ?? 1;
|
|
79053
79054
|
for (const layer of layers) {
|
|
79054
|
-
|
|
79055
|
-
|
|
79056
|
-
|
|
79057
|
-
|
|
79055
|
+
const objects = [];
|
|
79056
|
+
if (poses) {
|
|
79057
|
+
layer.traverse((object) => {
|
|
79058
|
+
if (poses.has(object)) objects.push(object);
|
|
79059
|
+
});
|
|
79060
|
+
} else {
|
|
79061
|
+
for (const bone of Object.keys(animation.bones)) {
|
|
79062
|
+
const object = layer.getObjectByName(`group:${bone}`);
|
|
79063
|
+
if (object) objects.push(object);
|
|
79064
|
+
}
|
|
79065
|
+
}
|
|
79066
|
+
for (const object of objects) {
|
|
79067
|
+
const bone = object.name.slice("group:".length);
|
|
79068
|
+
const pose = poses?.get(object);
|
|
79069
|
+
this.parts.push({
|
|
79070
|
+
bone,
|
|
79071
|
+
object,
|
|
79072
|
+
position: object.position.clone(),
|
|
79073
|
+
rotation: object.rotation.clone(),
|
|
79074
|
+
scale: object.scale.clone(),
|
|
79075
|
+
basePosition: pose ? new Vector3(...pose.offset) : object.position.clone(),
|
|
79076
|
+
baseRotation: pose ? new Euler(...pose.rotation, "ZYX") : object.rotation.clone(),
|
|
79077
|
+
baseScale: pose ? new Vector3(...pose.scale ?? [1, 1, 1]) : object.scale.clone()
|
|
79078
|
+
});
|
|
79058
79079
|
}
|
|
79059
79080
|
}
|
|
79060
79081
|
this.apply();
|
|
79061
79082
|
}
|
|
79062
|
-
/** Restores the
|
|
79083
|
+
/** Restores the poses from before playback. Returns whether an animation was active. */
|
|
79063
79084
|
stop() {
|
|
79064
79085
|
if (!this._animation) return false;
|
|
79065
79086
|
for (const part of this.parts) {
|
|
@@ -79088,10 +79109,10 @@ ${key}` : key;
|
|
|
79088
79109
|
apply() {
|
|
79089
79110
|
const pose = sampleEntityAnimation(this._animation, this._time, this.loop);
|
|
79090
79111
|
for (const part of this.parts) {
|
|
79091
|
-
const { position = ZERO, rotation = ZERO, scale = ZERO } = pose[part.bone];
|
|
79092
|
-
part.object.position.set(part.
|
|
79093
|
-
part.object.rotation.set(part.
|
|
79094
|
-
part.object.scale.set(part.
|
|
79112
|
+
const { position = ZERO, rotation = ZERO, scale = ZERO } = pose[part.bone] ?? {};
|
|
79113
|
+
part.object.position.set(part.basePosition.x + position[0], part.basePosition.y + position[1], part.basePosition.z + position[2]);
|
|
79114
|
+
part.object.rotation.set(part.baseRotation.x + rotation[0], part.baseRotation.y + rotation[1], part.baseRotation.z + rotation[2], part.baseRotation.order);
|
|
79115
|
+
part.object.scale.set(part.baseScale.x + scale[0], part.baseScale.y + scale[1], part.baseScale.z + scale[2]);
|
|
79095
79116
|
}
|
|
79096
79117
|
}
|
|
79097
79118
|
};
|
|
@@ -79634,7 +79655,8 @@ ${key}` : key;
|
|
|
79634
79655
|
this.scrollMaterials = [];
|
|
79635
79656
|
/** Entity age in ticks, as vanilla's `ageInTicks`; drives the scrolling render modes. */
|
|
79636
79657
|
this.age = 0;
|
|
79637
|
-
this.
|
|
79658
|
+
this.animationPlayers = [];
|
|
79659
|
+
this.partPoses = /* @__PURE__ */ new Map();
|
|
79638
79660
|
this.options = (0, import_ts_deepmerge4.default)({}, _EntityObject.DEFAULT_OPTIONS, options ?? {});
|
|
79639
79661
|
this.addEventListener("added", () => this.updateScrollSubscription());
|
|
79640
79662
|
this.addEventListener("removed", () => this.updateScrollSubscription());
|
|
@@ -79651,7 +79673,8 @@ ${key}` : key;
|
|
|
79651
79673
|
for (const geometry of this.geometries) geometry.dispose();
|
|
79652
79674
|
this.geometries.clear();
|
|
79653
79675
|
for (const dispose of this.disposeWireframes.splice(0)) dispose();
|
|
79654
|
-
this.
|
|
79676
|
+
for (const player of this.animationPlayers.splice(0)) player.clear();
|
|
79677
|
+
this.partPoses.clear();
|
|
79655
79678
|
super.disposeAndRemoveAllChildren();
|
|
79656
79679
|
}
|
|
79657
79680
|
clearScrollMaterials() {
|
|
@@ -79683,36 +79706,61 @@ ${key}` : key;
|
|
|
79683
79706
|
this.notifyDirty();
|
|
79684
79707
|
}
|
|
79685
79708
|
//<editor-fold desc="ANIMATION">
|
|
79686
|
-
/** The
|
|
79709
|
+
/** The first active clip, until playback is stopped or the object is disposed. */
|
|
79687
79710
|
get animation() {
|
|
79688
|
-
return this.
|
|
79711
|
+
return this.animationPlayers[0]?.animation;
|
|
79712
|
+
}
|
|
79713
|
+
/** Clips playing together, each targeting a separate geometry layer. */
|
|
79714
|
+
get activeAnimations() {
|
|
79715
|
+
return this.animationPlayers.map((player) => player.animation);
|
|
79689
79716
|
}
|
|
79690
79717
|
/** Seconds since the animation started, before looping. */
|
|
79691
79718
|
get animationTime() {
|
|
79692
|
-
return this.
|
|
79719
|
+
return this.animationPlayers[0]?.time ?? 0;
|
|
79693
79720
|
}
|
|
79694
79721
|
/**
|
|
79695
|
-
*
|
|
79696
|
-
*
|
|
79722
|
+
* Plays a clip from {@link Entities.getAnimations}, replacing all active clips.
|
|
79723
|
+
* Offsets apply to the baked pose in the clip's layer (`main` by default), including repeated draws of that layer.
|
|
79697
79724
|
* The object owns no clock: call {@link advanceAnimation} per frame, or {@link setAnimationTime}.
|
|
79698
79725
|
*/
|
|
79699
79726
|
playAnimation(animation, options) {
|
|
79727
|
+
this.playAnimations([animation], options);
|
|
79728
|
+
}
|
|
79729
|
+
/** Plays one clip per selected geometry layer, with a shared clock and no blending between clips. */
|
|
79730
|
+
playAnimations(animations, options) {
|
|
79731
|
+
const targets = /* @__PURE__ */ new Set();
|
|
79732
|
+
const selections = animations.map((animation) => {
|
|
79733
|
+
const layer = animation.layer ?? "main";
|
|
79734
|
+
if (targets.has(layer)) throw new Error(`Multiple animations target layer "${layer}"`);
|
|
79735
|
+
targets.add(layer);
|
|
79736
|
+
const names = Object.keys(this.entityLayers).filter((name2) => name2.split("#")[0] === layer);
|
|
79737
|
+
if (!names.length) throw new Error(`Entity ${this.entity.id} has no selected animation layer "${layer}"`);
|
|
79738
|
+
return { animation, names };
|
|
79739
|
+
});
|
|
79700
79740
|
this.createMeshes();
|
|
79701
|
-
|
|
79702
|
-
|
|
79741
|
+
this.stopAnimation();
|
|
79742
|
+
for (const { animation, names } of selections) {
|
|
79743
|
+
const player = new EntityAnimationPlayer();
|
|
79744
|
+
player.play(names.map((name2) => this.getLayerGroup(name2)), animation, options, this.partPoses);
|
|
79745
|
+
this.animationPlayers.push(player);
|
|
79746
|
+
}
|
|
79703
79747
|
this.notifyDirty();
|
|
79704
79748
|
}
|
|
79705
|
-
/** Stops
|
|
79749
|
+
/** Stops all clips and restores the poses from before playback. */
|
|
79706
79750
|
stopAnimation() {
|
|
79707
|
-
|
|
79751
|
+
const players = this.animationPlayers.splice(0);
|
|
79752
|
+
for (const player of players) player.stop();
|
|
79753
|
+
if (players.length) this.notifyDirty();
|
|
79708
79754
|
}
|
|
79709
79755
|
/** Poses the object at an explicit time in seconds. Has no effect without an animation. */
|
|
79710
79756
|
setAnimationTime(seconds) {
|
|
79711
|
-
|
|
79757
|
+
for (const player of this.animationPlayers) player.setTime(seconds);
|
|
79758
|
+
if (this.animationPlayers.length) this.notifyDirty();
|
|
79712
79759
|
}
|
|
79713
79760
|
/** Advances the animation by a frame delta in seconds, scaled by its speed. Has no effect without an animation. */
|
|
79714
79761
|
advanceAnimation(deltaSeconds) {
|
|
79715
|
-
|
|
79762
|
+
for (const player of this.animationPlayers) player.advance(deltaSeconds);
|
|
79763
|
+
if (this.animationPlayers.length) this.notifyDirty();
|
|
79716
79764
|
}
|
|
79717
79765
|
//</editor-fold>
|
|
79718
79766
|
getLayerGroup(name2) {
|
|
@@ -79772,6 +79820,7 @@ ${key}` : key;
|
|
|
79772
79820
|
anchor.position.fromArray(part.pose.offset);
|
|
79773
79821
|
anchor.rotation.set(...part.pose.rotation, "ZYX");
|
|
79774
79822
|
anchor.scale.fromArray(part.pose.scale ?? [1, 1, 1]);
|
|
79823
|
+
this.partPoses.set(anchor, part.pose);
|
|
79775
79824
|
parent.add(anchor);
|
|
79776
79825
|
const size = part.texture ?? textureSize;
|
|
79777
79826
|
for (const cube of part.cubes) {
|
|
@@ -80541,6 +80590,93 @@ ${shader.fragmentShader}`.replace(
|
|
|
80541
80590
|
}
|
|
80542
80591
|
});
|
|
80543
80592
|
|
|
80593
|
+
// src/texture/Colormaps.ts
|
|
80594
|
+
var Colormaps;
|
|
80595
|
+
var init_Colormaps = __esm({
|
|
80596
|
+
"src/texture/Colormaps.ts"() {
|
|
80597
|
+
init_dirname();
|
|
80598
|
+
init_buffer2();
|
|
80599
|
+
init_process2();
|
|
80600
|
+
init_AssetKey();
|
|
80601
|
+
init_ModelTextures();
|
|
80602
|
+
init_Caching();
|
|
80603
|
+
init_MineRenderError();
|
|
80604
|
+
Colormaps = class {
|
|
80605
|
+
/** Samples the selected resource pack's grass colormap using Minecraft's climate coordinates. */
|
|
80606
|
+
static async grassColor(origin, temperature = 0.5, downfall = 1) {
|
|
80607
|
+
const key = AssetKey.parse("textures", "minecraft:colormap/grass", origin);
|
|
80608
|
+
const temp = Math.fround(temperature);
|
|
80609
|
+
const rain = Math.fround(downfall) * temp;
|
|
80610
|
+
const x4 = Math.floor((1 - temp) * 255), y5 = Math.floor((1 - rain) * 255);
|
|
80611
|
+
return await Caching.blockTintCache.get(`${key.serialize()}|${x4},${y5}`, async () => {
|
|
80612
|
+
const image = await ModelTextures.get(key);
|
|
80613
|
+
if (!image) throw new MineRenderError(`Missing grass colormap: ${key.toNamespacedString()}`);
|
|
80614
|
+
if (image.width !== 256 || image.height !== 256) {
|
|
80615
|
+
throw new MineRenderError("Grass colormaps must be 256 \xD7 256 pixels");
|
|
80616
|
+
}
|
|
80617
|
+
const [red, green, blue] = image.data.getImageData(x4, y5, 1, 1).data;
|
|
80618
|
+
return red << 16 | green << 8 | blue;
|
|
80619
|
+
});
|
|
80620
|
+
}
|
|
80621
|
+
};
|
|
80622
|
+
}
|
|
80623
|
+
});
|
|
80624
|
+
|
|
80625
|
+
// src/model/ItemTints.ts
|
|
80626
|
+
var ItemTints;
|
|
80627
|
+
var init_ItemTints = __esm({
|
|
80628
|
+
"src/model/ItemTints.ts"() {
|
|
80629
|
+
init_dirname();
|
|
80630
|
+
init_buffer2();
|
|
80631
|
+
init_process2();
|
|
80632
|
+
init_MineRenderError();
|
|
80633
|
+
init_Colormaps();
|
|
80634
|
+
ItemTints = class {
|
|
80635
|
+
/** Resolves preview colors from item definitions; explicit per-index colors take precedence. */
|
|
80636
|
+
static async get(model, tints) {
|
|
80637
|
+
const sources = model.tints;
|
|
80638
|
+
if (!sources?.length) return tints;
|
|
80639
|
+
const colors = { ...tints };
|
|
80640
|
+
await Promise.all(sources.map(async (source, index) => {
|
|
80641
|
+
if (colors[index] !== void 0) return;
|
|
80642
|
+
switch (source.type) {
|
|
80643
|
+
case "constant":
|
|
80644
|
+
case "minecraft:constant":
|
|
80645
|
+
colors[index] = this.rgb(source.value);
|
|
80646
|
+
break;
|
|
80647
|
+
case "grass":
|
|
80648
|
+
case "minecraft:grass":
|
|
80649
|
+
colors[index] = await Colormaps.grassColor(model.key, source.temperature, source.downfall);
|
|
80650
|
+
break;
|
|
80651
|
+
case "dye":
|
|
80652
|
+
case "minecraft:dye":
|
|
80653
|
+
case "potion":
|
|
80654
|
+
case "minecraft:potion":
|
|
80655
|
+
case "map_color":
|
|
80656
|
+
case "minecraft:map_color":
|
|
80657
|
+
case "firework":
|
|
80658
|
+
case "minecraft:firework":
|
|
80659
|
+
case "team":
|
|
80660
|
+
case "minecraft:team":
|
|
80661
|
+
case "custom_model_data":
|
|
80662
|
+
case "minecraft:custom_model_data":
|
|
80663
|
+
colors[index] = this.rgb(source.default);
|
|
80664
|
+
break;
|
|
80665
|
+
default:
|
|
80666
|
+
throw new MineRenderError(`Unsupported item tint source ${source.type}`);
|
|
80667
|
+
}
|
|
80668
|
+
}));
|
|
80669
|
+
return colors;
|
|
80670
|
+
}
|
|
80671
|
+
static rgb(color2) {
|
|
80672
|
+
if (!Array.isArray(color2)) return color2 & 16777215;
|
|
80673
|
+
const [red, green, blue] = color2.map((channel) => Math.floor(Math.fround(Math.fround(channel) * 255)));
|
|
80674
|
+
return red << 16 | green << 8 | blue;
|
|
80675
|
+
}
|
|
80676
|
+
};
|
|
80677
|
+
}
|
|
80678
|
+
});
|
|
80679
|
+
|
|
80544
80680
|
// src/model/scene/ModelObject.ts
|
|
80545
80681
|
function isModelObject(obj) {
|
|
80546
80682
|
return obj.isModelObject;
|
|
@@ -80566,6 +80702,7 @@ ${shader.fragmentShader}`.replace(
|
|
|
80566
80702
|
init_SpecialItems();
|
|
80567
80703
|
init_EntityObject();
|
|
80568
80704
|
init_GuiLight();
|
|
80705
|
+
init_ItemTints();
|
|
80569
80706
|
p10 = prefix("ModelObject");
|
|
80570
80707
|
_ModelObject = class _ModelObject extends SceneObject {
|
|
80571
80708
|
constructor(originalModel, options) {
|
|
@@ -80581,6 +80718,7 @@ ${shader.fragmentShader}`.replace(
|
|
|
80581
80718
|
this.addEventListener("removed", () => this.updateAnimationSubscription());
|
|
80582
80719
|
}
|
|
80583
80720
|
async init() {
|
|
80721
|
+
this.options.tints = await ItemTints.get(this.originalModel, this.options.tints);
|
|
80584
80722
|
const special = this.originalModel.special;
|
|
80585
80723
|
if (special) {
|
|
80586
80724
|
const parts = await SpecialItems.getParts(special, this.originalModel.key?.root);
|
|
@@ -83855,6 +83993,7 @@ ${shader.fragmentShader}`.replace(
|
|
|
83855
83993
|
CanvasImage: () => CanvasImage,
|
|
83856
83994
|
Chunk: () => Chunk,
|
|
83857
83995
|
ChunkData: () => ChunkData,
|
|
83996
|
+
Colormaps: () => Colormaps,
|
|
83858
83997
|
CubeFace: () => CubeFace,
|
|
83859
83998
|
CubeFaceIndex: () => CubeFaceIndex,
|
|
83860
83999
|
DEFAULT_ELEMENTS: () => DEFAULT_ELEMENTS,
|
|
@@ -83880,6 +84019,7 @@ ${shader.fragmentShader}`.replace(
|
|
|
83880
84019
|
ImageLoader: () => ImageLoader,
|
|
83881
84020
|
InstanceManager: () => InstanceManager,
|
|
83882
84021
|
InstanceReference: () => InstanceReference,
|
|
84022
|
+
ItemTints: () => ItemTints,
|
|
83883
84023
|
MapControls: () => MapControls,
|
|
83884
84024
|
Materials: () => Materials,
|
|
83885
84025
|
Meshes: () => Meshes,
|
|
@@ -87614,6 +87754,7 @@ property list uchar int vertex_index
|
|
|
87614
87754
|
|
|
87615
87755
|
// src/model/index.ts
|
|
87616
87756
|
init_GuiLight();
|
|
87757
|
+
init_ItemTints();
|
|
87617
87758
|
init_Model();
|
|
87618
87759
|
init_ModelCulling();
|
|
87619
87760
|
|
|
@@ -87744,10 +87885,7 @@ property list uchar int vertex_index
|
|
|
87744
87885
|
init_dirname();
|
|
87745
87886
|
init_buffer2();
|
|
87746
87887
|
init_process2();
|
|
87747
|
-
|
|
87748
|
-
init_ModelTextures();
|
|
87749
|
-
init_Caching();
|
|
87750
|
-
init_MineRenderError();
|
|
87888
|
+
init_Colormaps();
|
|
87751
87889
|
|
|
87752
87890
|
// src/model/block/blockTints.json
|
|
87753
87891
|
var blockTints_default = {
|
|
@@ -87802,7 +87940,7 @@ property list uchar int vertex_index
|
|
|
87802
87940
|
color2 = rule.color;
|
|
87803
87941
|
break;
|
|
87804
87942
|
case "grass":
|
|
87805
|
-
color2 = await
|
|
87943
|
+
color2 = await Colormaps.grassColor(key);
|
|
87806
87944
|
break;
|
|
87807
87945
|
case "redstone": {
|
|
87808
87946
|
const power = Number(state.power ?? 0) / 15;
|
|
@@ -87820,18 +87958,6 @@ property list uchar int vertex_index
|
|
|
87820
87958
|
}
|
|
87821
87959
|
return { ...Object.fromEntries([...indices].map((index) => [index, color2])), ...tints };
|
|
87822
87960
|
}
|
|
87823
|
-
static async grassColor(origin) {
|
|
87824
|
-
const key = AssetKey.parse("textures", "minecraft:colormap/grass", origin);
|
|
87825
|
-
return await Caching.blockTintCache.get(key.serialize(), async () => {
|
|
87826
|
-
const image = await ModelTextures.get(key);
|
|
87827
|
-
if (!image) throw new MineRenderError(`Missing grass colormap: ${key.toNamespacedString()}`);
|
|
87828
|
-
if (image.width !== 256 || image.height !== 256) {
|
|
87829
|
-
throw new MineRenderError("Grass colormaps must be 256 \xD7 256 pixels");
|
|
87830
|
-
}
|
|
87831
|
-
const [red, green, blue] = image.data.getImageData(127, 127, 1, 1).data;
|
|
87832
|
-
return red << 16 | green << 8 | blue;
|
|
87833
|
-
});
|
|
87834
|
-
}
|
|
87835
87961
|
};
|
|
87836
87962
|
|
|
87837
87963
|
// src/model/block/scene/index.ts
|
|
@@ -91145,6 +91271,7 @@ property list uchar int vertex_index
|
|
|
91145
91271
|
|
|
91146
91272
|
// src/renderer/MineRenderScene.ts
|
|
91147
91273
|
init_EntityObject();
|
|
91274
|
+
init_ItemTints();
|
|
91148
91275
|
var _MineRenderScene = class _MineRenderScene extends Scene {
|
|
91149
91276
|
constructor(options) {
|
|
91150
91277
|
super();
|
|
@@ -91237,6 +91364,7 @@ property list uchar int vertex_index
|
|
|
91237
91364
|
}
|
|
91238
91365
|
}
|
|
91239
91366
|
async addModel(model, options, parent = this) {
|
|
91367
|
+
options = { ...options, tints: await ItemTints.get(model, options?.tints) };
|
|
91240
91368
|
return this.addSceneObject(model, () => new ModelObject(model, options), options, parent);
|
|
91241
91369
|
}
|
|
91242
91370
|
async addBlock(blockState, options, parent = this) {
|
|
@@ -94298,6 +94426,7 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
|
|
|
94298
94426
|
init_dirname();
|
|
94299
94427
|
init_buffer2();
|
|
94300
94428
|
init_process2();
|
|
94429
|
+
init_Colormaps();
|
|
94301
94430
|
init_TextureAtlas();
|
|
94302
94431
|
init_TextureLoader();
|
|
94303
94432
|
init_Textures();
|