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.
@@ -9263,6 +9263,7 @@ function copyDataTexture(source) {
9263
9263
 
9264
9264
  // src/gui/GuiHelper.ts
9265
9265
  init_AssetKey();
9266
+ init_ModelTextures();
9266
9267
 
9267
9268
  // src/gui/GuiText.ts
9268
9269
  import { BufferGeometry as BufferGeometry2, Color as Color8, Float32BufferAttribute as Float32BufferAttribute4 } from "three";
@@ -9372,7 +9373,128 @@ function createGuiTextGeometry(layout, shadow = true) {
9372
9373
  }
9373
9374
 
9374
9375
  // src/gui/GuiHelper.ts
9376
+ var GUI_CONTAINER_LAYOUTS = {
9377
+ generic_54: {
9378
+ texture: "minecraft:gui/container/generic_54",
9379
+ crop: [0, 0, 176, 222],
9380
+ slotOrigin: [8, 18],
9381
+ slotOffset: [18, 18],
9382
+ rowSize: 9,
9383
+ slotCount: 54
9384
+ },
9385
+ crafting_table: {
9386
+ texture: "minecraft:gui/container/crafting_table",
9387
+ crop: [0, 0, 176, 166],
9388
+ slotOrigin: [30, 17],
9389
+ slotOffset: [18, 18],
9390
+ rowSize: 3,
9391
+ slotCount: 9,
9392
+ resultPosition: [124, 35]
9393
+ }
9394
+ };
9375
9395
  var GuiHelper = class {
9396
+ /**
9397
+ * Creates a 182×5 boss bar using the active resource pack. Finite progress is clamped to 0–1.
9398
+ * The fill crops the source image; explicit crops do not apply `.mcmeta` sprite scaling.
9399
+ */
9400
+ static async bossBar(options = {}) {
9401
+ const { color: color2 = "pink", progress = 1, position = [0, 0] } = options;
9402
+ this.validatePosition(position);
9403
+ if (!["pink", "blue", "red", "green", "yellow", "purple", "white"].includes(color2)) {
9404
+ throw new Error(`Unsupported boss bar color: ${color2}`);
9405
+ }
9406
+ if (!Number.isFinite(progress)) throw new Error("Boss bar progress must be finite");
9407
+ const value = Math.max(0, Math.min(1, progress));
9408
+ const width = value > 0 ? Math.floor(value * 181) + 1 : 0;
9409
+ const texture = `minecraft:gui/sprites/boss_bar/${color2}`;
9410
+ const layers = [{
9411
+ name: "boss-bar-background",
9412
+ texture: `${texture}_background`,
9413
+ position: [...position],
9414
+ size: [182, 5]
9415
+ }];
9416
+ if (width > 0) {
9417
+ layers.push({
9418
+ ...await this.cropTexture(`${texture}_progress`, [0, 0, width, 5], [182, 5], position),
9419
+ name: "boss-bar-progress"
9420
+ });
9421
+ }
9422
+ return layers;
9423
+ }
9424
+ /**
9425
+ * Creates a 192×192 book page with optional arrows and supplied text. Buttons are hidden by default.
9426
+ * Callers choose the page content and button states; this helper does not paginate or handle clicks.
9427
+ */
9428
+ static async book(options = {}) {
9429
+ const {
9430
+ position = [0, 0],
9431
+ previous = "hidden",
9432
+ next = "hidden",
9433
+ text: text2,
9434
+ color: color2 = 0,
9435
+ shadow = false,
9436
+ maxWidth = 114,
9437
+ lineHeight = 9,
9438
+ ...style
9439
+ } = options;
9440
+ this.validatePosition(position);
9441
+ for (const state of [previous, next]) {
9442
+ if (!["hidden", "normal", "hover"].includes(state)) throw new Error(`Unsupported book button state: ${state}`);
9443
+ }
9444
+ const layers = [{
9445
+ ...await this.cropTexture("minecraft:gui/book", [0, 0, 192, 192], [256, 256], position),
9446
+ name: "book-background"
9447
+ }];
9448
+ for (const [name, direction, state, x] of [
9449
+ ["previous", "backward", previous, 43],
9450
+ ["next", "forward", next, 116]
9451
+ ]) {
9452
+ if (state === "hidden") continue;
9453
+ layers.push({
9454
+ name: `book-${name}`,
9455
+ texture: `minecraft:gui/sprites/widget/page_${direction}${state === "hover" ? "_highlighted" : ""}`,
9456
+ position: [position[0] + x, position[1] + 157],
9457
+ size: [23, 13]
9458
+ });
9459
+ }
9460
+ if (text2 !== void 0) {
9461
+ layers.push({
9462
+ name: "book-text",
9463
+ text: text2,
9464
+ position: [position[0] + 36, position[1] + 30],
9465
+ color: color2,
9466
+ shadow,
9467
+ maxWidth,
9468
+ lineHeight,
9469
+ ...style
9470
+ });
9471
+ }
9472
+ return layers;
9473
+ }
9474
+ /** Creates a container background. Use {@link GUI_CONTAINER_LAYOUTS} with {@link inventorySlot} to place its items. */
9475
+ static async container(type, position = [0, 0]) {
9476
+ this.validatePosition(position);
9477
+ if (type !== "generic_54" && type !== "crafting_table") throw new Error(`Unsupported GUI container: ${type}`);
9478
+ const layout = GUI_CONTAINER_LAYOUTS[type];
9479
+ return [{ ...await this.cropTexture(layout.texture, layout.crop, [256, 256], position), name: "background" }];
9480
+ }
9481
+ static validatePosition(position) {
9482
+ if (!Array.isArray(position) || position.length !== 2 || !position.every(Number.isFinite)) {
9483
+ throw new Error("GUI position must contain two finite coordinates");
9484
+ }
9485
+ }
9486
+ static async cropTexture(texture, crop, referenceSize, position) {
9487
+ const image = await ModelTextures.preload(AssetKey.parse("textures", texture));
9488
+ if (!image) throw new Error(`Could not load GUI texture ${texture}`);
9489
+ const [x, y, width, height] = crop;
9490
+ const scaleX = image.width / referenceSize[0], scaleY = image.height / referenceSize[1];
9491
+ return {
9492
+ texture,
9493
+ crop: [x * scaleX, y * scaleY, width * scaleX, height * scaleY],
9494
+ position: [...position],
9495
+ size: [width, height]
9496
+ };
9497
+ }
9376
9498
  /** Sizes a tooltip around supplied text; the first entry is its title. */
9377
9499
  static async tooltip(lines, options = {}) {
9378
9500
  if (!lines.length) return [];
@@ -9407,8 +9529,9 @@ var GuiHelper = class {
9407
9529
  }
9408
9530
  /** Creates crafting-table layers for ingredients and the result; stack counts are not drawn. */
9409
9531
  static recipe(recipe, options = {}) {
9532
+ const layout = GUI_CONTAINER_LAYOUTS.crafting_table;
9410
9533
  const layers = [
9411
- { name: "background", texture: "minecraft:gui/container/crafting_table", crop: [0, 0, 176, 166] }
9534
+ { name: "background", texture: layout.texture, crop: [...layout.crop] }
9412
9535
  ];
9413
9536
  const itemKey = (ingredient) => {
9414
9537
  const item = typeof ingredient === "string" && !ingredient.startsWith("#") ? ingredient : typeof ingredient === "object" && "item" in ingredient ? ingredient.item : options.resolveIngredient?.(ingredient);
@@ -9423,7 +9546,7 @@ var GuiHelper = class {
9423
9546
  layers.push({
9424
9547
  name: `ingredient-${slot}`,
9425
9548
  item: itemKey(ingredient),
9426
- position: this.inventorySlot(slot, [30, 17], [18, 18], 3)
9549
+ position: this.inventorySlot(slot, layout.slotOrigin, layout.slotOffset, layout.rowSize)
9427
9550
  });
9428
9551
  };
9429
9552
  switch (recipe.type) {
@@ -9458,7 +9581,7 @@ var GuiHelper = class {
9458
9581
  layers.push({
9459
9582
  name: "result",
9460
9583
  item: itemKey("id" in recipe.result ? recipe.result.id : recipe.result.item),
9461
- position: [124, 35]
9584
+ position: [...layout.resultPosition]
9462
9585
  });
9463
9586
  return layers;
9464
9587
  }
@@ -16436,6 +16559,7 @@ export {
16436
16559
  Env,
16437
16560
  FluidModelObject,
16438
16561
  Fonts,
16562
+ GUI_CONTAINER_LAYOUTS,
16439
16563
  Geometries,
16440
16564
  GuiHelper,
16441
16565
  GuiLight,