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/node/index.d.mts
CHANGED
|
@@ -624,6 +624,12 @@ declare enum AssetParser {
|
|
|
624
624
|
declare abstract class AssetSource {
|
|
625
625
|
protected constructor();
|
|
626
626
|
abstract get<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser | string): Promise<Maybe<T>>;
|
|
627
|
+
/**
|
|
628
|
+
* Identifies this source's content across sessions for persistent caching. Sources that
|
|
629
|
+
* cannot tell whether their content changed (an unnamed archive, for example) return
|
|
630
|
+
* undefined, which keeps their results out of long-lived caches.
|
|
631
|
+
*/
|
|
632
|
+
get cacheId(): Maybe<string>;
|
|
627
633
|
}
|
|
628
634
|
/** A source failed to load or parse an asset; cause retains the original failure. */
|
|
629
635
|
declare class AssetLoadError extends Error {
|
|
@@ -637,8 +643,18 @@ declare class AssetLoadError extends Error {
|
|
|
637
643
|
declare class AssetLoader {
|
|
638
644
|
static ROOT: string;
|
|
639
645
|
private static _SOURCES;
|
|
646
|
+
/** Used when a registered source cannot identify its content, so nothing persists past this session. */
|
|
647
|
+
private static readonly SESSION_SCOPE;
|
|
640
648
|
static get version(): string;
|
|
641
649
|
static setVersion(version: string): void;
|
|
650
|
+
/**
|
|
651
|
+
* Scope for persistent cache keys. Empty with only the default vanilla sources, so their
|
|
652
|
+
* entries stay valid across sessions; otherwise it names every added source (resource packs,
|
|
653
|
+
* mirrors) so their results never masquerade as vanilla assets after a reload.
|
|
654
|
+
*/
|
|
655
|
+
static get persistentScope(): string;
|
|
656
|
+
/** Prefixes a persistent cache key with the current source scope. */
|
|
657
|
+
static persistentKey(key: string): string;
|
|
642
658
|
static addSource(key: string, source: AssetSource, override?: boolean): void;
|
|
643
659
|
static removeSource(key: string): Maybe<AssetSource>;
|
|
644
660
|
static getAll<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser | string): Promise<T[]>;
|
|
@@ -904,12 +920,14 @@ declare class SkinObject extends SceneObject {
|
|
|
904
920
|
private skinTextureSrc?;
|
|
905
921
|
private skinMaterial?;
|
|
906
922
|
private skinLoad;
|
|
907
|
-
private
|
|
923
|
+
private capeLoad;
|
|
908
924
|
constructor(options?: DeepPartial<SkinObjectOptions>);
|
|
909
925
|
init(): Promise<void>;
|
|
910
926
|
protected removeMeshes(): void;
|
|
911
927
|
protected createMeshes(): void;
|
|
912
928
|
setSkinTexture(src: string): Promise<void>;
|
|
929
|
+
/** Load a vanilla cape texture, or pass undefined to remove the cape. */
|
|
930
|
+
setCapeTexture(src?: string): Promise<void>;
|
|
913
931
|
/** Select the arm model, or pass undefined to use texture detection. */
|
|
914
932
|
setSlim(slim?: boolean): void;
|
|
915
933
|
private updateSlim;
|
|
@@ -1187,6 +1205,7 @@ declare class HostedAssetSource extends AssetSource {
|
|
|
1187
1205
|
private readonly _options;
|
|
1188
1206
|
constructor(root: string, options?: Partial<HostedAssetSourceOptions>);
|
|
1189
1207
|
get root(): string;
|
|
1208
|
+
get cacheId(): string;
|
|
1190
1209
|
get options(): HostedAssetSourceOptions;
|
|
1191
1210
|
get<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser): Promise<Maybe<T>>;
|
|
1192
1211
|
}
|
|
@@ -1201,6 +1220,8 @@ interface ArchiveEntry {
|
|
|
1201
1220
|
}
|
|
1202
1221
|
|
|
1203
1222
|
interface ArchiveProxy {
|
|
1223
|
+
/** Identifies the archive's content across sessions; undefined when it cannot be identified. */
|
|
1224
|
+
readonly id?: string;
|
|
1204
1225
|
getEntries(): Promise<ArchiveEntry[]>;
|
|
1205
1226
|
}
|
|
1206
1227
|
|
|
@@ -1208,6 +1229,7 @@ declare class ArchiveAssetSource extends AssetSource implements ArchiveProxy {
|
|
|
1208
1229
|
readonly _archiveProxy: ArchiveProxy;
|
|
1209
1230
|
constructor(archiveProxy: ArchiveProxy);
|
|
1210
1231
|
static blob(blob: Blob): ArchiveAssetSource;
|
|
1232
|
+
get cacheId(): Maybe<string>;
|
|
1211
1233
|
getEntries(): Promise<ArchiveEntry[]>;
|
|
1212
1234
|
getEntry(path: string): Promise<Maybe<ArchiveEntry>>;
|
|
1213
1235
|
get<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser | string): Promise<Maybe<T>>;
|
|
@@ -1218,7 +1240,8 @@ declare class ArchiveAssetSource extends AssetSource implements ArchiveProxy {
|
|
|
1218
1240
|
declare class BrowserArchiveProxy implements ArchiveProxy {
|
|
1219
1241
|
readonly _blob: Blob;
|
|
1220
1242
|
readonly _reader: ZipReader<Blob>;
|
|
1221
|
-
|
|
1243
|
+
readonly id?: string;
|
|
1244
|
+
constructor(blob: Blob, id?: string);
|
|
1222
1245
|
getEntries(): Promise<ArchiveEntry[]>;
|
|
1223
1246
|
}
|
|
1224
1247
|
|
|
@@ -1563,6 +1586,8 @@ interface SkinTexture {
|
|
|
1563
1586
|
}
|
|
1564
1587
|
declare class SkinTextures {
|
|
1565
1588
|
static get(src: string, legacy?: boolean): Promise<SkinTexture>;
|
|
1589
|
+
static getCape(src: string): Promise<MeshBasicMaterial>;
|
|
1590
|
+
private static createMaterial;
|
|
1566
1591
|
private static isSlim;
|
|
1567
1592
|
private static normalizeLegacy;
|
|
1568
1593
|
}
|
package/dist/node/index.d.ts
CHANGED
|
@@ -624,6 +624,12 @@ declare enum AssetParser {
|
|
|
624
624
|
declare abstract class AssetSource {
|
|
625
625
|
protected constructor();
|
|
626
626
|
abstract get<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser | string): Promise<Maybe<T>>;
|
|
627
|
+
/**
|
|
628
|
+
* Identifies this source's content across sessions for persistent caching. Sources that
|
|
629
|
+
* cannot tell whether their content changed (an unnamed archive, for example) return
|
|
630
|
+
* undefined, which keeps their results out of long-lived caches.
|
|
631
|
+
*/
|
|
632
|
+
get cacheId(): Maybe<string>;
|
|
627
633
|
}
|
|
628
634
|
/** A source failed to load or parse an asset; cause retains the original failure. */
|
|
629
635
|
declare class AssetLoadError extends Error {
|
|
@@ -637,8 +643,18 @@ declare class AssetLoadError extends Error {
|
|
|
637
643
|
declare class AssetLoader {
|
|
638
644
|
static ROOT: string;
|
|
639
645
|
private static _SOURCES;
|
|
646
|
+
/** Used when a registered source cannot identify its content, so nothing persists past this session. */
|
|
647
|
+
private static readonly SESSION_SCOPE;
|
|
640
648
|
static get version(): string;
|
|
641
649
|
static setVersion(version: string): void;
|
|
650
|
+
/**
|
|
651
|
+
* Scope for persistent cache keys. Empty with only the default vanilla sources, so their
|
|
652
|
+
* entries stay valid across sessions; otherwise it names every added source (resource packs,
|
|
653
|
+
* mirrors) so their results never masquerade as vanilla assets after a reload.
|
|
654
|
+
*/
|
|
655
|
+
static get persistentScope(): string;
|
|
656
|
+
/** Prefixes a persistent cache key with the current source scope. */
|
|
657
|
+
static persistentKey(key: string): string;
|
|
642
658
|
static addSource(key: string, source: AssetSource, override?: boolean): void;
|
|
643
659
|
static removeSource(key: string): Maybe<AssetSource>;
|
|
644
660
|
static getAll<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser | string): Promise<T[]>;
|
|
@@ -904,12 +920,14 @@ declare class SkinObject extends SceneObject {
|
|
|
904
920
|
private skinTextureSrc?;
|
|
905
921
|
private skinMaterial?;
|
|
906
922
|
private skinLoad;
|
|
907
|
-
private
|
|
923
|
+
private capeLoad;
|
|
908
924
|
constructor(options?: DeepPartial<SkinObjectOptions>);
|
|
909
925
|
init(): Promise<void>;
|
|
910
926
|
protected removeMeshes(): void;
|
|
911
927
|
protected createMeshes(): void;
|
|
912
928
|
setSkinTexture(src: string): Promise<void>;
|
|
929
|
+
/** Load a vanilla cape texture, or pass undefined to remove the cape. */
|
|
930
|
+
setCapeTexture(src?: string): Promise<void>;
|
|
913
931
|
/** Select the arm model, or pass undefined to use texture detection. */
|
|
914
932
|
setSlim(slim?: boolean): void;
|
|
915
933
|
private updateSlim;
|
|
@@ -1187,6 +1205,7 @@ declare class HostedAssetSource extends AssetSource {
|
|
|
1187
1205
|
private readonly _options;
|
|
1188
1206
|
constructor(root: string, options?: Partial<HostedAssetSourceOptions>);
|
|
1189
1207
|
get root(): string;
|
|
1208
|
+
get cacheId(): string;
|
|
1190
1209
|
get options(): HostedAssetSourceOptions;
|
|
1191
1210
|
get<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser): Promise<Maybe<T>>;
|
|
1192
1211
|
}
|
|
@@ -1201,6 +1220,8 @@ interface ArchiveEntry {
|
|
|
1201
1220
|
}
|
|
1202
1221
|
|
|
1203
1222
|
interface ArchiveProxy {
|
|
1223
|
+
/** Identifies the archive's content across sessions; undefined when it cannot be identified. */
|
|
1224
|
+
readonly id?: string;
|
|
1204
1225
|
getEntries(): Promise<ArchiveEntry[]>;
|
|
1205
1226
|
}
|
|
1206
1227
|
|
|
@@ -1208,6 +1229,7 @@ declare class ArchiveAssetSource extends AssetSource implements ArchiveProxy {
|
|
|
1208
1229
|
readonly _archiveProxy: ArchiveProxy;
|
|
1209
1230
|
constructor(archiveProxy: ArchiveProxy);
|
|
1210
1231
|
static blob(blob: Blob): ArchiveAssetSource;
|
|
1232
|
+
get cacheId(): Maybe<string>;
|
|
1211
1233
|
getEntries(): Promise<ArchiveEntry[]>;
|
|
1212
1234
|
getEntry(path: string): Promise<Maybe<ArchiveEntry>>;
|
|
1213
1235
|
get<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser | string): Promise<Maybe<T>>;
|
|
@@ -1218,7 +1240,8 @@ declare class ArchiveAssetSource extends AssetSource implements ArchiveProxy {
|
|
|
1218
1240
|
declare class BrowserArchiveProxy implements ArchiveProxy {
|
|
1219
1241
|
readonly _blob: Blob;
|
|
1220
1242
|
readonly _reader: ZipReader<Blob>;
|
|
1221
|
-
|
|
1243
|
+
readonly id?: string;
|
|
1244
|
+
constructor(blob: Blob, id?: string);
|
|
1222
1245
|
getEntries(): Promise<ArchiveEntry[]>;
|
|
1223
1246
|
}
|
|
1224
1247
|
|
|
@@ -1563,6 +1586,8 @@ interface SkinTexture {
|
|
|
1563
1586
|
}
|
|
1564
1587
|
declare class SkinTextures {
|
|
1565
1588
|
static get(src: string, legacy?: boolean): Promise<SkinTexture>;
|
|
1589
|
+
static getCape(src: string): Promise<MeshBasicMaterial>;
|
|
1590
|
+
private static createMaterial;
|
|
1566
1591
|
private static isSlim;
|
|
1567
1592
|
private static normalizeLegacy;
|
|
1568
1593
|
}
|
package/dist/node/index.js
CHANGED
|
@@ -1474,7 +1474,7 @@ var Models = class _Models {
|
|
|
1474
1474
|
}
|
|
1475
1475
|
static async getItemModel(key) {
|
|
1476
1476
|
const itemKey = new AssetKey(key.namespace, key.path, "items", void 0, key.rootType, ".json", key.root);
|
|
1477
|
-
const model = await this.PERSISTENT_CACHE.getOrLoad(itemKey.serialize(), async () => {
|
|
1477
|
+
const model = await this.PERSISTENT_CACHE.getOrLoad(AssetLoader.persistentKey(itemKey.serialize()), async () => {
|
|
1478
1478
|
const result = await AssetLoader.getFirst([itemKey, key], "json" /* JSON */);
|
|
1479
1479
|
if (!result) return void 0;
|
|
1480
1480
|
if (result.key.assetType !== "items") return { ...result.asset, key };
|
|
@@ -1520,7 +1520,7 @@ var Models = class _Models {
|
|
|
1520
1520
|
}
|
|
1521
1521
|
const keyStr = key.serialize();
|
|
1522
1522
|
return Caching.rawModelCache.get(keyStr, (k) => {
|
|
1523
|
-
return this.PERSISTENT_CACHE.getOrLoad(keyStr, (k1) => {
|
|
1523
|
+
return this.PERSISTENT_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), (k1) => {
|
|
1524
1524
|
return AssetLoader.get(key, "model" /* MODEL */);
|
|
1525
1525
|
});
|
|
1526
1526
|
}).then((asset) => {
|
|
@@ -1592,7 +1592,7 @@ var BlockStates = class {
|
|
|
1592
1592
|
}
|
|
1593
1593
|
const keyStr = key.serialize();
|
|
1594
1594
|
return Caching.blockStateCache.get(keyStr, (k) => {
|
|
1595
|
-
return this.PERSISTENT_CACHE.getOrLoad(keyStr, (k1) => {
|
|
1595
|
+
return this.PERSISTENT_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), (k1) => {
|
|
1596
1596
|
return AssetLoader.get(key, "blockstate" /* BLOCKSTATE */);
|
|
1597
1597
|
});
|
|
1598
1598
|
}).then((asset) => {
|
|
@@ -1638,6 +1638,14 @@ var Assets = class {
|
|
|
1638
1638
|
var AssetSource = class {
|
|
1639
1639
|
constructor() {
|
|
1640
1640
|
}
|
|
1641
|
+
/**
|
|
1642
|
+
* Identifies this source's content across sessions for persistent caching. Sources that
|
|
1643
|
+
* cannot tell whether their content changed (an unnamed archive, for example) return
|
|
1644
|
+
* undefined, which keeps their results out of long-lived caches.
|
|
1645
|
+
*/
|
|
1646
|
+
get cacheId() {
|
|
1647
|
+
return void 0;
|
|
1648
|
+
}
|
|
1641
1649
|
};
|
|
1642
1650
|
var AssetLoadError = class extends Error {
|
|
1643
1651
|
constructor(source, key, path, cause) {
|
|
@@ -1926,6 +1934,9 @@ var HostedAssetSource = class _HostedAssetSource extends AssetSource {
|
|
|
1926
1934
|
get root() {
|
|
1927
1935
|
return this._root;
|
|
1928
1936
|
}
|
|
1937
|
+
get cacheId() {
|
|
1938
|
+
return `hosted:${this._root}`;
|
|
1939
|
+
}
|
|
1929
1940
|
get options() {
|
|
1930
1941
|
return this._options;
|
|
1931
1942
|
}
|
|
@@ -1941,9 +1952,10 @@ var HostedAssetSource = class _HostedAssetSource extends AssetSource {
|
|
|
1941
1952
|
// src/assets/source/archive/BrowserArchiveProxy.ts
|
|
1942
1953
|
var import_zip = require("@zip.js/zip.js");
|
|
1943
1954
|
var BrowserArchiveProxy = class {
|
|
1944
|
-
constructor(blob) {
|
|
1955
|
+
constructor(blob, id) {
|
|
1945
1956
|
this._blob = blob;
|
|
1946
1957
|
this._reader = new import_zip.ZipReader(new import_zip.BlobReader(this._blob));
|
|
1958
|
+
this.id = id ?? (typeof File !== "undefined" && blob instanceof File ? `${blob.name}:${blob.size}:${blob.lastModified}` : void 0);
|
|
1947
1959
|
}
|
|
1948
1960
|
async getEntries() {
|
|
1949
1961
|
return (await this._reader.getEntries()).map((e) => {
|
|
@@ -1968,6 +1980,10 @@ var ArchiveAssetSource = class _ArchiveAssetSource extends AssetSource {
|
|
|
1968
1980
|
static blob(blob) {
|
|
1969
1981
|
return new _ArchiveAssetSource(new BrowserArchiveProxy(blob));
|
|
1970
1982
|
}
|
|
1983
|
+
get cacheId() {
|
|
1984
|
+
const id = this._archiveProxy.id;
|
|
1985
|
+
return id === void 0 ? void 0 : `archive:${id}`;
|
|
1986
|
+
}
|
|
1971
1987
|
async getEntries() {
|
|
1972
1988
|
return this._archiveProxy.getEntries();
|
|
1973
1989
|
}
|
|
@@ -2010,6 +2026,7 @@ var ArchiveAssetSource = class _ArchiveAssetSource extends AssetSource {
|
|
|
2010
2026
|
|
|
2011
2027
|
// src/assets/AssetLoader.ts
|
|
2012
2028
|
var p4 = prefix("AssetLoader");
|
|
2029
|
+
var FALLBACK_ROOT = "https://raw.githubusercontent.com/InventivetalentDev/minerender-fallback-assets/master";
|
|
2013
2030
|
var AssetLoader = class {
|
|
2014
2031
|
static {
|
|
2015
2032
|
this.ROOT = DEFAULT_ROOT;
|
|
@@ -2017,6 +2034,10 @@ var AssetLoader = class {
|
|
|
2017
2034
|
static {
|
|
2018
2035
|
this._SOURCES = [];
|
|
2019
2036
|
}
|
|
2037
|
+
static {
|
|
2038
|
+
/** Used when a registered source cannot identify its content, so nothing persists past this session. */
|
|
2039
|
+
this.SESSION_SCOPE = `session:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
|
|
2040
|
+
}
|
|
2020
2041
|
static get version() {
|
|
2021
2042
|
return this.ROOT.substring(this.ROOT.lastIndexOf("/") + 1);
|
|
2022
2043
|
}
|
|
@@ -2031,6 +2052,28 @@ var AssetLoader = class {
|
|
|
2031
2052
|
}
|
|
2032
2053
|
Caching.clear();
|
|
2033
2054
|
}
|
|
2055
|
+
/**
|
|
2056
|
+
* Scope for persistent cache keys. Empty with only the default vanilla sources, so their
|
|
2057
|
+
* entries stay valid across sessions; otherwise it names every added source (resource packs,
|
|
2058
|
+
* mirrors) so their results never masquerade as vanilla assets after a reload.
|
|
2059
|
+
*/
|
|
2060
|
+
static get persistentScope() {
|
|
2061
|
+
const parts = [];
|
|
2062
|
+
for (const { key, source } of this._SOURCES) {
|
|
2063
|
+
const id = source.cacheId;
|
|
2064
|
+
if (key === "mcassets" && id === `hosted:${this.ROOT}`) continue;
|
|
2065
|
+
if (key === "mcassets-fallback" && id === `hosted:${FALLBACK_ROOT}`) continue;
|
|
2066
|
+
if (id === void 0) return this.SESSION_SCOPE;
|
|
2067
|
+
parts.push(`${key}=${id}`);
|
|
2068
|
+
}
|
|
2069
|
+
return parts.join("|");
|
|
2070
|
+
}
|
|
2071
|
+
/** Prefixes a persistent cache key with the current source scope. */
|
|
2072
|
+
static persistentKey(key) {
|
|
2073
|
+
const scope = this.persistentScope;
|
|
2074
|
+
return scope ? `${scope}
|
|
2075
|
+
${key}` : key;
|
|
2076
|
+
}
|
|
2034
2077
|
static addSource(key, source, override = true) {
|
|
2035
2078
|
if (override) {
|
|
2036
2079
|
const existing = this.removeSource(key);
|
|
@@ -2052,7 +2095,7 @@ var AssetLoader = class {
|
|
|
2052
2095
|
return void 0;
|
|
2053
2096
|
}
|
|
2054
2097
|
static {
|
|
2055
|
-
this.addSource("mcassets-fallback", new HostedAssetSource(
|
|
2098
|
+
this.addSource("mcassets-fallback", new HostedAssetSource(FALLBACK_ROOT, { retryDefaults: false }));
|
|
2056
2099
|
this.addSource("mcassets", new HostedAssetSource(this.ROOT, { retryDefaults: false }));
|
|
2057
2100
|
}
|
|
2058
2101
|
static async getAll(key, parser) {
|
|
@@ -2134,7 +2177,7 @@ var ModelTextures = class {
|
|
|
2134
2177
|
}
|
|
2135
2178
|
const keyStr = key.serialize();
|
|
2136
2179
|
return Caching.textureMetaCache.get(keyStr, (k) => {
|
|
2137
|
-
return this.PERSISTENT_META_CACHE.getOrLoad(keyStr, (k1) => {
|
|
2180
|
+
return this.PERSISTENT_META_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), (k1) => {
|
|
2138
2181
|
return AssetLoader.get(key, "meta" /* META */).then((asset) => {
|
|
2139
2182
|
if (asset)
|
|
2140
2183
|
asset.key = key;
|
|
@@ -4804,7 +4847,9 @@ var BlockObject = class _BlockObject extends SceneObject {
|
|
|
4804
4847
|
if (typeof variant.y !== "undefined") {
|
|
4805
4848
|
rotation.y = toRadians(clampRotationDegrees(typeof variant.x !== "undefined" ? variant.y : 360 - variant.y));
|
|
4806
4849
|
}
|
|
4807
|
-
const
|
|
4850
|
+
const modelKey = AssetKey.parse("models", variant.model);
|
|
4851
|
+
modelKey.root = this.blockState.key?.root;
|
|
4852
|
+
const model = await Models.getMerged(modelKey);
|
|
4808
4853
|
const options = {
|
|
4809
4854
|
...this.options,
|
|
4810
4855
|
tints: model ? await BlockTints.get(this.blockState.key, this.state, model, this.options.tints) : this.options.tints,
|
|
@@ -5596,56 +5641,12 @@ var baseSkinCoordinates = {
|
|
|
5596
5641
|
}
|
|
5597
5642
|
},
|
|
5598
5643
|
cape: {
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
48
|
|
5606
|
-
]
|
|
5607
|
-
},
|
|
5608
|
-
west: {
|
|
5609
|
-
uv: [
|
|
5610
|
-
8,
|
|
5611
|
-
36,
|
|
5612
|
-
12,
|
|
5613
|
-
48
|
|
5614
|
-
]
|
|
5615
|
-
},
|
|
5616
|
-
north: {
|
|
5617
|
-
uv: [
|
|
5618
|
-
4,
|
|
5619
|
-
36,
|
|
5620
|
-
8,
|
|
5621
|
-
48
|
|
5622
|
-
]
|
|
5623
|
-
},
|
|
5624
|
-
south: {
|
|
5625
|
-
uv: [
|
|
5626
|
-
12,
|
|
5627
|
-
36,
|
|
5628
|
-
16,
|
|
5629
|
-
48
|
|
5630
|
-
]
|
|
5631
|
-
},
|
|
5632
|
-
up: {
|
|
5633
|
-
uv: [
|
|
5634
|
-
4,
|
|
5635
|
-
32,
|
|
5636
|
-
8,
|
|
5637
|
-
36
|
|
5638
|
-
]
|
|
5639
|
-
},
|
|
5640
|
-
down: {
|
|
5641
|
-
uv: [
|
|
5642
|
-
8,
|
|
5643
|
-
32,
|
|
5644
|
-
12,
|
|
5645
|
-
36
|
|
5646
|
-
],
|
|
5647
|
-
rotation: 180
|
|
5648
|
-
}
|
|
5644
|
+
east: { uv: [0, 1, 1, 17] },
|
|
5645
|
+
west: { uv: [11, 1, 12, 17] },
|
|
5646
|
+
north: { uv: [1, 1, 11, 17] },
|
|
5647
|
+
south: { uv: [12, 1, 22, 17] },
|
|
5648
|
+
up: { uv: [11, 1, 1, 0] },
|
|
5649
|
+
down: { uv: [21, 0, 11, 1] }
|
|
5649
5650
|
}
|
|
5650
5651
|
};
|
|
5651
5652
|
var classicSkinTextureCoordinates = {
|
|
@@ -5744,14 +5745,27 @@ var SkinTextures = class {
|
|
|
5744
5745
|
const key = `skin:${serializeImageKey({ src })}:${isLegacy}`;
|
|
5745
5746
|
const material = Caching.materialCache.get(key, () => {
|
|
5746
5747
|
const pixels = isLegacy ? this.normalizeLegacy(image, scale) : new Uint8Array(image.data);
|
|
5747
|
-
|
|
5748
|
-
texture.colorSpace = import_three18.SRGBColorSpace;
|
|
5749
|
-
texture.flipY = true;
|
|
5750
|
-
texture.needsUpdate = true;
|
|
5751
|
-
return new import_three18.MeshBasicMaterial({ map: texture, transparent: true, side: import_three18.DoubleSide, alphaTest: 0.5 });
|
|
5748
|
+
return this.createMaterial(pixels, image.width, image.width);
|
|
5752
5749
|
});
|
|
5753
5750
|
return { material, slim, legacy: isLegacy };
|
|
5754
5751
|
}
|
|
5752
|
+
static async getCape(src) {
|
|
5753
|
+
const image = await ImageLoader.getData(src);
|
|
5754
|
+
const scale = image.width / 64;
|
|
5755
|
+
if (!Number.isInteger(scale) || scale < 1 || image.height !== image.width / 2) {
|
|
5756
|
+
throw new MineRenderError(`Invalid cape dimensions ${image.width}x${image.height}; expected 64x32 or an integer-scaled equivalent`);
|
|
5757
|
+
}
|
|
5758
|
+
return Caching.materialCache.get(`cape:${serializeImageKey({ src })}`, () => {
|
|
5759
|
+
return this.createMaterial(new Uint8Array(image.data), image.width, image.height, false);
|
|
5760
|
+
});
|
|
5761
|
+
}
|
|
5762
|
+
static createMaterial(pixels, width, height, transparent = true) {
|
|
5763
|
+
const texture = Textures.initTextureProps(new import_three18.DataTexture(pixels, width, height));
|
|
5764
|
+
texture.colorSpace = import_three18.SRGBColorSpace;
|
|
5765
|
+
texture.flipY = true;
|
|
5766
|
+
texture.needsUpdate = true;
|
|
5767
|
+
return new import_three18.MeshBasicMaterial({ map: texture, transparent, side: transparent ? import_three18.DoubleSide : import_three18.FrontSide, alphaTest: transparent ? 0.5 : 0 });
|
|
5768
|
+
}
|
|
5755
5769
|
static isSlim(image, scale) {
|
|
5756
5770
|
for (const [x, y] of [[46, 52], [54, 20]]) {
|
|
5757
5771
|
for (let row = y * scale; row < (y + 12) * scale; row++) {
|
|
@@ -5814,6 +5828,7 @@ var SkinObject = class extends SceneObject {
|
|
|
5814
5828
|
this.slim = false;
|
|
5815
5829
|
this.detectedSlim = false;
|
|
5816
5830
|
this.skinLoad = 0;
|
|
5831
|
+
this.capeLoad = 0;
|
|
5817
5832
|
this.options = (0, import_ts_deepmerge7.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
|
|
5818
5833
|
this.slim = this.options.slim ?? false;
|
|
5819
5834
|
}
|
|
@@ -5883,6 +5898,7 @@ var SkinObject = class extends SceneObject {
|
|
|
5883
5898
|
this.detectedSlim = texture.slim;
|
|
5884
5899
|
this.updateSlim(this.options.slim ?? this.detectedSlim);
|
|
5885
5900
|
for (const part of SKIN_PARTS) {
|
|
5901
|
+
if (part === "cape" /* CAPE */) continue;
|
|
5886
5902
|
const mesh = this.getMeshByName(part);
|
|
5887
5903
|
if (mesh) {
|
|
5888
5904
|
mesh.material = texture.material;
|
|
@@ -5890,7 +5906,34 @@ var SkinObject = class extends SceneObject {
|
|
|
5890
5906
|
}
|
|
5891
5907
|
this.notifyDirty();
|
|
5892
5908
|
}
|
|
5893
|
-
|
|
5909
|
+
/** Load a vanilla cape texture, or pass undefined to remove the cape. */
|
|
5910
|
+
async setCapeTexture(src) {
|
|
5911
|
+
const load = ++this.capeLoad;
|
|
5912
|
+
if (src === void 0) {
|
|
5913
|
+
const group = this.getGroupByName("cape" /* CAPE */);
|
|
5914
|
+
if (group) this.remove(group);
|
|
5915
|
+
this.notifyDirty();
|
|
5916
|
+
return;
|
|
5917
|
+
}
|
|
5918
|
+
const material = await SkinTextures.getCape(src);
|
|
5919
|
+
if (load !== this.capeLoad) return;
|
|
5920
|
+
const mesh = this.getMeshByName("cape" /* CAPE */);
|
|
5921
|
+
if (mesh) {
|
|
5922
|
+
mesh.material = material;
|
|
5923
|
+
} else {
|
|
5924
|
+
const group = this.createAndAddGroup("cape" /* CAPE */, 0, 24, 2);
|
|
5925
|
+
group.rotation.set(toRadians(-6), Math.PI, 0);
|
|
5926
|
+
const geometry = this._getBoxGeometryFromDimensions(
|
|
5927
|
+
classicSkinGeometries.cape,
|
|
5928
|
+
classicSkinTextureCoordinates.cape,
|
|
5929
|
+
[64, 32],
|
|
5930
|
+
[64, 32]
|
|
5931
|
+
);
|
|
5932
|
+
const cape = this.createAndAddMesh("cape" /* CAPE */, group, geometry, material);
|
|
5933
|
+
cape.position.set(0, -8, -0.5);
|
|
5934
|
+
}
|
|
5935
|
+
this.notifyDirty();
|
|
5936
|
+
}
|
|
5894
5937
|
/** Select the arm model, or pass undefined to use texture detection. */
|
|
5895
5938
|
setSlim(slim) {
|
|
5896
5939
|
this.options.slim = slim;
|
|
@@ -5918,6 +5961,7 @@ var SkinObject = class extends SceneObject {
|
|
|
5918
5961
|
}
|
|
5919
5962
|
dispose() {
|
|
5920
5963
|
this.skinLoad++;
|
|
5964
|
+
this.capeLoad++;
|
|
5921
5965
|
super.dispose();
|
|
5922
5966
|
}
|
|
5923
5967
|
//TODO: layer toggles
|