minerender 2.1.0-alpha.77 → 2.1.0-alpha.78

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.
@@ -9317,6 +9317,7 @@ function copyDataTexture(source) {
9317
9317
 
9318
9318
  // src/gui/GuiHelper.ts
9319
9319
  init_AssetKey();
9320
+ init_ModelTextures();
9320
9321
 
9321
9322
  // src/gui/GuiText.ts
9322
9323
  import { BufferGeometry as BufferGeometry2, Color as Color8, Float32BufferAttribute as Float32BufferAttribute4 } from "three";
@@ -9426,7 +9427,128 @@ function createGuiTextGeometry(layout, shadow = true) {
9426
9427
  }
9427
9428
 
9428
9429
  // src/gui/GuiHelper.ts
9430
+ var GUI_CONTAINER_LAYOUTS = {
9431
+ generic_54: {
9432
+ texture: "minecraft:gui/container/generic_54",
9433
+ crop: [0, 0, 176, 222],
9434
+ slotOrigin: [8, 18],
9435
+ slotOffset: [18, 18],
9436
+ rowSize: 9,
9437
+ slotCount: 54
9438
+ },
9439
+ crafting_table: {
9440
+ texture: "minecraft:gui/container/crafting_table",
9441
+ crop: [0, 0, 176, 166],
9442
+ slotOrigin: [30, 17],
9443
+ slotOffset: [18, 18],
9444
+ rowSize: 3,
9445
+ slotCount: 9,
9446
+ resultPosition: [124, 35]
9447
+ }
9448
+ };
9429
9449
  var GuiHelper = class {
9450
+ /**
9451
+ * Creates a 182×5 boss bar using the active resource pack. Finite progress is clamped to 0–1.
9452
+ * The fill crops the source image; explicit crops do not apply `.mcmeta` sprite scaling.
9453
+ */
9454
+ static async bossBar(options = {}) {
9455
+ const { color: color2 = "pink", progress = 1, position = [0, 0] } = options;
9456
+ this.validatePosition(position);
9457
+ if (!["pink", "blue", "red", "green", "yellow", "purple", "white"].includes(color2)) {
9458
+ throw new Error(`Unsupported boss bar color: ${color2}`);
9459
+ }
9460
+ if (!Number.isFinite(progress)) throw new Error("Boss bar progress must be finite");
9461
+ const value = Math.max(0, Math.min(1, progress));
9462
+ const width = value > 0 ? Math.floor(value * 181) + 1 : 0;
9463
+ const texture = `minecraft:gui/sprites/boss_bar/${color2}`;
9464
+ const layers = [{
9465
+ name: "boss-bar-background",
9466
+ texture: `${texture}_background`,
9467
+ position: [...position],
9468
+ size: [182, 5]
9469
+ }];
9470
+ if (width > 0) {
9471
+ layers.push({
9472
+ ...await this.cropTexture(`${texture}_progress`, [0, 0, width, 5], [182, 5], position),
9473
+ name: "boss-bar-progress"
9474
+ });
9475
+ }
9476
+ return layers;
9477
+ }
9478
+ /**
9479
+ * Creates a 192×192 book page with optional arrows and supplied text. Buttons are hidden by default.
9480
+ * Callers choose the page content and button states; this helper does not paginate or handle clicks.
9481
+ */
9482
+ static async book(options = {}) {
9483
+ const {
9484
+ position = [0, 0],
9485
+ previous = "hidden",
9486
+ next = "hidden",
9487
+ text: text2,
9488
+ color: color2 = 0,
9489
+ shadow = false,
9490
+ maxWidth = 114,
9491
+ lineHeight = 9,
9492
+ ...style
9493
+ } = options;
9494
+ this.validatePosition(position);
9495
+ for (const state of [previous, next]) {
9496
+ if (!["hidden", "normal", "hover"].includes(state)) throw new Error(`Unsupported book button state: ${state}`);
9497
+ }
9498
+ const layers = [{
9499
+ ...await this.cropTexture("minecraft:gui/book", [0, 0, 192, 192], [256, 256], position),
9500
+ name: "book-background"
9501
+ }];
9502
+ for (const [name, direction, state, x] of [
9503
+ ["previous", "backward", previous, 43],
9504
+ ["next", "forward", next, 116]
9505
+ ]) {
9506
+ if (state === "hidden") continue;
9507
+ layers.push({
9508
+ name: `book-${name}`,
9509
+ texture: `minecraft:gui/sprites/widget/page_${direction}${state === "hover" ? "_highlighted" : ""}`,
9510
+ position: [position[0] + x, position[1] + 157],
9511
+ size: [23, 13]
9512
+ });
9513
+ }
9514
+ if (text2 !== void 0) {
9515
+ layers.push({
9516
+ name: "book-text",
9517
+ text: text2,
9518
+ position: [position[0] + 36, position[1] + 30],
9519
+ color: color2,
9520
+ shadow,
9521
+ maxWidth,
9522
+ lineHeight,
9523
+ ...style
9524
+ });
9525
+ }
9526
+ return layers;
9527
+ }
9528
+ /** Creates a container background. Use {@link GUI_CONTAINER_LAYOUTS} with {@link inventorySlot} to place its items. */
9529
+ static async container(type, position = [0, 0]) {
9530
+ this.validatePosition(position);
9531
+ if (type !== "generic_54" && type !== "crafting_table") throw new Error(`Unsupported GUI container: ${type}`);
9532
+ const layout = GUI_CONTAINER_LAYOUTS[type];
9533
+ return [{ ...await this.cropTexture(layout.texture, layout.crop, [256, 256], position), name: "background" }];
9534
+ }
9535
+ static validatePosition(position) {
9536
+ if (!Array.isArray(position) || position.length !== 2 || !position.every(Number.isFinite)) {
9537
+ throw new Error("GUI position must contain two finite coordinates");
9538
+ }
9539
+ }
9540
+ static async cropTexture(texture, crop, referenceSize, position) {
9541
+ const image = await ModelTextures.preload(AssetKey.parse("textures", texture));
9542
+ if (!image) throw new Error(`Could not load GUI texture ${texture}`);
9543
+ const [x, y, width, height] = crop;
9544
+ const scaleX = image.width / referenceSize[0], scaleY = image.height / referenceSize[1];
9545
+ return {
9546
+ texture,
9547
+ crop: [x * scaleX, y * scaleY, width * scaleX, height * scaleY],
9548
+ position: [...position],
9549
+ size: [width, height]
9550
+ };
9551
+ }
9430
9552
  /** Sizes a tooltip around supplied text; the first entry is its title. */
9431
9553
  static async tooltip(lines, options = {}) {
9432
9554
  if (!lines.length) return [];
@@ -9461,8 +9583,9 @@ var GuiHelper = class {
9461
9583
  }
9462
9584
  /** Creates crafting-table layers for ingredients and the result; stack counts are not drawn. */
9463
9585
  static recipe(recipe, options = {}) {
9586
+ const layout = GUI_CONTAINER_LAYOUTS.crafting_table;
9464
9587
  const layers = [
9465
- { name: "background", texture: "minecraft:gui/container/crafting_table", crop: [0, 0, 176, 166] }
9588
+ { name: "background", texture: layout.texture, crop: [...layout.crop] }
9466
9589
  ];
9467
9590
  const itemKey = (ingredient) => {
9468
9591
  const item = typeof ingredient === "string" && !ingredient.startsWith("#") ? ingredient : typeof ingredient === "object" && "item" in ingredient ? ingredient.item : options.resolveIngredient?.(ingredient);
@@ -9477,7 +9600,7 @@ var GuiHelper = class {
9477
9600
  layers.push({
9478
9601
  name: `ingredient-${slot}`,
9479
9602
  item: itemKey(ingredient),
9480
- position: this.inventorySlot(slot, [30, 17], [18, 18], 3)
9603
+ position: this.inventorySlot(slot, layout.slotOrigin, layout.slotOffset, layout.rowSize)
9481
9604
  });
9482
9605
  };
9483
9606
  switch (recipe.type) {
@@ -9512,7 +9635,7 @@ var GuiHelper = class {
9512
9635
  layers.push({
9513
9636
  name: "result",
9514
9637
  item: itemKey("id" in recipe.result ? recipe.result.id : recipe.result.item),
9515
- position: [124, 35]
9638
+ position: [...layout.resultPosition]
9516
9639
  });
9517
9640
  return layers;
9518
9641
  }
@@ -16491,6 +16614,7 @@ export {
16491
16614
  Env,
16492
16615
  FluidModelObject,
16493
16616
  Fonts,
16617
+ GUI_CONTAINER_LAYOUTS,
16494
16618
  Geometries,
16495
16619
  GuiHelper,
16496
16620
  GuiLight,