@almadar/ui 5.72.0 → 5.73.0

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 (52) hide show
  1. package/dist/avl/index.cjs +402 -362
  2. package/dist/avl/index.js +402 -362
  3. package/dist/components/game/atoms/ActionButton.d.ts +3 -3
  4. package/dist/components/game/atoms/ChoiceButton.d.ts +3 -3
  5. package/dist/components/game/atoms/ComboCounter.d.ts +3 -3
  6. package/dist/components/game/atoms/ControlButton.d.ts +3 -3
  7. package/dist/components/game/atoms/DamageNumber.d.ts +3 -3
  8. package/dist/components/game/atoms/DialogueBubble.d.ts +3 -3
  9. package/dist/components/game/atoms/ItemSlot.d.ts +3 -3
  10. package/dist/components/game/atoms/ResourceCounter.d.ts +3 -3
  11. package/dist/components/game/atoms/ScoreDisplay.d.ts +3 -3
  12. package/dist/components/game/atoms/Sprite.d.ts +3 -20
  13. package/dist/components/game/atoms/StateIndicator.d.ts +2 -2
  14. package/dist/components/game/atoms/StatusEffect.d.ts +3 -3
  15. package/dist/components/game/atoms/TurnIndicator.d.ts +3 -3
  16. package/dist/components/game/atoms/WaypointMarker.d.ts +3 -3
  17. package/dist/components/game/molecules/CardHand.d.ts +2 -2
  18. package/dist/components/game/molecules/DialogueBox.d.ts +3 -3
  19. package/dist/components/game/molecules/EnemyPlate.d.ts +3 -3
  20. package/dist/components/game/molecules/GameCanvas2D.d.ts +3 -3
  21. package/dist/components/game/molecules/HealthPanel.d.ts +3 -3
  22. package/dist/components/game/molecules/IsometricCanvas.d.ts +8 -12
  23. package/dist/components/game/molecules/PowerupSlots.d.ts +3 -3
  24. package/dist/components/game/molecules/StatBadge.d.ts +5 -5
  25. package/dist/components/game/molecules/TurnPanel.d.ts +3 -3
  26. package/dist/components/game/molecules/three/index.cjs +51 -28
  27. package/dist/components/game/molecules/three/index.js +51 -28
  28. package/dist/components/game/molecules/useUnitSpriteAtlas.d.ts +3 -10
  29. package/dist/components/game/organisms/BattleBoard.d.ts +5 -6
  30. package/dist/components/game/organisms/CardBattlerBoard.d.ts +3 -4
  31. package/dist/components/game/organisms/CastleBoard.d.ts +5 -6
  32. package/dist/components/game/organisms/CityBuilderBoard.d.ts +6 -7
  33. package/dist/components/game/organisms/FishingBoard.d.ts +4 -6
  34. package/dist/components/game/organisms/PlatformerBoard.d.ts +5 -5
  35. package/dist/components/game/organisms/RoguelikeBoard.d.ts +4 -5
  36. package/dist/components/game/organisms/TopDownShooterBoard.d.ts +5 -6
  37. package/dist/components/game/organisms/TowerDefenseBoard.d.ts +5 -6
  38. package/dist/components/game/organisms/VisualNovelBoard.d.ts +4 -5
  39. package/dist/components/game/organisms/WorldMapBoard.d.ts +5 -6
  40. package/dist/components/game/organisms/types/effects.d.ts +7 -8
  41. package/dist/components/game/organisms/types/isometric.d.ts +8 -8
  42. package/dist/components/game/organisms/types/spriteAnimation.d.ts +3 -4
  43. package/dist/components/game/organisms/utils/makeAsset.d.ts +5 -0
  44. package/dist/components/game/templates/PlatformerTemplate.d.ts +5 -4
  45. package/dist/components/game/templates/game3dAssetManifest.d.ts +6 -8
  46. package/dist/components/index.cjs +417 -363
  47. package/dist/components/index.js +417 -363
  48. package/dist/providers/index.cjs +402 -362
  49. package/dist/providers/index.js +402 -362
  50. package/dist/runtime/index.cjs +402 -362
  51. package/dist/runtime/index.js +402 -362
  52. package/package.json +2 -2
@@ -6960,7 +6960,7 @@ function ScoreDisplay({
6960
6960
  assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
6961
6961
  "img",
6962
6962
  {
6963
- src: assetUrl,
6963
+ src: assetUrl.url,
6964
6964
  alt: "",
6965
6965
  width: 20,
6966
6966
  height: 20,
@@ -6985,7 +6985,11 @@ var init_ScoreDisplay = __esm({
6985
6985
  lg: "text-2xl",
6986
6986
  xl: "text-4xl"
6987
6987
  };
6988
- DEFAULT_ASSET_URL = "https://almadar-kflow-assets.web.app/shared/effects/particles/star_01.png";
6988
+ DEFAULT_ASSET_URL = {
6989
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/star_01.png",
6990
+ role: "effect",
6991
+ category: "effect"
6992
+ };
6989
6993
  ScoreDisplay.displayName = "ScoreDisplay";
6990
6994
  }
6991
6995
  });
@@ -7061,7 +7065,7 @@ function ControlButton({
7061
7065
  children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
7062
7066
  "img",
7063
7067
  {
7064
- src: assetUrl,
7068
+ src: assetUrl.url,
7065
7069
  alt: "",
7066
7070
  width: 24,
7067
7071
  height: 24,
@@ -7101,7 +7105,11 @@ var init_ControlButton = __esm({
7101
7105
  secondary: "bg-secondary text-secondary-foreground border-border hover:bg-secondary-hover",
7102
7106
  ghost: "bg-transparent text-foreground border-border hover:bg-muted"
7103
7107
  };
7104
- DEFAULT_ASSET_URL2 = "https://almadar-kflow-assets.web.app/shared/effects/particles/circle_01.png";
7108
+ DEFAULT_ASSET_URL2 = {
7109
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/circle_01.png",
7110
+ role: "effect",
7111
+ category: "effect"
7112
+ };
7105
7113
  ControlButton.displayName = "ControlButton";
7106
7114
  }
7107
7115
  });
@@ -7140,7 +7148,7 @@ var init_spriteAnimation = __esm({
7140
7148
  }
7141
7149
  });
7142
7150
  function Sprite({
7143
- spritesheet = "https://almadar-kflow-assets.web.app/shared/isometric-blocks/Spritesheet/allTiles_sheet.png",
7151
+ spritesheet = DEFAULT_SPRITESHEET,
7144
7152
  frameWidth = 64,
7145
7153
  frameHeight = 64,
7146
7154
  frame = 0,
@@ -7193,7 +7201,7 @@ function Sprite({
7193
7201
  position: "absolute",
7194
7202
  width: frameWidth,
7195
7203
  height: frameHeight,
7196
- backgroundImage: `url(${spritesheet})`,
7204
+ backgroundImage: `url(${spritesheet.url})`,
7197
7205
  backgroundPosition,
7198
7206
  backgroundRepeat: "no-repeat",
7199
7207
  imageRendering: "pixelated",
@@ -7206,11 +7214,17 @@ function Sprite({
7206
7214
  }
7207
7215
  );
7208
7216
  }
7217
+ var DEFAULT_SPRITESHEET;
7209
7218
  var init_Sprite = __esm({
7210
7219
  "components/game/atoms/Sprite.tsx"() {
7211
7220
  "use client";
7212
7221
  init_useEventBus();
7213
7222
  init_spriteAnimation();
7223
+ DEFAULT_SPRITESHEET = {
7224
+ url: "https://almadar-kflow-assets.web.app/shared/isometric-blocks/Spritesheet/allTiles_sheet.png",
7225
+ role: "tile",
7226
+ category: "tile"
7227
+ };
7214
7228
  }
7215
7229
  });
7216
7230
  function StateIndicator({
@@ -7240,7 +7254,7 @@ function StateIndicator({
7240
7254
  /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
7241
7255
  "img",
7242
7256
  {
7243
- src: assetUrl,
7257
+ src: assetUrl.url,
7244
7258
  alt: displayLabel,
7245
7259
  width: 16,
7246
7260
  height: 16,
@@ -7259,7 +7273,11 @@ var init_StateIndicator = __esm({
7259
7273
  init_Box();
7260
7274
  init_Icon();
7261
7275
  init_cn();
7262
- DEFAULT_ASSET_URL3 = "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png";
7276
+ DEFAULT_ASSET_URL3 = {
7277
+ url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
7278
+ role: "effect",
7279
+ category: "item"
7280
+ };
7263
7281
  DEFAULT_STATE_STYLES = {
7264
7282
  idle: { icon: "\u23F8", bgClass: "bg-muted" },
7265
7283
  active: { icon: "\u25B6", bgClass: "bg-success" },
@@ -7357,7 +7375,7 @@ function ResourceCounter({
7357
7375
  assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
7358
7376
  "img",
7359
7377
  {
7360
- src: assetUrl,
7378
+ src: assetUrl.url,
7361
7379
  alt: label,
7362
7380
  width: sizes.img,
7363
7381
  height: sizes.img,
@@ -7390,7 +7408,11 @@ var init_ResourceCounter = __esm({
7390
7408
  error: "text-error",
7391
7409
  muted: "text-muted-foreground"
7392
7410
  };
7393
- DEFAULT_ASSET_URL4 = "https://almadar-kflow-assets.web.app/shared/world-map/gold_mine.png";
7411
+ DEFAULT_ASSET_URL4 = {
7412
+ url: "https://almadar-kflow-assets.web.app/shared/world-map/gold_mine.png",
7413
+ role: "effect",
7414
+ category: "world"
7415
+ };
7394
7416
  sizeMap5 = {
7395
7417
  sm: { wrapper: "text-xs gap-1 px-1.5 py-0.5", icon: "text-sm", img: 16 },
7396
7418
  md: { wrapper: "text-sm gap-1.5 px-2 py-1", icon: "text-base", img: 20 },
@@ -7436,7 +7458,7 @@ function ItemSlot({
7436
7458
  assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
7437
7459
  "img",
7438
7460
  {
7439
- src: assetUrl,
7461
+ src: assetUrl?.url,
7440
7462
  alt: label,
7441
7463
  width: px,
7442
7464
  height: px,
@@ -7484,7 +7506,11 @@ var init_ItemSlot = __esm({
7484
7506
  epic: "shadow-lg",
7485
7507
  legendary: "shadow-lg"
7486
7508
  };
7487
- DEFAULT_ASSET_URL5 = "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png";
7509
+ DEFAULT_ASSET_URL5 = {
7510
+ url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
7511
+ role: "effect",
7512
+ category: "item"
7513
+ };
7488
7514
  assetSizeMap = {
7489
7515
  sm: 28,
7490
7516
  md: 40,
@@ -7530,7 +7556,7 @@ function TurnIndicator({
7530
7556
  assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
7531
7557
  "img",
7532
7558
  {
7533
- src: assetUrl,
7559
+ src: assetUrl.url,
7534
7560
  alt: "",
7535
7561
  width: 12,
7536
7562
  height: 12,
@@ -7553,7 +7579,11 @@ var init_TurnIndicator = __esm({
7553
7579
  md: { wrapper: "text-sm gap-2 px-3 py-1", dot: "w-2 h-2" },
7554
7580
  lg: { wrapper: "text-base gap-2.5 px-4 py-1.5", dot: "w-2.5 h-2.5" }
7555
7581
  };
7556
- DEFAULT_ASSET_URL6 = "https://almadar-kflow-assets.web.app/shared/effects/particles/symbol_01.png";
7582
+ DEFAULT_ASSET_URL6 = {
7583
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/symbol_01.png",
7584
+ role: "effect",
7585
+ category: "effect"
7586
+ };
7557
7587
  TurnIndicator.displayName = "TurnIndicator";
7558
7588
  }
7559
7589
  });
@@ -7592,7 +7622,7 @@ function ComboCounter({
7592
7622
  assetUrl && /* @__PURE__ */ jsxRuntime.jsx(
7593
7623
  "img",
7594
7624
  {
7595
- src: assetUrl,
7625
+ src: assetUrl.url,
7596
7626
  alt: "combo",
7597
7627
  width: 24,
7598
7628
  height: 24,
@@ -7618,7 +7648,11 @@ var DEFAULT_ASSET_URL7, sizeMap8;
7618
7648
  var init_ComboCounter = __esm({
7619
7649
  "components/game/atoms/ComboCounter.tsx"() {
7620
7650
  init_cn();
7621
- DEFAULT_ASSET_URL7 = "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png";
7651
+ DEFAULT_ASSET_URL7 = {
7652
+ url: "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png",
7653
+ role: "effect",
7654
+ category: "effect"
7655
+ };
7622
7656
  sizeMap8 = {
7623
7657
  sm: { combo: "text-lg", label: "text-xs", multiplier: "text-xs" },
7624
7658
  md: { combo: "text-2xl", label: "text-xs", multiplier: "text-sm" },
@@ -7738,7 +7772,7 @@ function WaypointMarker({
7738
7772
  children: completed ? checkIcon : assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
7739
7773
  "img",
7740
7774
  {
7741
- src: assetUrl,
7775
+ src: assetUrl.url,
7742
7776
  alt: label,
7743
7777
  width: sizes.img,
7744
7778
  height: sizes.img,
@@ -7767,7 +7801,11 @@ var init_WaypointMarker = __esm({
7767
7801
  "components/game/atoms/WaypointMarker.tsx"() {
7768
7802
  init_cn();
7769
7803
  init_Icon();
7770
- DEFAULT_ASSET_URL8 = "https://almadar-kflow-assets.web.app/shared/world-map/battle_marker.png";
7804
+ DEFAULT_ASSET_URL8 = {
7805
+ url: "https://almadar-kflow-assets.web.app/shared/world-map/battle_marker.png",
7806
+ role: "effect",
7807
+ category: "world"
7808
+ };
7771
7809
  sizeMap10 = {
7772
7810
  sm: { dot: "w-4 h-4", ring: "w-6 h-6", label: "text-xs mt-1", img: 12 },
7773
7811
  md: { dot: "w-6 h-6", ring: "w-8 h-8", label: "text-sm mt-1.5", img: 18 },
@@ -7808,7 +7846,7 @@ function StatusEffect({
7808
7846
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("flex items-center justify-center", sizes.icon), children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
7809
7847
  "img",
7810
7848
  {
7811
- src: assetUrl,
7849
+ src: assetUrl.url,
7812
7850
  alt: label,
7813
7851
  width: sizes.img,
7814
7852
  height: sizes.img,
@@ -7847,7 +7885,11 @@ var init_StatusEffect = __esm({
7847
7885
  "components/game/atoms/StatusEffect.tsx"() {
7848
7886
  init_cn();
7849
7887
  init_Icon();
7850
- DEFAULT_ASSET_URL9 = "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png";
7888
+ DEFAULT_ASSET_URL9 = {
7889
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png",
7890
+ role: "effect",
7891
+ category: "effect"
7892
+ };
7851
7893
  sizeMap11 = {
7852
7894
  sm: { container: "w-8 h-8", icon: "text-sm", badge: "text-xs -top-1 -right-1 w-4 h-4", timer: "text-[9px]", img: 20 },
7853
7895
  md: { container: "w-10 h-10", icon: "text-base", badge: "text-xs -top-1 -right-1 w-5 h-5", timer: "text-xs", img: 28 },
@@ -7885,7 +7927,7 @@ function DamageNumber({
7885
7927
  assetUrl && /* @__PURE__ */ jsxRuntime.jsx(
7886
7928
  "img",
7887
7929
  {
7888
- src: assetUrl,
7930
+ src: assetUrl.url,
7889
7931
  alt: "",
7890
7932
  width: 14,
7891
7933
  height: 14,
@@ -7921,14 +7963,18 @@ var init_DamageNumber = __esm({
7921
7963
  100% { opacity: 0; transform: translateY(-32px) scale(0.8); }
7922
7964
  }
7923
7965
  `;
7924
- DEFAULT_ASSET_URL10 = "https://almadar-kflow-assets.web.app/shared/effects/particles/spark_01.png";
7966
+ DEFAULT_ASSET_URL10 = {
7967
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/spark_01.png",
7968
+ role: "effect",
7969
+ category: "effect"
7970
+ };
7925
7971
  DamageNumber.displayName = "DamageNumber";
7926
7972
  }
7927
7973
  });
7928
7974
  function DialogueBubble({
7929
7975
  speaker = "Hero",
7930
7976
  text = "The dungeon awaits. Choose your path wisely.",
7931
- portrait = "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
7977
+ portrait = DEFAULT_PORTRAIT,
7932
7978
  position = "bottom",
7933
7979
  className
7934
7980
  }) {
@@ -7944,7 +7990,7 @@ function DialogueBubble({
7944
7990
  portrait && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 w-12 h-12 rounded-full overflow-hidden border-2 border-warning/60", children: /* @__PURE__ */ jsxRuntime.jsx(
7945
7991
  "img",
7946
7992
  {
7947
- src: portrait,
7993
+ src: portrait?.url,
7948
7994
  alt: speaker ?? "speaker",
7949
7995
  className: "w-full h-full object-cover"
7950
7996
  }
@@ -7957,9 +8003,15 @@ function DialogueBubble({
7957
8003
  }
7958
8004
  );
7959
8005
  }
8006
+ var DEFAULT_PORTRAIT;
7960
8007
  var init_DialogueBubble = __esm({
7961
8008
  "components/game/atoms/DialogueBubble.tsx"() {
7962
8009
  init_cn();
8010
+ DEFAULT_PORTRAIT = {
8011
+ url: "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
8012
+ role: "effect",
8013
+ category: "character"
8014
+ };
7963
8015
  DialogueBubble.displayName = "DialogueBubble";
7964
8016
  }
7965
8017
  });
@@ -8003,7 +8055,7 @@ function ChoiceButton({
8003
8055
  assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
8004
8056
  "img",
8005
8057
  {
8006
- src: assetUrl,
8058
+ src: assetUrl.url,
8007
8059
  alt: "",
8008
8060
  width: 16,
8009
8061
  height: 16,
@@ -8073,7 +8125,7 @@ function ActionButton({
8073
8125
  assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
8074
8126
  "img",
8075
8127
  {
8076
- src: assetUrl,
8128
+ src: assetUrl.url,
8077
8129
  alt: "",
8078
8130
  width: 16,
8079
8131
  height: 16,
@@ -8117,7 +8169,11 @@ var init_ActionButton = __esm({
8117
8169
  secondary: "bg-secondary text-secondary-foreground hover:bg-secondary-hover border-border",
8118
8170
  danger: "bg-error text-error-foreground hover:bg-error/90 border-error"
8119
8171
  };
8120
- DEFAULT_ASSET_URL11 = "https://almadar-kflow-assets.web.app/shared/effects/particles/slash_01.png";
8172
+ DEFAULT_ASSET_URL11 = {
8173
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/slash_01.png",
8174
+ role: "effect",
8175
+ category: "effect"
8176
+ };
8121
8177
  ActionButton.displayName = "ActionButton";
8122
8178
  }
8123
8179
  });
@@ -11048,12 +11104,7 @@ var init_useCanvasGestures = __esm({
11048
11104
  }
11049
11105
  });
11050
11106
  function unitAtlasUrl(unit) {
11051
- if (unit.spriteSheet) return unit.spriteSheet;
11052
- const sprite = unit.sprite;
11053
- if (!sprite) return null;
11054
- const match = /^(.*-sprite-sheet)(?:-(?:se|sw))?(?:-v\d+)?\.png$/.exec(sprite);
11055
- if (!match) return null;
11056
- return `${match[1]}.json`;
11107
+ return unit.spriteSheet?.url ?? null;
11057
11108
  }
11058
11109
  function resolveSheetUrl(atlasUrl, relativeSheetPath) {
11059
11110
  try {
@@ -11249,7 +11300,6 @@ function IsometricCanvas({
11249
11300
  // Tuning
11250
11301
  diamondTopY: diamondTopYProp,
11251
11302
  // Remote asset loading
11252
- assetBaseUrl,
11253
11303
  assetManifest
11254
11304
  }) {
11255
11305
  const tilesProp = Array.isArray(_tilesPropRaw) ? _tilesPropRaw : [];
@@ -11331,54 +11381,48 @@ function IsometricCanvas({
11331
11381
  const attackTargetSet = React88.useMemo(() => {
11332
11382
  return new Set(attackTargets.map((p2) => `${p2.x},${p2.y}`));
11333
11383
  }, [attackTargets]);
11334
- const resolveManifestUrl7 = React88.useCallback((relativePath) => {
11335
- if (!relativePath) return void 0;
11336
- if (assetBaseUrl) return `${assetBaseUrl.replace(/\/$/, "")}${relativePath.startsWith("/") ? "" : "/"}${relativePath}`;
11337
- return relativePath;
11338
- }, [assetBaseUrl]);
11339
11384
  const spriteUrls = React88.useMemo(() => {
11340
11385
  const urls = [];
11341
11386
  for (const tile of sortedTiles) {
11342
- if (tile.terrainSprite) urls.push(tile.terrainSprite);
11387
+ if (tile.terrainSprite) urls.push(tile.terrainSprite.url);
11343
11388
  else if (getTerrainSprite) {
11344
11389
  const url = getTerrainSprite(tile.terrain ?? "");
11345
11390
  if (url) urls.push(url);
11346
11391
  } else {
11347
- const url = resolveManifestUrl7(assetManifest?.terrains?.[tile.terrain ?? ""]);
11392
+ const url = assetManifest?.terrains?.[tile.terrain ?? ""]?.url;
11348
11393
  if (url) urls.push(url);
11349
11394
  }
11350
11395
  }
11351
11396
  for (const feature of features) {
11352
- if (feature.sprite) urls.push(feature.sprite);
11397
+ if (feature.sprite) urls.push(feature.sprite.url);
11353
11398
  else if (getFeatureSprite) {
11354
11399
  const url = getFeatureSprite(feature.type);
11355
11400
  if (url) urls.push(url);
11356
11401
  } else {
11357
- const url = resolveManifestUrl7(assetManifest?.features?.[feature.type]);
11402
+ const url = assetManifest?.features?.[feature.type]?.url;
11358
11403
  if (url) urls.push(url);
11359
11404
  }
11360
11405
  }
11361
11406
  for (const unit of units) {
11362
- if (unit.sprite) urls.push(unit.sprite);
11407
+ if (unit.sprite) urls.push(unit.sprite.url);
11363
11408
  else if (getUnitSprite) {
11364
11409
  const url = getUnitSprite(unit);
11365
11410
  if (url) urls.push(url);
11366
11411
  } else if (unit.unitType) {
11367
- const url = resolveManifestUrl7(assetManifest?.units?.[unit.unitType]);
11412
+ const url = assetManifest?.units?.[unit.unitType]?.url;
11368
11413
  if (url) urls.push(url);
11369
11414
  }
11370
11415
  }
11371
11416
  if (assetManifest?.effects) {
11372
- for (const path of Object.values(assetManifest.effects)) {
11373
- const url = resolveManifestUrl7(path);
11374
- if (url) urls.push(url);
11417
+ for (const asset of Object.values(assetManifest.effects)) {
11418
+ if (asset.url) urls.push(asset.url);
11375
11419
  }
11376
11420
  }
11377
11421
  if (effectSpriteUrls) urls.push(...effectSpriteUrls);
11378
11422
  if (atlasSheetUrls.length) urls.push(...atlasSheetUrls);
11379
11423
  if (backgroundImage) urls.push(backgroundImage);
11380
11424
  return [...new Set(urls.filter(Boolean))];
11381
- }, [sortedTiles, features, units, getTerrainSprite, getFeatureSprite, getUnitSprite, effectSpriteUrls, atlasSheetUrls, backgroundImage, assetManifest, resolveManifestUrl7]);
11425
+ }, [sortedTiles, features, units, getTerrainSprite, getFeatureSprite, getUnitSprite, effectSpriteUrls, atlasSheetUrls, backgroundImage, assetManifest]);
11382
11426
  const { getImage, pendingCount: _imagePendingCount } = useImageCache(spriteUrls);
11383
11427
  React88.useEffect(() => {
11384
11428
  if (typeof window === "undefined") return;
@@ -11403,14 +11447,14 @@ function IsometricCanvas({
11403
11447
  lerpToTarget
11404
11448
  } = useCamera();
11405
11449
  const resolveTerrainSpriteUrl = React88.useCallback((tile) => {
11406
- return tile.terrainSprite || getTerrainSprite?.(tile.terrain ?? "") || resolveManifestUrl7(assetManifest?.terrains?.[tile.terrain ?? ""]);
11407
- }, [getTerrainSprite, assetManifest, resolveManifestUrl7]);
11450
+ return tile.terrainSprite?.url || getTerrainSprite?.(tile.terrain ?? "") || assetManifest?.terrains?.[tile.terrain ?? ""]?.url;
11451
+ }, [getTerrainSprite, assetManifest]);
11408
11452
  const resolveFeatureSpriteUrl = React88.useCallback((featureType) => {
11409
- return getFeatureSprite?.(featureType) || resolveManifestUrl7(assetManifest?.features?.[featureType]);
11410
- }, [getFeatureSprite, assetManifest, resolveManifestUrl7]);
11453
+ return getFeatureSprite?.(featureType) || assetManifest?.features?.[featureType]?.url;
11454
+ }, [getFeatureSprite, assetManifest]);
11411
11455
  const resolveUnitSpriteUrl = React88.useCallback((unit) => {
11412
- return unit.sprite || getUnitSprite?.(unit) || (unit.unitType ? resolveManifestUrl7(assetManifest?.units?.[unit.unitType]) : void 0);
11413
- }, [getUnitSprite, assetManifest, resolveManifestUrl7]);
11456
+ return unit.sprite?.url || getUnitSprite?.(unit) || (unit.unitType ? assetManifest?.units?.[unit.unitType]?.url : void 0);
11457
+ }, [getUnitSprite, assetManifest]);
11414
11458
  const miniMapTiles = React88.useMemo(() => {
11415
11459
  if (!showMinimap) return [];
11416
11460
  return sortedTiles.map((t2) => ({
@@ -11557,7 +11601,7 @@ function IsometricCanvas({
11557
11601
  if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
11558
11602
  continue;
11559
11603
  }
11560
- const spriteUrl = feature.sprite || resolveFeatureSpriteUrl(feature.type);
11604
+ const spriteUrl = feature.sprite?.url || resolveFeatureSpriteUrl(feature.type);
11561
11605
  const img = spriteUrl ? getImage(spriteUrl) : null;
11562
11606
  const centerX = pos.x + scaledTileWidth / 2;
11563
11607
  const featureGroundY = pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
@@ -11606,12 +11650,12 @@ function IsometricCanvas({
11606
11650
  const img = unitSpriteUrl ? getImage(unitSpriteUrl) : null;
11607
11651
  const unitDrawH = scaledFloorHeight * spriteHeightRatio * unitScale;
11608
11652
  const maxUnitW = scaledTileWidth * spriteMaxWidthRatio * unitScale;
11653
+ const unitIsSheet = unit.sprite?.dimension === "2d" && (unit.sprite?.animations?.length ?? 0) > 0;
11609
11654
  const SHEET_ROWS = 5;
11610
11655
  const sheetFrameW = img ? img.naturalWidth / SHEET_COLUMNS : 0;
11611
11656
  const sheetFrameH = img ? img.naturalHeight / SHEET_ROWS : 0;
11612
- const imgIsSheet = img ? img.naturalWidth % SHEET_COLUMNS === 0 && img.naturalHeight % SHEET_ROWS === 0 && Math.abs(sheetFrameW - sheetFrameH) < 2 : false;
11613
- const frameW = imgIsSheet ? sheetFrameW : img?.naturalWidth ?? 1;
11614
- const frameH = imgIsSheet ? sheetFrameH : img?.naturalHeight ?? 1;
11657
+ const frameW = unitIsSheet ? sheetFrameW : img?.naturalWidth ?? 1;
11658
+ const frameH = unitIsSheet ? sheetFrameH : img?.naturalHeight ?? 1;
11615
11659
  const ar = frameW / (frameH || 1);
11616
11660
  let drawH = unitDrawH;
11617
11661
  let drawW = unitDrawH * ar;
@@ -11626,7 +11670,7 @@ function IsometricCanvas({
11626
11670
  ctx.save();
11627
11671
  ctx.globalAlpha = 0.25;
11628
11672
  if (img) {
11629
- if (imgIsSheet) {
11673
+ if (unitIsSheet) {
11630
11674
  ctx.drawImage(img, 0, 0, sheetFrameW, sheetFrameH, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
11631
11675
  } else {
11632
11676
  ctx.drawImage(img, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
@@ -11674,7 +11718,7 @@ function IsometricCanvas({
11674
11718
  } else if (img) {
11675
11719
  const spriteY = groundY - drawH - breatheOffset;
11676
11720
  const drawUnit = (x) => {
11677
- if (imgIsSheet) {
11721
+ if (unitIsSheet) {
11678
11722
  ctx.drawImage(img, 0, 0, sheetFrameW, sheetFrameH, x, spriteY, drawW, drawH);
11679
11723
  } else {
11680
11724
  ctx.drawImage(img, x, spriteY, drawW, drawH);
@@ -11701,7 +11745,7 @@ function IsometricCanvas({
11701
11745
  }
11702
11746
  }
11703
11747
  for (const fx of effects) {
11704
- const spriteUrl = resolveManifestUrl7(assetManifest?.effects?.[fx.key]);
11748
+ const spriteUrl = assetManifest?.effects?.[fx.key]?.url;
11705
11749
  if (!spriteUrl) continue;
11706
11750
  const img = getImage(spriteUrl);
11707
11751
  if (!img) continue;
@@ -11745,7 +11789,6 @@ function IsometricCanvas({
11745
11789
  backgroundImage,
11746
11790
  cameraRef,
11747
11791
  unitScale,
11748
- resolveManifestUrl7,
11749
11792
  assetManifest
11750
11793
  ]);
11751
11794
  React88.useEffect(() => {
@@ -12023,6 +12066,42 @@ var init_boardEntity = __esm({
12023
12066
  "components/game/organisms/boardEntity.ts"() {
12024
12067
  }
12025
12068
  });
12069
+
12070
+ // components/game/organisms/utils/makeAsset.ts
12071
+ function makeAsset(url, role, overrides = {}) {
12072
+ const defaults = ROLE_DEFAULTS[role] ?? { dimension: "2d", animations: ["static"], aspect: "1:1" };
12073
+ return {
12074
+ url,
12075
+ role,
12076
+ category: url.split("/").pop()?.replace(/\.[^.]+$/, "") ?? role,
12077
+ ...defaults,
12078
+ ...overrides
12079
+ };
12080
+ }
12081
+ function makeAssetMap(record, role, overrides = {}) {
12082
+ const result = {};
12083
+ for (const [key, url] of Object.entries(record)) {
12084
+ result[key] = makeAsset(url, role, overrides);
12085
+ }
12086
+ return result;
12087
+ }
12088
+ var ROLE_DEFAULTS;
12089
+ var init_makeAsset = __esm({
12090
+ "components/game/organisms/utils/makeAsset.ts"() {
12091
+ ROLE_DEFAULTS = {
12092
+ tile: { dimension: "2d", animations: ["static"], aspect: "1:1" },
12093
+ decoration: { dimension: "2d", animations: ["static"], aspect: "1:1" },
12094
+ effect: { dimension: "2d", animations: ["static"], aspect: "1:1" },
12095
+ item: { dimension: "2d", animations: ["static"], aspect: "5:7" },
12096
+ player: { dimension: "2d", animations: ["idle", "walk", "attack", "hit", "death"], aspect: "1:1" },
12097
+ enemy: { dimension: "2d", animations: ["idle", "walk", "attack", "hit", "death"], aspect: "1:1" },
12098
+ npc: { dimension: "2d", animations: ["idle", "walk", "attack", "hit", "death"], aspect: "1:1" },
12099
+ projectile: { dimension: "2d", animations: ["static"], aspect: "1:1" },
12100
+ vehicle: { dimension: "2d", animations: ["idle", "walk"], aspect: "1:1" },
12101
+ ui: { dimension: "2d", animations: ["static"], aspect: "1:1" }
12102
+ };
12103
+ }
12104
+ });
12026
12105
  function buildDefaultBattleTiles() {
12027
12106
  const tiles = [];
12028
12107
  for (let y = 0; y < BATTLE_GRID_H; y++) {
@@ -12081,14 +12160,14 @@ function BattleBoard({
12081
12160
  if (o === null || typeof o.x !== "number" || typeof o.y !== "number") return [];
12082
12161
  const tile = { x: o.x, y: o.y };
12083
12162
  if (typeof o.terrain === "string") tile.terrain = o.terrain;
12084
- if (typeof o.terrainSprite === "string") tile.terrainSprite = o.terrainSprite;
12163
+ if (typeof o.terrainSprite === "string") tile.terrainSprite = makeAsset(o.terrainSprite, "tile");
12085
12164
  if (typeof o.passable === "boolean") tile.passable = o.passable;
12086
12165
  if (typeof o.movementCost === "number") tile.movementCost = o.movementCost;
12087
12166
  if (typeof o.elevation === "number") tile.elevation = o.elevation;
12088
12167
  if (typeof o.type === "string") tile.type = o.type;
12089
12168
  if (typeof o.tileType === "string") tile.tileType = o.tileType;
12090
12169
  if (typeof o.id === "string") tile.id = o.id;
12091
- if (typeof o.modelUrl === "string") tile.modelUrl = o.modelUrl;
12170
+ if (typeof o.modelUrl === "string") tile.modelUrl = makeAsset(o.modelUrl, "decoration", { dimension: "3d" });
12092
12171
  return [tile];
12093
12172
  }) : []);
12094
12173
  const tiles = rawTiles.length === 0 ? DEFAULT_BATTLE_TILES : rawTiles;
@@ -12097,10 +12176,10 @@ function BattleBoard({
12097
12176
  if (o === null || typeof o.type !== "string" || typeof o.x !== "number" || typeof o.y !== "number") return [];
12098
12177
  const feat = { type: o.type, x: o.x, y: o.y };
12099
12178
  if (typeof o.id === "string") feat.id = o.id;
12100
- if (typeof o.sprite === "string") feat.sprite = o.sprite;
12179
+ if (typeof o.sprite === "string") feat.sprite = makeAsset(o.sprite, "decoration");
12101
12180
  if (typeof o.color === "string") feat.color = o.color;
12102
12181
  if (typeof o.elevation === "number") feat.elevation = o.elevation;
12103
- if (typeof o.assetUrl === "string") feat.assetUrl = o.assetUrl;
12182
+ if (typeof o.assetUrl === "string") feat.assetUrl = makeAsset(o.assetUrl, "decoration", { dimension: "3d" });
12104
12183
  return [feat];
12105
12184
  }) : []);
12106
12185
  const boardWidth = num(board.gridWidth ?? board.boardWidth, BATTLE_GRID_W);
@@ -12216,7 +12295,7 @@ function BattleBoard({
12216
12295
  maxHealth: num(unit.maxHealth),
12217
12296
  unitType: unit.unitType == null ? void 0 : str(unit.unitType),
12218
12297
  heroId: unit.heroId == null ? void 0 : str(unit.heroId),
12219
- sprite: unit.sprite == null ? void 0 : str(unit.sprite),
12298
+ sprite: unit.sprite == null ? void 0 : makeAsset(str(unit.sprite), "npc"),
12220
12299
  traits: unitTraits?.map((tr) => ({
12221
12300
  name: tr.name,
12222
12301
  currentState: tr.currentState,
@@ -12366,7 +12445,6 @@ function BattleBoard({
12366
12445
  onTileHover: (x, y) => setHoveredTile({ x, y }),
12367
12446
  onTileLeave: () => setHoveredTile(null),
12368
12447
  scale,
12369
- assetBaseUrl: assetManifest?.baseUrl,
12370
12448
  assetManifest,
12371
12449
  backgroundImage,
12372
12450
  onDrawEffects,
@@ -12444,15 +12522,16 @@ var init_BattleBoard = __esm({
12444
12522
  init_IsometricCanvas();
12445
12523
  init_boardEntity();
12446
12524
  init_isometric();
12525
+ init_makeAsset();
12447
12526
  BATTLE_CDN = "https://almadar-kflow-assets.web.app/shared";
12448
12527
  BATTLE_GRID_W = 16;
12449
12528
  BATTLE_GRID_H = 16;
12450
12529
  BATTLE_TERRAIN_SPRITES = [
12451
- `${BATTLE_CDN}/isometric-dungeon/Isometric/dirt_E.png`,
12452
- `${BATTLE_CDN}/isometric-dungeon/Isometric/dirtTiles_E.png`,
12453
- `${BATTLE_CDN}/isometric-dungeon/Isometric/planks_E.png`,
12454
- `${BATTLE_CDN}/isometric-dungeon/Isometric/stoneTile_E.png`,
12455
- `${BATTLE_CDN}/isometric-dungeon/Isometric/stoneInset_E.png`
12530
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/dirt_E.png`, "tile"),
12531
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/dirtTiles_E.png`, "tile"),
12532
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/planks_E.png`, "tile"),
12533
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/stoneTile_E.png`, "tile"),
12534
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/stoneInset_E.png`, "tile")
12456
12535
  ];
12457
12536
  DEFAULT_BATTLE_TILES = buildDefaultBattleTiles();
12458
12537
  BattleBoard.displayName = "BattleBoard";
@@ -12491,61 +12570,64 @@ function BattleTemplate({
12491
12570
  }
12492
12571
  );
12493
12572
  }
12494
- var CDN, DEFAULT_BATTLE_TILES2, DEFAULT_BATTLE_UNITS, DEFAULT_BATTLE_FEATURES, DEFAULT_BATTLE_MANIFEST;
12573
+ var CDN, STONE, DIRT, GRASS, DEFAULT_BATTLE_TILES2, DEFAULT_BATTLE_UNITS, DEFAULT_BATTLE_FEATURES, DEFAULT_BATTLE_MANIFEST;
12495
12574
  var init_BattleTemplate = __esm({
12496
12575
  "components/game/templates/BattleTemplate.tsx"() {
12497
12576
  init_BattleBoard();
12577
+ init_makeAsset();
12498
12578
  CDN = "https://almadar-kflow-assets.web.app/shared";
12579
+ STONE = makeAsset(`${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png`, "tile");
12580
+ DIRT = makeAsset(`${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png`, "tile");
12581
+ GRASS = makeAsset(`${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png`, "tile");
12499
12582
  DEFAULT_BATTLE_TILES2 = [
12500
- { x: 0, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12501
- { x: 1, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12502
- { x: 2, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12503
- { x: 3, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12504
- { x: 4, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12505
- { x: 0, y: 1, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12506
- { x: 1, y: 1, terrain: "dirt", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png` },
12507
- { x: 2, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12508
- { x: 3, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12509
- { x: 4, y: 1, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12510
- { x: 0, y: 2, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12511
- { x: 1, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12512
- { x: 2, y: 2, terrain: "dirt", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png` },
12513
- { x: 3, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12514
- { x: 4, y: 2, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12515
- { x: 0, y: 3, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12516
- { x: 1, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12517
- { x: 2, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12518
- { x: 3, y: 3, terrain: "dirt", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png` },
12519
- { x: 4, y: 3, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12520
- { x: 0, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12521
- { x: 1, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12522
- { x: 2, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12523
- { x: 3, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12524
- { x: 4, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` }
12583
+ { x: 0, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12584
+ { x: 1, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12585
+ { x: 2, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12586
+ { x: 3, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12587
+ { x: 4, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12588
+ { x: 0, y: 1, terrain: "stone", passable: false, terrainSprite: STONE },
12589
+ { x: 1, y: 1, terrain: "dirt", passable: true, terrainSprite: DIRT },
12590
+ { x: 2, y: 1, terrain: "grass", passable: true, terrainSprite: GRASS },
12591
+ { x: 3, y: 1, terrain: "grass", passable: true, terrainSprite: GRASS },
12592
+ { x: 4, y: 1, terrain: "stone", passable: false, terrainSprite: STONE },
12593
+ { x: 0, y: 2, terrain: "stone", passable: false, terrainSprite: STONE },
12594
+ { x: 1, y: 2, terrain: "grass", passable: true, terrainSprite: GRASS },
12595
+ { x: 2, y: 2, terrain: "dirt", passable: true, terrainSprite: DIRT },
12596
+ { x: 3, y: 2, terrain: "grass", passable: true, terrainSprite: GRASS },
12597
+ { x: 4, y: 2, terrain: "stone", passable: false, terrainSprite: STONE },
12598
+ { x: 0, y: 3, terrain: "stone", passable: false, terrainSprite: STONE },
12599
+ { x: 1, y: 3, terrain: "grass", passable: true, terrainSprite: GRASS },
12600
+ { x: 2, y: 3, terrain: "grass", passable: true, terrainSprite: GRASS },
12601
+ { x: 3, y: 3, terrain: "dirt", passable: true, terrainSprite: DIRT },
12602
+ { x: 4, y: 3, terrain: "stone", passable: false, terrainSprite: STONE },
12603
+ { x: 0, y: 4, terrain: "stone", passable: false, terrainSprite: STONE },
12604
+ { x: 1, y: 4, terrain: "stone", passable: false, terrainSprite: STONE },
12605
+ { x: 2, y: 4, terrain: "stone", passable: false, terrainSprite: STONE },
12606
+ { x: 3, y: 4, terrain: "stone", passable: false, terrainSprite: STONE },
12607
+ { x: 4, y: 4, terrain: "stone", passable: false, terrainSprite: STONE }
12525
12608
  ];
12526
12609
  DEFAULT_BATTLE_UNITS = [
12527
- { id: "u1", position: { x: 1, y: 1 }, unitType: "worker", name: "Worker", team: "player", health: 10, maxHealth: 10, sprite: `${CDN}/sprite-sheets/amir-sprite-sheet-se.png` },
12528
- { id: "u2", position: { x: 3, y: 3 }, unitType: "guardian", name: "Guardian", team: "enemy", health: 8, maxHealth: 10, sprite: `${CDN}/sprite-sheets/destroyer-sprite-sheet-sw.png` }
12610
+ { id: "u1", position: { x: 1, y: 1 }, unitType: "worker", name: "Worker", team: "player", health: 10, maxHealth: 10, sprite: makeAsset(`${CDN}/sprite-sheets/amir-sprite-sheet-se.png`, "player") },
12611
+ { id: "u2", position: { x: 3, y: 3 }, unitType: "guardian", name: "Guardian", team: "enemy", health: 8, maxHealth: 10, sprite: makeAsset(`${CDN}/sprite-sheets/destroyer-sprite-sheet-sw.png`, "enemy") }
12529
12612
  ];
12530
12613
  DEFAULT_BATTLE_FEATURES = [
12531
- { id: "f1", x: 2, y: 2, type: "gold_mine", sprite: `${CDN}/world-map/gold_mine.png` },
12532
- { id: "f2", x: 3, y: 1, type: "portal", sprite: `${CDN}/world-map/portal_open.png` }
12614
+ { id: "f1", x: 2, y: 2, type: "gold_mine", sprite: makeAsset(`${CDN}/world-map/gold_mine.png`, "decoration") },
12615
+ { id: "f2", x: 3, y: 1, type: "portal", sprite: makeAsset(`${CDN}/world-map/portal_open.png`, "decoration") }
12533
12616
  ];
12534
12617
  DEFAULT_BATTLE_MANIFEST = {
12535
- baseUrl: CDN,
12536
- terrains: {
12537
- stone: "/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png",
12538
- dirt: "/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png",
12539
- grass: "/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png"
12540
- },
12541
- units: {
12542
- worker: "/sprite-sheets/amir-sprite-sheet-se.png",
12543
- guardian: "/sprite-sheets/destroyer-sprite-sheet-sw.png"
12544
- },
12545
- features: {
12546
- gold_mine: "/world-map/gold_mine.png",
12547
- portal: "/world-map/portal_open.png"
12548
- }
12618
+ terrains: makeAssetMap({
12619
+ stone: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png`,
12620
+ dirt: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png`,
12621
+ grass: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png`
12622
+ }, "tile"),
12623
+ units: makeAssetMap({
12624
+ worker: `${CDN}/sprite-sheets/amir-sprite-sheet-se.png`,
12625
+ guardian: `${CDN}/sprite-sheets/destroyer-sprite-sheet-sw.png`
12626
+ }, "npc"),
12627
+ features: makeAssetMap({
12628
+ gold_mine: `${CDN}/world-map/gold_mine.png`,
12629
+ portal: `${CDN}/world-map/portal_open.png`
12630
+ }, "decoration")
12549
12631
  };
12550
12632
  BattleTemplate.displayName = "BattleTemplate";
12551
12633
  }
@@ -14760,7 +14842,6 @@ function BoardgameBoard({
14760
14842
  units,
14761
14843
  features,
14762
14844
  assetManifest,
14763
- assetBaseUrl,
14764
14845
  scale,
14765
14846
  showMinimap,
14766
14847
  enableCamera,
@@ -19830,7 +19911,7 @@ function CardHand({
19830
19911
  /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex-1 flex items-center justify-center w-full", children: card.iconUrl ? /* @__PURE__ */ jsxRuntime.jsx(
19831
19912
  "img",
19832
19913
  {
19833
- src: card.iconUrl,
19914
+ src: card.iconUrl.url,
19834
19915
  alt: card.title ?? card.id,
19835
19916
  width: art,
19836
19917
  height: art,
@@ -19888,15 +19969,6 @@ var init_CardHand = __esm({
19888
19969
  CardHand.displayName = "CardHand";
19889
19970
  }
19890
19971
  });
19891
- function resolveManifestUrl(manifest, relative) {
19892
- if (relative == null) return void 0;
19893
- if (/^https?:\/\//.test(relative)) return relative;
19894
- const base = manifest?.baseUrl;
19895
- if (base == null) return relative;
19896
- const cleanBase = base.replace(/\/$/, "");
19897
- const cleanRel = relative.replace(/^\//, "");
19898
- return `${cleanBase}/${cleanRel}`;
19899
- }
19900
19972
  function rowToCard(r) {
19901
19973
  return {
19902
19974
  id: str(r.id),
@@ -19910,7 +19982,7 @@ function rowToCard(r) {
19910
19982
  function toHandCards(cards, manifest, mana) {
19911
19983
  return cards.map((c) => {
19912
19984
  const key = c.iconKey ?? c.id;
19913
- const iconUrl = resolveManifestUrl(manifest, manifest?.cards?.[key]);
19985
+ const iconUrl = manifest?.cards?.[key];
19914
19986
  return {
19915
19987
  id: c.id,
19916
19988
  iconUrl,
@@ -21024,7 +21096,6 @@ function CastleBoard({
21024
21096
  onTileHover: (x, y) => setHoveredTile({ x, y }),
21025
21097
  onTileLeave: () => setHoveredTile(null),
21026
21098
  scale,
21027
- assetBaseUrl: assetManifest?.baseUrl,
21028
21099
  assetManifest,
21029
21100
  backgroundImage
21030
21101
  }
@@ -21100,60 +21171,63 @@ function CastleTemplate({
21100
21171
  }
21101
21172
  );
21102
21173
  }
21103
- var CDN2, DEFAULT_CASTLE_TILES, DEFAULT_CASTLE_UNITS, DEFAULT_CASTLE_FEATURES, DEFAULT_CASTLE_MANIFEST;
21174
+ var CDN2, WALL, FLOOR, FLOOR_CENTER, DEFAULT_CASTLE_TILES, DEFAULT_CASTLE_UNITS, DEFAULT_CASTLE_FEATURES, DEFAULT_CASTLE_MANIFEST;
21104
21175
  var init_CastleTemplate = __esm({
21105
21176
  "components/game/templates/CastleTemplate.tsx"() {
21106
21177
  init_CastleBoard();
21178
+ init_makeAsset();
21107
21179
  CDN2 = "https://almadar-kflow-assets.web.app/shared";
21180
+ WALL = makeAsset(`${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png`, "tile");
21181
+ FLOOR = makeAsset(`${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`, "tile");
21182
+ FLOOR_CENTER = makeAsset(`${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_09.png`, "tile");
21108
21183
  DEFAULT_CASTLE_TILES = [
21109
- { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21110
- { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21111
- { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21112
- { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21113
- { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21114
- { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21115
- { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
21116
- { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
21117
- { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
21118
- { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21119
- { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21120
- { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
21121
- { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_09.png` },
21122
- { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
21123
- { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21124
- { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21125
- { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
21126
- { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
21127
- { x: 3, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
21128
- { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21129
- { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21130
- { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21131
- { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21132
- { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21133
- { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` }
21184
+ { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
21185
+ { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
21186
+ { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
21187
+ { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
21188
+ { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
21189
+ { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: WALL },
21190
+ { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: FLOOR },
21191
+ { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: FLOOR },
21192
+ { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: FLOOR },
21193
+ { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: WALL },
21194
+ { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: WALL },
21195
+ { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: FLOOR },
21196
+ { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: FLOOR_CENTER },
21197
+ { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: FLOOR },
21198
+ { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: WALL },
21199
+ { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: WALL },
21200
+ { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: FLOOR },
21201
+ { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: FLOOR },
21202
+ { x: 3, y: 3, terrain: "floor", passable: true, terrainSprite: FLOOR },
21203
+ { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: WALL },
21204
+ { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: WALL },
21205
+ { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: WALL },
21206
+ { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: WALL },
21207
+ { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: WALL },
21208
+ { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: WALL }
21134
21209
  ];
21135
21210
  DEFAULT_CASTLE_UNITS = [
21136
- { id: "u1", position: { x: 1, y: 1 }, unitType: "worker", name: "Worker", team: "player", health: 10, maxHealth: 10, sprite: `${CDN2}/sprite-sheets/coordinator-sprite-sheet-se.png` },
21137
- { id: "u2", position: { x: 3, y: 3 }, unitType: "guardian", name: "Guardian", team: "player", health: 10, maxHealth: 10, sprite: `${CDN2}/sprite-sheets/forger-sprite-sheet-se.png` }
21211
+ { id: "u1", position: { x: 1, y: 1 }, unitType: "worker", name: "Worker", team: "player", health: 10, maxHealth: 10, sprite: makeAsset(`${CDN2}/sprite-sheets/coordinator-sprite-sheet-se.png`, "player") },
21212
+ { id: "u2", position: { x: 3, y: 3 }, unitType: "guardian", name: "Guardian", team: "player", health: 10, maxHealth: 10, sprite: makeAsset(`${CDN2}/sprite-sheets/forger-sprite-sheet-se.png`, "player") }
21138
21213
  ];
21139
21214
  DEFAULT_CASTLE_FEATURES = [
21140
- { id: "f1", x: 2, y: 2, type: "chest", sprite: `${CDN2}/world-map/treasure_chest_closed.png` },
21141
- { id: "f2", x: 3, y: 1, type: "crystal", sprite: `${CDN2}/world-map/resonance_crystal.png` }
21215
+ { id: "f1", x: 2, y: 2, type: "chest", sprite: makeAsset(`${CDN2}/world-map/treasure_chest_closed.png`, "decoration") },
21216
+ { id: "f2", x: 3, y: 1, type: "crystal", sprite: makeAsset(`${CDN2}/world-map/resonance_crystal.png`, "decoration") }
21142
21217
  ];
21143
21218
  DEFAULT_CASTLE_MANIFEST = {
21144
- baseUrl: CDN2,
21145
- terrains: {
21146
- wall: "/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png",
21147
- floor: "/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png"
21148
- },
21149
- units: {
21150
- worker: "/sprite-sheets/coordinator-sprite-sheet-se.png",
21151
- guardian: "/sprite-sheets/forger-sprite-sheet-se.png"
21152
- },
21153
- features: {
21154
- chest: "/world-map/treasure_chest_closed.png",
21155
- crystal: "/world-map/resonance_crystal.png"
21156
- }
21219
+ terrains: makeAssetMap({
21220
+ wall: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png`,
21221
+ floor: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`
21222
+ }, "tile"),
21223
+ units: makeAssetMap({
21224
+ worker: `${CDN2}/sprite-sheets/coordinator-sprite-sheet-se.png`,
21225
+ guardian: `${CDN2}/sprite-sheets/forger-sprite-sheet-se.png`
21226
+ }, "player"),
21227
+ features: makeAssetMap({
21228
+ chest: `${CDN2}/world-map/treasure_chest_closed.png`,
21229
+ crystal: `${CDN2}/world-map/resonance_crystal.png`
21230
+ }, "decoration")
21157
21231
  };
21158
21232
  CastleTemplate.displayName = "CastleTemplate";
21159
21233
  }
@@ -22141,15 +22215,6 @@ var init_ChatBar = __esm({
22141
22215
  ChatBar.displayName = "ChatBar";
22142
22216
  }
22143
22217
  });
22144
- function resolveManifestUrl2(manifest, relative) {
22145
- if (relative == null) return void 0;
22146
- if (/^https?:\/\//.test(relative)) return relative;
22147
- const base = manifest?.baseUrl;
22148
- if (base == null) return relative;
22149
- const cleanBase = base.replace(/\/$/, "");
22150
- const cleanRel = relative.replace(/^\//, "");
22151
- return `${cleanBase}/${cleanRel}`;
22152
- }
22153
22218
  function buildDefaultCBTiles() {
22154
22219
  const tiles = [];
22155
22220
  for (let y = 0; y < CB_GRID_H; y++) {
@@ -22164,12 +22229,12 @@ function buildDefaultCBTiles() {
22164
22229
  function tilesToIso(tiles, manifest) {
22165
22230
  return tiles.map((t) => {
22166
22231
  const key = t.terrain ?? "grass";
22167
- const sprite = t.terrainSprite ?? resolveManifestUrl2(manifest, manifest?.terrains?.[key]) ?? resolveManifestUrl2(manifest, manifest?.terrains?.grass);
22232
+ const terrainSprite = t.terrainSprite ?? manifest?.terrains?.[key] ?? manifest?.terrains?.grass;
22168
22233
  return {
22169
22234
  x: t.x,
22170
22235
  y: t.y,
22171
22236
  terrain: t.terrain,
22172
- terrainSprite: sprite,
22237
+ terrainSprite,
22173
22238
  passable: t.passable
22174
22239
  };
22175
22240
  });
@@ -22180,7 +22245,7 @@ function buildingsToFeatures(buildings, manifest) {
22180
22245
  x: b.x,
22181
22246
  y: b.y,
22182
22247
  type: b.type,
22183
- sprite: resolveManifestUrl2(manifest, manifest?.features?.[b.type])
22248
+ sprite: manifest?.features?.[b.type]
22184
22249
  }));
22185
22250
  }
22186
22251
  function CityBuilderBoard({
@@ -22212,7 +22277,7 @@ function CityBuilderBoard({
22212
22277
  x: num(r.x),
22213
22278
  y: num(r.y),
22214
22279
  terrain: r.terrain == null ? void 0 : str(r.terrain),
22215
- terrainSprite: r.terrainSprite == null ? void 0 : str(r.terrainSprite),
22280
+ terrainSprite: r.terrainSprite == null ? void 0 : makeAsset(str(r.terrainSprite), "tile"),
22216
22281
  passable: r.passable !== false
22217
22282
  })),
22218
22283
  [board.tiles]
@@ -22321,7 +22386,6 @@ function CityBuilderBoard({
22321
22386
  {
22322
22387
  tiles: isoTiles,
22323
22388
  features: buildingFeatures,
22324
- assetBaseUrl: assetManifest?.baseUrl,
22325
22389
  assetManifest,
22326
22390
  validMoves,
22327
22391
  hoveredTile,
@@ -22356,6 +22420,7 @@ var CB_GRID_W, CB_GRID_H, DEFAULT_BUILD_TYPES, DEFAULT_CB_TILES;
22356
22420
  var init_CityBuilderBoard = __esm({
22357
22421
  "components/game/organisms/CityBuilderBoard.tsx"() {
22358
22422
  "use client";
22423
+ init_makeAsset();
22359
22424
  init_cn();
22360
22425
  init_useEventBus();
22361
22426
  init_Box();
@@ -28350,7 +28415,7 @@ function StatBadge({
28350
28415
  resolvedAsset ? /* @__PURE__ */ jsxRuntime.jsx(
28351
28416
  "img",
28352
28417
  {
28353
- src: resolvedAsset,
28418
+ src: resolvedAsset.url,
28354
28419
  alt: "",
28355
28420
  width: 16,
28356
28421
  height: 16,
@@ -28657,7 +28722,7 @@ function GameCanvas2D({
28657
28722
  tickEvent,
28658
28723
  drawEvent,
28659
28724
  fps = 60,
28660
- backgroundImage = "",
28725
+ backgroundImage,
28661
28726
  assetBaseUrl,
28662
28727
  className
28663
28728
  }) {
@@ -28721,7 +28786,7 @@ function GameCanvas2D({
28721
28786
  emitRef.current(tickEventRef.current, { dt, frame });
28722
28787
  }
28723
28788
  if (backgroundImageRef.current) {
28724
- const bgImg = loadImage(backgroundImageRef.current);
28789
+ const bgImg = loadImage(backgroundImageRef.current.url);
28725
28790
  if (bgImg) {
28726
28791
  ctx.drawImage(bgImg, 0, 0, widthRef.current, heightRef.current);
28727
28792
  } else {
@@ -29092,7 +29157,7 @@ function EnemyPlate({
29092
29157
  assetUrl && /* @__PURE__ */ jsxRuntime.jsx(
29093
29158
  "img",
29094
29159
  {
29095
- src: assetUrl,
29160
+ src: assetUrl.url,
29096
29161
  alt: name,
29097
29162
  width: 24,
29098
29163
  height: 24,
@@ -29434,7 +29499,7 @@ function DialogueBox({
29434
29499
  "div",
29435
29500
  {
29436
29501
  className: "fixed inset-0 z-20 bg-center bg-cover bg-no-repeat",
29437
- style: { backgroundImage: `url(${backgroundImage})` },
29502
+ style: { backgroundImage: `url(${backgroundImage?.url})` },
29438
29503
  "aria-hidden": "true"
29439
29504
  }
29440
29505
  ),
@@ -29449,7 +29514,7 @@ function DialogueBox({
29449
29514
  children: /* @__PURE__ */ jsxRuntime.jsx(
29450
29515
  "img",
29451
29516
  {
29452
- src: portraitUrl,
29517
+ src: portraitUrl?.url,
29453
29518
  alt: dialogue.speaker,
29454
29519
  className: "h-full w-auto object-contain drop-shadow-2xl"
29455
29520
  }
@@ -41755,7 +41820,6 @@ var init_FeatureGridOrganism = __esm({
41755
41820
  });
41756
41821
  function FishingBoard({
41757
41822
  backgroundImage,
41758
- assetBaseUrl,
41759
41823
  scale = 1,
41760
41824
  showMinimap = false,
41761
41825
  enableCamera = true,
@@ -41773,8 +41837,7 @@ function FishingBoard({
41773
41837
  {
41774
41838
  width,
41775
41839
  height,
41776
- backgroundImage: backgroundImage ?? "",
41777
- assetBaseUrl,
41840
+ backgroundImage,
41778
41841
  fps: 60,
41779
41842
  className: "w-full h-full"
41780
41843
  }
@@ -43993,7 +44056,7 @@ var init_GameCanvas3D2 = __esm({
43993
44056
  children: /* @__PURE__ */ jsxRuntime.jsx(
43994
44057
  ModelLoader,
43995
44058
  {
43996
- url: tile.modelUrl,
44059
+ url: tile.modelUrl.url,
43997
44060
  scale: 0.95,
43998
44061
  fallbackGeometry: "box",
43999
44062
  castShadow: true,
@@ -44058,7 +44121,7 @@ var init_GameCanvas3D2 = __esm({
44058
44121
  /* @__PURE__ */ jsxRuntime.jsx(
44059
44122
  ModelLoader,
44060
44123
  {
44061
- url: unit.modelUrl,
44124
+ url: unit.modelUrl.url,
44062
44125
  scale: modelScale,
44063
44126
  fallbackGeometry: "box",
44064
44127
  castShadow: true
@@ -44118,7 +44181,7 @@ var init_GameCanvas3D2 = __esm({
44118
44181
  return /* @__PURE__ */ jsxRuntime.jsx(
44119
44182
  ModelLoader,
44120
44183
  {
44121
- url: feature.assetUrl,
44184
+ url: feature.assetUrl.url,
44122
44185
  position,
44123
44186
  scale: 0.5,
44124
44187
  rotation: [0, feature.rotation ?? 0, 0],
@@ -44339,7 +44402,18 @@ function GameBoard3D({
44339
44402
  const row = boardEntity(entity);
44340
44403
  const eventBus = useEventBus();
44341
44404
  const entityUnits = row ? rows(row.units) : [];
44342
- const units = entityUnits;
44405
+ const units = entityUnits.map((r) => ({
44406
+ id: str(r.id),
44407
+ x: num(r.x),
44408
+ y: num(r.y),
44409
+ z: num(r.z),
44410
+ faction: str(r.faction) || "neutral",
44411
+ team: str(r.team) || str(r.faction) || "neutral",
44412
+ unitType: r.unitType == null ? void 0 : str(r.unitType),
44413
+ name: r.name == null ? void 0 : str(r.name),
44414
+ health: r.health == null ? void 0 : num(r.health),
44415
+ maxHealth: r.maxHealth == null ? void 0 : num(r.maxHealth)
44416
+ }));
44343
44417
  const selectedUnitId = row ? str(row.selectedUnitId) || null : null;
44344
44418
  const phase = row ? str(row.phase) : "observation";
44345
44419
  const result = row ? str(row.result) : "none";
@@ -44934,7 +45008,6 @@ function HexStrategyBoard({
44934
45008
  units,
44935
45009
  features,
44936
45010
  assetManifest,
44937
- assetBaseUrl,
44938
45011
  scale,
44939
45012
  showMinimap,
44940
45013
  enableCamera,
@@ -44976,7 +45049,6 @@ function HolidayRunnerBoard({
44976
45049
  units,
44977
45050
  features,
44978
45051
  assetManifest,
44979
- assetBaseUrl,
44980
45052
  scale,
44981
45053
  showMinimap,
44982
45054
  enableCamera,
@@ -45771,7 +45843,6 @@ function MatchPuzzleBoard({
45771
45843
  units,
45772
45844
  features,
45773
45845
  assetManifest,
45774
- assetBaseUrl,
45775
45846
  scale,
45776
45847
  showMinimap,
45777
45848
  enableCamera,
@@ -46032,7 +46103,6 @@ function MinigolfBoard({
46032
46103
  units,
46033
46104
  features,
46034
46105
  assetManifest,
46035
- assetBaseUrl,
46036
46106
  scale,
46037
46107
  showMinimap,
46038
46108
  enableCamera,
@@ -46338,7 +46408,6 @@ function PirateBoard({
46338
46408
  units,
46339
46409
  features,
46340
46410
  assetManifest,
46341
- assetBaseUrl,
46342
46411
  scale,
46343
46412
  showMinimap,
46344
46413
  enableCamera,
@@ -46459,8 +46528,8 @@ function PlatformerBoard({
46459
46528
  canvasHeight,
46460
46529
  followCamera: true,
46461
46530
  bgColor,
46462
- playerSprite,
46463
- tileSprites,
46531
+ playerSprite: playerSprite?.url,
46532
+ tileSprites: tileSprites ? Object.fromEntries(Object.entries(tileSprites).map(([k, a]) => [k, a.url])) : void 0,
46464
46533
  leftEvent,
46465
46534
  rightEvent,
46466
46535
  jumpEvent,
@@ -46525,7 +46594,7 @@ function PlatformerTemplate({
46525
46594
  worldHeight = 400,
46526
46595
  canvasWidth = 800,
46527
46596
  canvasHeight = 400,
46528
- playerSprite = `${CDN3}/characters/platformChar_idle.png`,
46597
+ playerSprite = makeAsset(`${CDN3}/characters/platformChar_idle.png`, "player"),
46529
46598
  tileSprites = DEFAULT_TILE_SPRITES,
46530
46599
  bgColor = "#5c94fc",
46531
46600
  gameEndEvent = "GAME_END",
@@ -46578,13 +46647,14 @@ var init_PlatformerTemplate = __esm({
46578
46647
  init_PlatformerBoard();
46579
46648
  init_GameHud();
46580
46649
  init_ScoreBoard();
46650
+ init_makeAsset();
46581
46651
  CDN3 = "https://almadar-kflow-assets.web.app/shared/platformer";
46582
- DEFAULT_TILE_SPRITES = {
46652
+ DEFAULT_TILE_SPRITES = makeAssetMap({
46583
46653
  ground: `${CDN3}/tiles/platformPack_tile001.png`,
46584
46654
  platform: `${CDN3}/tiles/platformPack_tile004.png`,
46585
46655
  hazard: `${CDN3}/tiles/platformPack_tile017.png`,
46586
46656
  goal: `${CDN3}/tiles/platformPack_tile007.png`
46587
- };
46657
+ }, "tile");
46588
46658
  DEFAULT_PLATFORMS = [
46589
46659
  { x: 0, y: 368, width: 800, height: 32, type: "ground" },
46590
46660
  { x: 150, y: 280, width: 160, height: 16, type: "platform" },
@@ -46740,7 +46810,6 @@ function RacingBoard({
46740
46810
  units,
46741
46811
  features,
46742
46812
  assetManifest,
46743
- assetBaseUrl,
46744
46813
  scale,
46745
46814
  showMinimap,
46746
46815
  enableCamera,
@@ -46759,27 +46828,18 @@ var init_RacingBoard = __esm({
46759
46828
  RacingBoard.displayName = "RacingBoard";
46760
46829
  }
46761
46830
  });
46762
- function resolveManifestUrl3(manifest, relative) {
46763
- if (relative == null) return void 0;
46764
- if (/^https?:\/\//.test(relative)) return relative;
46765
- const base = manifest?.baseUrl;
46766
- if (base == null) return relative;
46767
- const cleanBase = base.replace(/\/$/, "");
46768
- const cleanRel = relative.replace(/^\//, "");
46769
- return `${cleanBase}/${cleanRel}`;
46770
- }
46771
46831
  function dungeonTerrain(x, y, stairsX, stairsY, manifest) {
46772
46832
  const isBorder = x === 0 || y === 0 || x === DUNGEON_GRID_W - 1 || y === DUNGEON_GRID_H - 1;
46773
46833
  const isPillar = x % 4 === 0 && y % 4 === 0 && !isBorder;
46774
46834
  const isWall = isBorder || isPillar;
46775
46835
  const terrains = manifest?.terrains;
46776
46836
  if (x === stairsX && y === stairsY) {
46777
- return { terrain: "stairs", passable: true, terrainSprite: resolveManifestUrl3(manifest, terrains?.stairs) };
46837
+ return { terrain: "stairs", passable: true, terrainSprite: terrains?.stairs };
46778
46838
  }
46779
46839
  if (isWall) {
46780
- return { terrain: "wall", passable: false, terrainSprite: resolveManifestUrl3(manifest, terrains?.wall) };
46840
+ return { terrain: "wall", passable: false, terrainSprite: terrains?.wall };
46781
46841
  }
46782
- return { terrain: "floor", passable: true, terrainSprite: resolveManifestUrl3(manifest, terrains?.floor) };
46842
+ return { terrain: "floor", passable: true, terrainSprite: terrains?.floor };
46783
46843
  }
46784
46844
  function buildDefaultDungeonTiles(stairsX, stairsY, manifest) {
46785
46845
  const tiles = [];
@@ -46823,7 +46883,7 @@ function RoguelikeBoard({
46823
46883
  x: num(r.x),
46824
46884
  y: num(r.y),
46825
46885
  terrain: r.terrain == null ? void 0 : str(r.terrain),
46826
- terrainSprite: r.terrainSprite == null ? void 0 : str(r.terrainSprite),
46886
+ terrainSprite: r.terrainSprite == null ? void 0 : makeAsset(str(r.terrainSprite), "tile"),
46827
46887
  passable: r.passable !== false
46828
46888
  })),
46829
46889
  [board.tiles]
@@ -46903,7 +46963,7 @@ function RoguelikeBoard({
46903
46963
  health: playerHp,
46904
46964
  maxHealth: playerMaxHp,
46905
46965
  unitType: "player",
46906
- sprite: resolveManifestUrl3(assetManifest, assetManifest?.units?.player)
46966
+ sprite: assetManifest?.units?.player
46907
46967
  },
46908
46968
  ...liveEnemies.map((e) => ({
46909
46969
  id: e.id,
@@ -46913,7 +46973,7 @@ function RoguelikeBoard({
46913
46973
  health: e.hp,
46914
46974
  maxHealth: 6,
46915
46975
  unitType: "enemy",
46916
- sprite: resolveManifestUrl3(assetManifest, assetManifest?.units?.enemy)
46976
+ sprite: assetManifest?.units?.enemy
46917
46977
  }))
46918
46978
  ];
46919
46979
  }, [player, enemies, playerHp, playerMaxHp, assetManifest, t]);
@@ -46923,7 +46983,7 @@ function RoguelikeBoard({
46923
46983
  x: it.x,
46924
46984
  y: it.y,
46925
46985
  type: it.kind,
46926
- sprite: resolveManifestUrl3(assetManifest, assetManifest?.features?.[it.kind])
46986
+ sprite: assetManifest?.features?.[it.kind]
46927
46987
  })),
46928
46988
  [items, assetManifest]
46929
46989
  );
@@ -46984,7 +47044,6 @@ function RoguelikeBoard({
46984
47044
  onTileHover: (x, y) => setHoveredTile({ x, y }),
46985
47045
  onTileLeave: () => setHoveredTile(null),
46986
47046
  scale,
46987
- assetBaseUrl: assetManifest?.baseUrl,
46988
47047
  assetManifest,
46989
47048
  unitScale,
46990
47049
  spriteHeightRatio,
@@ -47044,6 +47103,7 @@ var init_RoguelikeBoard = __esm({
47044
47103
  init_Stack();
47045
47104
  init_IsometricCanvas();
47046
47105
  init_boardEntity();
47106
+ init_makeAsset();
47047
47107
  DUNGEON_GRID_W = 16;
47048
47108
  DUNGEON_GRID_H = 16;
47049
47109
  DEFAULT_ENEMIES = [
@@ -47094,55 +47154,59 @@ function RoguelikeTemplate({
47094
47154
  }
47095
47155
  );
47096
47156
  }
47097
- var CDN4, DEFAULT_ROGUELIKE_TILES, DEFAULT_ROGUELIKE_MANIFEST;
47157
+ var CDN4, wall, floor, tiles2, stairs, DEFAULT_ROGUELIKE_TILES, DEFAULT_ROGUELIKE_MANIFEST;
47098
47158
  var init_RoguelikeTemplate = __esm({
47099
47159
  "components/game/templates/RoguelikeTemplate.tsx"() {
47100
47160
  init_RoguelikeBoard();
47161
+ init_makeAsset();
47101
47162
  CDN4 = "https://almadar-kflow-assets.web.app/shared";
47163
+ wall = makeAsset(`${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png`, "tile");
47164
+ floor = makeAsset(`${CDN4}/isometric-dungeon/Isometric/dirt_E.png`, "tile");
47165
+ tiles2 = makeAsset(`${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png`, "tile");
47166
+ stairs = makeAsset(`${CDN4}/isometric-dungeon/Isometric/stairs_E.png`, "tile");
47102
47167
  DEFAULT_ROGUELIKE_TILES = [
47103
- { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47104
- { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47105
- { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47106
- { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47107
- { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47108
- { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47109
- { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
47110
- { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
47111
- { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
47112
- { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47113
- { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47114
- { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
47115
- { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
47116
- { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
47117
- { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47118
- { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47119
- { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
47120
- { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
47121
- { x: 3, y: 3, terrain: "stairs", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stairs_E.png` },
47122
- { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47123
- { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47124
- { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47125
- { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47126
- { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47127
- { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` }
47168
+ { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
47169
+ { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
47170
+ { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
47171
+ { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
47172
+ { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
47173
+ { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: wall },
47174
+ { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: floor },
47175
+ { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: floor },
47176
+ { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: floor },
47177
+ { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: wall },
47178
+ { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: wall },
47179
+ { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: tiles2 },
47180
+ { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: tiles2 },
47181
+ { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: floor },
47182
+ { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: wall },
47183
+ { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: wall },
47184
+ { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: floor },
47185
+ { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: tiles2 },
47186
+ { x: 3, y: 3, terrain: "stairs", passable: true, terrainSprite: stairs },
47187
+ { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: wall },
47188
+ { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
47189
+ { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
47190
+ { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
47191
+ { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
47192
+ { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: wall }
47128
47193
  ];
47129
47194
  DEFAULT_ROGUELIKE_MANIFEST = {
47130
- baseUrl: CDN4,
47131
- terrains: {
47132
- floor: "/isometric-dungeon/Isometric/dirt_E.png",
47133
- wall: "/isometric-dungeon/Isometric/stoneInset_E.png",
47134
- stairs: "/isometric-dungeon/Isometric/stairs_E.png",
47135
- planks: "/isometric-dungeon/Isometric/planks_E.png"
47136
- },
47195
+ terrains: makeAssetMap({
47196
+ floor: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png`,
47197
+ wall: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png`,
47198
+ stairs: `${CDN4}/isometric-dungeon/Isometric/stairs_E.png`,
47199
+ planks: `${CDN4}/isometric-dungeon/Isometric/planks_E.png`
47200
+ }, "tile"),
47137
47201
  units: {
47138
- player: "/isometric-dungeon/Characters/Male/Male_0_Idle0.png",
47139
- enemy: "/sprite-sheets/shadow-legion-sprite-sheet-sw.png"
47202
+ player: makeAsset(`${CDN4}/isometric-dungeon/Characters/Male/Male_0_Idle0.png`, "player"),
47203
+ enemy: makeAsset(`${CDN4}/sprite-sheets/shadow-legion-sprite-sheet-sw.png`, "enemy")
47140
47204
  },
47141
- features: {
47142
- health_potion: "/isometric-dungeon/Isometric/chestClosed_E.png",
47143
- sword: "/isometric-dungeon/Isometric/barrel_E.png",
47144
- shield: "/isometric-dungeon/Isometric/barrel_E.png"
47145
- }
47205
+ features: makeAssetMap({
47206
+ health_potion: `${CDN4}/isometric-dungeon/Isometric/chestClosed_E.png`,
47207
+ sword: `${CDN4}/isometric-dungeon/Isometric/barrel_E.png`,
47208
+ shield: `${CDN4}/isometric-dungeon/Isometric/barrel_E.png`
47209
+ }, "item")
47146
47210
  };
47147
47211
  RoguelikeTemplate.displayName = "RoguelikeTemplate";
47148
47212
  }
@@ -49997,7 +50061,6 @@ function SokobanBoard({
49997
50061
  units,
49998
50062
  features,
49999
50063
  assetManifest,
50000
- assetBaseUrl,
50001
50064
  scale,
50002
50065
  showMinimap,
50003
50066
  enableCamera,
@@ -50039,7 +50102,6 @@ function SpaceShmupBoard({
50039
50102
  units,
50040
50103
  features,
50041
50104
  assetManifest,
50042
- assetBaseUrl,
50043
50105
  scale,
50044
50106
  showMinimap,
50045
50107
  enableCamera,
@@ -50081,7 +50143,6 @@ function SpaceStationBoard({
50081
50143
  units,
50082
50144
  features,
50083
50145
  assetManifest,
50084
- assetBaseUrl,
50085
50146
  scale,
50086
50147
  showMinimap,
50087
50148
  enableCamera,
@@ -50216,7 +50277,6 @@ function SportsBoard({
50216
50277
  units,
50217
50278
  features,
50218
50279
  assetManifest,
50219
- assetBaseUrl,
50220
50280
  scale,
50221
50281
  showMinimap,
50222
50282
  enableCamera,
@@ -52060,7 +52120,6 @@ function TanksBoard({
52060
52120
  units,
52061
52121
  features,
52062
52122
  assetManifest,
52063
- assetBaseUrl,
52064
52123
  scale,
52065
52124
  showMinimap,
52066
52125
  enableCamera,
@@ -52338,15 +52397,6 @@ var init_ToastSlot = __esm({
52338
52397
  ToastSlot.displayName = "ToastSlot";
52339
52398
  }
52340
52399
  });
52341
- function resolveManifestUrl4(manifest, relative) {
52342
- if (relative == null || relative === "") return void 0;
52343
- if (/^https?:\/\//.test(relative)) return relative;
52344
- const base = manifest?.baseUrl;
52345
- if (base == null) return relative;
52346
- const cleanBase = base.replace(/\/$/, "");
52347
- const cleanRel = relative.replace(/^\//, "");
52348
- return `${cleanBase}/${cleanRel}`;
52349
- }
52350
52400
  function readPlayer(v) {
52351
52401
  if (v == null || typeof v !== "object") return void 0;
52352
52402
  const o = v;
@@ -52399,10 +52449,10 @@ function TopDownShooterBoard({
52399
52449
  const wave = propWave ?? num(board.wave, 1);
52400
52450
  const lives = propLives ?? num(board.lives, 3);
52401
52451
  const result = propResult ?? (str(board.result) || "none");
52402
- const playerSprite = resolveManifestUrl4(assetManifest, assetManifest?.units?.player);
52403
- const enemySprite = resolveManifestUrl4(assetManifest, assetManifest?.units?.enemy);
52404
- const projectileSprite = resolveManifestUrl4(assetManifest, assetManifest?.features?.projectile);
52405
- const backgroundSprite = resolveManifestUrl4(assetManifest, assetManifest?.background);
52452
+ const playerSprite = assetManifest?.units?.player?.url;
52453
+ const enemySprite = assetManifest?.units?.enemy?.url;
52454
+ const projectileSprite = assetManifest?.features?.projectile?.url;
52455
+ const backgroundSprite = assetManifest?.background;
52406
52456
  const spriteUrls = React88.useMemo(
52407
52457
  () => [playerSprite, enemySprite, projectileSprite].filter((u) => u != null),
52408
52458
  [playerSprite, enemySprite, projectileSprite]
@@ -52569,7 +52619,6 @@ function TopDownShooterBoard({
52569
52619
  width,
52570
52620
  height,
52571
52621
  backgroundImage: backgroundSprite,
52572
- assetBaseUrl: assetManifest?.baseUrl,
52573
52622
  onDraw
52574
52623
  }
52575
52624
  ),
@@ -52694,15 +52743,6 @@ var init_TopDownShooterTemplate = __esm({
52694
52743
  TopDownShooterTemplate.displayName = "TopDownShooterTemplate";
52695
52744
  }
52696
52745
  });
52697
- function resolveManifestUrl5(manifest, relative) {
52698
- if (relative == null) return void 0;
52699
- if (/^https?:\/\//.test(relative)) return relative;
52700
- const base = manifest?.baseUrl;
52701
- if (base == null) return relative;
52702
- const cleanBase = base.replace(/\/$/, "");
52703
- const cleanRel = relative.replace(/^\//, "");
52704
- return `${cleanBase}/${cleanRel}`;
52705
- }
52706
52746
  function buildDefaultTDTiles() {
52707
52747
  const pathSet = new Set(DEFAULT_TD_PATH.map((p2) => `${p2.x},${p2.y}`));
52708
52748
  const tiles = [];
@@ -52722,18 +52762,18 @@ function buildDefaultTDTiles() {
52722
52762
  function tilesToIso2(tiles, manifest) {
52723
52763
  return tiles.map((t) => {
52724
52764
  const key = t.terrain ?? "ground";
52725
- const sprite = t.terrainSprite ?? resolveManifestUrl5(manifest, manifest?.terrains?.[key]) ?? resolveManifestUrl5(manifest, manifest?.terrains?.ground);
52765
+ const terrainSprite = t.terrainSprite != null ? makeAsset(t.terrainSprite, "tile") : manifest?.terrains?.[key] ?? manifest?.terrains?.ground;
52726
52766
  return {
52727
52767
  x: t.x,
52728
52768
  y: t.y,
52729
52769
  terrain: t.terrain,
52730
- terrainSprite: sprite,
52770
+ terrainSprite,
52731
52771
  passable: t.passable
52732
52772
  };
52733
52773
  });
52734
52774
  }
52735
52775
  function creepsToUnits(creeps, manifest) {
52736
- const sprite = resolveManifestUrl5(manifest, manifest?.units?.creep);
52776
+ const sprite = manifest?.units?.creep;
52737
52777
  return creeps.map((c) => ({
52738
52778
  id: c.id,
52739
52779
  position: { x: c.x, y: c.y },
@@ -52751,14 +52791,14 @@ function heroToUnit(hero, manifest) {
52751
52791
  position: { x: hero.x, y: hero.y },
52752
52792
  name: "Hero",
52753
52793
  team: "player",
52754
- sprite: resolveManifestUrl5(manifest, manifest?.units?.hero),
52794
+ sprite: manifest?.units?.hero,
52755
52795
  unitType: "hero",
52756
52796
  health: 1,
52757
52797
  maxHealth: 1
52758
52798
  };
52759
52799
  }
52760
52800
  function towersToFeatures(towers, manifest) {
52761
- const sprite = resolveManifestUrl5(manifest, manifest?.features?.tower);
52801
+ const sprite = manifest?.features?.tower;
52762
52802
  return towers.map((t) => ({
52763
52803
  id: t.id,
52764
52804
  x: t.x,
@@ -52956,7 +52996,6 @@ function TowerDefenseBoard({
52956
52996
  tiles: isoTiles,
52957
52997
  units: isoUnits,
52958
52998
  features: towerFeatures,
52959
- assetBaseUrl: assetManifest?.baseUrl,
52960
52999
  assetManifest,
52961
53000
  validMoves,
52962
53001
  hoveredTile,
@@ -53000,6 +53039,7 @@ var TD_GRID_W, TD_GRID_H, DEFAULT_TD_PATH, DEFAULT_TD_TILES;
53000
53039
  var init_TowerDefenseBoard = __esm({
53001
53040
  "components/game/organisms/TowerDefenseBoard.tsx"() {
53002
53041
  "use client";
53042
+ init_makeAsset();
53003
53043
  init_cn();
53004
53044
  init_useEventBus();
53005
53045
  init_Box();
@@ -53329,15 +53369,6 @@ var init_UncontrolledBattleBoard = __esm({
53329
53369
  UncontrolledBattleBoard.displayName = "UncontrolledBattleBoard";
53330
53370
  }
53331
53371
  });
53332
- function resolveManifestUrl6(manifest, relative) {
53333
- if (relative == null) return void 0;
53334
- if (/^https?:\/\//.test(relative)) return relative;
53335
- const base = manifest?.baseUrl;
53336
- if (base == null) return relative;
53337
- const cleanBase = base.replace(/\/$/, "");
53338
- const cleanRel = relative.replace(/^\//, "");
53339
- return `${cleanBase}/${cleanRel}`;
53340
- }
53341
53372
  function VisualNovelBoard({
53342
53373
  entity,
53343
53374
  nodes: propNodes,
@@ -53372,11 +53403,11 @@ function VisualNovelBoard({
53372
53403
  const currentNodeId = propCurrentNodeId ?? (str(board.currentNodeId) || nodes[0]?.id);
53373
53404
  const currentNode = nodes.find((n) => n.id === currentNodeId) ?? nodes[0];
53374
53405
  const backgroundImage = React88.useMemo(
53375
- () => resolveManifestUrl6(assetManifest, assetManifest?.backgrounds?.[currentNode?.backgroundKey ?? ""]),
53406
+ () => assetManifest?.backgrounds?.[currentNode?.backgroundKey ?? ""],
53376
53407
  [assetManifest, currentNode?.backgroundKey]
53377
53408
  );
53378
53409
  const portraitUrl = React88.useMemo(
53379
- () => resolveManifestUrl6(assetManifest, assetManifest?.portraits?.[currentNode?.portraitKey ?? ""]),
53410
+ () => assetManifest?.portraits?.[currentNode?.portraitKey ?? ""],
53380
53411
  [assetManifest, currentNode?.portraitKey]
53381
53412
  );
53382
53413
  const dialogueChoices = React88.useMemo(
@@ -53550,7 +53581,7 @@ function buildDefaultWorldTiles() {
53550
53581
  for (let x = 0; x < WORLD_GRID_W; x++) {
53551
53582
  const isBorder = x === 0 || y === 0 || x === WORLD_GRID_W - 1 || y === WORLD_GRID_H - 1;
53552
53583
  const def = isBorder ? WORLD_TERRAIN_DEFS[3] : WORLD_TERRAIN_DEFS[(x * 5 + y * 3 + (x ^ y)) % (WORLD_TERRAIN_DEFS.length - 1)];
53553
- tiles.push({ x, y, terrain: def.terrain, terrainSprite: def.sprite, passable: def.passable });
53584
+ tiles.push({ x, y, terrain: def.terrain, terrainSprite: makeAsset(def.sprite, "tile"), passable: def.passable });
53554
53585
  }
53555
53586
  }
53556
53587
  return tiles;
@@ -53594,7 +53625,12 @@ function WorldMapBoard({
53594
53625
  const resolved = boardEntity(entity);
53595
53626
  const entityUnits = rows(resolved?.units);
53596
53627
  const entityTiles = rows(resolved?.tiles);
53597
- const features = propFeatures ?? rows(resolved?.features);
53628
+ const features = propFeatures ?? rows(resolved?.features).map((r) => ({
53629
+ id: r.id == null ? void 0 : str(r.id),
53630
+ x: num(r.x),
53631
+ y: num(r.y),
53632
+ type: str(r.type)
53633
+ }));
53598
53634
  const selectedHeroId = resolved?.selectedHeroId ?? null;
53599
53635
  const assetManifest = propAssetManifest ?? resolved?.assetManifest;
53600
53636
  const backgroundImage = resolved?.backgroundImage;
@@ -53604,7 +53640,7 @@ function WorldMapBoard({
53604
53640
  x: num(t.x),
53605
53641
  y: num(t.y),
53606
53642
  terrain: str(t.terrain),
53607
- terrainSprite: t.terrainSprite == null ? void 0 : str(t.terrainSprite),
53643
+ terrainSprite: t.terrainSprite == null ? void 0 : makeAsset(str(t.terrainSprite), "tile"),
53608
53644
  passable: t.passable !== false
53609
53645
  })),
53610
53646
  [entityTiles]
@@ -53620,7 +53656,7 @@ function WorldMapBoard({
53620
53656
  team: str(u.team) === "enemy" ? "enemy" : "player",
53621
53657
  health: num(u.health) || 100,
53622
53658
  maxHealth: num(u.maxHealth) || 100,
53623
- sprite: u.sprite == null ? void 0 : str(u.sprite)
53659
+ sprite: u.sprite == null ? void 0 : makeAsset(str(u.sprite), "player")
53624
53660
  })),
53625
53661
  [entityUnits, propUnits]
53626
53662
  );
@@ -53802,7 +53838,6 @@ function WorldMapBoard({
53802
53838
  onTileHover: (x, y) => setHoveredTile({ x, y }),
53803
53839
  onTileLeave: () => setHoveredTile(null),
53804
53840
  scale,
53805
- assetBaseUrl: assetManifest?.baseUrl,
53806
53841
  assetManifest,
53807
53842
  backgroundImage,
53808
53843
  effectSpriteUrls,
@@ -53825,6 +53860,7 @@ var WORLD_CDN, WORLD_GRID_W, WORLD_GRID_H, WORLD_TERRAIN_DEFS, DEFAULT_WORLD_TIL
53825
53860
  var init_WorldMapBoard = __esm({
53826
53861
  "components/game/organisms/WorldMapBoard.tsx"() {
53827
53862
  "use client";
53863
+ init_makeAsset();
53828
53864
  init_cn();
53829
53865
  init_useEventBus();
53830
53866
  init_Stack();
@@ -53878,62 +53914,66 @@ function WorldMapTemplate({
53878
53914
  }
53879
53915
  );
53880
53916
  }
53881
- var CDN5, DEFAULT_WORLDMAP_TILES, DEFAULT_WORLDMAP_UNITS, DEFAULT_WORLDMAP_FEATURES, DEFAULT_WORLDMAP_MANIFEST;
53917
+ var CDN5, mountain, water, grass, road, DEFAULT_WORLDMAP_TILES, DEFAULT_WORLDMAP_UNITS, DEFAULT_WORLDMAP_FEATURES, DEFAULT_WORLDMAP_MANIFEST;
53882
53918
  var init_WorldMapTemplate = __esm({
53883
53919
  "components/game/templates/WorldMapTemplate.tsx"() {
53884
53920
  init_WorldMapBoard();
53921
+ init_makeAsset();
53885
53922
  CDN5 = "https://almadar-kflow-assets.web.app/shared";
53923
+ mountain = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png`, "tile");
53924
+ water = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png`, "tile");
53925
+ grass = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`, "tile");
53926
+ road = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png`, "tile");
53886
53927
  DEFAULT_WORLDMAP_TILES = [
53887
- { x: 0, y: 0, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53888
- { x: 1, y: 0, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53889
- { x: 2, y: 0, terrain: "water", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png` },
53890
- { x: 3, y: 0, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53891
- { x: 4, y: 0, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53892
- { x: 0, y: 1, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53893
- { x: 1, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53894
- { x: 2, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53895
- { x: 3, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53896
- { x: 4, y: 1, terrain: "water", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png` },
53897
- { x: 0, y: 2, terrain: "water", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png` },
53898
- { x: 1, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53899
- { x: 2, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png` },
53900
- { x: 3, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53901
- { x: 4, y: 2, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53902
- { x: 0, y: 3, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53903
- { x: 1, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53904
- { x: 2, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53905
- { x: 3, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png` },
53906
- { x: 4, y: 3, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53907
- { x: 0, y: 4, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53908
- { x: 1, y: 4, terrain: "water", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png` },
53909
- { x: 2, y: 4, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53910
- { x: 3, y: 4, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53911
- { x: 4, y: 4, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` }
53928
+ { x: 0, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53929
+ { x: 1, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53930
+ { x: 2, y: 0, terrain: "water", passable: false, terrainSprite: water },
53931
+ { x: 3, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53932
+ { x: 4, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53933
+ { x: 0, y: 1, terrain: "mountain", passable: false, terrainSprite: mountain },
53934
+ { x: 1, y: 1, terrain: "grass", passable: true, terrainSprite: grass },
53935
+ { x: 2, y: 1, terrain: "grass", passable: true, terrainSprite: grass },
53936
+ { x: 3, y: 1, terrain: "grass", passable: true, terrainSprite: grass },
53937
+ { x: 4, y: 1, terrain: "water", passable: false, terrainSprite: water },
53938
+ { x: 0, y: 2, terrain: "water", passable: false, terrainSprite: water },
53939
+ { x: 1, y: 2, terrain: "grass", passable: true, terrainSprite: grass },
53940
+ { x: 2, y: 2, terrain: "grass", passable: true, terrainSprite: road },
53941
+ { x: 3, y: 2, terrain: "grass", passable: true, terrainSprite: grass },
53942
+ { x: 4, y: 2, terrain: "mountain", passable: false, terrainSprite: mountain },
53943
+ { x: 0, y: 3, terrain: "mountain", passable: false, terrainSprite: mountain },
53944
+ { x: 1, y: 3, terrain: "grass", passable: true, terrainSprite: grass },
53945
+ { x: 2, y: 3, terrain: "grass", passable: true, terrainSprite: grass },
53946
+ { x: 3, y: 3, terrain: "grass", passable: true, terrainSprite: road },
53947
+ { x: 4, y: 3, terrain: "mountain", passable: false, terrainSprite: mountain },
53948
+ { x: 0, y: 4, terrain: "mountain", passable: false, terrainSprite: mountain },
53949
+ { x: 1, y: 4, terrain: "water", passable: false, terrainSprite: water },
53950
+ { x: 2, y: 4, terrain: "grass", passable: true, terrainSprite: grass },
53951
+ { x: 3, y: 4, terrain: "mountain", passable: false, terrainSprite: mountain },
53952
+ { x: 4, y: 4, terrain: "mountain", passable: false, terrainSprite: mountain }
53912
53953
  ];
53913
53954
  DEFAULT_WORLDMAP_UNITS = [
53914
- { id: "h1", position: { x: 1, y: 1 }, unitType: "hero", name: "Amir", team: "player", health: 10, maxHealth: 10, sprite: `${CDN5}/sprite-sheets/amir-sprite-sheet-se.png` },
53915
- { id: "h2", position: { x: 3, y: 3 }, unitType: "scout", name: "Archivist", team: "player", health: 10, maxHealth: 10, sprite: `${CDN5}/sprite-sheets/archivist-sprite-sheet-se.png` }
53955
+ { id: "h1", position: { x: 1, y: 1 }, unitType: "hero", name: "Amir", team: "player", health: 10, maxHealth: 10, sprite: makeAsset(`${CDN5}/sprite-sheets/amir-sprite-sheet-se.png`, "player") },
53956
+ { id: "h2", position: { x: 3, y: 3 }, unitType: "scout", name: "Archivist", team: "player", health: 10, maxHealth: 10, sprite: makeAsset(`${CDN5}/sprite-sheets/archivist-sprite-sheet-se.png`, "npc") }
53916
53957
  ];
53917
53958
  DEFAULT_WORLDMAP_FEATURES = [
53918
- { id: "f1", x: 2, y: 2, type: "capital", sprite: `${CDN5}/scenes/world/capital.png` },
53919
- { id: "f2", x: 4, y: 2, type: "power_node", sprite: `${CDN5}/world-map/power_node.png` }
53959
+ { id: "f1", x: 2, y: 2, type: "capital", sprite: makeAsset(`${CDN5}/scenes/world/capital.png`, "decoration") },
53960
+ { id: "f2", x: 4, y: 2, type: "power_node", sprite: makeAsset(`${CDN5}/world-map/power_node.png`, "decoration") }
53920
53961
  ];
53921
53962
  DEFAULT_WORLDMAP_MANIFEST = {
53922
- baseUrl: CDN5,
53923
- terrains: {
53924
- grass: "/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png",
53925
- water: "/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png",
53926
- mountain: "/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png",
53927
- road: "/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png"
53928
- },
53963
+ terrains: makeAssetMap({
53964
+ grass: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`,
53965
+ water: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png`,
53966
+ mountain: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png`,
53967
+ road: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png`
53968
+ }, "tile"),
53929
53969
  units: {
53930
- hero: "/sprite-sheets/amir-sprite-sheet-se.png",
53931
- scout: "/sprite-sheets/archivist-sprite-sheet-se.png"
53970
+ hero: makeAsset(`${CDN5}/sprite-sheets/amir-sprite-sheet-se.png`, "player"),
53971
+ scout: makeAsset(`${CDN5}/sprite-sheets/archivist-sprite-sheet-se.png`, "npc")
53932
53972
  },
53933
- features: {
53934
- capital: "/scenes/world/capital.png",
53935
- power_node: "/world-map/power_node.png"
53936
- }
53973
+ features: makeAssetMap({
53974
+ capital: `${CDN5}/scenes/world/capital.png`,
53975
+ power_node: `${CDN5}/world-map/power_node.png`
53976
+ }, "decoration")
53937
53977
  };
53938
53978
  WorldMapTemplate.displayName = "WorldMapTemplate";
53939
53979
  }