minerender 2.1.0-beta.7 → 2.1.0-beta.8

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.
Files changed (73) hide show
  1. package/README.md +10 -1
  2. package/dist/browser/esm/armor/Armor.mjs +84 -0
  3. package/dist/browser/esm/armor/Armor.mjs.map +1 -0
  4. package/dist/browser/esm/armor/index.mjs +3 -0
  5. package/dist/browser/esm/armor/index.mjs.map +1 -0
  6. package/dist/browser/esm/assets/BlockEntities.mjs +2 -0
  7. package/dist/browser/esm/assets/BlockEntities.mjs.map +1 -1
  8. package/dist/browser/esm/assets/Entities.mjs +39 -11
  9. package/dist/browser/esm/assets/Entities.mjs.map +1 -1
  10. package/dist/browser/esm/assets/MineRenderData.mjs +8 -17
  11. package/dist/browser/esm/assets/MineRenderData.mjs.map +1 -1
  12. package/dist/browser/esm/assets/ModelTextures.mjs +13 -7
  13. package/dist/browser/esm/assets/ModelTextures.mjs.map +1 -1
  14. package/dist/browser/esm/assets/_versions/DatasetVersions.mjs +22 -0
  15. package/dist/browser/esm/assets/_versions/DatasetVersions.mjs.map +1 -0
  16. package/dist/browser/esm/cache/Caching.mjs +8 -0
  17. package/dist/browser/esm/cache/Caching.mjs.map +1 -1
  18. package/dist/browser/esm/entity/scene/EntityObject.mjs +31 -5
  19. package/dist/browser/esm/entity/scene/EntityObject.mjs.map +1 -1
  20. package/dist/browser/esm/env/browser/BrowserEnv.mjs +11 -4
  21. package/dist/browser/esm/env/browser/BrowserEnv.mjs.map +1 -1
  22. package/dist/browser/esm/index.browser.d.mts +129 -13
  23. package/dist/browser/esm/index.browser.mjs.map +1 -1
  24. package/dist/browser/esm/index.mjs +1 -0
  25. package/dist/browser/esm/index.mjs.map +1 -1
  26. package/dist/browser/esm/model/ItemGlint.mjs +7 -6
  27. package/dist/browser/esm/model/ItemGlint.mjs.map +1 -1
  28. package/dist/browser/esm/model/block/scene/BlockObject.mjs +16 -5
  29. package/dist/browser/esm/model/block/scene/BlockObject.mjs.map +1 -1
  30. package/dist/browser/esm/scene/SceneDocument.mjs +35 -5
  31. package/dist/browser/esm/scene/SceneDocument.mjs.map +1 -1
  32. package/dist/browser/esm/scene/SceneDocumentLoader.mjs +14 -3
  33. package/dist/browser/esm/scene/SceneDocumentLoader.mjs.map +1 -1
  34. package/dist/browser/esm/skin/SkinGeometries.mjs +4 -1
  35. package/dist/browser/esm/skin/SkinGeometries.mjs.map +1 -1
  36. package/dist/browser/esm/skin/SkinPart.mjs +2 -0
  37. package/dist/browser/esm/skin/SkinPart.mjs.map +1 -1
  38. package/dist/browser/esm/skin/SkinTextureCoordinates.mjs +11 -1
  39. package/dist/browser/esm/skin/SkinTextureCoordinates.mjs.map +1 -1
  40. package/dist/browser/esm/skin/SkinTextures.mjs +1 -1
  41. package/dist/browser/esm/skin/SkinTextures.mjs.map +1 -1
  42. package/dist/browser/esm/skin/scene/SkinObject.mjs +119 -7
  43. package/dist/browser/esm/skin/scene/SkinObject.mjs.map +1 -1
  44. package/dist/browser/esm/texture/PalettedTextures.mjs +46 -0
  45. package/dist/browser/esm/texture/PalettedTextures.mjs.map +1 -0
  46. package/dist/browser/esm/texture/index.mjs +1 -0
  47. package/dist/browser/esm/texture/index.mjs.map +1 -1
  48. package/dist/browser/esm/util/util.mjs +0 -2
  49. package/dist/browser/esm/util/util.mjs.map +1 -1
  50. package/dist/browser/esm/world/Chunk.mjs +62 -33
  51. package/dist/browser/esm/world/Chunk.mjs.map +1 -1
  52. package/dist/browser/esm/world/MineRenderWorld.mjs +98 -13
  53. package/dist/browser/esm/world/MineRenderWorld.mjs.map +1 -1
  54. package/dist/browser/esm/world/SectionMesh.mjs +65 -9
  55. package/dist/browser/esm/world/SectionMesh.mjs.map +1 -1
  56. package/dist/browser/esm/world/SectionModels.mjs +21 -15
  57. package/dist/browser/esm/world/SectionModels.mjs.map +1 -1
  58. package/dist/browser/esm/world/SectionWorker.mjs +8 -2
  59. package/dist/browser/esm/world/SectionWorker.mjs.map +1 -1
  60. package/dist/browser/esm/world/WorldStreamer.mjs +109 -15
  61. package/dist/browser/esm/world/WorldStreamer.mjs.map +1 -1
  62. package/dist/browser/index.d.ts +129 -13
  63. package/dist/browser/index.js +1592 -894
  64. package/dist/browser/index.js.map +1 -1
  65. package/dist/bundle.js +1330 -619
  66. package/dist/bundle.js.map +1 -1
  67. package/dist/node/index.d.mts +117 -12
  68. package/dist/node/index.d.ts +117 -12
  69. package/dist/node/index.js +1505 -793
  70. package/dist/node/index.js.map +1 -1
  71. package/dist/node/index.mjs +1303 -593
  72. package/dist/node/index.mjs.map +1 -1
  73. package/package.json +2 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/skin/SkinTextureCoordinates.ts"],"sourcesContent":["import { SkinPart } from \"./SkinPart\";\nimport { ModelFaces } from \"../model/ModelElement\";\n\n\nexport type SkinTextureCoordinates = Record<SkinPart, ModelFaces>;\n\n// The player faces +Z: south is the front, north the back and east the player's left.\n// down UVs are flipped on Y - v0 is v1, v1 is v0\n\nconst baseSkinCoordinates: SkinTextureCoordinates = {\n head: {\n west: { // left\n uv: [\n 0,\n 8,\n 8,\n 16\n ]\n },\n east: { // right\n uv: [\n 16,\n 8,\n 24,\n 16\n ]\n },\n south: { // front\n uv: [\n 8,\n 8,\n 16,\n 16\n ]\n },\n north: { // back\n uv: [\n 24,\n 8,\n 32,\n 16\n ]\n },\n up: { // top\n uv: [\n 8,\n 0,\n 16,\n 8\n ]\n },\n down: { // bottom\n uv: [\n 16,\n 8,\n 24,\n 0\n ]\n }\n },\n body: {\n west: {\n uv: [\n 16,\n 20,\n 20,\n 32\n ]\n },\n east: {\n uv: [\n 28,\n 20,\n 32,\n 32\n ]\n },\n south: {\n uv: [\n 20,\n 20,\n 28,\n 32\n ]\n },\n north: {\n uv: [\n 32,\n 20,\n 40,\n 32\n ]\n },\n up: {\n uv: [\n 20,\n 16,\n 28,\n 20\n ]\n },\n down: {\n uv: [\n 28,\n 20,\n 36,\n 16\n ]\n }\n },\n leftArm: {\n west: {\n uv: [\n 32,\n 52,\n 36,\n 64\n ]\n },\n east: {\n uv: [\n 40,\n 52,\n 44,\n 64\n ]\n },\n south: {\n uv: [\n 36,\n 52,\n 40,\n 64\n ]\n },\n north: {\n uv: [\n 44,\n 52,\n 48,\n 64\n ]\n },\n up: {\n uv: [\n 36,\n 48,\n 40,\n 52\n ]\n },\n down: {\n uv: [\n 40,\n 52,\n 44,\n 48\n ]\n }\n },\n rightArm: {\n west: {\n uv: [\n 40,\n 20,\n 44,\n 32\n ],\n\n },\n east: {\n uv: [\n 48,\n 20,\n 52,\n 32\n ],\n\n },\n south: {\n uv: [\n 44,\n 20,\n 48,\n 32\n ],\n\n },\n north: {\n uv: [\n 52,\n 20,\n 56,\n 32\n ],\n\n },\n up: {\n uv: [\n 44,\n 16,\n 48,\n 20\n ],\n\n },\n down: {\n uv: [\n 48,\n 20,\n 52,\n 16\n ],\n\n\n }\n },\n leftLeg: {\n west: {\n uv: [\n 16,\n 52,\n 20,\n 64\n ]\n },\n east: {\n uv: [\n 24,\n 52,\n 28,\n 64\n ]\n },\n south: {\n uv: [\n 20,\n 52,\n 24,\n 64\n ]\n },\n north: {\n uv: [\n 28,\n 52,\n 32,\n 64\n ]\n },\n up: {\n uv: [\n 20,\n 48,\n 24,\n 52\n ]\n },\n down: {\n uv: [\n 24,\n 52,\n 28,\n 48\n ],\n rotation: 180\n }\n },\n rightLeg: {\n west: {\n uv: [\n 0,\n 20,\n 4,\n 32\n ],\n\n },\n east: {\n uv: [\n 8,\n 20,\n 12,\n 32\n ]\n },\n south: {\n uv: [\n 4,\n 20,\n 8,\n 32\n ],\n\n },\n north: {\n uv: [\n 12,\n 20,\n 16,\n 32\n ],\n\n },\n up: {\n uv: [\n 4,\n 16,\n 8,\n 20\n ],\n\n },\n down: {\n uv: [\n 8,\n 20,\n 12,\n 16\n ],\n\n\n }\n },\n hat: {\n west: {\n uv: [\n 32,\n 8,\n 40,\n 16\n ]\n },\n east: {\n uv: [\n 48,\n 8,\n 56,\n 16\n ]\n },\n south: {\n uv: [\n 40,\n 8,\n 48,\n 16\n ]\n },\n north: {\n uv: [\n 56,\n 8,\n 64,\n 16\n ]\n },\n up: {\n uv: [\n 40,\n 0,\n 48,\n 8\n ]\n },\n down: {\n uv: [\n 48,\n 8,\n 56,\n 0\n ],\n rotation: 180\n }\n },\n jacket: {\n west: {\n uv: [\n 16,\n 36,\n 20,\n 48\n ]\n },\n east: {\n uv: [\n 28,\n 36,\n 32,\n 48\n ]\n },\n south: {\n uv: [\n 20,\n 36,\n 28,\n 48\n ]\n },\n north: {\n uv: [\n 32,\n 36,\n 40,\n 48\n ]\n },\n up: {\n uv: [\n 20,\n 32,\n 28,\n 36\n ]\n },\n down: {\n uv: [\n 28,\n 36,\n 36,\n 32\n ],\n rotation: 180\n }\n },\n leftSleeve: {\n west: {\n uv: [\n 48,\n 52,\n 52,\n 64\n ]\n },\n east: {\n uv: [\n 56,\n 52,\n 60,\n 64\n ]\n },\n south: {\n uv: [\n 52,\n 52,\n 56,\n 64\n ]\n },\n north: {\n uv: [\n 60,\n 52,\n 64,\n 64\n ]\n },\n up: {\n uv: [\n 52,\n 48,\n 56,\n 52\n ]\n },\n down: {\n uv: [\n 56,\n 52,\n 60,\n 48\n ],\n rotation: 180\n }\n },\n rightSleeve: {\n west: {\n uv: [\n 40,\n 36,\n 44,\n 48\n ]\n },\n east: {\n uv: [\n 48,\n 36,\n 52,\n 48\n ]\n },\n south: {\n uv: [\n 44,\n 36,\n 48,\n 48\n ]\n },\n north: {\n uv: [\n 52,\n 36,\n 56,\n 48\n ]\n },\n up: {\n uv: [\n 44,\n 32,\n 48,\n 36\n ]\n },\n down: {\n uv: [\n 48,\n 36,\n 52,\n 32\n ],\n rotation: 180\n }\n },\n leftTrousers: {\n west: {\n uv: [\n 0,\n 52,\n 4,\n 64\n ]\n },\n east: {\n uv: [\n 8,\n 52,\n 12,\n 64\n ]\n },\n south: {\n uv: [\n 4,\n 52,\n 8,\n 64\n ]\n },\n north: {\n uv: [\n 12,\n 52,\n 16,\n 64\n ]\n },\n up: {\n uv: [\n 4,\n 48,\n 8,\n 52\n ]\n },\n down: {\n uv: [\n 8,\n 52,\n 12,\n 48\n ]\n }\n },\n rightTrousers: {\n west: {\n uv: [\n 0,\n 36,\n 4,\n 48\n ]\n },\n east: {\n uv: [\n 8,\n 36,\n 12,\n 48\n ]\n },\n south: {\n uv: [\n 4,\n 36,\n 8,\n 48\n ]\n },\n north: {\n uv: [\n 12,\n 36,\n 16,\n 48\n ]\n },\n up: {\n uv: [\n 4,\n 32,\n 8,\n 36\n ]\n },\n down: {\n uv: [\n 8,\n 36,\n 12,\n 32\n ],\n rotation: 180\n }\n },\n cape: {\n east: { uv: [0, 1, 1, 17] },\n west: { uv: [11, 1, 12, 17] },\n north: { uv: [1, 1, 11, 17] },\n south: { uv: [12, 1, 22, 17] },\n up: { uv: [11, 1, 1, 0] },\n down: { uv: [21, 0, 11, 1] }\n }\n}\n\n\nexport const classicSkinTextureCoordinates: Readonly<SkinTextureCoordinates> = {\n ...baseSkinCoordinates\n};\n\nexport const slimSkinTextureCoordinates: Readonly<SkinTextureCoordinates> = {\n ...baseSkinCoordinates,\n leftArm: {\n ...baseSkinCoordinates.leftArm,\n east: { uv: [39, 52, 43, 64] },\n south: { uv: [36, 52, 39, 64] },\n north: { uv: [43, 52, 46, 64] },\n up: { uv: [36, 48, 39, 52] },\n down: { uv: [39, 52, 42, 48] }\n },\n rightArm: {\n ...baseSkinCoordinates.rightArm,\n east: { uv: [47, 20, 51, 32] },\n south: { uv: [44, 20, 47, 32] },\n north: { uv: [51, 20, 54, 32] },\n up: { uv: [44, 16, 47, 20] },\n down: { uv: [47, 20, 50, 16] }\n },\n leftSleeve: {\n ...baseSkinCoordinates.leftSleeve,\n east: { uv: [55, 52, 59, 64] },\n south: { uv: [52, 52, 55, 64] },\n north: { uv: [59, 52, 62, 64] },\n up: { uv: [52, 48, 55, 52] },\n down: { uv: [55, 52, 58, 48], rotation: 180 }\n },\n rightSleeve: {\n ...baseSkinCoordinates.rightSleeve,\n east: { uv: [47, 36, 51, 48] },\n south: { uv: [44, 36, 47, 48] },\n north: { uv: [51, 36, 54, 48] },\n up: { uv: [44, 32, 47, 36] },\n down: { uv: [47, 36, 50, 32], rotation: 180 }\n }\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/skin/SkinTextureCoordinates.ts"],"sourcesContent":["import { SkinPart } from \"./SkinPart\";\nimport { ModelFaces } from \"../model/ModelElement\";\n\n\nexport type SkinTextureCoordinates = Record<SkinPart, ModelFaces>;\n\n// The player faces +Z: south is the front, north the back and east the player's left.\n// down UVs are flipped on Y - v0 is v1, v1 is v0\n\n// deadmau5's ears use the 6x6x1 box at 24,0 for both sides.\nconst earCoordinates: ModelFaces = {\n west: { uv: [24, 1, 25, 7] },\n east: { uv: [31, 1, 32, 7] },\n south: { uv: [25, 1, 31, 7] },\n north: { uv: [32, 1, 38, 7] },\n up: { uv: [25, 0, 31, 1] },\n down: { uv: [31, 1, 37, 0] }\n};\n\nconst baseSkinCoordinates: SkinTextureCoordinates = {\n head: {\n west: { // left\n uv: [\n 0,\n 8,\n 8,\n 16\n ]\n },\n east: { // right\n uv: [\n 16,\n 8,\n 24,\n 16\n ]\n },\n south: { // front\n uv: [\n 8,\n 8,\n 16,\n 16\n ]\n },\n north: { // back\n uv: [\n 24,\n 8,\n 32,\n 16\n ]\n },\n up: { // top\n uv: [\n 8,\n 0,\n 16,\n 8\n ]\n },\n down: { // bottom\n uv: [\n 16,\n 8,\n 24,\n 0\n ]\n }\n },\n body: {\n west: {\n uv: [\n 16,\n 20,\n 20,\n 32\n ]\n },\n east: {\n uv: [\n 28,\n 20,\n 32,\n 32\n ]\n },\n south: {\n uv: [\n 20,\n 20,\n 28,\n 32\n ]\n },\n north: {\n uv: [\n 32,\n 20,\n 40,\n 32\n ]\n },\n up: {\n uv: [\n 20,\n 16,\n 28,\n 20\n ]\n },\n down: {\n uv: [\n 28,\n 20,\n 36,\n 16\n ]\n }\n },\n leftArm: {\n west: {\n uv: [\n 32,\n 52,\n 36,\n 64\n ]\n },\n east: {\n uv: [\n 40,\n 52,\n 44,\n 64\n ]\n },\n south: {\n uv: [\n 36,\n 52,\n 40,\n 64\n ]\n },\n north: {\n uv: [\n 44,\n 52,\n 48,\n 64\n ]\n },\n up: {\n uv: [\n 36,\n 48,\n 40,\n 52\n ]\n },\n down: {\n uv: [\n 40,\n 52,\n 44,\n 48\n ]\n }\n },\n rightArm: {\n west: {\n uv: [\n 40,\n 20,\n 44,\n 32\n ],\n\n },\n east: {\n uv: [\n 48,\n 20,\n 52,\n 32\n ],\n\n },\n south: {\n uv: [\n 44,\n 20,\n 48,\n 32\n ],\n\n },\n north: {\n uv: [\n 52,\n 20,\n 56,\n 32\n ],\n\n },\n up: {\n uv: [\n 44,\n 16,\n 48,\n 20\n ],\n\n },\n down: {\n uv: [\n 48,\n 20,\n 52,\n 16\n ],\n\n\n }\n },\n leftLeg: {\n west: {\n uv: [\n 16,\n 52,\n 20,\n 64\n ]\n },\n east: {\n uv: [\n 24,\n 52,\n 28,\n 64\n ]\n },\n south: {\n uv: [\n 20,\n 52,\n 24,\n 64\n ]\n },\n north: {\n uv: [\n 28,\n 52,\n 32,\n 64\n ]\n },\n up: {\n uv: [\n 20,\n 48,\n 24,\n 52\n ]\n },\n down: {\n uv: [\n 24,\n 52,\n 28,\n 48\n ],\n rotation: 180\n }\n },\n rightLeg: {\n west: {\n uv: [\n 0,\n 20,\n 4,\n 32\n ],\n\n },\n east: {\n uv: [\n 8,\n 20,\n 12,\n 32\n ]\n },\n south: {\n uv: [\n 4,\n 20,\n 8,\n 32\n ],\n\n },\n north: {\n uv: [\n 12,\n 20,\n 16,\n 32\n ],\n\n },\n up: {\n uv: [\n 4,\n 16,\n 8,\n 20\n ],\n\n },\n down: {\n uv: [\n 8,\n 20,\n 12,\n 16\n ],\n\n\n }\n },\n hat: {\n west: {\n uv: [\n 32,\n 8,\n 40,\n 16\n ]\n },\n east: {\n uv: [\n 48,\n 8,\n 56,\n 16\n ]\n },\n south: {\n uv: [\n 40,\n 8,\n 48,\n 16\n ]\n },\n north: {\n uv: [\n 56,\n 8,\n 64,\n 16\n ]\n },\n up: {\n uv: [\n 40,\n 0,\n 48,\n 8\n ]\n },\n down: {\n uv: [\n 48,\n 8,\n 56,\n 0\n ],\n rotation: 180\n }\n },\n jacket: {\n west: {\n uv: [\n 16,\n 36,\n 20,\n 48\n ]\n },\n east: {\n uv: [\n 28,\n 36,\n 32,\n 48\n ]\n },\n south: {\n uv: [\n 20,\n 36,\n 28,\n 48\n ]\n },\n north: {\n uv: [\n 32,\n 36,\n 40,\n 48\n ]\n },\n up: {\n uv: [\n 20,\n 32,\n 28,\n 36\n ]\n },\n down: {\n uv: [\n 28,\n 36,\n 36,\n 32\n ],\n rotation: 180\n }\n },\n leftSleeve: {\n west: {\n uv: [\n 48,\n 52,\n 52,\n 64\n ]\n },\n east: {\n uv: [\n 56,\n 52,\n 60,\n 64\n ]\n },\n south: {\n uv: [\n 52,\n 52,\n 56,\n 64\n ]\n },\n north: {\n uv: [\n 60,\n 52,\n 64,\n 64\n ]\n },\n up: {\n uv: [\n 52,\n 48,\n 56,\n 52\n ]\n },\n down: {\n uv: [\n 56,\n 52,\n 60,\n 48\n ],\n rotation: 180\n }\n },\n rightSleeve: {\n west: {\n uv: [\n 40,\n 36,\n 44,\n 48\n ]\n },\n east: {\n uv: [\n 48,\n 36,\n 52,\n 48\n ]\n },\n south: {\n uv: [\n 44,\n 36,\n 48,\n 48\n ]\n },\n north: {\n uv: [\n 52,\n 36,\n 56,\n 48\n ]\n },\n up: {\n uv: [\n 44,\n 32,\n 48,\n 36\n ]\n },\n down: {\n uv: [\n 48,\n 36,\n 52,\n 32\n ],\n rotation: 180\n }\n },\n leftTrousers: {\n west: {\n uv: [\n 0,\n 52,\n 4,\n 64\n ]\n },\n east: {\n uv: [\n 8,\n 52,\n 12,\n 64\n ]\n },\n south: {\n uv: [\n 4,\n 52,\n 8,\n 64\n ]\n },\n north: {\n uv: [\n 12,\n 52,\n 16,\n 64\n ]\n },\n up: {\n uv: [\n 4,\n 48,\n 8,\n 52\n ]\n },\n down: {\n uv: [\n 8,\n 52,\n 12,\n 48\n ]\n }\n },\n rightTrousers: {\n west: {\n uv: [\n 0,\n 36,\n 4,\n 48\n ]\n },\n east: {\n uv: [\n 8,\n 36,\n 12,\n 48\n ]\n },\n south: {\n uv: [\n 4,\n 36,\n 8,\n 48\n ]\n },\n north: {\n uv: [\n 12,\n 36,\n 16,\n 48\n ]\n },\n up: {\n uv: [\n 4,\n 32,\n 8,\n 36\n ]\n },\n down: {\n uv: [\n 8,\n 36,\n 12,\n 32\n ],\n rotation: 180\n }\n },\n cape: {\n east: { uv: [0, 1, 1, 17] },\n west: { uv: [11, 1, 12, 17] },\n north: { uv: [1, 1, 11, 17] },\n south: { uv: [12, 1, 22, 17] },\n up: { uv: [11, 1, 1, 0] },\n down: { uv: [21, 0, 11, 1] }\n },\n leftEar: earCoordinates,\n rightEar: earCoordinates\n}\n\n\nexport const classicSkinTextureCoordinates: Readonly<SkinTextureCoordinates> = {\n ...baseSkinCoordinates\n};\n\nexport const slimSkinTextureCoordinates: Readonly<SkinTextureCoordinates> = {\n ...baseSkinCoordinates,\n leftArm: {\n ...baseSkinCoordinates.leftArm,\n east: { uv: [39, 52, 43, 64] },\n south: { uv: [36, 52, 39, 64] },\n north: { uv: [43, 52, 46, 64] },\n up: { uv: [36, 48, 39, 52] },\n down: { uv: [39, 52, 42, 48] }\n },\n rightArm: {\n ...baseSkinCoordinates.rightArm,\n east: { uv: [47, 20, 51, 32] },\n south: { uv: [44, 20, 47, 32] },\n north: { uv: [51, 20, 54, 32] },\n up: { uv: [44, 16, 47, 20] },\n down: { uv: [47, 20, 50, 16] }\n },\n leftSleeve: {\n ...baseSkinCoordinates.leftSleeve,\n east: { uv: [55, 52, 59, 64] },\n south: { uv: [52, 52, 55, 64] },\n north: { uv: [59, 52, 62, 64] },\n up: { uv: [52, 48, 55, 52] },\n down: { uv: [55, 52, 58, 48], rotation: 180 }\n },\n rightSleeve: {\n ...baseSkinCoordinates.rightSleeve,\n east: { uv: [47, 36, 51, 48] },\n south: { uv: [44, 36, 47, 48] },\n north: { uv: [51, 36, 54, 48] },\n up: { uv: [44, 32, 47, 36] },\n down: { uv: [47, 36, 50, 32], rotation: 180 }\n }\n};\n"],"mappings":"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","names":[]}
@@ -94,7 +94,7 @@ var SkinTextures = class {
94
94
  return pixels;
95
95
  }
96
96
  static makeBaseOpaque(pixels, width, scale) {
97
- for (const [x0, y0, x1, y1] of [[0, 0, 32, 16], [0, 16, 64, 32], [16, 48, 48, 64]]) {
97
+ for (const [x0, y0, x1, y1] of [[0, 0, 32, 16], [0, 16, 64, 32], [16, 48, 48, 64], [32, 0, 38, 7]]) {
98
98
  for (let y = y0 * scale; y < y1 * scale; y++) {
99
99
  for (let x = x0 * scale; x < x1 * scale; x++) pixels[(y * width + x) * 4 + 3] = 255;
100
100
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/skin/SkinTextures.ts"],"sourcesContent":["import { DataTexture, DoubleSide, FrontSide, MeshBasicMaterial, SRGBColorSpace } from \"three\";\nimport { Caching } from \"../cache/Caching\";\nimport { serializeImageKey } from \"../cache/CacheKey\";\nimport { MineRenderError } from \"../error/MineRenderError\";\nimport { SkinImage } from \"./SkinImage\";\nimport { Textures } from \"../texture/Textures\";\nimport { CapeLayout } from \"./CapeLayout\";\n\n/** A prepared shared skin material with detected arm-model and texture-layout flags. */\nexport interface SkinTexture {\n material: MeshBasicMaterial;\n slim: boolean;\n legacy: boolean;\n}\n\n/** Prepares shared skin and cape materials, including legacy layout conversion and base-layer opacity. */\nexport class SkinTextures {\n\n /** Loads a skin URL. Pass `legacy` to override layout detection from the image dimensions. */\n public static async get(src: string, legacy?: boolean): Promise<SkinTexture> {\n const image = await SkinImage.getData(src);\n const scale = image.width / 64;\n if (!Number.isInteger(scale) || scale < 1 || (image.height !== image.width && image.height !== image.width / 2)) {\n throw new MineRenderError(`Invalid skin dimensions ${image.width}x${image.height}; expected 64x64 or 64x32, or an integer-scaled equivalent`);\n }\n const isLegacy = legacy ?? image.height === image.width / 2;\n if (!isLegacy && image.height !== image.width) {\n throw new MineRenderError(`Invalid skin dimensions ${image.width}x${image.height}; non-legacy skins must be square`);\n }\n const slim = !isLegacy && this.isSlim(image, scale);\n const key = `skin:${serializeImageKey({ src })}:${isLegacy}`;\n const material = Caching.materialCache.get(key, () => {\n const pixels = isLegacy ? this.normalizeLegacy(image, scale) : new Uint8Array(image.data);\n this.makeBaseOpaque(pixels, image.width, scale);\n return this.createMaterial(pixels, image.width, image.width);\n }) as MeshBasicMaterial;\n return { material, slim, legacy: isLegacy };\n }\n\n public static async getCape(src: string, layout: CapeLayout = \"minecraft\"): Promise<MeshBasicMaterial> {\n const image = await SkinImage.getData(src);\n const scale = image.width / 64;\n if (layout === \"minecraft\" && (!Number.isInteger(scale) || scale < 1 || image.height !== image.width / 2)) {\n throw new MineRenderError(`Invalid cape dimensions ${image.width}x${image.height}; expected 64x32 or an integer-scaled equivalent`);\n }\n return Caching.materialCache.get(`cape:${serializeImageKey({ src })}`, () => {\n return this.createMaterial(new Uint8Array(image.data), image.width, image.height, false);\n }) as MeshBasicMaterial;\n }\n\n private static createMaterial(pixels: Uint8Array, width: number, height: number, transparent: boolean = true): MeshBasicMaterial {\n const texture = Textures.initTextureProps(new DataTexture(pixels, width, height));\n texture.colorSpace = SRGBColorSpace;\n texture.flipY = true;\n texture.needsUpdate = true;\n return new MeshBasicMaterial({ map: texture, transparent, side: transparent ? DoubleSide : FrontSide, alphaTest: transparent ? 0.1 : 0 });\n }\n\n private static isSlim(image: ImageData, scale: number): boolean {\n for (const [x, y] of [[46, 52], [54, 20]]) {\n for (let row = y * scale; row < (y + 12) * scale; row++) {\n for (let column = x * scale; column < (x + 1) * scale; column++) {\n if (image.data[(row * image.width + column) * 4 + 3] !== 0) return false;\n }\n }\n }\n return true;\n }\n\n private static normalizeLegacy(image: ImageData, scale: number): Uint8Array {\n const pixels = new Uint8Array(image.width * image.width * 4);\n pixels.set(image.data.subarray(0, image.width * image.width / 2 * 4));\n // Vanilla mirrors each right-limb face into the modern left-limb texture regions.\n for (const [sx, sy, dx, dy, width, height] of [\n [4, 16, 20, 48, 4, 4], [8, 16, 24, 48, 4, 4],\n [0, 20, 24, 52, 4, 12], [4, 20, 20, 52, 4, 12],\n [8, 20, 16, 52, 4, 12], [12, 20, 28, 52, 4, 12],\n [44, 16, 36, 48, 4, 4], [48, 16, 40, 48, 4, 4],\n [40, 20, 40, 52, 4, 12], [44, 20, 36, 52, 4, 12],\n [48, 20, 32, 52, 4, 12], [52, 20, 44, 52, 4, 12]\n ]) {\n for (let y = 0; y < height * scale; y++) {\n for (let x = 0; x < width * scale; x++) {\n const source = ((sy * scale + y) * image.width + sx * scale + x) * 4;\n const target = ((dy * scale + y) * image.width + (dx + width) * scale - 1 - x) * 4;\n pixels.set(image.data.subarray(source, source + 4), target);\n }\n }\n }\n let clearHat = true;\n for (let y = 0; y < 32 * scale; y++) {\n for (let x = 32 * scale; x < image.width; x++) {\n if (pixels[(y * image.width + x) * 4 + 3] < 128) clearHat = false;\n }\n }\n if (clearHat) {\n for (let y = 0; y < 32 * scale; y++) {\n for (let x = 32 * scale; x < image.width; x++) {\n pixels[(y * image.width + x) * 4 + 3] = 0;\n }\n }\n }\n return pixels;\n }\n\n private static makeBaseOpaque(pixels: Uint8Array, width: number, scale: number): void {\n for (const [x0, y0, x1, y1] of [[0, 0, 32, 16], [0, 16, 64, 32], [16, 48, 48, 64]]) {\n for (let y = y0 * scale; y < y1 * scale; y++) {\n for (let x = x0 * scale; x < x1 * scale; x++) pixels[(y * width + x) * 4 + 3] = 255;\n }\n }\n }\n\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/skin/SkinTextures.ts"],"sourcesContent":["import { DataTexture, DoubleSide, FrontSide, MeshBasicMaterial, SRGBColorSpace } from \"three\";\nimport { Caching } from \"../cache/Caching\";\nimport { serializeImageKey } from \"../cache/CacheKey\";\nimport { MineRenderError } from \"../error/MineRenderError\";\nimport { SkinImage } from \"./SkinImage\";\nimport { Textures } from \"../texture/Textures\";\nimport { CapeLayout } from \"./CapeLayout\";\n\n/** A prepared shared skin material with detected arm-model and texture-layout flags. */\nexport interface SkinTexture {\n material: MeshBasicMaterial;\n slim: boolean;\n legacy: boolean;\n}\n\n/** Prepares shared skin and cape materials, including legacy layout conversion and base-layer opacity. */\nexport class SkinTextures {\n\n /** Loads a skin URL. Pass `legacy` to override layout detection from the image dimensions. */\n public static async get(src: string, legacy?: boolean): Promise<SkinTexture> {\n const image = await SkinImage.getData(src);\n const scale = image.width / 64;\n if (!Number.isInteger(scale) || scale < 1 || (image.height !== image.width && image.height !== image.width / 2)) {\n throw new MineRenderError(`Invalid skin dimensions ${image.width}x${image.height}; expected 64x64 or 64x32, or an integer-scaled equivalent`);\n }\n const isLegacy = legacy ?? image.height === image.width / 2;\n if (!isLegacy && image.height !== image.width) {\n throw new MineRenderError(`Invalid skin dimensions ${image.width}x${image.height}; non-legacy skins must be square`);\n }\n const slim = !isLegacy && this.isSlim(image, scale);\n const key = `skin:${serializeImageKey({ src })}:${isLegacy}`;\n const material = Caching.materialCache.get(key, () => {\n const pixels = isLegacy ? this.normalizeLegacy(image, scale) : new Uint8Array(image.data);\n this.makeBaseOpaque(pixels, image.width, scale);\n return this.createMaterial(pixels, image.width, image.width);\n }) as MeshBasicMaterial;\n return { material, slim, legacy: isLegacy };\n }\n\n public static async getCape(src: string, layout: CapeLayout = \"minecraft\"): Promise<MeshBasicMaterial> {\n const image = await SkinImage.getData(src);\n const scale = image.width / 64;\n if (layout === \"minecraft\" && (!Number.isInteger(scale) || scale < 1 || image.height !== image.width / 2)) {\n throw new MineRenderError(`Invalid cape dimensions ${image.width}x${image.height}; expected 64x32 or an integer-scaled equivalent`);\n }\n return Caching.materialCache.get(`cape:${serializeImageKey({ src })}`, () => {\n return this.createMaterial(new Uint8Array(image.data), image.width, image.height, false);\n }) as MeshBasicMaterial;\n }\n\n private static createMaterial(pixels: Uint8Array, width: number, height: number, transparent: boolean = true): MeshBasicMaterial {\n const texture = Textures.initTextureProps(new DataTexture(pixels, width, height));\n texture.colorSpace = SRGBColorSpace;\n texture.flipY = true;\n texture.needsUpdate = true;\n return new MeshBasicMaterial({ map: texture, transparent, side: transparent ? DoubleSide : FrontSide, alphaTest: transparent ? 0.1 : 0 });\n }\n\n private static isSlim(image: ImageData, scale: number): boolean {\n for (const [x, y] of [[46, 52], [54, 20]]) {\n for (let row = y * scale; row < (y + 12) * scale; row++) {\n for (let column = x * scale; column < (x + 1) * scale; column++) {\n if (image.data[(row * image.width + column) * 4 + 3] !== 0) return false;\n }\n }\n }\n return true;\n }\n\n private static normalizeLegacy(image: ImageData, scale: number): Uint8Array {\n const pixels = new Uint8Array(image.width * image.width * 4);\n pixels.set(image.data.subarray(0, image.width * image.width / 2 * 4));\n // Vanilla mirrors each right-limb face into the modern left-limb texture regions.\n for (const [sx, sy, dx, dy, width, height] of [\n [4, 16, 20, 48, 4, 4], [8, 16, 24, 48, 4, 4],\n [0, 20, 24, 52, 4, 12], [4, 20, 20, 52, 4, 12],\n [8, 20, 16, 52, 4, 12], [12, 20, 28, 52, 4, 12],\n [44, 16, 36, 48, 4, 4], [48, 16, 40, 48, 4, 4],\n [40, 20, 40, 52, 4, 12], [44, 20, 36, 52, 4, 12],\n [48, 20, 32, 52, 4, 12], [52, 20, 44, 52, 4, 12]\n ]) {\n for (let y = 0; y < height * scale; y++) {\n for (let x = 0; x < width * scale; x++) {\n const source = ((sy * scale + y) * image.width + sx * scale + x) * 4;\n const target = ((dy * scale + y) * image.width + (dx + width) * scale - 1 - x) * 4;\n pixels.set(image.data.subarray(source, source + 4), target);\n }\n }\n }\n let clearHat = true;\n for (let y = 0; y < 32 * scale; y++) {\n for (let x = 32 * scale; x < image.width; x++) {\n if (pixels[(y * image.width + x) * 4 + 3] < 128) clearHat = false;\n }\n }\n if (clearHat) {\n for (let y = 0; y < 32 * scale; y++) {\n for (let x = 32 * scale; x < image.width; x++) {\n pixels[(y * image.width + x) * 4 + 3] = 0;\n }\n }\n }\n return pixels;\n }\n\n private static makeBaseOpaque(pixels: Uint8Array, width: number, scale: number): void {\n // Vanilla draws deadmau5's ears without alpha; no other part samples their hat-side strip.\n for (const [x0, y0, x1, y1] of [[0, 0, 32, 16], [0, 16, 64, 32], [16, 48, 48, 64], [32, 0, 38, 7]]) {\n for (let y = y0 * scale; y < y1 * scale; y++) {\n for (let x = x0 * scale; x < x1 * scale; x++) pixels[(y * width + x) * 4 + 3] = 255;\n }\n }\n }\n\n}\n"],"mappings":"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","names":[]}
@@ -1,5 +1,6 @@
1
1
  // src/skin/scene/SkinObject.ts
2
2
  import { SceneObject } from "../../renderer/SceneObject.mjs";
3
+ import { Object3D } from "three";
3
4
  import { SKIN_PARTS, SkinPart } from "../SkinPart.mjs";
4
5
  import { classicSkinTextureCoordinates, slimSkinTextureCoordinates } from "../SkinTextureCoordinates.mjs";
5
6
  import { classicSkinGeometries, slimSkinGeometries } from "../SkinGeometries.mjs";
@@ -9,6 +10,12 @@ import { merge } from "../../util/_internal/merge.mjs";
9
10
  import { toRadians } from "../../util/util.mjs";
10
11
  import { SkinTextures } from "../SkinTextures.mjs";
11
12
  import { capeTextureSizes } from "../CapeLayout.mjs";
13
+ var ArmorClass;
14
+ var EntityObjectClass;
15
+ function hasCubes(part) {
16
+ return part.cubes.length > 0 || Object.values(part.children).some(hasCubes);
17
+ }
18
+ var UPSIDE_DOWN_OFFSET = (1.8 + 0.1) * 16 / 0.9375;
12
19
  var SkinObject = class extends SceneObject {
13
20
  constructor(options) {
14
21
  super();
@@ -16,27 +23,42 @@ var SkinObject = class extends SceneObject {
16
23
  this.detectedSlim = false;
17
24
  this.skinLoad = 0;
18
25
  this.capeLoad = 0;
26
+ this.armorLoad = 0;
27
+ this.armorObjects = [];
19
28
  this.options = merge({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
20
29
  this.slim = this.options.slim ?? false;
21
30
  }
22
31
  async init() {
23
32
  const cape = this.getGroupByName(SkinPart.CAPE);
33
+ const capeOnBody = cape?.parent === this.getGroupByName(SkinPart.BODY);
24
34
  this.createMeshes();
25
- if (cape) this.getGroupByName(SkinPart.BODY).attach(cape);
35
+ if (cape) {
36
+ const body = this.getGroupByName(SkinPart.BODY);
37
+ if (capeOnBody) body.add(cape);
38
+ else body.attach(cape);
39
+ }
40
+ for (const { part, object } of this.armorObjects) this.getGroupByName(part).add(object);
41
+ this.updateEars();
42
+ this.updateUpsideDown();
26
43
  }
27
44
  removeMeshes() {
28
45
  }
29
46
  createMeshes() {
30
47
  const mat = this.skinMaterial ?? Materials.MISSING_TEXTURE;
48
+ this.model?.removeFromParent();
49
+ const model = this.model = new Object3D();
50
+ this.add(model);
31
51
  {
32
- const headGroup = this.createAndAddGroup("head", 0, 28, 0, Axis.Y, -4);
52
+ const headGroup = this.createGroup("head", 0, 28, 0, Axis.Y, -4);
53
+ model.add(headGroup);
33
54
  const headGeo = this.getBoxGeometry(SkinPart.HEAD);
34
55
  const head = this.createAndAddMesh("head", headGroup, headGeo, mat, Axis.Y, 4);
35
56
  const hatGeo = this.getBoxGeometry(SkinPart.HAT);
36
57
  const hat = this.createAndAddMesh("hat", headGroup, hatGeo, mat, Axis.Y, 4);
37
58
  }
38
59
  {
39
- const bodyGroup = this.createAndAddGroup("body", 0, 24, 0);
60
+ const bodyGroup = this.createGroup("body", 0, 24, 0);
61
+ model.add(bodyGroup);
40
62
  const bodyGeo = this.getBoxGeometry(SkinPart.BODY);
41
63
  const body = this.createAndAddMesh("body", bodyGroup, bodyGeo, mat, Axis.Y, -6);
42
64
  const jacketGeo = this.getBoxGeometry(SkinPart.JACKET);
@@ -44,7 +66,8 @@ var SkinObject = class extends SceneObject {
44
66
  }
45
67
  {
46
68
  {
47
- const leftArmGroup = this.createAndAddGroup("leftArm", 5, 22, 0);
69
+ const leftArmGroup = this.createGroup("leftArm", 5, 22, 0);
70
+ model.add(leftArmGroup);
48
71
  const leftArmGeo = this.getBoxGeometry(SkinPart.LEFT_ARM);
49
72
  const leftArm = this.createAndAddMesh("leftArm", leftArmGroup, leftArmGeo, mat, Axis.Y, -4);
50
73
  leftArm.position.x = this.slim ? 0.5 : 1;
@@ -53,7 +76,8 @@ var SkinObject = class extends SceneObject {
53
76
  leftSleeve.position.x = this.slim ? 0.5 : 1;
54
77
  }
55
78
  {
56
- const rightArmGroup = this.createAndAddGroup("rightArm", -5, 22, 0);
79
+ const rightArmGroup = this.createGroup("rightArm", -5, 22, 0);
80
+ model.add(rightArmGroup);
57
81
  const rightArmGeo = this.getBoxGeometry(SkinPart.RIGHT_ARM);
58
82
  const rightArm = this.createAndAddMesh("rightArm", rightArmGroup, rightArmGeo, mat, Axis.Y, -4);
59
83
  rightArm.position.x = this.slim ? -0.5 : -1;
@@ -64,14 +88,16 @@ var SkinObject = class extends SceneObject {
64
88
  }
65
89
  {
66
90
  {
67
- const leftLegGroup = this.createAndAddGroup("leftLeg", 1.9, 12, 0);
91
+ const leftLegGroup = this.createGroup("leftLeg", 1.9, 12, 0);
92
+ model.add(leftLegGroup);
68
93
  const leftLegGeo = this.getBoxGeometry(SkinPart.LEFT_LEG);
69
94
  const leftLeg = this.createAndAddMesh("leftLeg", leftLegGroup, leftLegGeo, mat, Axis.Y, -6);
70
95
  const leftTrousersGeo = this.getBoxGeometry(SkinPart.LEFT_TROUSERS);
71
96
  const leftTrousers = this.createAndAddMesh("leftTrousers", leftLegGroup, leftTrousersGeo, mat, Axis.Y, -6);
72
97
  }
73
98
  {
74
- const rightLegGroup = this.createAndAddGroup("rightLeg", -1.9, 12, 0);
99
+ const rightLegGroup = this.createGroup("rightLeg", -1.9, 12, 0);
100
+ model.add(rightLegGroup);
75
101
  const rightLegGeo = this.getBoxGeometry(SkinPart.RIGHT_LEG);
76
102
  const rightLeg = this.createAndAddMesh("rightLeg", rightLegGroup, rightLegGeo, mat, Axis.Y, -6);
77
103
  const rightTrousersGeo = this.getBoxGeometry(SkinPart.RIGHT_TROUSERS);
@@ -138,6 +164,54 @@ var SkinObject = class extends SceneObject {
138
164
  }
139
165
  this.notifyDirty();
140
166
  }
167
+ /**
168
+ * Loads armor from 1.21.4+ equipment assets, or pass undefined to remove it.
169
+ * Each piece moves with the skin part it covers.
170
+ */
171
+ async setArmor(armor) {
172
+ const load = ++this.armorLoad;
173
+ const objects = [];
174
+ if (armor) {
175
+ const Armor = ArmorClass ?? (ArmorClass = (await import("../../armor/Armor.mjs")).Armor);
176
+ const EntityObject = EntityObjectClass ?? (EntityObjectClass = (await import("../../entity/scene/EntityObject.mjs")).EntityObject);
177
+ const model = await Armor.getEntity(armor);
178
+ if (model) {
179
+ const parts = { head: "head", body: "body", left_arm: "leftArm", right_arm: "rightArm", left_leg: "leftLeg", right_leg: "rightLeg" };
180
+ for (const [name, part] of Object.entries(parts)) {
181
+ const layers = {};
182
+ for (const [draw, layer] of Object.entries(model.layers)) {
183
+ const child = layer.layer.root.children[name];
184
+ if (!child || !hasCubes(child)) continue;
185
+ const pose = { offset: [0, 0, 0], rotation: [0, 0, 0] };
186
+ layers[draw] = { ...layer, layer: { ...layer.layer, root: {
187
+ pose,
188
+ cubes: [],
189
+ children: { [name]: { ...child, pose } }
190
+ } } };
191
+ }
192
+ const first = Object.values(layers)[0];
193
+ if (!first) continue;
194
+ const object = new EntityObject({ ...first, id: model.id, layers }, { flip: false });
195
+ object.rotation.x = Math.PI;
196
+ objects.push({ part, object });
197
+ }
198
+ }
199
+ }
200
+ const results = await Promise.allSettled(objects.map(({ object }) => object.init()));
201
+ const failure = results.find((result) => result.status === "rejected");
202
+ if (load !== this.armorLoad || failure) {
203
+ for (const { object } of objects) object.dispose();
204
+ if (load === this.armorLoad && failure?.status === "rejected") throw failure.reason;
205
+ return;
206
+ }
207
+ for (const { object } of this.armorObjects) {
208
+ object.dispose();
209
+ object.removeFromParent();
210
+ }
211
+ this.armorObjects = objects;
212
+ for (const { part, object } of objects) this.getGroupByName(part)?.add(object);
213
+ this.notifyDirty();
214
+ }
141
215
  /** Select the arm model, or pass undefined to use texture detection. */
142
216
  setSlim(slim) {
143
217
  this.options.slim = slim;
@@ -156,6 +230,39 @@ var SkinObject = class extends SceneObject {
156
230
  }
157
231
  this.notifyDirty();
158
232
  }
233
+ /** Shows or hides deadmau5's ears, which vanilla draws from the skin texture at 24,0 for that player only. */
234
+ setEars(ears) {
235
+ if (ears === (this.options.ears ?? false)) return;
236
+ this.options.ears = ears;
237
+ this.updateEars();
238
+ }
239
+ updateEars() {
240
+ const head = this.getGroupByName(SkinPart.HEAD);
241
+ if (!head) return;
242
+ for (const [part, x] of [[SkinPart.LEFT_EAR, 6], [SkinPart.RIGHT_EAR, -6]]) {
243
+ const ear = this.getMeshByName(part);
244
+ if (!this.options.ears) {
245
+ ear?.removeFromParent();
246
+ } else if (!ear) {
247
+ const mesh = this.createAndAddMesh(part, head, this.getBoxGeometry(part), this.skinMaterial ?? Materials.MISSING_TEXTURE);
248
+ mesh.position.set(x, 9, 0.5);
249
+ }
250
+ }
251
+ this.notifyDirty();
252
+ }
253
+ /** Turns the player upside down, as vanilla does for players named Dinnerbone or Grumm. */
254
+ setUpsideDown(upsideDown) {
255
+ if (upsideDown === (this.options.upsideDown ?? false)) return;
256
+ this.options.upsideDown = upsideDown;
257
+ this.updateUpsideDown();
258
+ }
259
+ updateUpsideDown() {
260
+ if (!this.model) return;
261
+ const upsideDown = this.options.upsideDown ?? false;
262
+ this.model.position.y = upsideDown ? UPSIDE_DOWN_OFFSET : 0;
263
+ this.model.rotation.z = upsideDown ? Math.PI : 0;
264
+ this.notifyDirty();
265
+ }
159
266
  /** Select the texture layout, or pass undefined to detect it from image dimensions. */
160
267
  async setLegacy(legacy) {
161
268
  if (legacy === this.options.legacy) return;
@@ -165,6 +272,11 @@ var SkinObject = class extends SceneObject {
165
272
  dispose() {
166
273
  this.skinLoad++;
167
274
  this.capeLoad++;
275
+ this.armorLoad++;
276
+ for (const { object } of this.armorObjects.splice(0)) {
277
+ object.dispose();
278
+ object.removeFromParent();
279
+ }
168
280
  super.dispose();
169
281
  }
170
282
  //TODO: layer toggles
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/skin/scene/SkinObject.ts"],"sourcesContent":["import { SceneObject } from \"../../renderer/SceneObject\";\nimport { BoxGeometry, Material } from \"three\";\nimport { SKIN_PARTS, SkinPart } from \"../SkinPart\";\nimport { classicSkinTextureCoordinates, SkinTextureCoordinates, slimSkinTextureCoordinates } from \"../SkinTextureCoordinates\";\nimport { classicSkinGeometries, SkinGeometries, slimSkinGeometries } from \"../SkinGeometries\";\nimport { Axis } from \"../../Axis\";\nimport { Materials } from \"../../Materials\";\nimport { merge } from \"../../util/_internal/merge\";\nimport { SceneObjectOptions } from \"../../renderer/SceneObjectOptions\";\nimport { DeepPartial, toRadians } from \"../../util/util\";\nimport { SkinTextures } from \"../SkinTextures\";\nimport { CapeLayout, capeTextureSizes } from \"../CapeLayout\";\n\n/** A player model facing +Z. Left and right parts are the player's own: left is +X, right is -X. */\nexport class SkinObject extends SceneObject {\n\n public readonly options: SkinObjectOptions;\n\n private slim: boolean = false;\n private detectedSlim: boolean = false;\n private skinTextureSrc?: string;\n private skinMaterial?: Material;\n private skinLoad: number = 0;\n\n private capeLoad: number = 0;\n\n\n constructor(options?: DeepPartial<SkinObjectOptions>) {\n super();\n this.options = merge({}, SceneObject.DEFAULT_OPTIONS, options ?? {});\n this.slim = this.options.slim ?? false;\n }\n\n async init(): Promise<void> {\n const cape = this.getGroupByName(SkinPart.CAPE);\n this.createMeshes();\n if (cape) this.getGroupByName(SkinPart.BODY)!.attach(cape);\n }\n\n protected removeMeshes(): void {\n\n }\n\n protected createMeshes() {\n const mat = this.skinMaterial ?? Materials.MISSING_TEXTURE;\n\n {\n const headGroup = this.createAndAddGroup(\"head\", 0, 28, 0, Axis.Y, -4);\n\n const headGeo = this.getBoxGeometry(SkinPart.HEAD);\n const head = this.createAndAddMesh(\"head\", headGroup, headGeo, mat, Axis.Y, 4);\n\n const hatGeo = this.getBoxGeometry(SkinPart.HAT);\n const hat = this.createAndAddMesh(\"hat\", headGroup, hatGeo, mat, Axis.Y, 4);\n }\n\n {\n const bodyGroup = this.createAndAddGroup(\"body\", 0, 24, 0);\n\n const bodyGeo = this.getBoxGeometry(SkinPart.BODY);\n const body = this.createAndAddMesh(\"body\", bodyGroup, bodyGeo, mat, Axis.Y, -6);\n\n const jacketGeo = this.getBoxGeometry(SkinPart.JACKET);\n const jacket = this.createAndAddMesh(\"jacket\", bodyGroup, jacketGeo, mat, Axis.Y, -6);\n }\n\n {\n {\n const leftArmGroup = this.createAndAddGroup(\"leftArm\", 5, 22, 0);\n\n const leftArmGeo = this.getBoxGeometry(SkinPart.LEFT_ARM);\n const leftArm = this.createAndAddMesh(\"leftArm\", leftArmGroup, leftArmGeo, mat, Axis.Y, -4);\n leftArm.position.x = this.slim ? 0.5 : 1;\n\n const leftSleeveGeo = this.getBoxGeometry(SkinPart.LEFT_SLEEVE);\n const leftSleeve = this.createAndAddMesh(\"leftSleeve\", leftArmGroup, leftSleeveGeo, mat, Axis.Y, -4);\n leftSleeve.position.x = this.slim ? 0.5 : 1;\n }\n {\n const rightArmGroup = this.createAndAddGroup(\"rightArm\", -5, 22, 0);\n\n const rightArmGeo = this.getBoxGeometry(SkinPart.RIGHT_ARM);\n const rightArm = this.createAndAddMesh(\"rightArm\", rightArmGroup, rightArmGeo, mat, Axis.Y, -4);\n rightArm.position.x = this.slim ? -0.5 : -1;\n\n const rightSleeveGeo = this.getBoxGeometry(SkinPart.RIGHT_SLEEVE);\n const rightSleeve = this.createAndAddMesh(\"rightSleeve\", rightArmGroup, rightSleeveGeo, mat, Axis.Y, -4);\n rightSleeve.position.x = this.slim ? -0.5 : -1;\n }\n }\n\n {\n {\n const leftLegGroup = this.createAndAddGroup(\"leftLeg\", 1.9, 12, 0);\n\n const leftLegGeo = this.getBoxGeometry(SkinPart.LEFT_LEG);\n const leftLeg = this.createAndAddMesh(\"leftLeg\", leftLegGroup, leftLegGeo, mat, Axis.Y, -6);\n\n const leftTrousersGeo = this.getBoxGeometry(SkinPart.LEFT_TROUSERS);\n const leftTrousers = this.createAndAddMesh(\"leftTrousers\", leftLegGroup, leftTrousersGeo, mat, Axis.Y, -6);\n }\n {\n const rightLegGroup = this.createAndAddGroup(\"rightLeg\", -1.9, 12, 0);\n\n const rightLegGeo = this.getBoxGeometry(SkinPart.RIGHT_LEG);\n const rightLeg = this.createAndAddMesh(\"rightLeg\", rightLegGroup, rightLegGeo, mat, Axis.Y, -6);\n\n const rightTrousersGeo = this.getBoxGeometry(SkinPart.RIGHT_TROUSERS);\n const rightTrousers = this.createAndAddMesh(\"rightTrousers\", rightLegGroup, rightTrousersGeo, mat, Axis.Y, -6);\n }\n }\n\n\n }\n\n\n /**\n * Loads a skin texture, detecting slim arms and legacy layouts by default.\n * To override detection, set `slim` or `legacy` in the options passed to\n * `new SkinObject(options)` or `scene.addSkin(src, options)`.\n * Use {@link setSlim} or {@link setLegacy} to change these settings later.\n *\n * @param src - URL of the skin texture.\n */\n public async setSkinTexture(src: string): Promise<void> {\n if (typeof src === \"undefined\") return;\n this.skinTextureSrc = src;\n const load = ++this.skinLoad;\n const texture = await SkinTextures.get(src, this.options.legacy);\n if (load !== this.skinLoad) return;\n\n this.skinMaterial = texture.material;\n this.detectedSlim = texture.slim;\n this.updateSlim(this.options.slim ?? this.detectedSlim);\n for (const part of SKIN_PARTS) {\n if (part === SkinPart.CAPE) continue;\n const mesh = this.getMeshByName(part);\n if (mesh) {\n mesh.material = texture.material;\n }\n }\n this.notifyDirty();\n }\n\n /** Load a cape texture in the selected layout, or pass undefined to remove the cape. */\n public async setCapeTexture(src?: string, layout: CapeLayout = \"minecraft\"): Promise<void> {\n const load = ++this.capeLoad;\n if (src === undefined) {\n const group = this.getGroupByName(SkinPart.CAPE);\n group?.removeFromParent();\n this.notifyDirty();\n return;\n }\n\n const material = await SkinTextures.getCape(src, layout);\n if (load !== this.capeLoad) return;\n const size = capeTextureSizes[layout];\n const geometry = this._getBoxGeometryFromDimensions(\n classicSkinGeometries.cape, classicSkinTextureCoordinates.cape, size, size);\n const mesh = this.getMeshByName(SkinPart.CAPE);\n if (mesh) {\n mesh.material = material;\n mesh.geometry = geometry;\n } else {\n const body = this.getGroupByName(SkinPart.BODY);\n const group = this.createGroup(SkinPart.CAPE);\n group.position.set(0, body ? 0 : 24, -2);\n (body ?? this).add(group);\n group.rotation.x = toRadians(6);\n const cape = this.createAndAddMesh(SkinPart.CAPE, group, geometry, material);\n cape.position.set(0, -8, -0.5);\n }\n this.notifyDirty();\n }\n\n /** Select the arm model, or pass undefined to use texture detection. */\n public setSlim(slim?: boolean): void {\n this.options.slim = slim;\n this.updateSlim(slim ?? this.detectedSlim);\n }\n\n private updateSlim(slim: boolean): void {\n if (slim === this.slim) return;\n this.slim = slim;\n\n const offset = slim ? -0.5 : 0.5;\n for (const part of [SkinPart.LEFT_ARM, SkinPart.LEFT_SLEEVE, SkinPart.RIGHT_ARM, SkinPart.RIGHT_SLEEVE]) {\n const mesh = this.getMeshByName(part);\n if (mesh) {\n mesh.geometry = this.getBoxGeometry(part);\n mesh.position.x += part === SkinPart.LEFT_ARM || part === SkinPart.LEFT_SLEEVE ? offset : -offset;\n }\n }\n this.notifyDirty();\n }\n\n /** Select the texture layout, or pass undefined to detect it from image dimensions. */\n public async setLegacy(legacy?: boolean): Promise<void> {\n if (legacy === this.options.legacy) return;\n this.options.legacy = legacy;\n if (this.skinTextureSrc) await this.setSkinTexture(this.skinTextureSrc);\n }\n\n public dispose(): void {\n this.skinLoad++;\n this.capeLoad++;\n super.dispose();\n }\n\n //TODO: layer toggles\n\n\n protected getBoxGeometry(part: SkinPart): BoxGeometry {\n const coordinates: SkinTextureCoordinates = this.slim ? slimSkinTextureCoordinates : classicSkinTextureCoordinates;\n const geometries: SkinGeometries = this.slim ? slimSkinGeometries : classicSkinGeometries;\n return this._getBoxGeometryFromDimensions(geometries[part], coordinates[part], [64, 64], [64, 64]);\n }\n\n\n}\n\n/** Player settings passed to `new SkinObject(options)` or `scene.addSkin(src, options)`. */\nexport interface SkinObjectOptions extends SceneObjectOptions {\n /** Forces slim (`true`) or classic (`false`) arms. Omit it to detect the model from the texture. */\n slim?: boolean;\n /** Forces the legacy (`true`) or modern (`false`) texture layout. Omit it to detect the layout. */\n legacy?: boolean;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../../src/skin/scene/SkinObject.ts"],"sourcesContent":["import { SceneObject } from \"../../renderer/SceneObject\";\nimport { BoxGeometry, Material, Object3D } from \"three\";\nimport { SKIN_PARTS, SkinPart } from \"../SkinPart\";\nimport { classicSkinTextureCoordinates, SkinTextureCoordinates, slimSkinTextureCoordinates } from \"../SkinTextureCoordinates\";\nimport { classicSkinGeometries, SkinGeometries, slimSkinGeometries } from \"../SkinGeometries\";\nimport { Axis } from \"../../Axis\";\nimport { Materials } from \"../../Materials\";\nimport { merge } from \"../../util/_internal/merge\";\nimport { SceneObjectOptions } from \"../../renderer/SceneObjectOptions\";\nimport { DeepPartial, toRadians } from \"../../util/util\";\nimport { SkinTextures } from \"../SkinTextures\";\nimport { CapeLayout, capeTextureSizes } from \"../CapeLayout\";\nimport type { Armor, ArmorSet } from \"../../armor/Armor\";\nimport type { EntityObject } from \"../../entity/scene/EntityObject\";\nimport type { EntityLayer, EntityModelPart } from \"../../entity/EntityModel\";\n\nlet ArmorClass: typeof Armor | undefined;\nlet EntityObjectClass: typeof EntityObject | undefined;\n\nfunction hasCubes(part: EntityModelPart): boolean {\n return part.cubes.length > 0 || Object.values(part.children).some(hasCubes);\n}\n\n// Vanilla raises upside-down players by their 1.8-block height plus 0.1, before the 15/16 player scale.\nconst UPSIDE_DOWN_OFFSET = (1.8 + 0.1) * 16 / 0.9375;\n\n/** A player model facing +Z. Left and right parts are the player's own: left is +X, right is -X. */\nexport class SkinObject extends SceneObject {\n\n public readonly options: SkinObjectOptions;\n\n private slim: boolean = false;\n private detectedSlim: boolean = false;\n private skinTextureSrc?: string;\n private skinMaterial?: Material;\n private skinLoad: number = 0;\n\n private capeLoad: number = 0;\n private armorLoad: number = 0;\n private armorObjects: { part: string; object: EntityObject }[] = [];\n\n private model?: Object3D;\n\n\n constructor(options?: DeepPartial<SkinObjectOptions>) {\n super();\n this.options = merge({}, SceneObject.DEFAULT_OPTIONS, options ?? {});\n this.slim = this.options.slim ?? false;\n }\n\n async init(): Promise<void> {\n const cape = this.getGroupByName(SkinPart.CAPE);\n const capeOnBody = cape?.parent === this.getGroupByName(SkinPart.BODY);\n this.createMeshes();\n if (cape) {\n const body = this.getGroupByName(SkinPart.BODY)!;\n // Existing capes keep their body-relative pose; pre-init capes use skin coordinates.\n if (capeOnBody) body.add(cape);\n else body.attach(cape);\n }\n for (const { part, object } of this.armorObjects) this.getGroupByName(part)!.add(object);\n this.updateEars();\n this.updateUpsideDown();\n }\n\n protected removeMeshes(): void {\n\n }\n\n protected createMeshes() {\n const mat = this.skinMaterial ?? Materials.MISSING_TEXTURE;\n // The parts share one root so the upside-down transform keeps caller placement and joint poses.\n this.model?.removeFromParent();\n const model = this.model = new Object3D();\n this.add(model);\n\n {\n const headGroup = this.createGroup(\"head\", 0, 28, 0, Axis.Y, -4);\n model.add(headGroup);\n\n const headGeo = this.getBoxGeometry(SkinPart.HEAD);\n const head = this.createAndAddMesh(\"head\", headGroup, headGeo, mat, Axis.Y, 4);\n\n const hatGeo = this.getBoxGeometry(SkinPart.HAT);\n const hat = this.createAndAddMesh(\"hat\", headGroup, hatGeo, mat, Axis.Y, 4);\n }\n\n {\n const bodyGroup = this.createGroup(\"body\", 0, 24, 0);\n model.add(bodyGroup);\n\n const bodyGeo = this.getBoxGeometry(SkinPart.BODY);\n const body = this.createAndAddMesh(\"body\", bodyGroup, bodyGeo, mat, Axis.Y, -6);\n\n const jacketGeo = this.getBoxGeometry(SkinPart.JACKET);\n const jacket = this.createAndAddMesh(\"jacket\", bodyGroup, jacketGeo, mat, Axis.Y, -6);\n }\n\n {\n {\n const leftArmGroup = this.createGroup(\"leftArm\", 5, 22, 0);\n model.add(leftArmGroup);\n\n const leftArmGeo = this.getBoxGeometry(SkinPart.LEFT_ARM);\n const leftArm = this.createAndAddMesh(\"leftArm\", leftArmGroup, leftArmGeo, mat, Axis.Y, -4);\n leftArm.position.x = this.slim ? 0.5 : 1;\n\n const leftSleeveGeo = this.getBoxGeometry(SkinPart.LEFT_SLEEVE);\n const leftSleeve = this.createAndAddMesh(\"leftSleeve\", leftArmGroup, leftSleeveGeo, mat, Axis.Y, -4);\n leftSleeve.position.x = this.slim ? 0.5 : 1;\n }\n {\n const rightArmGroup = this.createGroup(\"rightArm\", -5, 22, 0);\n model.add(rightArmGroup);\n\n const rightArmGeo = this.getBoxGeometry(SkinPart.RIGHT_ARM);\n const rightArm = this.createAndAddMesh(\"rightArm\", rightArmGroup, rightArmGeo, mat, Axis.Y, -4);\n rightArm.position.x = this.slim ? -0.5 : -1;\n\n const rightSleeveGeo = this.getBoxGeometry(SkinPart.RIGHT_SLEEVE);\n const rightSleeve = this.createAndAddMesh(\"rightSleeve\", rightArmGroup, rightSleeveGeo, mat, Axis.Y, -4);\n rightSleeve.position.x = this.slim ? -0.5 : -1;\n }\n }\n\n {\n {\n const leftLegGroup = this.createGroup(\"leftLeg\", 1.9, 12, 0);\n model.add(leftLegGroup);\n\n const leftLegGeo = this.getBoxGeometry(SkinPart.LEFT_LEG);\n const leftLeg = this.createAndAddMesh(\"leftLeg\", leftLegGroup, leftLegGeo, mat, Axis.Y, -6);\n\n const leftTrousersGeo = this.getBoxGeometry(SkinPart.LEFT_TROUSERS);\n const leftTrousers = this.createAndAddMesh(\"leftTrousers\", leftLegGroup, leftTrousersGeo, mat, Axis.Y, -6);\n }\n {\n const rightLegGroup = this.createGroup(\"rightLeg\", -1.9, 12, 0);\n model.add(rightLegGroup);\n\n const rightLegGeo = this.getBoxGeometry(SkinPart.RIGHT_LEG);\n const rightLeg = this.createAndAddMesh(\"rightLeg\", rightLegGroup, rightLegGeo, mat, Axis.Y, -6);\n\n const rightTrousersGeo = this.getBoxGeometry(SkinPart.RIGHT_TROUSERS);\n const rightTrousers = this.createAndAddMesh(\"rightTrousers\", rightLegGroup, rightTrousersGeo, mat, Axis.Y, -6);\n }\n }\n\n\n }\n\n\n /**\n * Loads a skin texture, detecting slim arms and legacy layouts by default.\n * To override detection, set `slim` or `legacy` in the options passed to\n * `new SkinObject(options)` or `scene.addSkin(src, options)`.\n * Use {@link setSlim} or {@link setLegacy} to change these settings later.\n *\n * @param src - URL of the skin texture.\n */\n public async setSkinTexture(src: string): Promise<void> {\n if (typeof src === \"undefined\") return;\n this.skinTextureSrc = src;\n const load = ++this.skinLoad;\n const texture = await SkinTextures.get(src, this.options.legacy);\n if (load !== this.skinLoad) return;\n\n this.skinMaterial = texture.material;\n this.detectedSlim = texture.slim;\n this.updateSlim(this.options.slim ?? this.detectedSlim);\n for (const part of SKIN_PARTS) {\n if (part === SkinPart.CAPE) continue;\n const mesh = this.getMeshByName(part);\n if (mesh) {\n mesh.material = texture.material;\n }\n }\n this.notifyDirty();\n }\n\n /** Load a cape texture in the selected layout, or pass undefined to remove the cape. */\n public async setCapeTexture(src?: string, layout: CapeLayout = \"minecraft\"): Promise<void> {\n const load = ++this.capeLoad;\n if (src === undefined) {\n const group = this.getGroupByName(SkinPart.CAPE);\n group?.removeFromParent();\n this.notifyDirty();\n return;\n }\n\n const material = await SkinTextures.getCape(src, layout);\n if (load !== this.capeLoad) return;\n const size = capeTextureSizes[layout];\n const geometry = this._getBoxGeometryFromDimensions(\n classicSkinGeometries.cape, classicSkinTextureCoordinates.cape, size, size);\n const mesh = this.getMeshByName(SkinPart.CAPE);\n if (mesh) {\n mesh.material = material;\n mesh.geometry = geometry;\n } else {\n const body = this.getGroupByName(SkinPart.BODY);\n const group = this.createGroup(SkinPart.CAPE);\n group.position.set(0, body ? 0 : 24, -2);\n (body ?? this).add(group);\n group.rotation.x = toRadians(6);\n const cape = this.createAndAddMesh(SkinPart.CAPE, group, geometry, material);\n cape.position.set(0, -8, -0.5);\n }\n this.notifyDirty();\n }\n\n /**\n * Loads armor from 1.21.4+ equipment assets, or pass undefined to remove it.\n * Each piece moves with the skin part it covers.\n */\n public async setArmor(armor?: ArmorSet): Promise<void> {\n const load = ++this.armorLoad;\n const objects: { part: string; object: EntityObject }[] = [];\n if (armor) {\n const Armor = ArmorClass ??= (await import(\"../../armor/Armor\")).Armor;\n const EntityObject = EntityObjectClass ??= (await import(\"../../entity/scene/EntityObject\")).EntityObject;\n const model = await Armor.getEntity(armor);\n if (model) {\n const parts = { head: \"head\", body: \"body\", left_arm: \"leftArm\", right_arm: \"rightArm\", left_leg: \"leftLeg\", right_leg: \"rightLeg\" };\n for (const [name, part] of Object.entries(parts)) {\n const layers: Record<string, EntityLayer> = {};\n for (const [draw, layer] of Object.entries(model.layers!)) {\n const child = layer.layer.root.children[name];\n if (!child || !hasCubes(child)) continue;\n // The skin group supplies the dataset part's pivot; nested parts retain their own poses.\n const pose: EntityModelPart[\"pose\"] = { offset: [0, 0, 0], rotation: [0, 0, 0] };\n layers[draw] = { ...layer, layer: { ...layer.layer, root: {\n pose, cubes: [], children: { [name]: { ...child, pose } }\n } } };\n }\n const first = Object.values(layers)[0];\n if (!first) continue;\n const object = new EntityObject({ ...first, id: model.id, layers }, { flip: false });\n object.rotation.x = Math.PI;\n objects.push({ part, object });\n }\n }\n }\n const results = await Promise.allSettled(objects.map(({ object }) => object.init()));\n const failure = results.find(result => result.status === \"rejected\");\n if (load !== this.armorLoad || failure) {\n for (const { object } of objects) object.dispose();\n if (load === this.armorLoad && failure?.status === \"rejected\") throw failure.reason;\n return;\n }\n for (const { object } of this.armorObjects) { object.dispose(); object.removeFromParent(); }\n this.armorObjects = objects;\n for (const { part, object } of objects) this.getGroupByName(part)?.add(object);\n this.notifyDirty();\n }\n\n /** Select the arm model, or pass undefined to use texture detection. */\n public setSlim(slim?: boolean): void {\n this.options.slim = slim;\n this.updateSlim(slim ?? this.detectedSlim);\n }\n\n private updateSlim(slim: boolean): void {\n if (slim === this.slim) return;\n this.slim = slim;\n\n const offset = slim ? -0.5 : 0.5;\n for (const part of [SkinPart.LEFT_ARM, SkinPart.LEFT_SLEEVE, SkinPart.RIGHT_ARM, SkinPart.RIGHT_SLEEVE]) {\n const mesh = this.getMeshByName(part);\n if (mesh) {\n mesh.geometry = this.getBoxGeometry(part);\n mesh.position.x += part === SkinPart.LEFT_ARM || part === SkinPart.LEFT_SLEEVE ? offset : -offset;\n }\n }\n this.notifyDirty();\n }\n\n /** Shows or hides deadmau5's ears, which vanilla draws from the skin texture at 24,0 for that player only. */\n public setEars(ears: boolean): void {\n if (ears === (this.options.ears ?? false)) return;\n this.options.ears = ears;\n this.updateEars();\n }\n\n private updateEars(): void {\n const head = this.getGroupByName(SkinPart.HEAD);\n if (!head) return;\n // Vanilla's left_ear is on the player's right; these names follow the player's own sides, like the arms.\n for (const [part, x] of [[SkinPart.LEFT_EAR, 6], [SkinPart.RIGHT_EAR, -6]] as const) {\n const ear = this.getMeshByName(part);\n if (!this.options.ears) {\n ear?.removeFromParent();\n } else if (!ear) {\n const mesh = this.createAndAddMesh(part, head, this.getBoxGeometry(part), this.skinMaterial ?? Materials.MISSING_TEXTURE);\n mesh.position.set(x, 9, 0.5);\n }\n }\n this.notifyDirty();\n }\n\n /** Turns the player upside down, as vanilla does for players named Dinnerbone or Grumm. */\n public setUpsideDown(upsideDown: boolean): void {\n if (upsideDown === (this.options.upsideDown ?? false)) return;\n this.options.upsideDown = upsideDown;\n this.updateUpsideDown();\n }\n\n private updateUpsideDown(): void {\n if (!this.model) return;\n const upsideDown = this.options.upsideDown ?? false;\n this.model.position.y = upsideDown ? UPSIDE_DOWN_OFFSET : 0;\n this.model.rotation.z = upsideDown ? Math.PI : 0;\n this.notifyDirty();\n }\n\n /** Select the texture layout, or pass undefined to detect it from image dimensions. */\n public async setLegacy(legacy?: boolean): Promise<void> {\n if (legacy === this.options.legacy) return;\n this.options.legacy = legacy;\n if (this.skinTextureSrc) await this.setSkinTexture(this.skinTextureSrc);\n }\n\n public dispose(): void {\n this.skinLoad++;\n this.capeLoad++;\n this.armorLoad++;\n for (const { object } of this.armorObjects.splice(0)) { object.dispose(); object.removeFromParent(); }\n super.dispose();\n }\n\n //TODO: layer toggles\n\n\n protected getBoxGeometry(part: SkinPart): BoxGeometry {\n const coordinates: SkinTextureCoordinates = this.slim ? slimSkinTextureCoordinates : classicSkinTextureCoordinates;\n const geometries: SkinGeometries = this.slim ? slimSkinGeometries : classicSkinGeometries;\n return this._getBoxGeometryFromDimensions(geometries[part], coordinates[part], [64, 64], [64, 64]);\n }\n\n\n}\n\n/** Player settings passed to `new SkinObject(options)` or `scene.addSkin(src, options)`. */\nexport interface SkinObjectOptions extends SceneObjectOptions {\n /** Forces slim (`true`) or classic (`false`) arms. Omit it to detect the model from the texture. */\n slim?: boolean;\n /** Forces the legacy (`true`) or modern (`false`) texture layout. Omit it to detect the layout. */\n legacy?: boolean;\n /** Draws deadmau5's ears from the skin texture. Vanilla shows them only for that player name. */\n ears?: boolean;\n /** Turns the player upside down. Vanilla does this for players named Dinnerbone or Grumm. */\n upsideDown?: boolean;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,46 @@
1
+ // src/texture/PalettedTextures.ts
2
+ import { ModelTextures } from "../assets/ModelTextures.mjs";
3
+ import { Caching } from "../cache/Caching.mjs";
4
+ import { CanvasImage } from "../canvas/CanvasImage.mjs";
5
+ import { MineRenderError } from "../error/MineRenderError.mjs";
6
+ var PalettedTextures = class {
7
+ /** Loads a texture with a palette permutation, sharing the resulting canvas between callers. */
8
+ static async get(texture, key, permutation) {
9
+ return Caching.canvasImageDataCache.get(`palette:${texture.serialize()}:${key.serialize()}:${permutation.serialize()}`, async () => {
10
+ const source = await ModelTextures.get(texture);
11
+ if (!source) return void 0;
12
+ const [palette, replacement] = await Promise.all([ModelTextures.get(key), ModelTextures.get(permutation)]);
13
+ if (!palette) throw new MineRenderError(`Missing palette ${key.toNamespacedString()}`);
14
+ if (!replacement) throw new MineRenderError(`Missing palette ${permutation.toNamespacedString()}`);
15
+ const pixels = source.data.getImageData(0, 0, source.width, source.height);
16
+ const colors = palette.data.getImageData(0, 0, palette.width, palette.height).data;
17
+ const replacements = replacement.data.getImageData(0, 0, replacement.width, replacement.height).data;
18
+ const image = new CanvasImage(source.width, source.height);
19
+ const output = image.context.createImageData(source.width, source.height);
20
+ output.data.set(this.permute(pixels.data, colors, replacements));
21
+ image.putData(output);
22
+ return { data: image.context, width: image.width, height: image.height };
23
+ });
24
+ }
25
+ /** @internal */
26
+ static permute(pixels, key, permutation) {
27
+ if (key.length !== permutation.length) throw new MineRenderError("Palette images must have the same pixel count");
28
+ const mapping = /* @__PURE__ */ new Map();
29
+ for (let i = 0; i < key.length; i += 4) {
30
+ if (key[i + 3] !== 0) mapping.set(key[i] << 16 | key[i + 1] << 8 | key[i + 2], i);
31
+ }
32
+ const output = new Uint8ClampedArray(pixels);
33
+ for (let i = 0; i < pixels.length; i += 4) {
34
+ if (pixels[i + 3] === 0) continue;
35
+ const mapped = mapping.get(pixels[i] << 16 | pixels[i + 1] << 8 | pixels[i + 2]);
36
+ if (mapped === void 0) continue;
37
+ output.set(permutation.subarray(mapped, mapped + 3), i);
38
+ output[i + 3] = Math.floor(pixels[i + 3] * permutation[mapped + 3] / 255);
39
+ }
40
+ return output;
41
+ }
42
+ };
43
+ export {
44
+ PalettedTextures
45
+ };
46
+ //# sourceMappingURL=PalettedTextures.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/texture/PalettedTextures.ts"],"sourcesContent":["import { AssetKey } from \"../assets/AssetKey\";\nimport { ModelTextures } from \"../assets/ModelTextures\";\nimport { Caching } from \"../cache/Caching\";\nimport { CanvasImage } from \"../canvas/CanvasImage\";\nimport { MineRenderError } from \"../error/MineRenderError\";\nimport type { ExtractableImageData } from \"../ExtractableImageData\";\nimport type { Maybe } from \"../util/util\";\n\n/** Recolours textures using indexed pairs of palette images. */\nexport class PalettedTextures {\n /** Loads a texture with a palette permutation, sharing the resulting canvas between callers. */\n public static async get(texture: AssetKey, key: AssetKey, permutation: AssetKey): Promise<Maybe<ExtractableImageData>> {\n return Caching.canvasImageDataCache.get(`palette:${texture.serialize()}:${key.serialize()}:${permutation.serialize()}`, async () => {\n const source = await ModelTextures.get(texture);\n if (!source) return undefined;\n const [palette, replacement] = await Promise.all([ModelTextures.get(key), ModelTextures.get(permutation)]);\n if (!palette) throw new MineRenderError(`Missing palette ${key.toNamespacedString()}`);\n if (!replacement) throw new MineRenderError(`Missing palette ${permutation.toNamespacedString()}`);\n const pixels = source.data.getImageData(0, 0, source.width, source.height);\n const colors = palette.data.getImageData(0, 0, palette.width, palette.height).data;\n const replacements = replacement.data.getImageData(0, 0, replacement.width, replacement.height).data;\n const image = new CanvasImage(source.width, source.height);\n const output = image.context.createImageData(source.width, source.height);\n output.data.set(this.permute(pixels.data, colors, replacements));\n image.putData(output);\n return { data: image.context as unknown as CanvasRenderingContext2D, width: image.width, height: image.height };\n });\n }\n\n /** @internal */\n public static permute(pixels: Uint8ClampedArray, key: Uint8ClampedArray, permutation: Uint8ClampedArray): Uint8ClampedArray {\n if (key.length !== permutation.length) throw new MineRenderError(\"Palette images must have the same pixel count\");\n const mapping = new Map<number, number>();\n for (let i = 0; i < key.length; i += 4) {\n if (key[i + 3] !== 0) mapping.set((key[i] << 16) | (key[i + 1] << 8) | key[i + 2], i);\n }\n const output = new Uint8ClampedArray(pixels);\n // PalettedPermutations.createPaletteMapping matches RGB and multiplies source and replacement alpha.\n for (let i = 0; i < pixels.length; i += 4) {\n if (pixels[i + 3] === 0) continue;\n const mapped = mapping.get((pixels[i] << 16) | (pixels[i + 1] << 8) | pixels[i + 2]);\n if (mapped === undefined) continue;\n output.set(permutation.subarray(mapped, mapped + 3), i);\n output[i + 3] = Math.floor(pixels[i + 3] * permutation[mapped + 3] / 255);\n }\n return output;\n }\n}\n"],"mappings":";AACA,SAAS,qBAAqB;AAC9B,SAAS,eAAe;AACxB,SAAS,mBAAmB;AAC5B,SAAS,uBAAuB;AAKzB,IAAM,mBAAN,MAAuB;AAAA;AAAA,EAE1B,aAAoB,IAAI,SAAmB,KAAe,aAA6D;AACnH,WAAO,QAAQ,qBAAqB,IAAI,WAAW,QAAQ,UAAU,CAAC,IAAI,IAAI,UAAU,CAAC,IAAI,YAAY,UAAU,CAAC,IAAI,YAAY;AAChI,YAAM,SAAS,MAAM,cAAc,IAAI,OAAO;AAC9C,UAAI,CAAC,OAAQ,QAAO;AACpB,YAAM,CAAC,SAAS,WAAW,IAAI,MAAM,QAAQ,IAAI,CAAC,cAAc,IAAI,GAAG,GAAG,cAAc,IAAI,WAAW,CAAC,CAAC;AACzG,UAAI,CAAC,QAAS,OAAM,IAAI,gBAAgB,mBAAmB,IAAI,mBAAmB,CAAC,EAAE;AACrF,UAAI,CAAC,YAAa,OAAM,IAAI,gBAAgB,mBAAmB,YAAY,mBAAmB,CAAC,EAAE;AACjG,YAAM,SAAS,OAAO,KAAK,aAAa,GAAG,GAAG,OAAO,OAAO,OAAO,MAAM;AACzE,YAAM,SAAS,QAAQ,KAAK,aAAa,GAAG,GAAG,QAAQ,OAAO,QAAQ,MAAM,EAAE;AAC9E,YAAM,eAAe,YAAY,KAAK,aAAa,GAAG,GAAG,YAAY,OAAO,YAAY,MAAM,EAAE;AAChG,YAAM,QAAQ,IAAI,YAAY,OAAO,OAAO,OAAO,MAAM;AACzD,YAAM,SAAS,MAAM,QAAQ,gBAAgB,OAAO,OAAO,OAAO,MAAM;AACxE,aAAO,KAAK,IAAI,KAAK,QAAQ,OAAO,MAAM,QAAQ,YAAY,CAAC;AAC/D,YAAM,QAAQ,MAAM;AACpB,aAAO,EAAE,MAAM,MAAM,SAAgD,OAAO,MAAM,OAAO,QAAQ,MAAM,OAAO;AAAA,IAClH,CAAC;AAAA,EACL;AAAA;AAAA,EAGA,OAAc,QAAQ,QAA2B,KAAwB,aAAmD;AACxH,QAAI,IAAI,WAAW,YAAY,OAAQ,OAAM,IAAI,gBAAgB,+CAA+C;AAChH,UAAM,UAAU,oBAAI,IAAoB;AACxC,aAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK,GAAG;AACpC,UAAI,IAAI,IAAI,CAAC,MAAM,EAAG,SAAQ,IAAK,IAAI,CAAC,KAAK,KAAO,IAAI,IAAI,CAAC,KAAK,IAAK,IAAI,IAAI,CAAC,GAAG,CAAC;AAAA,IACxF;AACA,UAAM,SAAS,IAAI,kBAAkB,MAAM;AAE3C,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK,GAAG;AACvC,UAAI,OAAO,IAAI,CAAC,MAAM,EAAG;AACzB,YAAM,SAAS,QAAQ,IAAK,OAAO,CAAC,KAAK,KAAO,OAAO,IAAI,CAAC,KAAK,IAAK,OAAO,IAAI,CAAC,CAAC;AACnF,UAAI,WAAW,OAAW;AAC1B,aAAO,IAAI,YAAY,SAAS,QAAQ,SAAS,CAAC,GAAG,CAAC;AACtD,aAAO,IAAI,CAAC,IAAI,KAAK,MAAM,OAAO,IAAI,CAAC,IAAI,YAAY,SAAS,CAAC,IAAI,GAAG;AAAA,IAC5E;AACA,WAAO;AAAA,EACX;AACJ;","names":[]}
@@ -1,5 +1,6 @@
1
1
  // src/texture/index.ts
2
2
  export * from "./Colormaps.mjs";
3
+ export * from "./PalettedTextures.mjs";
3
4
  export * from "./TextureAtlas.mjs";
4
5
  export * from "./TextureLoader.mjs";
5
6
  export * from "./Textures.mjs";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/texture/index.ts"],"sourcesContent":["// autogenerated\nexport * from './Colormaps';\nexport * from './TextureAtlas';\nexport * from './TextureLoader';\nexport * from './Textures';\n"],"mappings":";AACA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
1
+ {"version":3,"sources":["../../../../src/texture/index.ts"],"sourcesContent":["// autogenerated\nexport * from './Colormaps';\nexport * from './PalettedTextures';\nexport * from './TextureAtlas';\nexport * from './TextureLoader';\nexport * from './Textures';\n"],"mappings":";AACA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
@@ -28,8 +28,6 @@ async function sleep(timeout) {
28
28
  });
29
29
  }
30
30
  function yieldToEventLoop() {
31
- const scheduler = globalThis.scheduler;
32
- if (scheduler?.yield) return scheduler.yield();
33
31
  return new Promise((resolve) => {
34
32
  if (typeof MessageChannel !== "undefined") {
35
33
  const channel = new MessageChannel();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/util/util.ts"],"sourcesContent":["// Node ESM needs the explicit .js extension for the CommonJS hash module.\nimport MD5 from \"crypto-js/md5.js\";\nimport { Vector3 } from \"three\";\n\nexport const changeEvent = { type: 'change' as const };\n\nexport type Maybe<T> = T | undefined;\n\n// MD5 runs in both environments without pulling Node's crypto into the browser graph.\nexport function md5(str: string): string {\n return MD5(str).toString();\n}\n\nexport function base64encode(str: string): string {\n if (typeof btoa !== \"undefined\") {\n return btoa(str);\n }\n return Buffer.from(str).toString(\"base64\");\n}\n\nexport function base64decode(str: string): string {\n if (typeof atob !== \"undefined\") {\n return atob(str);\n }\n return Buffer.from(str, \"base64\").toString(\"ascii\");\n}\n\nexport function toRadians(degrees: number): number {\n return degrees * Math.PI / 180;\n}\n\nexport function toDegrees(radians: number): number {\n return radians * 180 / Math.PI;\n}\n\n/** Resolves after a delay in milliseconds. */\nexport async function sleep(timeout: number): Promise<void> {\n return new Promise(resolve => {\n setTimeout(() => resolve(), timeout);\n });\n}\n\n/** Yields to the next macrotask without timer clamping when the platform supports it. */\nexport function yieldToEventLoop(): Promise<void> {\n const scheduler = (globalThis as typeof globalThis & { scheduler?: { yield?: () => Promise<void> } }).scheduler;\n if (scheduler?.yield) return scheduler.yield();\n return new Promise(resolve => {\n if (typeof MessageChannel !== \"undefined\") {\n const channel = new MessageChannel();\n channel.port1.onmessage = () => {\n channel.port1.close();\n channel.port2.close();\n resolve();\n };\n channel.port2.postMessage(undefined);\n } else {\n setTimeout(resolve, 0);\n }\n });\n}\n\n/** Reduces an angle modulo 360, retaining a negative sign for negative inputs. */\nexport function clampRotationDegrees(deg: number): number {\n return deg % 360;\n}\n\nexport function isVector3(obj: any): obj is Vector3 {\n return (<Vector3>obj).isVector3;\n}\n\nexport type DeepPartial<T> = {\n [P in keyof T]?: DeepPartial<T[P]>;\n};\n"],"mappings":";AACA,OAAO,SAAS;AAGT,IAAM,cAAc,EAAE,MAAM,SAAkB;AAK9C,SAAS,IAAI,KAAqB;AACrC,SAAO,IAAI,GAAG,EAAE,SAAS;AAC7B;AAEO,SAAS,aAAa,KAAqB;AAC9C,MAAI,OAAO,SAAS,aAAa;AAC7B,WAAO,KAAK,GAAG;AAAA,EACnB;AACA,SAAO,OAAO,KAAK,GAAG,EAAE,SAAS,QAAQ;AAC7C;AAEO,SAAS,aAAa,KAAqB;AAC9C,MAAI,OAAO,SAAS,aAAa;AAC7B,WAAO,KAAK,GAAG;AAAA,EACnB;AACA,SAAO,OAAO,KAAK,KAAK,QAAQ,EAAE,SAAS,OAAO;AACtD;AAEO,SAAS,UAAU,SAAyB;AAC/C,SAAO,UAAU,KAAK,KAAK;AAC/B;AAEO,SAAS,UAAU,SAAyB;AAC/C,SAAO,UAAU,MAAM,KAAK;AAChC;AAGA,eAAsB,MAAM,SAAgC;AACxD,SAAO,IAAI,QAAQ,aAAW;AAC1B,eAAW,MAAM,QAAQ,GAAG,OAAO;AAAA,EACvC,CAAC;AACL;AAGO,SAAS,mBAAkC;AAC9C,QAAM,YAAa,WAAmF;AACtG,MAAI,WAAW,MAAO,QAAO,UAAU,MAAM;AAC7C,SAAO,IAAI,QAAQ,aAAW;AAC1B,QAAI,OAAO,mBAAmB,aAAa;AACvC,YAAM,UAAU,IAAI,eAAe;AACnC,cAAQ,MAAM,YAAY,MAAM;AAC5B,gBAAQ,MAAM,MAAM;AACpB,gBAAQ,MAAM,MAAM;AACpB,gBAAQ;AAAA,MACZ;AACA,cAAQ,MAAM,YAAY,MAAS;AAAA,IACvC,OAAO;AACH,iBAAW,SAAS,CAAC;AAAA,IACzB;AAAA,EACJ,CAAC;AACL;AAGO,SAAS,qBAAqB,KAAqB;AACtD,SAAO,MAAM;AACjB;AAEO,SAAS,UAAU,KAA0B;AAChD,SAAiB,IAAK;AAC1B;","names":[]}
1
+ {"version":3,"sources":["../../../../src/util/util.ts"],"sourcesContent":["// Node ESM needs the explicit .js extension for the CommonJS hash module.\nimport MD5 from \"crypto-js/md5.js\";\nimport { Vector3 } from \"three\";\n\nexport const changeEvent = { type: 'change' as const };\n\nexport type Maybe<T> = T | undefined;\n\n// MD5 runs in both environments without pulling Node's crypto into the browser graph.\nexport function md5(str: string): string {\n return MD5(str).toString();\n}\n\nexport function base64encode(str: string): string {\n if (typeof btoa !== \"undefined\") {\n return btoa(str);\n }\n return Buffer.from(str).toString(\"base64\");\n}\n\nexport function base64decode(str: string): string {\n if (typeof atob !== \"undefined\") {\n return atob(str);\n }\n return Buffer.from(str, \"base64\").toString(\"ascii\");\n}\n\nexport function toRadians(degrees: number): number {\n return degrees * Math.PI / 180;\n}\n\nexport function toDegrees(radians: number): number {\n return radians * 180 / Math.PI;\n}\n\n/** Resolves after a delay in milliseconds. */\nexport async function sleep(timeout: number): Promise<void> {\n return new Promise(resolve => {\n setTimeout(() => resolve(), timeout);\n });\n}\n\n/**\n * Yields to the next macrotask without timer clamping when the platform supports it.\n * Not `scheduler.yield()`: Chrome runs its continuations ahead of rendering, so chained yields delay frames.\n */\nexport function yieldToEventLoop(): Promise<void> {\n return new Promise(resolve => {\n if (typeof MessageChannel !== \"undefined\") {\n const channel = new MessageChannel();\n channel.port1.onmessage = () => {\n channel.port1.close();\n channel.port2.close();\n resolve();\n };\n channel.port2.postMessage(undefined);\n } else {\n setTimeout(resolve, 0);\n }\n });\n}\n\n/** Reduces an angle modulo 360, retaining a negative sign for negative inputs. */\nexport function clampRotationDegrees(deg: number): number {\n return deg % 360;\n}\n\nexport function isVector3(obj: any): obj is Vector3 {\n return (<Vector3>obj).isVector3;\n}\n\nexport type DeepPartial<T> = {\n [P in keyof T]?: DeepPartial<T[P]>;\n};\n"],"mappings":";AACA,OAAO,SAAS;AAGT,IAAM,cAAc,EAAE,MAAM,SAAkB;AAK9C,SAAS,IAAI,KAAqB;AACrC,SAAO,IAAI,GAAG,EAAE,SAAS;AAC7B;AAEO,SAAS,aAAa,KAAqB;AAC9C,MAAI,OAAO,SAAS,aAAa;AAC7B,WAAO,KAAK,GAAG;AAAA,EACnB;AACA,SAAO,OAAO,KAAK,GAAG,EAAE,SAAS,QAAQ;AAC7C;AAEO,SAAS,aAAa,KAAqB;AAC9C,MAAI,OAAO,SAAS,aAAa;AAC7B,WAAO,KAAK,GAAG;AAAA,EACnB;AACA,SAAO,OAAO,KAAK,KAAK,QAAQ,EAAE,SAAS,OAAO;AACtD;AAEO,SAAS,UAAU,SAAyB;AAC/C,SAAO,UAAU,KAAK,KAAK;AAC/B;AAEO,SAAS,UAAU,SAAyB;AAC/C,SAAO,UAAU,MAAM,KAAK;AAChC;AAGA,eAAsB,MAAM,SAAgC;AACxD,SAAO,IAAI,QAAQ,aAAW;AAC1B,eAAW,MAAM,QAAQ,GAAG,OAAO;AAAA,EACvC,CAAC;AACL;AAMO,SAAS,mBAAkC;AAC9C,SAAO,IAAI,QAAQ,aAAW;AAC1B,QAAI,OAAO,mBAAmB,aAAa;AACvC,YAAM,UAAU,IAAI,eAAe;AACnC,cAAQ,MAAM,YAAY,MAAM;AAC5B,gBAAQ,MAAM,MAAM;AACpB,gBAAQ,MAAM,MAAM;AACpB,gBAAQ;AAAA,MACZ;AACA,cAAQ,MAAM,YAAY,MAAS;AAAA,IACvC,OAAO;AACH,iBAAW,SAAS,CAAC;AAAA,IACzB;AAAA,EACJ,CAAC;AACL;AAGO,SAAS,qBAAqB,KAAqB;AACtD,SAAO,MAAM;AACjB;AAEO,SAAS,UAAU,KAA0B;AAChD,SAAiB,IAAK;AAC1B;","names":[]}