minerender 2.1.0-alpha.28 → 2.1.0-alpha.29
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 +27 -2
- package/dist/browser/index.d.ts +27 -2
- package/dist/browser/index.js +105 -63
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.mjs +106 -64
- package/dist/browser/index.mjs.map +1 -1
- package/dist/bundle.js +105 -63
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +27 -2
- package/dist/node/index.d.ts +27 -2
- package/dist/node/index.js +107 -63
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +108 -64
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/browser/index.d.mts
CHANGED
|
@@ -623,6 +623,12 @@ declare enum AssetParser {
|
|
|
623
623
|
declare abstract class AssetSource {
|
|
624
624
|
protected constructor();
|
|
625
625
|
abstract get<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser | string): Promise<Maybe<T>>;
|
|
626
|
+
/**
|
|
627
|
+
* Identifies this source's content across sessions for persistent caching. Sources that
|
|
628
|
+
* cannot tell whether their content changed (an unnamed archive, for example) return
|
|
629
|
+
* undefined, which keeps their results out of long-lived caches.
|
|
630
|
+
*/
|
|
631
|
+
get cacheId(): Maybe<string>;
|
|
626
632
|
}
|
|
627
633
|
/** A source failed to load or parse an asset; cause retains the original failure. */
|
|
628
634
|
declare class AssetLoadError extends Error {
|
|
@@ -636,8 +642,18 @@ declare class AssetLoadError extends Error {
|
|
|
636
642
|
declare class AssetLoader {
|
|
637
643
|
static ROOT: string;
|
|
638
644
|
private static _SOURCES;
|
|
645
|
+
/** Used when a registered source cannot identify its content, so nothing persists past this session. */
|
|
646
|
+
private static readonly SESSION_SCOPE;
|
|
639
647
|
static get version(): string;
|
|
640
648
|
static setVersion(version: string): void;
|
|
649
|
+
/**
|
|
650
|
+
* Scope for persistent cache keys. Empty with only the default vanilla sources, so their
|
|
651
|
+
* entries stay valid across sessions; otherwise it names every added source (resource packs,
|
|
652
|
+
* mirrors) so their results never masquerade as vanilla assets after a reload.
|
|
653
|
+
*/
|
|
654
|
+
static get persistentScope(): string;
|
|
655
|
+
/** Prefixes a persistent cache key with the current source scope. */
|
|
656
|
+
static persistentKey(key: string): string;
|
|
641
657
|
static addSource(key: string, source: AssetSource, override?: boolean): void;
|
|
642
658
|
static removeSource(key: string): Maybe<AssetSource>;
|
|
643
659
|
static getAll<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser | string): Promise<T[]>;
|
|
@@ -903,12 +919,14 @@ declare class SkinObject extends SceneObject {
|
|
|
903
919
|
private skinTextureSrc?;
|
|
904
920
|
private skinMaterial?;
|
|
905
921
|
private skinLoad;
|
|
906
|
-
private
|
|
922
|
+
private capeLoad;
|
|
907
923
|
constructor(options?: DeepPartial<SkinObjectOptions>);
|
|
908
924
|
init(): Promise<void>;
|
|
909
925
|
protected removeMeshes(): void;
|
|
910
926
|
protected createMeshes(): void;
|
|
911
927
|
setSkinTexture(src: string): Promise<void>;
|
|
928
|
+
/** Load a vanilla cape texture, or pass undefined to remove the cape. */
|
|
929
|
+
setCapeTexture(src?: string): Promise<void>;
|
|
912
930
|
/** Select the arm model, or pass undefined to use texture detection. */
|
|
913
931
|
setSlim(slim?: boolean): void;
|
|
914
932
|
private updateSlim;
|
|
@@ -1186,6 +1204,7 @@ declare class HostedAssetSource extends AssetSource {
|
|
|
1186
1204
|
private readonly _options;
|
|
1187
1205
|
constructor(root: string, options?: Partial<HostedAssetSourceOptions>);
|
|
1188
1206
|
get root(): string;
|
|
1207
|
+
get cacheId(): string;
|
|
1189
1208
|
get options(): HostedAssetSourceOptions;
|
|
1190
1209
|
get<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser): Promise<Maybe<T>>;
|
|
1191
1210
|
}
|
|
@@ -1200,6 +1219,8 @@ interface ArchiveEntry {
|
|
|
1200
1219
|
}
|
|
1201
1220
|
|
|
1202
1221
|
interface ArchiveProxy {
|
|
1222
|
+
/** Identifies the archive's content across sessions; undefined when it cannot be identified. */
|
|
1223
|
+
readonly id?: string;
|
|
1203
1224
|
getEntries(): Promise<ArchiveEntry[]>;
|
|
1204
1225
|
}
|
|
1205
1226
|
|
|
@@ -1207,6 +1228,7 @@ declare class ArchiveAssetSource extends AssetSource implements ArchiveProxy {
|
|
|
1207
1228
|
readonly _archiveProxy: ArchiveProxy;
|
|
1208
1229
|
constructor(archiveProxy: ArchiveProxy);
|
|
1209
1230
|
static blob(blob: Blob): ArchiveAssetSource;
|
|
1231
|
+
get cacheId(): Maybe<string>;
|
|
1210
1232
|
getEntries(): Promise<ArchiveEntry[]>;
|
|
1211
1233
|
getEntry(path: string): Promise<Maybe<ArchiveEntry>>;
|
|
1212
1234
|
get<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser | string): Promise<Maybe<T>>;
|
|
@@ -1217,7 +1239,8 @@ declare class ArchiveAssetSource extends AssetSource implements ArchiveProxy {
|
|
|
1217
1239
|
declare class BrowserArchiveProxy implements ArchiveProxy {
|
|
1218
1240
|
readonly _blob: Blob;
|
|
1219
1241
|
readonly _reader: ZipReader<Blob>;
|
|
1220
|
-
|
|
1242
|
+
readonly id?: string;
|
|
1243
|
+
constructor(blob: Blob, id?: string);
|
|
1221
1244
|
getEntries(): Promise<ArchiveEntry[]>;
|
|
1222
1245
|
}
|
|
1223
1246
|
|
|
@@ -1562,6 +1585,8 @@ interface SkinTexture {
|
|
|
1562
1585
|
}
|
|
1563
1586
|
declare class SkinTextures {
|
|
1564
1587
|
static get(src: string, legacy?: boolean): Promise<SkinTexture>;
|
|
1588
|
+
static getCape(src: string): Promise<MeshBasicMaterial>;
|
|
1589
|
+
private static createMaterial;
|
|
1565
1590
|
private static isSlim;
|
|
1566
1591
|
private static normalizeLegacy;
|
|
1567
1592
|
}
|
package/dist/browser/index.d.ts
CHANGED
|
@@ -623,6 +623,12 @@ declare enum AssetParser {
|
|
|
623
623
|
declare abstract class AssetSource {
|
|
624
624
|
protected constructor();
|
|
625
625
|
abstract get<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser | string): Promise<Maybe<T>>;
|
|
626
|
+
/**
|
|
627
|
+
* Identifies this source's content across sessions for persistent caching. Sources that
|
|
628
|
+
* cannot tell whether their content changed (an unnamed archive, for example) return
|
|
629
|
+
* undefined, which keeps their results out of long-lived caches.
|
|
630
|
+
*/
|
|
631
|
+
get cacheId(): Maybe<string>;
|
|
626
632
|
}
|
|
627
633
|
/** A source failed to load or parse an asset; cause retains the original failure. */
|
|
628
634
|
declare class AssetLoadError extends Error {
|
|
@@ -636,8 +642,18 @@ declare class AssetLoadError extends Error {
|
|
|
636
642
|
declare class AssetLoader {
|
|
637
643
|
static ROOT: string;
|
|
638
644
|
private static _SOURCES;
|
|
645
|
+
/** Used when a registered source cannot identify its content, so nothing persists past this session. */
|
|
646
|
+
private static readonly SESSION_SCOPE;
|
|
639
647
|
static get version(): string;
|
|
640
648
|
static setVersion(version: string): void;
|
|
649
|
+
/**
|
|
650
|
+
* Scope for persistent cache keys. Empty with only the default vanilla sources, so their
|
|
651
|
+
* entries stay valid across sessions; otherwise it names every added source (resource packs,
|
|
652
|
+
* mirrors) so their results never masquerade as vanilla assets after a reload.
|
|
653
|
+
*/
|
|
654
|
+
static get persistentScope(): string;
|
|
655
|
+
/** Prefixes a persistent cache key with the current source scope. */
|
|
656
|
+
static persistentKey(key: string): string;
|
|
641
657
|
static addSource(key: string, source: AssetSource, override?: boolean): void;
|
|
642
658
|
static removeSource(key: string): Maybe<AssetSource>;
|
|
643
659
|
static getAll<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser | string): Promise<T[]>;
|
|
@@ -903,12 +919,14 @@ declare class SkinObject extends SceneObject {
|
|
|
903
919
|
private skinTextureSrc?;
|
|
904
920
|
private skinMaterial?;
|
|
905
921
|
private skinLoad;
|
|
906
|
-
private
|
|
922
|
+
private capeLoad;
|
|
907
923
|
constructor(options?: DeepPartial<SkinObjectOptions>);
|
|
908
924
|
init(): Promise<void>;
|
|
909
925
|
protected removeMeshes(): void;
|
|
910
926
|
protected createMeshes(): void;
|
|
911
927
|
setSkinTexture(src: string): Promise<void>;
|
|
928
|
+
/** Load a vanilla cape texture, or pass undefined to remove the cape. */
|
|
929
|
+
setCapeTexture(src?: string): Promise<void>;
|
|
912
930
|
/** Select the arm model, or pass undefined to use texture detection. */
|
|
913
931
|
setSlim(slim?: boolean): void;
|
|
914
932
|
private updateSlim;
|
|
@@ -1186,6 +1204,7 @@ declare class HostedAssetSource extends AssetSource {
|
|
|
1186
1204
|
private readonly _options;
|
|
1187
1205
|
constructor(root: string, options?: Partial<HostedAssetSourceOptions>);
|
|
1188
1206
|
get root(): string;
|
|
1207
|
+
get cacheId(): string;
|
|
1189
1208
|
get options(): HostedAssetSourceOptions;
|
|
1190
1209
|
get<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser): Promise<Maybe<T>>;
|
|
1191
1210
|
}
|
|
@@ -1200,6 +1219,8 @@ interface ArchiveEntry {
|
|
|
1200
1219
|
}
|
|
1201
1220
|
|
|
1202
1221
|
interface ArchiveProxy {
|
|
1222
|
+
/** Identifies the archive's content across sessions; undefined when it cannot be identified. */
|
|
1223
|
+
readonly id?: string;
|
|
1203
1224
|
getEntries(): Promise<ArchiveEntry[]>;
|
|
1204
1225
|
}
|
|
1205
1226
|
|
|
@@ -1207,6 +1228,7 @@ declare class ArchiveAssetSource extends AssetSource implements ArchiveProxy {
|
|
|
1207
1228
|
readonly _archiveProxy: ArchiveProxy;
|
|
1208
1229
|
constructor(archiveProxy: ArchiveProxy);
|
|
1209
1230
|
static blob(blob: Blob): ArchiveAssetSource;
|
|
1231
|
+
get cacheId(): Maybe<string>;
|
|
1210
1232
|
getEntries(): Promise<ArchiveEntry[]>;
|
|
1211
1233
|
getEntry(path: string): Promise<Maybe<ArchiveEntry>>;
|
|
1212
1234
|
get<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser | string): Promise<Maybe<T>>;
|
|
@@ -1217,7 +1239,8 @@ declare class ArchiveAssetSource extends AssetSource implements ArchiveProxy {
|
|
|
1217
1239
|
declare class BrowserArchiveProxy implements ArchiveProxy {
|
|
1218
1240
|
readonly _blob: Blob;
|
|
1219
1241
|
readonly _reader: ZipReader<Blob>;
|
|
1220
|
-
|
|
1242
|
+
readonly id?: string;
|
|
1243
|
+
constructor(blob: Blob, id?: string);
|
|
1221
1244
|
getEntries(): Promise<ArchiveEntry[]>;
|
|
1222
1245
|
}
|
|
1223
1246
|
|
|
@@ -1562,6 +1585,8 @@ interface SkinTexture {
|
|
|
1562
1585
|
}
|
|
1563
1586
|
declare class SkinTextures {
|
|
1564
1587
|
static get(src: string, legacy?: boolean): Promise<SkinTexture>;
|
|
1588
|
+
static getCape(src: string): Promise<MeshBasicMaterial>;
|
|
1589
|
+
private static createMaterial;
|
|
1565
1590
|
private static isSlim;
|
|
1566
1591
|
private static normalizeLegacy;
|
|
1567
1592
|
}
|
package/dist/browser/index.js
CHANGED
|
@@ -1468,7 +1468,7 @@ var Models = class _Models {
|
|
|
1468
1468
|
}
|
|
1469
1469
|
static async getItemModel(key) {
|
|
1470
1470
|
const itemKey = new AssetKey(key.namespace, key.path, "items", void 0, key.rootType, ".json", key.root);
|
|
1471
|
-
const model = await this.PERSISTENT_CACHE.getOrLoad(itemKey.serialize(), async () => {
|
|
1471
|
+
const model = await this.PERSISTENT_CACHE.getOrLoad(AssetLoader.persistentKey(itemKey.serialize()), async () => {
|
|
1472
1472
|
const result = await AssetLoader.getFirst([itemKey, key], "json" /* JSON */);
|
|
1473
1473
|
if (!result) return void 0;
|
|
1474
1474
|
if (result.key.assetType !== "items") return { ...result.asset, key };
|
|
@@ -1514,7 +1514,7 @@ var Models = class _Models {
|
|
|
1514
1514
|
}
|
|
1515
1515
|
const keyStr = key.serialize();
|
|
1516
1516
|
return Caching.rawModelCache.get(keyStr, (k) => {
|
|
1517
|
-
return this.PERSISTENT_CACHE.getOrLoad(keyStr, (k1) => {
|
|
1517
|
+
return this.PERSISTENT_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), (k1) => {
|
|
1518
1518
|
return AssetLoader.get(key, "model" /* MODEL */);
|
|
1519
1519
|
});
|
|
1520
1520
|
}).then((asset) => {
|
|
@@ -1586,7 +1586,7 @@ var BlockStates = class {
|
|
|
1586
1586
|
}
|
|
1587
1587
|
const keyStr = key.serialize();
|
|
1588
1588
|
return Caching.blockStateCache.get(keyStr, (k) => {
|
|
1589
|
-
return this.PERSISTENT_CACHE.getOrLoad(keyStr, (k1) => {
|
|
1589
|
+
return this.PERSISTENT_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), (k1) => {
|
|
1590
1590
|
return AssetLoader.get(key, "blockstate" /* BLOCKSTATE */);
|
|
1591
1591
|
});
|
|
1592
1592
|
}).then((asset) => {
|
|
@@ -1632,6 +1632,14 @@ var Assets = class {
|
|
|
1632
1632
|
var AssetSource = class {
|
|
1633
1633
|
constructor() {
|
|
1634
1634
|
}
|
|
1635
|
+
/**
|
|
1636
|
+
* Identifies this source's content across sessions for persistent caching. Sources that
|
|
1637
|
+
* cannot tell whether their content changed (an unnamed archive, for example) return
|
|
1638
|
+
* undefined, which keeps their results out of long-lived caches.
|
|
1639
|
+
*/
|
|
1640
|
+
get cacheId() {
|
|
1641
|
+
return void 0;
|
|
1642
|
+
}
|
|
1635
1643
|
};
|
|
1636
1644
|
var AssetLoadError = class extends Error {
|
|
1637
1645
|
constructor(source, key, path, cause) {
|
|
@@ -1844,6 +1852,9 @@ var _HostedAssetSource = class _HostedAssetSource extends AssetSource {
|
|
|
1844
1852
|
get root() {
|
|
1845
1853
|
return this._root;
|
|
1846
1854
|
}
|
|
1855
|
+
get cacheId() {
|
|
1856
|
+
return `hosted:${this._root}`;
|
|
1857
|
+
}
|
|
1847
1858
|
get options() {
|
|
1848
1859
|
return this._options;
|
|
1849
1860
|
}
|
|
@@ -1920,9 +1931,10 @@ var HostedAssetSource = _HostedAssetSource;
|
|
|
1920
1931
|
// src/assets/source/archive/BrowserArchiveProxy.ts
|
|
1921
1932
|
var import_zip = require("@zip.js/zip.js");
|
|
1922
1933
|
var BrowserArchiveProxy = class {
|
|
1923
|
-
constructor(blob) {
|
|
1934
|
+
constructor(blob, id) {
|
|
1924
1935
|
this._blob = blob;
|
|
1925
1936
|
this._reader = new import_zip.ZipReader(new import_zip.BlobReader(this._blob));
|
|
1937
|
+
this.id = id ?? (typeof File !== "undefined" && blob instanceof File ? `${blob.name}:${blob.size}:${blob.lastModified}` : void 0);
|
|
1926
1938
|
}
|
|
1927
1939
|
async getEntries() {
|
|
1928
1940
|
return (await this._reader.getEntries()).map((e) => {
|
|
@@ -1947,6 +1959,10 @@ var ArchiveAssetSource = class _ArchiveAssetSource extends AssetSource {
|
|
|
1947
1959
|
static blob(blob) {
|
|
1948
1960
|
return new _ArchiveAssetSource(new BrowserArchiveProxy(blob));
|
|
1949
1961
|
}
|
|
1962
|
+
get cacheId() {
|
|
1963
|
+
const id = this._archiveProxy.id;
|
|
1964
|
+
return id === void 0 ? void 0 : `archive:${id}`;
|
|
1965
|
+
}
|
|
1950
1966
|
async getEntries() {
|
|
1951
1967
|
return this._archiveProxy.getEntries();
|
|
1952
1968
|
}
|
|
@@ -1989,6 +2005,7 @@ var ArchiveAssetSource = class _ArchiveAssetSource extends AssetSource {
|
|
|
1989
2005
|
|
|
1990
2006
|
// src/assets/AssetLoader.ts
|
|
1991
2007
|
var p4 = prefix("AssetLoader");
|
|
2008
|
+
var FALLBACK_ROOT = "https://raw.githubusercontent.com/InventivetalentDev/minerender-fallback-assets/master";
|
|
1992
2009
|
var _AssetLoader = class _AssetLoader {
|
|
1993
2010
|
static get version() {
|
|
1994
2011
|
return this.ROOT.substring(this.ROOT.lastIndexOf("/") + 1);
|
|
@@ -2004,6 +2021,28 @@ var _AssetLoader = class _AssetLoader {
|
|
|
2004
2021
|
}
|
|
2005
2022
|
Caching.clear();
|
|
2006
2023
|
}
|
|
2024
|
+
/**
|
|
2025
|
+
* Scope for persistent cache keys. Empty with only the default vanilla sources, so their
|
|
2026
|
+
* entries stay valid across sessions; otherwise it names every added source (resource packs,
|
|
2027
|
+
* mirrors) so their results never masquerade as vanilla assets after a reload.
|
|
2028
|
+
*/
|
|
2029
|
+
static get persistentScope() {
|
|
2030
|
+
const parts = [];
|
|
2031
|
+
for (const { key, source } of this._SOURCES) {
|
|
2032
|
+
const id = source.cacheId;
|
|
2033
|
+
if (key === "mcassets" && id === `hosted:${this.ROOT}`) continue;
|
|
2034
|
+
if (key === "mcassets-fallback" && id === `hosted:${FALLBACK_ROOT}`) continue;
|
|
2035
|
+
if (id === void 0) return this.SESSION_SCOPE;
|
|
2036
|
+
parts.push(`${key}=${id}`);
|
|
2037
|
+
}
|
|
2038
|
+
return parts.join("|");
|
|
2039
|
+
}
|
|
2040
|
+
/** Prefixes a persistent cache key with the current source scope. */
|
|
2041
|
+
static persistentKey(key) {
|
|
2042
|
+
const scope = this.persistentScope;
|
|
2043
|
+
return scope ? `${scope}
|
|
2044
|
+
${key}` : key;
|
|
2045
|
+
}
|
|
2007
2046
|
static addSource(key, source, override = true) {
|
|
2008
2047
|
if (override) {
|
|
2009
2048
|
const existing = this.removeSource(key);
|
|
@@ -2065,7 +2104,9 @@ var _AssetLoader = class _AssetLoader {
|
|
|
2065
2104
|
};
|
|
2066
2105
|
_AssetLoader.ROOT = DEFAULT_ROOT;
|
|
2067
2106
|
_AssetLoader._SOURCES = [];
|
|
2068
|
-
|
|
2107
|
+
/** Used when a registered source cannot identify its content, so nothing persists past this session. */
|
|
2108
|
+
_AssetLoader.SESSION_SCOPE = `session:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
|
|
2109
|
+
_AssetLoader.addSource("mcassets-fallback", new HostedAssetSource(FALLBACK_ROOT, { retryDefaults: false }));
|
|
2069
2110
|
_AssetLoader.addSource("mcassets", new HostedAssetSource(_AssetLoader.ROOT, { retryDefaults: false }));
|
|
2070
2111
|
var AssetLoader = _AssetLoader;
|
|
2071
2112
|
|
|
@@ -2108,7 +2149,7 @@ var ModelTextures = class {
|
|
|
2108
2149
|
}
|
|
2109
2150
|
const keyStr = key.serialize();
|
|
2110
2151
|
return Caching.textureMetaCache.get(keyStr, (k) => {
|
|
2111
|
-
return this.PERSISTENT_META_CACHE.getOrLoad(keyStr, (k1) => {
|
|
2152
|
+
return this.PERSISTENT_META_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), (k1) => {
|
|
2112
2153
|
return AssetLoader.get(key, "meta" /* META */).then((asset) => {
|
|
2113
2154
|
if (asset)
|
|
2114
2155
|
asset.key = key;
|
|
@@ -4755,7 +4796,9 @@ var _BlockObject = class _BlockObject extends SceneObject {
|
|
|
4755
4796
|
if (typeof variant.y !== "undefined") {
|
|
4756
4797
|
rotation.y = toRadians(clampRotationDegrees(typeof variant.x !== "undefined" ? variant.y : 360 - variant.y));
|
|
4757
4798
|
}
|
|
4758
|
-
const
|
|
4799
|
+
const modelKey = AssetKey.parse("models", variant.model);
|
|
4800
|
+
modelKey.root = this.blockState.key?.root;
|
|
4801
|
+
const model = await Models.getMerged(modelKey);
|
|
4759
4802
|
const options = {
|
|
4760
4803
|
...this.options,
|
|
4761
4804
|
tints: model ? await BlockTints.get(this.blockState.key, this.state, model, this.options.tints) : this.options.tints,
|
|
@@ -5551,56 +5594,12 @@ var baseSkinCoordinates = {
|
|
|
5551
5594
|
}
|
|
5552
5595
|
},
|
|
5553
5596
|
cape: {
|
|
5554
|
-
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5560
|
-
48
|
|
5561
|
-
]
|
|
5562
|
-
},
|
|
5563
|
-
west: {
|
|
5564
|
-
uv: [
|
|
5565
|
-
8,
|
|
5566
|
-
36,
|
|
5567
|
-
12,
|
|
5568
|
-
48
|
|
5569
|
-
]
|
|
5570
|
-
},
|
|
5571
|
-
north: {
|
|
5572
|
-
uv: [
|
|
5573
|
-
4,
|
|
5574
|
-
36,
|
|
5575
|
-
8,
|
|
5576
|
-
48
|
|
5577
|
-
]
|
|
5578
|
-
},
|
|
5579
|
-
south: {
|
|
5580
|
-
uv: [
|
|
5581
|
-
12,
|
|
5582
|
-
36,
|
|
5583
|
-
16,
|
|
5584
|
-
48
|
|
5585
|
-
]
|
|
5586
|
-
},
|
|
5587
|
-
up: {
|
|
5588
|
-
uv: [
|
|
5589
|
-
4,
|
|
5590
|
-
32,
|
|
5591
|
-
8,
|
|
5592
|
-
36
|
|
5593
|
-
]
|
|
5594
|
-
},
|
|
5595
|
-
down: {
|
|
5596
|
-
uv: [
|
|
5597
|
-
8,
|
|
5598
|
-
32,
|
|
5599
|
-
12,
|
|
5600
|
-
36
|
|
5601
|
-
],
|
|
5602
|
-
rotation: 180
|
|
5603
|
-
}
|
|
5597
|
+
east: { uv: [0, 1, 1, 17] },
|
|
5598
|
+
west: { uv: [11, 1, 12, 17] },
|
|
5599
|
+
north: { uv: [1, 1, 11, 17] },
|
|
5600
|
+
south: { uv: [12, 1, 22, 17] },
|
|
5601
|
+
up: { uv: [11, 1, 1, 0] },
|
|
5602
|
+
down: { uv: [21, 0, 11, 1] }
|
|
5604
5603
|
}
|
|
5605
5604
|
};
|
|
5606
5605
|
var classicSkinTextureCoordinates = {
|
|
@@ -5699,14 +5698,27 @@ var SkinTextures = class {
|
|
|
5699
5698
|
const key = `skin:${serializeImageKey({ src })}:${isLegacy}`;
|
|
5700
5699
|
const material = Caching.materialCache.get(key, () => {
|
|
5701
5700
|
const pixels = isLegacy ? this.normalizeLegacy(image, scale) : new Uint8Array(image.data);
|
|
5702
|
-
|
|
5703
|
-
texture.colorSpace = import_three18.SRGBColorSpace;
|
|
5704
|
-
texture.flipY = true;
|
|
5705
|
-
texture.needsUpdate = true;
|
|
5706
|
-
return new import_three18.MeshBasicMaterial({ map: texture, transparent: true, side: import_three18.DoubleSide, alphaTest: 0.5 });
|
|
5701
|
+
return this.createMaterial(pixels, image.width, image.width);
|
|
5707
5702
|
});
|
|
5708
5703
|
return { material, slim, legacy: isLegacy };
|
|
5709
5704
|
}
|
|
5705
|
+
static async getCape(src) {
|
|
5706
|
+
const image = await ImageLoader.getData(src);
|
|
5707
|
+
const scale = image.width / 64;
|
|
5708
|
+
if (!Number.isInteger(scale) || scale < 1 || image.height !== image.width / 2) {
|
|
5709
|
+
throw new MineRenderError(`Invalid cape dimensions ${image.width}x${image.height}; expected 64x32 or an integer-scaled equivalent`);
|
|
5710
|
+
}
|
|
5711
|
+
return Caching.materialCache.get(`cape:${serializeImageKey({ src })}`, () => {
|
|
5712
|
+
return this.createMaterial(new Uint8Array(image.data), image.width, image.height, false);
|
|
5713
|
+
});
|
|
5714
|
+
}
|
|
5715
|
+
static createMaterial(pixels, width, height, transparent = true) {
|
|
5716
|
+
const texture = Textures.initTextureProps(new import_three18.DataTexture(pixels, width, height));
|
|
5717
|
+
texture.colorSpace = import_three18.SRGBColorSpace;
|
|
5718
|
+
texture.flipY = true;
|
|
5719
|
+
texture.needsUpdate = true;
|
|
5720
|
+
return new import_three18.MeshBasicMaterial({ map: texture, transparent, side: transparent ? import_three18.DoubleSide : import_three18.FrontSide, alphaTest: transparent ? 0.5 : 0 });
|
|
5721
|
+
}
|
|
5710
5722
|
static isSlim(image, scale) {
|
|
5711
5723
|
for (const [x, y] of [[46, 52], [54, 20]]) {
|
|
5712
5724
|
for (let row = y * scale; row < (y + 12) * scale; row++) {
|
|
@@ -5769,6 +5781,7 @@ var SkinObject = class extends SceneObject {
|
|
|
5769
5781
|
this.slim = false;
|
|
5770
5782
|
this.detectedSlim = false;
|
|
5771
5783
|
this.skinLoad = 0;
|
|
5784
|
+
this.capeLoad = 0;
|
|
5772
5785
|
this.options = (0, import_ts_deepmerge7.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
|
|
5773
5786
|
this.slim = this.options.slim ?? false;
|
|
5774
5787
|
}
|
|
@@ -5838,6 +5851,7 @@ var SkinObject = class extends SceneObject {
|
|
|
5838
5851
|
this.detectedSlim = texture.slim;
|
|
5839
5852
|
this.updateSlim(this.options.slim ?? this.detectedSlim);
|
|
5840
5853
|
for (const part of SKIN_PARTS) {
|
|
5854
|
+
if (part === "cape" /* CAPE */) continue;
|
|
5841
5855
|
const mesh = this.getMeshByName(part);
|
|
5842
5856
|
if (mesh) {
|
|
5843
5857
|
mesh.material = texture.material;
|
|
@@ -5845,7 +5859,34 @@ var SkinObject = class extends SceneObject {
|
|
|
5845
5859
|
}
|
|
5846
5860
|
this.notifyDirty();
|
|
5847
5861
|
}
|
|
5848
|
-
|
|
5862
|
+
/** Load a vanilla cape texture, or pass undefined to remove the cape. */
|
|
5863
|
+
async setCapeTexture(src) {
|
|
5864
|
+
const load = ++this.capeLoad;
|
|
5865
|
+
if (src === void 0) {
|
|
5866
|
+
const group = this.getGroupByName("cape" /* CAPE */);
|
|
5867
|
+
if (group) this.remove(group);
|
|
5868
|
+
this.notifyDirty();
|
|
5869
|
+
return;
|
|
5870
|
+
}
|
|
5871
|
+
const material = await SkinTextures.getCape(src);
|
|
5872
|
+
if (load !== this.capeLoad) return;
|
|
5873
|
+
const mesh = this.getMeshByName("cape" /* CAPE */);
|
|
5874
|
+
if (mesh) {
|
|
5875
|
+
mesh.material = material;
|
|
5876
|
+
} else {
|
|
5877
|
+
const group = this.createAndAddGroup("cape" /* CAPE */, 0, 24, 2);
|
|
5878
|
+
group.rotation.set(toRadians(-6), Math.PI, 0);
|
|
5879
|
+
const geometry = this._getBoxGeometryFromDimensions(
|
|
5880
|
+
classicSkinGeometries.cape,
|
|
5881
|
+
classicSkinTextureCoordinates.cape,
|
|
5882
|
+
[64, 32],
|
|
5883
|
+
[64, 32]
|
|
5884
|
+
);
|
|
5885
|
+
const cape = this.createAndAddMesh("cape" /* CAPE */, group, geometry, material);
|
|
5886
|
+
cape.position.set(0, -8, -0.5);
|
|
5887
|
+
}
|
|
5888
|
+
this.notifyDirty();
|
|
5889
|
+
}
|
|
5849
5890
|
/** Select the arm model, or pass undefined to use texture detection. */
|
|
5850
5891
|
setSlim(slim) {
|
|
5851
5892
|
this.options.slim = slim;
|
|
@@ -5873,6 +5914,7 @@ var SkinObject = class extends SceneObject {
|
|
|
5873
5914
|
}
|
|
5874
5915
|
dispose() {
|
|
5875
5916
|
this.skinLoad++;
|
|
5917
|
+
this.capeLoad++;
|
|
5876
5918
|
super.dispose();
|
|
5877
5919
|
}
|
|
5878
5920
|
//TODO: layer toggles
|