@almadar/ui 5.72.0 → 5.74.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 +410 -365
  2. package/dist/avl/index.js +410 -365
  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 +425 -366
  47. package/dist/components/index.js +425 -366
  48. package/dist/providers/index.cjs +410 -365
  49. package/dist/providers/index.js +410 -365
  50. package/dist/runtime/index.cjs +410 -365
  51. package/dist/runtime/index.js +410 -365
  52. package/package.json +2 -2
@@ -6955,7 +6955,7 @@ function ScoreDisplay({
6955
6955
  assetUrl ? /* @__PURE__ */ jsx(
6956
6956
  "img",
6957
6957
  {
6958
- src: assetUrl,
6958
+ src: assetUrl.url,
6959
6959
  alt: "",
6960
6960
  width: 20,
6961
6961
  height: 20,
@@ -6980,7 +6980,11 @@ var init_ScoreDisplay = __esm({
6980
6980
  lg: "text-2xl",
6981
6981
  xl: "text-4xl"
6982
6982
  };
6983
- DEFAULT_ASSET_URL = "https://almadar-kflow-assets.web.app/shared/effects/particles/star_01.png";
6983
+ DEFAULT_ASSET_URL = {
6984
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/star_01.png",
6985
+ role: "effect",
6986
+ category: "effect"
6987
+ };
6984
6988
  ScoreDisplay.displayName = "ScoreDisplay";
6985
6989
  }
6986
6990
  });
@@ -7056,7 +7060,7 @@ function ControlButton({
7056
7060
  children: assetUrl ? /* @__PURE__ */ jsx(
7057
7061
  "img",
7058
7062
  {
7059
- src: assetUrl,
7063
+ src: assetUrl.url,
7060
7064
  alt: "",
7061
7065
  width: 24,
7062
7066
  height: 24,
@@ -7096,7 +7100,11 @@ var init_ControlButton = __esm({
7096
7100
  secondary: "bg-secondary text-secondary-foreground border-border hover:bg-secondary-hover",
7097
7101
  ghost: "bg-transparent text-foreground border-border hover:bg-muted"
7098
7102
  };
7099
- DEFAULT_ASSET_URL2 = "https://almadar-kflow-assets.web.app/shared/effects/particles/circle_01.png";
7103
+ DEFAULT_ASSET_URL2 = {
7104
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/circle_01.png",
7105
+ role: "effect",
7106
+ category: "effect"
7107
+ };
7100
7108
  ControlButton.displayName = "ControlButton";
7101
7109
  }
7102
7110
  });
@@ -7135,7 +7143,7 @@ var init_spriteAnimation = __esm({
7135
7143
  }
7136
7144
  });
7137
7145
  function Sprite({
7138
- spritesheet = "https://almadar-kflow-assets.web.app/shared/isometric-blocks/Spritesheet/allTiles_sheet.png",
7146
+ spritesheet = DEFAULT_SPRITESHEET,
7139
7147
  frameWidth = 64,
7140
7148
  frameHeight = 64,
7141
7149
  frame = 0,
@@ -7188,7 +7196,7 @@ function Sprite({
7188
7196
  position: "absolute",
7189
7197
  width: frameWidth,
7190
7198
  height: frameHeight,
7191
- backgroundImage: `url(${spritesheet})`,
7199
+ backgroundImage: `url(${spritesheet.url})`,
7192
7200
  backgroundPosition,
7193
7201
  backgroundRepeat: "no-repeat",
7194
7202
  imageRendering: "pixelated",
@@ -7201,11 +7209,17 @@ function Sprite({
7201
7209
  }
7202
7210
  );
7203
7211
  }
7212
+ var DEFAULT_SPRITESHEET;
7204
7213
  var init_Sprite = __esm({
7205
7214
  "components/game/atoms/Sprite.tsx"() {
7206
7215
  "use client";
7207
7216
  init_useEventBus();
7208
7217
  init_spriteAnimation();
7218
+ DEFAULT_SPRITESHEET = {
7219
+ url: "https://almadar-kflow-assets.web.app/shared/isometric-blocks/Spritesheet/allTiles_sheet.png",
7220
+ role: "tile",
7221
+ category: "tile"
7222
+ };
7209
7223
  }
7210
7224
  });
7211
7225
  function StateIndicator({
@@ -7235,7 +7249,7 @@ function StateIndicator({
7235
7249
  /* @__PURE__ */ jsx(Box, { as: "span", children: assetUrl ? /* @__PURE__ */ jsx(
7236
7250
  "img",
7237
7251
  {
7238
- src: assetUrl,
7252
+ src: assetUrl.url,
7239
7253
  alt: displayLabel,
7240
7254
  width: 16,
7241
7255
  height: 16,
@@ -7254,7 +7268,11 @@ var init_StateIndicator = __esm({
7254
7268
  init_Box();
7255
7269
  init_Icon();
7256
7270
  init_cn();
7257
- DEFAULT_ASSET_URL3 = "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png";
7271
+ DEFAULT_ASSET_URL3 = {
7272
+ url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
7273
+ role: "effect",
7274
+ category: "item"
7275
+ };
7258
7276
  DEFAULT_STATE_STYLES = {
7259
7277
  idle: { icon: "\u23F8", bgClass: "bg-muted" },
7260
7278
  active: { icon: "\u25B6", bgClass: "bg-success" },
@@ -7352,7 +7370,7 @@ function ResourceCounter({
7352
7370
  assetUrl ? /* @__PURE__ */ jsx(
7353
7371
  "img",
7354
7372
  {
7355
- src: assetUrl,
7373
+ src: assetUrl.url,
7356
7374
  alt: label,
7357
7375
  width: sizes.img,
7358
7376
  height: sizes.img,
@@ -7385,7 +7403,11 @@ var init_ResourceCounter = __esm({
7385
7403
  error: "text-error",
7386
7404
  muted: "text-muted-foreground"
7387
7405
  };
7388
- DEFAULT_ASSET_URL4 = "https://almadar-kflow-assets.web.app/shared/world-map/gold_mine.png";
7406
+ DEFAULT_ASSET_URL4 = {
7407
+ url: "https://almadar-kflow-assets.web.app/shared/world-map/gold_mine.png",
7408
+ role: "effect",
7409
+ category: "world"
7410
+ };
7389
7411
  sizeMap5 = {
7390
7412
  sm: { wrapper: "text-xs gap-1 px-1.5 py-0.5", icon: "text-sm", img: 16 },
7391
7413
  md: { wrapper: "text-sm gap-1.5 px-2 py-1", icon: "text-base", img: 20 },
@@ -7431,7 +7453,7 @@ function ItemSlot({
7431
7453
  assetUrl ? /* @__PURE__ */ jsx(
7432
7454
  "img",
7433
7455
  {
7434
- src: assetUrl,
7456
+ src: assetUrl?.url,
7435
7457
  alt: label,
7436
7458
  width: px,
7437
7459
  height: px,
@@ -7479,7 +7501,11 @@ var init_ItemSlot = __esm({
7479
7501
  epic: "shadow-lg",
7480
7502
  legendary: "shadow-lg"
7481
7503
  };
7482
- DEFAULT_ASSET_URL5 = "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png";
7504
+ DEFAULT_ASSET_URL5 = {
7505
+ url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
7506
+ role: "effect",
7507
+ category: "item"
7508
+ };
7483
7509
  assetSizeMap = {
7484
7510
  sm: 28,
7485
7511
  md: 40,
@@ -7525,7 +7551,7 @@ function TurnIndicator({
7525
7551
  assetUrl ? /* @__PURE__ */ jsx(
7526
7552
  "img",
7527
7553
  {
7528
- src: assetUrl,
7554
+ src: assetUrl.url,
7529
7555
  alt: "",
7530
7556
  width: 12,
7531
7557
  height: 12,
@@ -7548,7 +7574,11 @@ var init_TurnIndicator = __esm({
7548
7574
  md: { wrapper: "text-sm gap-2 px-3 py-1", dot: "w-2 h-2" },
7549
7575
  lg: { wrapper: "text-base gap-2.5 px-4 py-1.5", dot: "w-2.5 h-2.5" }
7550
7576
  };
7551
- DEFAULT_ASSET_URL6 = "https://almadar-kflow-assets.web.app/shared/effects/particles/symbol_01.png";
7577
+ DEFAULT_ASSET_URL6 = {
7578
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/symbol_01.png",
7579
+ role: "effect",
7580
+ category: "effect"
7581
+ };
7552
7582
  TurnIndicator.displayName = "TurnIndicator";
7553
7583
  }
7554
7584
  });
@@ -7587,7 +7617,7 @@ function ComboCounter({
7587
7617
  assetUrl && /* @__PURE__ */ jsx(
7588
7618
  "img",
7589
7619
  {
7590
- src: assetUrl,
7620
+ src: assetUrl.url,
7591
7621
  alt: "combo",
7592
7622
  width: 24,
7593
7623
  height: 24,
@@ -7613,7 +7643,11 @@ var DEFAULT_ASSET_URL7, sizeMap8;
7613
7643
  var init_ComboCounter = __esm({
7614
7644
  "components/game/atoms/ComboCounter.tsx"() {
7615
7645
  init_cn();
7616
- DEFAULT_ASSET_URL7 = "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png";
7646
+ DEFAULT_ASSET_URL7 = {
7647
+ url: "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png",
7648
+ role: "effect",
7649
+ category: "effect"
7650
+ };
7617
7651
  sizeMap8 = {
7618
7652
  sm: { combo: "text-lg", label: "text-xs", multiplier: "text-xs" },
7619
7653
  md: { combo: "text-2xl", label: "text-xs", multiplier: "text-sm" },
@@ -7733,7 +7767,7 @@ function WaypointMarker({
7733
7767
  children: completed ? checkIcon : assetUrl ? /* @__PURE__ */ jsx(
7734
7768
  "img",
7735
7769
  {
7736
- src: assetUrl,
7770
+ src: assetUrl.url,
7737
7771
  alt: label,
7738
7772
  width: sizes.img,
7739
7773
  height: sizes.img,
@@ -7762,7 +7796,11 @@ var init_WaypointMarker = __esm({
7762
7796
  "components/game/atoms/WaypointMarker.tsx"() {
7763
7797
  init_cn();
7764
7798
  init_Icon();
7765
- DEFAULT_ASSET_URL8 = "https://almadar-kflow-assets.web.app/shared/world-map/battle_marker.png";
7799
+ DEFAULT_ASSET_URL8 = {
7800
+ url: "https://almadar-kflow-assets.web.app/shared/world-map/battle_marker.png",
7801
+ role: "effect",
7802
+ category: "world"
7803
+ };
7766
7804
  sizeMap10 = {
7767
7805
  sm: { dot: "w-4 h-4", ring: "w-6 h-6", label: "text-xs mt-1", img: 12 },
7768
7806
  md: { dot: "w-6 h-6", ring: "w-8 h-8", label: "text-sm mt-1.5", img: 18 },
@@ -7803,7 +7841,7 @@ function StatusEffect({
7803
7841
  /* @__PURE__ */ jsx("span", { className: cn("flex items-center justify-center", sizes.icon), children: assetUrl ? /* @__PURE__ */ jsx(
7804
7842
  "img",
7805
7843
  {
7806
- src: assetUrl,
7844
+ src: assetUrl.url,
7807
7845
  alt: label,
7808
7846
  width: sizes.img,
7809
7847
  height: sizes.img,
@@ -7842,7 +7880,11 @@ var init_StatusEffect = __esm({
7842
7880
  "components/game/atoms/StatusEffect.tsx"() {
7843
7881
  init_cn();
7844
7882
  init_Icon();
7845
- DEFAULT_ASSET_URL9 = "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png";
7883
+ DEFAULT_ASSET_URL9 = {
7884
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png",
7885
+ role: "effect",
7886
+ category: "effect"
7887
+ };
7846
7888
  sizeMap11 = {
7847
7889
  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 },
7848
7890
  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 },
@@ -7880,7 +7922,7 @@ function DamageNumber({
7880
7922
  assetUrl && /* @__PURE__ */ jsx(
7881
7923
  "img",
7882
7924
  {
7883
- src: assetUrl,
7925
+ src: assetUrl.url,
7884
7926
  alt: "",
7885
7927
  width: 14,
7886
7928
  height: 14,
@@ -7916,14 +7958,18 @@ var init_DamageNumber = __esm({
7916
7958
  100% { opacity: 0; transform: translateY(-32px) scale(0.8); }
7917
7959
  }
7918
7960
  `;
7919
- DEFAULT_ASSET_URL10 = "https://almadar-kflow-assets.web.app/shared/effects/particles/spark_01.png";
7961
+ DEFAULT_ASSET_URL10 = {
7962
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/spark_01.png",
7963
+ role: "effect",
7964
+ category: "effect"
7965
+ };
7920
7966
  DamageNumber.displayName = "DamageNumber";
7921
7967
  }
7922
7968
  });
7923
7969
  function DialogueBubble({
7924
7970
  speaker = "Hero",
7925
7971
  text = "The dungeon awaits. Choose your path wisely.",
7926
- portrait = "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
7972
+ portrait = DEFAULT_PORTRAIT,
7927
7973
  position = "bottom",
7928
7974
  className
7929
7975
  }) {
@@ -7939,7 +7985,7 @@ function DialogueBubble({
7939
7985
  portrait && /* @__PURE__ */ jsx("div", { className: "flex-shrink-0 w-12 h-12 rounded-full overflow-hidden border-2 border-warning/60", children: /* @__PURE__ */ jsx(
7940
7986
  "img",
7941
7987
  {
7942
- src: portrait,
7988
+ src: portrait?.url,
7943
7989
  alt: speaker ?? "speaker",
7944
7990
  className: "w-full h-full object-cover"
7945
7991
  }
@@ -7952,9 +7998,15 @@ function DialogueBubble({
7952
7998
  }
7953
7999
  );
7954
8000
  }
8001
+ var DEFAULT_PORTRAIT;
7955
8002
  var init_DialogueBubble = __esm({
7956
8003
  "components/game/atoms/DialogueBubble.tsx"() {
7957
8004
  init_cn();
8005
+ DEFAULT_PORTRAIT = {
8006
+ url: "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
8007
+ role: "effect",
8008
+ category: "character"
8009
+ };
7958
8010
  DialogueBubble.displayName = "DialogueBubble";
7959
8011
  }
7960
8012
  });
@@ -7998,7 +8050,7 @@ function ChoiceButton({
7998
8050
  assetUrl ? /* @__PURE__ */ jsx(
7999
8051
  "img",
8000
8052
  {
8001
- src: assetUrl,
8053
+ src: assetUrl.url,
8002
8054
  alt: "",
8003
8055
  width: 16,
8004
8056
  height: 16,
@@ -8068,7 +8120,7 @@ function ActionButton({
8068
8120
  assetUrl ? /* @__PURE__ */ jsx(
8069
8121
  "img",
8070
8122
  {
8071
- src: assetUrl,
8123
+ src: assetUrl.url,
8072
8124
  alt: "",
8073
8125
  width: 16,
8074
8126
  height: 16,
@@ -8112,7 +8164,11 @@ var init_ActionButton = __esm({
8112
8164
  secondary: "bg-secondary text-secondary-foreground hover:bg-secondary-hover border-border",
8113
8165
  danger: "bg-error text-error-foreground hover:bg-error/90 border-error"
8114
8166
  };
8115
- DEFAULT_ASSET_URL11 = "https://almadar-kflow-assets.web.app/shared/effects/particles/slash_01.png";
8167
+ DEFAULT_ASSET_URL11 = {
8168
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/slash_01.png",
8169
+ role: "effect",
8170
+ category: "effect"
8171
+ };
8116
8172
  ActionButton.displayName = "ActionButton";
8117
8173
  }
8118
8174
  });
@@ -10699,12 +10755,7 @@ var init_useCanvasGestures = __esm({
10699
10755
  }
10700
10756
  });
10701
10757
  function unitAtlasUrl(unit) {
10702
- if (unit.spriteSheet) return unit.spriteSheet;
10703
- const sprite = unit.sprite;
10704
- if (!sprite) return null;
10705
- const match = /^(.*-sprite-sheet)(?:-(?:se|sw))?(?:-v\d+)?\.png$/.exec(sprite);
10706
- if (!match) return null;
10707
- return `${match[1]}.json`;
10758
+ return unit.spriteSheet?.url ?? null;
10708
10759
  }
10709
10760
  function resolveSheetUrl(atlasUrl, relativeSheetPath) {
10710
10761
  try {
@@ -10900,7 +10951,6 @@ function IsometricCanvas({
10900
10951
  // Tuning
10901
10952
  diamondTopY: diamondTopYProp,
10902
10953
  // Remote asset loading
10903
- assetBaseUrl,
10904
10954
  assetManifest
10905
10955
  }) {
10906
10956
  const tilesProp = Array.isArray(_tilesPropRaw) ? _tilesPropRaw : [];
@@ -10982,54 +11032,48 @@ function IsometricCanvas({
10982
11032
  const attackTargetSet = useMemo(() => {
10983
11033
  return new Set(attackTargets.map((p2) => `${p2.x},${p2.y}`));
10984
11034
  }, [attackTargets]);
10985
- const resolveManifestUrl7 = useCallback((relativePath) => {
10986
- if (!relativePath) return void 0;
10987
- if (assetBaseUrl) return `${assetBaseUrl.replace(/\/$/, "")}${relativePath.startsWith("/") ? "" : "/"}${relativePath}`;
10988
- return relativePath;
10989
- }, [assetBaseUrl]);
10990
11035
  const spriteUrls = useMemo(() => {
10991
11036
  const urls = [];
10992
11037
  for (const tile of sortedTiles) {
10993
- if (tile.terrainSprite) urls.push(tile.terrainSprite);
11038
+ if (tile.terrainSprite) urls.push(tile.terrainSprite.url);
10994
11039
  else if (getTerrainSprite) {
10995
11040
  const url = getTerrainSprite(tile.terrain ?? "");
10996
11041
  if (url) urls.push(url);
10997
11042
  } else {
10998
- const url = resolveManifestUrl7(assetManifest?.terrains?.[tile.terrain ?? ""]);
11043
+ const url = assetManifest?.terrains?.[tile.terrain ?? ""]?.url;
10999
11044
  if (url) urls.push(url);
11000
11045
  }
11001
11046
  }
11002
11047
  for (const feature of features) {
11003
- if (feature.sprite) urls.push(feature.sprite);
11048
+ if (feature.sprite) urls.push(feature.sprite.url);
11004
11049
  else if (getFeatureSprite) {
11005
11050
  const url = getFeatureSprite(feature.type);
11006
11051
  if (url) urls.push(url);
11007
11052
  } else {
11008
- const url = resolveManifestUrl7(assetManifest?.features?.[feature.type]);
11053
+ const url = assetManifest?.features?.[feature.type]?.url;
11009
11054
  if (url) urls.push(url);
11010
11055
  }
11011
11056
  }
11012
11057
  for (const unit of units) {
11013
- if (unit.sprite) urls.push(unit.sprite);
11058
+ if (unit.sprite) urls.push(unit.sprite.url);
11014
11059
  else if (getUnitSprite) {
11015
11060
  const url = getUnitSprite(unit);
11016
11061
  if (url) urls.push(url);
11017
11062
  } else if (unit.unitType) {
11018
- const url = resolveManifestUrl7(assetManifest?.units?.[unit.unitType]);
11063
+ const url = assetManifest?.units?.[unit.unitType]?.url;
11019
11064
  if (url) urls.push(url);
11020
11065
  }
11021
11066
  }
11022
11067
  if (assetManifest?.effects) {
11023
- for (const path of Object.values(assetManifest.effects)) {
11024
- const url = resolveManifestUrl7(path);
11025
- if (url) urls.push(url);
11068
+ for (const asset of Object.values(assetManifest.effects)) {
11069
+ if (asset.url) urls.push(asset.url);
11026
11070
  }
11027
11071
  }
11028
11072
  if (effectSpriteUrls) urls.push(...effectSpriteUrls);
11029
11073
  if (atlasSheetUrls.length) urls.push(...atlasSheetUrls);
11030
11074
  if (backgroundImage) urls.push(backgroundImage);
11031
11075
  return [...new Set(urls.filter(Boolean))];
11032
- }, [sortedTiles, features, units, getTerrainSprite, getFeatureSprite, getUnitSprite, effectSpriteUrls, atlasSheetUrls, backgroundImage, assetManifest, resolveManifestUrl7]);
11076
+ }, [sortedTiles, features, units, getTerrainSprite, getFeatureSprite, getUnitSprite, effectSpriteUrls, atlasSheetUrls, backgroundImage, assetManifest]);
11033
11077
  const { getImage, pendingCount: _imagePendingCount } = useImageCache(spriteUrls);
11034
11078
  useEffect(() => {
11035
11079
  if (typeof window === "undefined") return;
@@ -11054,14 +11098,14 @@ function IsometricCanvas({
11054
11098
  lerpToTarget
11055
11099
  } = useCamera();
11056
11100
  const resolveTerrainSpriteUrl = useCallback((tile) => {
11057
- return tile.terrainSprite || getTerrainSprite?.(tile.terrain ?? "") || resolveManifestUrl7(assetManifest?.terrains?.[tile.terrain ?? ""]);
11058
- }, [getTerrainSprite, assetManifest, resolveManifestUrl7]);
11101
+ return tile.terrainSprite?.url || getTerrainSprite?.(tile.terrain ?? "") || assetManifest?.terrains?.[tile.terrain ?? ""]?.url;
11102
+ }, [getTerrainSprite, assetManifest]);
11059
11103
  const resolveFeatureSpriteUrl = useCallback((featureType) => {
11060
- return getFeatureSprite?.(featureType) || resolveManifestUrl7(assetManifest?.features?.[featureType]);
11061
- }, [getFeatureSprite, assetManifest, resolveManifestUrl7]);
11104
+ return getFeatureSprite?.(featureType) || assetManifest?.features?.[featureType]?.url;
11105
+ }, [getFeatureSprite, assetManifest]);
11062
11106
  const resolveUnitSpriteUrl = useCallback((unit) => {
11063
- return unit.sprite || getUnitSprite?.(unit) || (unit.unitType ? resolveManifestUrl7(assetManifest?.units?.[unit.unitType]) : void 0);
11064
- }, [getUnitSprite, assetManifest, resolveManifestUrl7]);
11107
+ return unit.sprite?.url || getUnitSprite?.(unit) || (unit.unitType ? assetManifest?.units?.[unit.unitType]?.url : void 0);
11108
+ }, [getUnitSprite, assetManifest]);
11065
11109
  const miniMapTiles = useMemo(() => {
11066
11110
  if (!showMinimap) return [];
11067
11111
  return sortedTiles.map((t2) => ({
@@ -11208,7 +11252,7 @@ function IsometricCanvas({
11208
11252
  if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
11209
11253
  continue;
11210
11254
  }
11211
- const spriteUrl = feature.sprite || resolveFeatureSpriteUrl(feature.type);
11255
+ const spriteUrl = feature.sprite?.url || resolveFeatureSpriteUrl(feature.type);
11212
11256
  const img = spriteUrl ? getImage(spriteUrl) : null;
11213
11257
  const centerX = pos.x + scaledTileWidth / 2;
11214
11258
  const featureGroundY = pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
@@ -11257,12 +11301,12 @@ function IsometricCanvas({
11257
11301
  const img = unitSpriteUrl ? getImage(unitSpriteUrl) : null;
11258
11302
  const unitDrawH = scaledFloorHeight * spriteHeightRatio * unitScale;
11259
11303
  const maxUnitW = scaledTileWidth * spriteMaxWidthRatio * unitScale;
11304
+ const unitIsSheet = unit.sprite?.dimension === "2d" && (unit.sprite?.animations?.length ?? 0) > 0;
11260
11305
  const SHEET_ROWS = 5;
11261
11306
  const sheetFrameW = img ? img.naturalWidth / SHEET_COLUMNS : 0;
11262
11307
  const sheetFrameH = img ? img.naturalHeight / SHEET_ROWS : 0;
11263
- const imgIsSheet = img ? img.naturalWidth % SHEET_COLUMNS === 0 && img.naturalHeight % SHEET_ROWS === 0 && Math.abs(sheetFrameW - sheetFrameH) < 2 : false;
11264
- const frameW = imgIsSheet ? sheetFrameW : img?.naturalWidth ?? 1;
11265
- const frameH = imgIsSheet ? sheetFrameH : img?.naturalHeight ?? 1;
11308
+ const frameW = unitIsSheet ? sheetFrameW : img?.naturalWidth ?? 1;
11309
+ const frameH = unitIsSheet ? sheetFrameH : img?.naturalHeight ?? 1;
11266
11310
  const ar = frameW / (frameH || 1);
11267
11311
  let drawH = unitDrawH;
11268
11312
  let drawW = unitDrawH * ar;
@@ -11277,7 +11321,7 @@ function IsometricCanvas({
11277
11321
  ctx.save();
11278
11322
  ctx.globalAlpha = 0.25;
11279
11323
  if (img) {
11280
- if (imgIsSheet) {
11324
+ if (unitIsSheet) {
11281
11325
  ctx.drawImage(img, 0, 0, sheetFrameW, sheetFrameH, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
11282
11326
  } else {
11283
11327
  ctx.drawImage(img, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
@@ -11325,7 +11369,7 @@ function IsometricCanvas({
11325
11369
  } else if (img) {
11326
11370
  const spriteY = groundY - drawH - breatheOffset;
11327
11371
  const drawUnit = (x) => {
11328
- if (imgIsSheet) {
11372
+ if (unitIsSheet) {
11329
11373
  ctx.drawImage(img, 0, 0, sheetFrameW, sheetFrameH, x, spriteY, drawW, drawH);
11330
11374
  } else {
11331
11375
  ctx.drawImage(img, x, spriteY, drawW, drawH);
@@ -11352,7 +11396,7 @@ function IsometricCanvas({
11352
11396
  }
11353
11397
  }
11354
11398
  for (const fx of effects) {
11355
- const spriteUrl = resolveManifestUrl7(assetManifest?.effects?.[fx.key]);
11399
+ const spriteUrl = assetManifest?.effects?.[fx.key]?.url;
11356
11400
  if (!spriteUrl) continue;
11357
11401
  const img = getImage(spriteUrl);
11358
11402
  if (!img) continue;
@@ -11396,7 +11440,6 @@ function IsometricCanvas({
11396
11440
  backgroundImage,
11397
11441
  cameraRef,
11398
11442
  unitScale,
11399
- resolveManifestUrl7,
11400
11443
  assetManifest
11401
11444
  ]);
11402
11445
  useEffect(() => {
@@ -11674,6 +11717,42 @@ var init_boardEntity = __esm({
11674
11717
  "components/game/organisms/boardEntity.ts"() {
11675
11718
  }
11676
11719
  });
11720
+
11721
+ // components/game/organisms/utils/makeAsset.ts
11722
+ function makeAsset(url, role, overrides = {}) {
11723
+ const defaults = ROLE_DEFAULTS[role] ?? { dimension: "2d", animations: ["static"], aspect: "1:1" };
11724
+ return {
11725
+ url,
11726
+ role,
11727
+ category: url.split("/").pop()?.replace(/\.[^.]+$/, "") ?? role,
11728
+ ...defaults,
11729
+ ...overrides
11730
+ };
11731
+ }
11732
+ function makeAssetMap(record, role, overrides = {}) {
11733
+ const result = {};
11734
+ for (const [key, url] of Object.entries(record)) {
11735
+ result[key] = makeAsset(url, role, overrides);
11736
+ }
11737
+ return result;
11738
+ }
11739
+ var ROLE_DEFAULTS;
11740
+ var init_makeAsset = __esm({
11741
+ "components/game/organisms/utils/makeAsset.ts"() {
11742
+ ROLE_DEFAULTS = {
11743
+ tile: { dimension: "2d", animations: ["static"], aspect: "1:1" },
11744
+ decoration: { dimension: "2d", animations: ["static"], aspect: "1:1" },
11745
+ effect: { dimension: "2d", animations: ["static"], aspect: "1:1" },
11746
+ item: { dimension: "2d", animations: ["static"], aspect: "5:7" },
11747
+ player: { dimension: "2d", animations: ["idle", "walk", "attack", "hit", "death"], aspect: "1:1" },
11748
+ enemy: { dimension: "2d", animations: ["idle", "walk", "attack", "hit", "death"], aspect: "1:1" },
11749
+ npc: { dimension: "2d", animations: ["idle", "walk", "attack", "hit", "death"], aspect: "1:1" },
11750
+ projectile: { dimension: "2d", animations: ["static"], aspect: "1:1" },
11751
+ vehicle: { dimension: "2d", animations: ["idle", "walk"], aspect: "1:1" },
11752
+ ui: { dimension: "2d", animations: ["static"], aspect: "1:1" }
11753
+ };
11754
+ }
11755
+ });
11677
11756
  function buildDefaultBattleTiles() {
11678
11757
  const tiles = [];
11679
11758
  for (let y = 0; y < BATTLE_GRID_H; y++) {
@@ -11732,14 +11811,14 @@ function BattleBoard({
11732
11811
  if (o === null || typeof o.x !== "number" || typeof o.y !== "number") return [];
11733
11812
  const tile = { x: o.x, y: o.y };
11734
11813
  if (typeof o.terrain === "string") tile.terrain = o.terrain;
11735
- if (typeof o.terrainSprite === "string") tile.terrainSprite = o.terrainSprite;
11814
+ if (typeof o.terrainSprite === "string") tile.terrainSprite = makeAsset(o.terrainSprite, "tile");
11736
11815
  if (typeof o.passable === "boolean") tile.passable = o.passable;
11737
11816
  if (typeof o.movementCost === "number") tile.movementCost = o.movementCost;
11738
11817
  if (typeof o.elevation === "number") tile.elevation = o.elevation;
11739
11818
  if (typeof o.type === "string") tile.type = o.type;
11740
11819
  if (typeof o.tileType === "string") tile.tileType = o.tileType;
11741
11820
  if (typeof o.id === "string") tile.id = o.id;
11742
- if (typeof o.modelUrl === "string") tile.modelUrl = o.modelUrl;
11821
+ if (typeof o.modelUrl === "string") tile.modelUrl = makeAsset(o.modelUrl, "decoration", { dimension: "3d" });
11743
11822
  return [tile];
11744
11823
  }) : []);
11745
11824
  const tiles = rawTiles.length === 0 ? DEFAULT_BATTLE_TILES : rawTiles;
@@ -11748,10 +11827,10 @@ function BattleBoard({
11748
11827
  if (o === null || typeof o.type !== "string" || typeof o.x !== "number" || typeof o.y !== "number") return [];
11749
11828
  const feat = { type: o.type, x: o.x, y: o.y };
11750
11829
  if (typeof o.id === "string") feat.id = o.id;
11751
- if (typeof o.sprite === "string") feat.sprite = o.sprite;
11830
+ if (typeof o.sprite === "string") feat.sprite = makeAsset(o.sprite, "decoration");
11752
11831
  if (typeof o.color === "string") feat.color = o.color;
11753
11832
  if (typeof o.elevation === "number") feat.elevation = o.elevation;
11754
- if (typeof o.assetUrl === "string") feat.assetUrl = o.assetUrl;
11833
+ if (typeof o.assetUrl === "string") feat.assetUrl = makeAsset(o.assetUrl, "decoration", { dimension: "3d" });
11755
11834
  return [feat];
11756
11835
  }) : []);
11757
11836
  const boardWidth = num(board.gridWidth ?? board.boardWidth, BATTLE_GRID_W);
@@ -11867,7 +11946,7 @@ function BattleBoard({
11867
11946
  maxHealth: num(unit.maxHealth),
11868
11947
  unitType: unit.unitType == null ? void 0 : str(unit.unitType),
11869
11948
  heroId: unit.heroId == null ? void 0 : str(unit.heroId),
11870
- sprite: unit.sprite == null ? void 0 : str(unit.sprite),
11949
+ sprite: unit.sprite == null ? void 0 : makeAsset(str(unit.sprite), "npc"),
11871
11950
  traits: unitTraits?.map((tr) => ({
11872
11951
  name: tr.name,
11873
11952
  currentState: tr.currentState,
@@ -12017,7 +12096,6 @@ function BattleBoard({
12017
12096
  onTileHover: (x, y) => setHoveredTile({ x, y }),
12018
12097
  onTileLeave: () => setHoveredTile(null),
12019
12098
  scale,
12020
- assetBaseUrl: assetManifest?.baseUrl,
12021
12099
  assetManifest,
12022
12100
  backgroundImage,
12023
12101
  onDrawEffects,
@@ -12095,15 +12173,16 @@ var init_BattleBoard = __esm({
12095
12173
  init_IsometricCanvas();
12096
12174
  init_boardEntity();
12097
12175
  init_isometric();
12176
+ init_makeAsset();
12098
12177
  BATTLE_CDN = "https://almadar-kflow-assets.web.app/shared";
12099
12178
  BATTLE_GRID_W = 16;
12100
12179
  BATTLE_GRID_H = 16;
12101
12180
  BATTLE_TERRAIN_SPRITES = [
12102
- `${BATTLE_CDN}/isometric-dungeon/Isometric/dirt_E.png`,
12103
- `${BATTLE_CDN}/isometric-dungeon/Isometric/dirtTiles_E.png`,
12104
- `${BATTLE_CDN}/isometric-dungeon/Isometric/planks_E.png`,
12105
- `${BATTLE_CDN}/isometric-dungeon/Isometric/stoneTile_E.png`,
12106
- `${BATTLE_CDN}/isometric-dungeon/Isometric/stoneInset_E.png`
12181
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/dirt_E.png`, "tile"),
12182
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/dirtTiles_E.png`, "tile"),
12183
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/planks_E.png`, "tile"),
12184
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/stoneTile_E.png`, "tile"),
12185
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/stoneInset_E.png`, "tile")
12107
12186
  ];
12108
12187
  DEFAULT_BATTLE_TILES = buildDefaultBattleTiles();
12109
12188
  BattleBoard.displayName = "BattleBoard";
@@ -12142,61 +12221,64 @@ function BattleTemplate({
12142
12221
  }
12143
12222
  );
12144
12223
  }
12145
- var CDN, DEFAULT_BATTLE_TILES2, DEFAULT_BATTLE_UNITS, DEFAULT_BATTLE_FEATURES, DEFAULT_BATTLE_MANIFEST;
12224
+ var CDN, STONE, DIRT, GRASS, DEFAULT_BATTLE_TILES2, DEFAULT_BATTLE_UNITS, DEFAULT_BATTLE_FEATURES, DEFAULT_BATTLE_MANIFEST;
12146
12225
  var init_BattleTemplate = __esm({
12147
12226
  "components/game/templates/BattleTemplate.tsx"() {
12148
12227
  init_BattleBoard();
12228
+ init_makeAsset();
12149
12229
  CDN = "https://almadar-kflow-assets.web.app/shared";
12230
+ STONE = makeAsset(`${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png`, "tile");
12231
+ DIRT = makeAsset(`${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png`, "tile");
12232
+ GRASS = makeAsset(`${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png`, "tile");
12150
12233
  DEFAULT_BATTLE_TILES2 = [
12151
- { x: 0, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12152
- { x: 1, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12153
- { x: 2, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12154
- { x: 3, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12155
- { x: 4, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12156
- { x: 0, y: 1, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12157
- { x: 1, y: 1, terrain: "dirt", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png` },
12158
- { x: 2, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12159
- { x: 3, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12160
- { x: 4, y: 1, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12161
- { x: 0, y: 2, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12162
- { x: 1, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12163
- { x: 2, y: 2, terrain: "dirt", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png` },
12164
- { x: 3, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12165
- { x: 4, y: 2, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12166
- { x: 0, y: 3, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12167
- { x: 1, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12168
- { x: 2, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12169
- { x: 3, y: 3, terrain: "dirt", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png` },
12170
- { x: 4, y: 3, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12171
- { x: 0, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12172
- { x: 1, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12173
- { x: 2, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12174
- { x: 3, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12175
- { x: 4, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` }
12234
+ { x: 0, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12235
+ { x: 1, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12236
+ { x: 2, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12237
+ { x: 3, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12238
+ { x: 4, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12239
+ { x: 0, y: 1, terrain: "stone", passable: false, terrainSprite: STONE },
12240
+ { x: 1, y: 1, terrain: "dirt", passable: true, terrainSprite: DIRT },
12241
+ { x: 2, y: 1, terrain: "grass", passable: true, terrainSprite: GRASS },
12242
+ { x: 3, y: 1, terrain: "grass", passable: true, terrainSprite: GRASS },
12243
+ { x: 4, y: 1, terrain: "stone", passable: false, terrainSprite: STONE },
12244
+ { x: 0, y: 2, terrain: "stone", passable: false, terrainSprite: STONE },
12245
+ { x: 1, y: 2, terrain: "grass", passable: true, terrainSprite: GRASS },
12246
+ { x: 2, y: 2, terrain: "dirt", passable: true, terrainSprite: DIRT },
12247
+ { x: 3, y: 2, terrain: "grass", passable: true, terrainSprite: GRASS },
12248
+ { x: 4, y: 2, terrain: "stone", passable: false, terrainSprite: STONE },
12249
+ { x: 0, y: 3, terrain: "stone", passable: false, terrainSprite: STONE },
12250
+ { x: 1, y: 3, terrain: "grass", passable: true, terrainSprite: GRASS },
12251
+ { x: 2, y: 3, terrain: "grass", passable: true, terrainSprite: GRASS },
12252
+ { x: 3, y: 3, terrain: "dirt", passable: true, terrainSprite: DIRT },
12253
+ { x: 4, y: 3, terrain: "stone", passable: false, terrainSprite: STONE },
12254
+ { x: 0, y: 4, terrain: "stone", passable: false, terrainSprite: STONE },
12255
+ { x: 1, y: 4, terrain: "stone", passable: false, terrainSprite: STONE },
12256
+ { x: 2, y: 4, terrain: "stone", passable: false, terrainSprite: STONE },
12257
+ { x: 3, y: 4, terrain: "stone", passable: false, terrainSprite: STONE },
12258
+ { x: 4, y: 4, terrain: "stone", passable: false, terrainSprite: STONE }
12176
12259
  ];
12177
12260
  DEFAULT_BATTLE_UNITS = [
12178
- { 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` },
12179
- { 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` }
12261
+ { 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") },
12262
+ { 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") }
12180
12263
  ];
12181
12264
  DEFAULT_BATTLE_FEATURES = [
12182
- { id: "f1", x: 2, y: 2, type: "gold_mine", sprite: `${CDN}/world-map/gold_mine.png` },
12183
- { id: "f2", x: 3, y: 1, type: "portal", sprite: `${CDN}/world-map/portal_open.png` }
12265
+ { id: "f1", x: 2, y: 2, type: "gold_mine", sprite: makeAsset(`${CDN}/world-map/gold_mine.png`, "decoration") },
12266
+ { id: "f2", x: 3, y: 1, type: "portal", sprite: makeAsset(`${CDN}/world-map/portal_open.png`, "decoration") }
12184
12267
  ];
12185
12268
  DEFAULT_BATTLE_MANIFEST = {
12186
- baseUrl: CDN,
12187
- terrains: {
12188
- stone: "/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png",
12189
- dirt: "/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png",
12190
- grass: "/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png"
12191
- },
12192
- units: {
12193
- worker: "/sprite-sheets/amir-sprite-sheet-se.png",
12194
- guardian: "/sprite-sheets/destroyer-sprite-sheet-sw.png"
12195
- },
12196
- features: {
12197
- gold_mine: "/world-map/gold_mine.png",
12198
- portal: "/world-map/portal_open.png"
12199
- }
12269
+ terrains: makeAssetMap({
12270
+ stone: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png`,
12271
+ dirt: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png`,
12272
+ grass: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png`
12273
+ }, "tile"),
12274
+ units: makeAssetMap({
12275
+ worker: `${CDN}/sprite-sheets/amir-sprite-sheet-se.png`,
12276
+ guardian: `${CDN}/sprite-sheets/destroyer-sprite-sheet-sw.png`
12277
+ }, "npc"),
12278
+ features: makeAssetMap({
12279
+ gold_mine: `${CDN}/world-map/gold_mine.png`,
12280
+ portal: `${CDN}/world-map/portal_open.png`
12281
+ }, "decoration")
12200
12282
  };
12201
12283
  BattleTemplate.displayName = "BattleTemplate";
12202
12284
  }
@@ -14411,7 +14493,6 @@ function BoardgameBoard({
14411
14493
  units,
14412
14494
  features,
14413
14495
  assetManifest,
14414
- assetBaseUrl,
14415
14496
  scale,
14416
14497
  showMinimap,
14417
14498
  enableCamera,
@@ -19481,7 +19562,7 @@ function CardHand({
19481
19562
  /* @__PURE__ */ jsx(Box, { className: "flex-1 flex items-center justify-center w-full", children: card.iconUrl ? /* @__PURE__ */ jsx(
19482
19563
  "img",
19483
19564
  {
19484
- src: card.iconUrl,
19565
+ src: card.iconUrl.url,
19485
19566
  alt: card.title ?? card.id,
19486
19567
  width: art,
19487
19568
  height: art,
@@ -19539,15 +19620,6 @@ var init_CardHand = __esm({
19539
19620
  CardHand.displayName = "CardHand";
19540
19621
  }
19541
19622
  });
19542
- function resolveManifestUrl(manifest, relative) {
19543
- if (relative == null) return void 0;
19544
- if (/^https?:\/\//.test(relative)) return relative;
19545
- const base = manifest?.baseUrl;
19546
- if (base == null) return relative;
19547
- const cleanBase = base.replace(/\/$/, "");
19548
- const cleanRel = relative.replace(/^\//, "");
19549
- return `${cleanBase}/${cleanRel}`;
19550
- }
19551
19623
  function rowToCard(r) {
19552
19624
  return {
19553
19625
  id: str(r.id),
@@ -19561,7 +19633,7 @@ function rowToCard(r) {
19561
19633
  function toHandCards(cards, manifest, mana) {
19562
19634
  return cards.map((c) => {
19563
19635
  const key = c.iconKey ?? c.id;
19564
- const iconUrl = resolveManifestUrl(manifest, manifest?.cards?.[key]);
19636
+ const iconUrl = manifest?.cards?.[key];
19565
19637
  return {
19566
19638
  id: c.id,
19567
19639
  iconUrl,
@@ -20675,7 +20747,6 @@ function CastleBoard({
20675
20747
  onTileHover: (x, y) => setHoveredTile({ x, y }),
20676
20748
  onTileLeave: () => setHoveredTile(null),
20677
20749
  scale,
20678
- assetBaseUrl: assetManifest?.baseUrl,
20679
20750
  assetManifest,
20680
20751
  backgroundImage
20681
20752
  }
@@ -20751,60 +20822,63 @@ function CastleTemplate({
20751
20822
  }
20752
20823
  );
20753
20824
  }
20754
- var CDN2, DEFAULT_CASTLE_TILES, DEFAULT_CASTLE_UNITS, DEFAULT_CASTLE_FEATURES, DEFAULT_CASTLE_MANIFEST;
20825
+ var CDN2, WALL, FLOOR, FLOOR_CENTER, DEFAULT_CASTLE_TILES, DEFAULT_CASTLE_UNITS, DEFAULT_CASTLE_FEATURES, DEFAULT_CASTLE_MANIFEST;
20755
20826
  var init_CastleTemplate = __esm({
20756
20827
  "components/game/templates/CastleTemplate.tsx"() {
20757
20828
  init_CastleBoard();
20829
+ init_makeAsset();
20758
20830
  CDN2 = "https://almadar-kflow-assets.web.app/shared";
20831
+ WALL = makeAsset(`${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png`, "tile");
20832
+ FLOOR = makeAsset(`${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`, "tile");
20833
+ FLOOR_CENTER = makeAsset(`${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_09.png`, "tile");
20759
20834
  DEFAULT_CASTLE_TILES = [
20760
- { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20761
- { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20762
- { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20763
- { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20764
- { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20765
- { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20766
- { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20767
- { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20768
- { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20769
- { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20770
- { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20771
- { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20772
- { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_09.png` },
20773
- { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20774
- { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20775
- { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20776
- { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20777
- { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20778
- { x: 3, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20779
- { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20780
- { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20781
- { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20782
- { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20783
- { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20784
- { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` }
20835
+ { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
20836
+ { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
20837
+ { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
20838
+ { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
20839
+ { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
20840
+ { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: WALL },
20841
+ { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: FLOOR },
20842
+ { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: FLOOR },
20843
+ { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: FLOOR },
20844
+ { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: WALL },
20845
+ { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: WALL },
20846
+ { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: FLOOR },
20847
+ { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: FLOOR_CENTER },
20848
+ { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: FLOOR },
20849
+ { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: WALL },
20850
+ { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: WALL },
20851
+ { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: FLOOR },
20852
+ { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: FLOOR },
20853
+ { x: 3, y: 3, terrain: "floor", passable: true, terrainSprite: FLOOR },
20854
+ { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: WALL },
20855
+ { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: WALL },
20856
+ { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: WALL },
20857
+ { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: WALL },
20858
+ { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: WALL },
20859
+ { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: WALL }
20785
20860
  ];
20786
20861
  DEFAULT_CASTLE_UNITS = [
20787
- { 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` },
20788
- { 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` }
20862
+ { 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") },
20863
+ { 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") }
20789
20864
  ];
20790
20865
  DEFAULT_CASTLE_FEATURES = [
20791
- { id: "f1", x: 2, y: 2, type: "chest", sprite: `${CDN2}/world-map/treasure_chest_closed.png` },
20792
- { id: "f2", x: 3, y: 1, type: "crystal", sprite: `${CDN2}/world-map/resonance_crystal.png` }
20866
+ { id: "f1", x: 2, y: 2, type: "chest", sprite: makeAsset(`${CDN2}/world-map/treasure_chest_closed.png`, "decoration") },
20867
+ { id: "f2", x: 3, y: 1, type: "crystal", sprite: makeAsset(`${CDN2}/world-map/resonance_crystal.png`, "decoration") }
20793
20868
  ];
20794
20869
  DEFAULT_CASTLE_MANIFEST = {
20795
- baseUrl: CDN2,
20796
- terrains: {
20797
- wall: "/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png",
20798
- floor: "/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png"
20799
- },
20800
- units: {
20801
- worker: "/sprite-sheets/coordinator-sprite-sheet-se.png",
20802
- guardian: "/sprite-sheets/forger-sprite-sheet-se.png"
20803
- },
20804
- features: {
20805
- chest: "/world-map/treasure_chest_closed.png",
20806
- crystal: "/world-map/resonance_crystal.png"
20807
- }
20870
+ terrains: makeAssetMap({
20871
+ wall: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png`,
20872
+ floor: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`
20873
+ }, "tile"),
20874
+ units: makeAssetMap({
20875
+ worker: `${CDN2}/sprite-sheets/coordinator-sprite-sheet-se.png`,
20876
+ guardian: `${CDN2}/sprite-sheets/forger-sprite-sheet-se.png`
20877
+ }, "player"),
20878
+ features: makeAssetMap({
20879
+ chest: `${CDN2}/world-map/treasure_chest_closed.png`,
20880
+ crystal: `${CDN2}/world-map/resonance_crystal.png`
20881
+ }, "decoration")
20808
20882
  };
20809
20883
  CastleTemplate.displayName = "CastleTemplate";
20810
20884
  }
@@ -21792,15 +21866,6 @@ var init_ChatBar = __esm({
21792
21866
  ChatBar.displayName = "ChatBar";
21793
21867
  }
21794
21868
  });
21795
- function resolveManifestUrl2(manifest, relative) {
21796
- if (relative == null) return void 0;
21797
- if (/^https?:\/\//.test(relative)) return relative;
21798
- const base = manifest?.baseUrl;
21799
- if (base == null) return relative;
21800
- const cleanBase = base.replace(/\/$/, "");
21801
- const cleanRel = relative.replace(/^\//, "");
21802
- return `${cleanBase}/${cleanRel}`;
21803
- }
21804
21869
  function buildDefaultCBTiles() {
21805
21870
  const tiles = [];
21806
21871
  for (let y = 0; y < CB_GRID_H; y++) {
@@ -21815,12 +21880,12 @@ function buildDefaultCBTiles() {
21815
21880
  function tilesToIso(tiles, manifest) {
21816
21881
  return tiles.map((t) => {
21817
21882
  const key = t.terrain ?? "grass";
21818
- const sprite = t.terrainSprite ?? resolveManifestUrl2(manifest, manifest?.terrains?.[key]) ?? resolveManifestUrl2(manifest, manifest?.terrains?.grass);
21883
+ const terrainSprite = t.terrainSprite ?? manifest?.terrains?.[key] ?? manifest?.terrains?.grass;
21819
21884
  return {
21820
21885
  x: t.x,
21821
21886
  y: t.y,
21822
21887
  terrain: t.terrain,
21823
- terrainSprite: sprite,
21888
+ terrainSprite,
21824
21889
  passable: t.passable
21825
21890
  };
21826
21891
  });
@@ -21831,7 +21896,7 @@ function buildingsToFeatures(buildings, manifest) {
21831
21896
  x: b.x,
21832
21897
  y: b.y,
21833
21898
  type: b.type,
21834
- sprite: resolveManifestUrl2(manifest, manifest?.features?.[b.type])
21899
+ sprite: manifest?.features?.[b.type]
21835
21900
  }));
21836
21901
  }
21837
21902
  function CityBuilderBoard({
@@ -21863,7 +21928,7 @@ function CityBuilderBoard({
21863
21928
  x: num(r.x),
21864
21929
  y: num(r.y),
21865
21930
  terrain: r.terrain == null ? void 0 : str(r.terrain),
21866
- terrainSprite: r.terrainSprite == null ? void 0 : str(r.terrainSprite),
21931
+ terrainSprite: r.terrainSprite == null ? void 0 : makeAsset(str(r.terrainSprite), "tile"),
21867
21932
  passable: r.passable !== false
21868
21933
  })),
21869
21934
  [board.tiles]
@@ -21972,7 +22037,6 @@ function CityBuilderBoard({
21972
22037
  {
21973
22038
  tiles: isoTiles,
21974
22039
  features: buildingFeatures,
21975
- assetBaseUrl: assetManifest?.baseUrl,
21976
22040
  assetManifest,
21977
22041
  validMoves,
21978
22042
  hoveredTile,
@@ -22007,6 +22071,7 @@ var CB_GRID_W, CB_GRID_H, DEFAULT_BUILD_TYPES, DEFAULT_CB_TILES;
22007
22071
  var init_CityBuilderBoard = __esm({
22008
22072
  "components/game/organisms/CityBuilderBoard.tsx"() {
22009
22073
  "use client";
22074
+ init_makeAsset();
22010
22075
  init_cn();
22011
22076
  init_useEventBus();
22012
22077
  init_Box();
@@ -28001,7 +28066,7 @@ function StatBadge({
28001
28066
  resolvedAsset ? /* @__PURE__ */ jsx(
28002
28067
  "img",
28003
28068
  {
28004
- src: resolvedAsset,
28069
+ src: resolvedAsset.url,
28005
28070
  alt: "",
28006
28071
  width: 16,
28007
28072
  height: 16,
@@ -28308,7 +28373,7 @@ function GameCanvas2D({
28308
28373
  tickEvent,
28309
28374
  drawEvent,
28310
28375
  fps = 60,
28311
- backgroundImage = "",
28376
+ backgroundImage,
28312
28377
  assetBaseUrl,
28313
28378
  className
28314
28379
  }) {
@@ -28372,7 +28437,7 @@ function GameCanvas2D({
28372
28437
  emitRef.current(tickEventRef.current, { dt, frame });
28373
28438
  }
28374
28439
  if (backgroundImageRef.current) {
28375
- const bgImg = loadImage(backgroundImageRef.current);
28440
+ const bgImg = loadImage(backgroundImageRef.current.url);
28376
28441
  if (bgImg) {
28377
28442
  ctx.drawImage(bgImg, 0, 0, widthRef.current, heightRef.current);
28378
28443
  } else {
@@ -28743,7 +28808,7 @@ function EnemyPlate({
28743
28808
  assetUrl && /* @__PURE__ */ jsx(
28744
28809
  "img",
28745
28810
  {
28746
- src: assetUrl,
28811
+ src: assetUrl.url,
28747
28812
  alt: name,
28748
28813
  width: 24,
28749
28814
  height: 24,
@@ -29085,7 +29150,7 @@ function DialogueBox({
29085
29150
  "div",
29086
29151
  {
29087
29152
  className: "fixed inset-0 z-20 bg-center bg-cover bg-no-repeat",
29088
- style: { backgroundImage: `url(${backgroundImage})` },
29153
+ style: { backgroundImage: `url(${backgroundImage?.url})` },
29089
29154
  "aria-hidden": "true"
29090
29155
  }
29091
29156
  ),
@@ -29100,7 +29165,7 @@ function DialogueBox({
29100
29165
  children: /* @__PURE__ */ jsx(
29101
29166
  "img",
29102
29167
  {
29103
- src: portraitUrl,
29168
+ src: portraitUrl?.url,
29104
29169
  alt: dialogue.speaker,
29105
29170
  className: "h-full w-auto object-contain drop-shadow-2xl"
29106
29171
  }
@@ -41406,7 +41471,6 @@ var init_FeatureGridOrganism = __esm({
41406
41471
  });
41407
41472
  function FishingBoard({
41408
41473
  backgroundImage,
41409
- assetBaseUrl,
41410
41474
  scale = 1,
41411
41475
  showMinimap = false,
41412
41476
  enableCamera = true,
@@ -41424,8 +41488,7 @@ function FishingBoard({
41424
41488
  {
41425
41489
  width,
41426
41490
  height,
41427
- backgroundImage: backgroundImage ?? "",
41428
- assetBaseUrl,
41491
+ backgroundImage,
41429
41492
  fps: 60,
41430
41493
  className: "w-full h-full"
41431
41494
  }
@@ -43644,7 +43707,7 @@ var init_GameCanvas3D2 = __esm({
43644
43707
  children: /* @__PURE__ */ jsx(
43645
43708
  ModelLoader,
43646
43709
  {
43647
- url: tile.modelUrl,
43710
+ url: tile.modelUrl.url,
43648
43711
  scale: 0.95,
43649
43712
  fallbackGeometry: "box",
43650
43713
  castShadow: true,
@@ -43709,7 +43772,7 @@ var init_GameCanvas3D2 = __esm({
43709
43772
  /* @__PURE__ */ jsx(
43710
43773
  ModelLoader,
43711
43774
  {
43712
- url: unit.modelUrl,
43775
+ url: unit.modelUrl.url,
43713
43776
  scale: modelScale,
43714
43777
  fallbackGeometry: "box",
43715
43778
  castShadow: true
@@ -43769,7 +43832,7 @@ var init_GameCanvas3D2 = __esm({
43769
43832
  return /* @__PURE__ */ jsx(
43770
43833
  ModelLoader,
43771
43834
  {
43772
- url: feature.assetUrl,
43835
+ url: feature.assetUrl.url,
43773
43836
  position,
43774
43837
  scale: 0.5,
43775
43838
  rotation: [0, feature.rotation ?? 0, 0],
@@ -43990,7 +44053,18 @@ function GameBoard3D({
43990
44053
  const row = boardEntity(entity);
43991
44054
  const eventBus = useEventBus();
43992
44055
  const entityUnits = row ? rows(row.units) : [];
43993
- const units = entityUnits;
44056
+ const units = entityUnits.map((r) => ({
44057
+ id: str(r.id),
44058
+ x: num(r.x),
44059
+ y: num(r.y),
44060
+ z: num(r.z),
44061
+ faction: str(r.faction) || "neutral",
44062
+ team: str(r.team) || str(r.faction) || "neutral",
44063
+ unitType: r.unitType == null ? void 0 : str(r.unitType),
44064
+ name: r.name == null ? void 0 : str(r.name),
44065
+ health: r.health == null ? void 0 : num(r.health),
44066
+ maxHealth: r.maxHealth == null ? void 0 : num(r.maxHealth)
44067
+ }));
43994
44068
  const selectedUnitId = row ? str(row.selectedUnitId) || null : null;
43995
44069
  const phase = row ? str(row.phase) : "observation";
43996
44070
  const result = row ? str(row.result) : "none";
@@ -44169,22 +44243,27 @@ function resolveDescriptor(value, idPrefix) {
44169
44243
  }
44170
44244
  if (typeof value === "object" && value !== null) {
44171
44245
  const desc = asDescriptor(value);
44172
- if (desc !== null && getComponentForPattern(desc.type) !== null) {
44246
+ const hasComp = desc !== null && getComponentForPattern(desc.type) !== null;
44247
+ shellLog.debug("resolve", { idPrefix, type: desc?.type ?? null, hasDesc: desc !== null, render: hasComp });
44248
+ if (hasComp) {
44173
44249
  const resolvedProps = desc.props ?? {};
44174
44250
  const content = { id: desc._id ?? idPrefix, pattern: desc.type, props: resolvedProps, priority: 0 };
44175
44251
  const SCR = getSlotContentRenderer2();
44176
- return /* @__PURE__ */ jsx(SCR, { content, onDismiss: () => void 0 });
44252
+ return /* @__PURE__ */ jsx(SCR, { content, onDismiss: () => void 0 }, content.id);
44177
44253
  }
44254
+ } else {
44255
+ shellLog.debug("resolve", { idPrefix, type: null, hasDesc: false, render: false, branch: typeof value });
44178
44256
  }
44179
44257
  return null;
44180
44258
  }
44181
- var _scr, GameShell;
44259
+ var shellLog, _scr, GameShell;
44182
44260
  var init_GameShell = __esm({
44183
44261
  "components/game/templates/GameShell.tsx"() {
44184
44262
  init_cn();
44185
44263
  init_Box();
44186
44264
  init_Stack();
44187
44265
  init_Typography();
44266
+ shellLog = createLogger("almadar:ui:game:game-shell");
44188
44267
  _scr = null;
44189
44268
  GameShell = ({
44190
44269
  appName = "Game",
@@ -44585,7 +44664,6 @@ function HexStrategyBoard({
44585
44664
  units,
44586
44665
  features,
44587
44666
  assetManifest,
44588
- assetBaseUrl,
44589
44667
  scale,
44590
44668
  showMinimap,
44591
44669
  enableCamera,
@@ -44627,7 +44705,6 @@ function HolidayRunnerBoard({
44627
44705
  units,
44628
44706
  features,
44629
44707
  assetManifest,
44630
- assetBaseUrl,
44631
44708
  scale,
44632
44709
  showMinimap,
44633
44710
  enableCamera,
@@ -45422,7 +45499,6 @@ function MatchPuzzleBoard({
45422
45499
  units,
45423
45500
  features,
45424
45501
  assetManifest,
45425
- assetBaseUrl,
45426
45502
  scale,
45427
45503
  showMinimap,
45428
45504
  enableCamera,
@@ -45683,7 +45759,6 @@ function MinigolfBoard({
45683
45759
  units,
45684
45760
  features,
45685
45761
  assetManifest,
45686
- assetBaseUrl,
45687
45762
  scale,
45688
45763
  showMinimap,
45689
45764
  enableCamera,
@@ -45989,7 +46064,6 @@ function PirateBoard({
45989
46064
  units,
45990
46065
  features,
45991
46066
  assetManifest,
45992
- assetBaseUrl,
45993
46067
  scale,
45994
46068
  showMinimap,
45995
46069
  enableCamera,
@@ -46110,8 +46184,8 @@ function PlatformerBoard({
46110
46184
  canvasHeight,
46111
46185
  followCamera: true,
46112
46186
  bgColor,
46113
- playerSprite,
46114
- tileSprites,
46187
+ playerSprite: playerSprite?.url,
46188
+ tileSprites: tileSprites ? Object.fromEntries(Object.entries(tileSprites).map(([k, a]) => [k, a.url])) : void 0,
46115
46189
  leftEvent,
46116
46190
  rightEvent,
46117
46191
  jumpEvent,
@@ -46176,7 +46250,7 @@ function PlatformerTemplate({
46176
46250
  worldHeight = 400,
46177
46251
  canvasWidth = 800,
46178
46252
  canvasHeight = 400,
46179
- playerSprite = `${CDN3}/characters/platformChar_idle.png`,
46253
+ playerSprite = makeAsset(`${CDN3}/characters/platformChar_idle.png`, "player"),
46180
46254
  tileSprites = DEFAULT_TILE_SPRITES,
46181
46255
  bgColor = "#5c94fc",
46182
46256
  gameEndEvent = "GAME_END",
@@ -46229,13 +46303,14 @@ var init_PlatformerTemplate = __esm({
46229
46303
  init_PlatformerBoard();
46230
46304
  init_GameHud();
46231
46305
  init_ScoreBoard();
46306
+ init_makeAsset();
46232
46307
  CDN3 = "https://almadar-kflow-assets.web.app/shared/platformer";
46233
- DEFAULT_TILE_SPRITES = {
46308
+ DEFAULT_TILE_SPRITES = makeAssetMap({
46234
46309
  ground: `${CDN3}/tiles/platformPack_tile001.png`,
46235
46310
  platform: `${CDN3}/tiles/platformPack_tile004.png`,
46236
46311
  hazard: `${CDN3}/tiles/platformPack_tile017.png`,
46237
46312
  goal: `${CDN3}/tiles/platformPack_tile007.png`
46238
- };
46313
+ }, "tile");
46239
46314
  DEFAULT_PLATFORMS = [
46240
46315
  { x: 0, y: 368, width: 800, height: 32, type: "ground" },
46241
46316
  { x: 150, y: 280, width: 160, height: 16, type: "platform" },
@@ -46391,7 +46466,6 @@ function RacingBoard({
46391
46466
  units,
46392
46467
  features,
46393
46468
  assetManifest,
46394
- assetBaseUrl,
46395
46469
  scale,
46396
46470
  showMinimap,
46397
46471
  enableCamera,
@@ -46410,27 +46484,18 @@ var init_RacingBoard = __esm({
46410
46484
  RacingBoard.displayName = "RacingBoard";
46411
46485
  }
46412
46486
  });
46413
- function resolveManifestUrl3(manifest, relative) {
46414
- if (relative == null) return void 0;
46415
- if (/^https?:\/\//.test(relative)) return relative;
46416
- const base = manifest?.baseUrl;
46417
- if (base == null) return relative;
46418
- const cleanBase = base.replace(/\/$/, "");
46419
- const cleanRel = relative.replace(/^\//, "");
46420
- return `${cleanBase}/${cleanRel}`;
46421
- }
46422
46487
  function dungeonTerrain(x, y, stairsX, stairsY, manifest) {
46423
46488
  const isBorder = x === 0 || y === 0 || x === DUNGEON_GRID_W - 1 || y === DUNGEON_GRID_H - 1;
46424
46489
  const isPillar = x % 4 === 0 && y % 4 === 0 && !isBorder;
46425
46490
  const isWall = isBorder || isPillar;
46426
46491
  const terrains = manifest?.terrains;
46427
46492
  if (x === stairsX && y === stairsY) {
46428
- return { terrain: "stairs", passable: true, terrainSprite: resolveManifestUrl3(manifest, terrains?.stairs) };
46493
+ return { terrain: "stairs", passable: true, terrainSprite: terrains?.stairs };
46429
46494
  }
46430
46495
  if (isWall) {
46431
- return { terrain: "wall", passable: false, terrainSprite: resolveManifestUrl3(manifest, terrains?.wall) };
46496
+ return { terrain: "wall", passable: false, terrainSprite: terrains?.wall };
46432
46497
  }
46433
- return { terrain: "floor", passable: true, terrainSprite: resolveManifestUrl3(manifest, terrains?.floor) };
46498
+ return { terrain: "floor", passable: true, terrainSprite: terrains?.floor };
46434
46499
  }
46435
46500
  function buildDefaultDungeonTiles(stairsX, stairsY, manifest) {
46436
46501
  const tiles = [];
@@ -46474,7 +46539,7 @@ function RoguelikeBoard({
46474
46539
  x: num(r.x),
46475
46540
  y: num(r.y),
46476
46541
  terrain: r.terrain == null ? void 0 : str(r.terrain),
46477
- terrainSprite: r.terrainSprite == null ? void 0 : str(r.terrainSprite),
46542
+ terrainSprite: r.terrainSprite == null ? void 0 : makeAsset(str(r.terrainSprite), "tile"),
46478
46543
  passable: r.passable !== false
46479
46544
  })),
46480
46545
  [board.tiles]
@@ -46554,7 +46619,7 @@ function RoguelikeBoard({
46554
46619
  health: playerHp,
46555
46620
  maxHealth: playerMaxHp,
46556
46621
  unitType: "player",
46557
- sprite: resolveManifestUrl3(assetManifest, assetManifest?.units?.player)
46622
+ sprite: assetManifest?.units?.player
46558
46623
  },
46559
46624
  ...liveEnemies.map((e) => ({
46560
46625
  id: e.id,
@@ -46564,7 +46629,7 @@ function RoguelikeBoard({
46564
46629
  health: e.hp,
46565
46630
  maxHealth: 6,
46566
46631
  unitType: "enemy",
46567
- sprite: resolveManifestUrl3(assetManifest, assetManifest?.units?.enemy)
46632
+ sprite: assetManifest?.units?.enemy
46568
46633
  }))
46569
46634
  ];
46570
46635
  }, [player, enemies, playerHp, playerMaxHp, assetManifest, t]);
@@ -46574,7 +46639,7 @@ function RoguelikeBoard({
46574
46639
  x: it.x,
46575
46640
  y: it.y,
46576
46641
  type: it.kind,
46577
- sprite: resolveManifestUrl3(assetManifest, assetManifest?.features?.[it.kind])
46642
+ sprite: assetManifest?.features?.[it.kind]
46578
46643
  })),
46579
46644
  [items, assetManifest]
46580
46645
  );
@@ -46635,7 +46700,6 @@ function RoguelikeBoard({
46635
46700
  onTileHover: (x, y) => setHoveredTile({ x, y }),
46636
46701
  onTileLeave: () => setHoveredTile(null),
46637
46702
  scale,
46638
- assetBaseUrl: assetManifest?.baseUrl,
46639
46703
  assetManifest,
46640
46704
  unitScale,
46641
46705
  spriteHeightRatio,
@@ -46695,6 +46759,7 @@ var init_RoguelikeBoard = __esm({
46695
46759
  init_Stack();
46696
46760
  init_IsometricCanvas();
46697
46761
  init_boardEntity();
46762
+ init_makeAsset();
46698
46763
  DUNGEON_GRID_W = 16;
46699
46764
  DUNGEON_GRID_H = 16;
46700
46765
  DEFAULT_ENEMIES = [
@@ -46745,55 +46810,59 @@ function RoguelikeTemplate({
46745
46810
  }
46746
46811
  );
46747
46812
  }
46748
- var CDN4, DEFAULT_ROGUELIKE_TILES, DEFAULT_ROGUELIKE_MANIFEST;
46813
+ var CDN4, wall, floor, tiles2, stairs, DEFAULT_ROGUELIKE_TILES, DEFAULT_ROGUELIKE_MANIFEST;
46749
46814
  var init_RoguelikeTemplate = __esm({
46750
46815
  "components/game/templates/RoguelikeTemplate.tsx"() {
46751
46816
  init_RoguelikeBoard();
46817
+ init_makeAsset();
46752
46818
  CDN4 = "https://almadar-kflow-assets.web.app/shared";
46819
+ wall = makeAsset(`${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png`, "tile");
46820
+ floor = makeAsset(`${CDN4}/isometric-dungeon/Isometric/dirt_E.png`, "tile");
46821
+ tiles2 = makeAsset(`${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png`, "tile");
46822
+ stairs = makeAsset(`${CDN4}/isometric-dungeon/Isometric/stairs_E.png`, "tile");
46753
46823
  DEFAULT_ROGUELIKE_TILES = [
46754
- { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46755
- { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46756
- { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46757
- { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46758
- { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46759
- { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46760
- { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
46761
- { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
46762
- { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
46763
- { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46764
- { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46765
- { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
46766
- { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
46767
- { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
46768
- { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46769
- { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46770
- { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
46771
- { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
46772
- { x: 3, y: 3, terrain: "stairs", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stairs_E.png` },
46773
- { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46774
- { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46775
- { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46776
- { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46777
- { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46778
- { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` }
46824
+ { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
46825
+ { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
46826
+ { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
46827
+ { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
46828
+ { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
46829
+ { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: wall },
46830
+ { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: floor },
46831
+ { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: floor },
46832
+ { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: floor },
46833
+ { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: wall },
46834
+ { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: wall },
46835
+ { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: tiles2 },
46836
+ { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: tiles2 },
46837
+ { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: floor },
46838
+ { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: wall },
46839
+ { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: wall },
46840
+ { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: floor },
46841
+ { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: tiles2 },
46842
+ { x: 3, y: 3, terrain: "stairs", passable: true, terrainSprite: stairs },
46843
+ { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: wall },
46844
+ { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
46845
+ { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
46846
+ { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
46847
+ { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
46848
+ { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: wall }
46779
46849
  ];
46780
46850
  DEFAULT_ROGUELIKE_MANIFEST = {
46781
- baseUrl: CDN4,
46782
- terrains: {
46783
- floor: "/isometric-dungeon/Isometric/dirt_E.png",
46784
- wall: "/isometric-dungeon/Isometric/stoneInset_E.png",
46785
- stairs: "/isometric-dungeon/Isometric/stairs_E.png",
46786
- planks: "/isometric-dungeon/Isometric/planks_E.png"
46787
- },
46851
+ terrains: makeAssetMap({
46852
+ floor: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png`,
46853
+ wall: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png`,
46854
+ stairs: `${CDN4}/isometric-dungeon/Isometric/stairs_E.png`,
46855
+ planks: `${CDN4}/isometric-dungeon/Isometric/planks_E.png`
46856
+ }, "tile"),
46788
46857
  units: {
46789
- player: "/isometric-dungeon/Characters/Male/Male_0_Idle0.png",
46790
- enemy: "/sprite-sheets/shadow-legion-sprite-sheet-sw.png"
46858
+ player: makeAsset(`${CDN4}/isometric-dungeon/Characters/Male/Male_0_Idle0.png`, "player"),
46859
+ enemy: makeAsset(`${CDN4}/sprite-sheets/shadow-legion-sprite-sheet-sw.png`, "enemy")
46791
46860
  },
46792
- features: {
46793
- health_potion: "/isometric-dungeon/Isometric/chestClosed_E.png",
46794
- sword: "/isometric-dungeon/Isometric/barrel_E.png",
46795
- shield: "/isometric-dungeon/Isometric/barrel_E.png"
46796
- }
46861
+ features: makeAssetMap({
46862
+ health_potion: `${CDN4}/isometric-dungeon/Isometric/chestClosed_E.png`,
46863
+ sword: `${CDN4}/isometric-dungeon/Isometric/barrel_E.png`,
46864
+ shield: `${CDN4}/isometric-dungeon/Isometric/barrel_E.png`
46865
+ }, "item")
46797
46866
  };
46798
46867
  RoguelikeTemplate.displayName = "RoguelikeTemplate";
46799
46868
  }
@@ -49667,7 +49736,6 @@ function SokobanBoard({
49667
49736
  units,
49668
49737
  features,
49669
49738
  assetManifest,
49670
- assetBaseUrl,
49671
49739
  scale,
49672
49740
  showMinimap,
49673
49741
  enableCamera,
@@ -49709,7 +49777,6 @@ function SpaceShmupBoard({
49709
49777
  units,
49710
49778
  features,
49711
49779
  assetManifest,
49712
- assetBaseUrl,
49713
49780
  scale,
49714
49781
  showMinimap,
49715
49782
  enableCamera,
@@ -49751,7 +49818,6 @@ function SpaceStationBoard({
49751
49818
  units,
49752
49819
  features,
49753
49820
  assetManifest,
49754
- assetBaseUrl,
49755
49821
  scale,
49756
49822
  showMinimap,
49757
49823
  enableCamera,
@@ -49886,7 +49952,6 @@ function SportsBoard({
49886
49952
  units,
49887
49953
  features,
49888
49954
  assetManifest,
49889
- assetBaseUrl,
49890
49955
  scale,
49891
49956
  showMinimap,
49892
49957
  enableCamera,
@@ -51730,7 +51795,6 @@ function TanksBoard({
51730
51795
  units,
51731
51796
  features,
51732
51797
  assetManifest,
51733
- assetBaseUrl,
51734
51798
  scale,
51735
51799
  showMinimap,
51736
51800
  enableCamera,
@@ -52008,15 +52072,6 @@ var init_ToastSlot = __esm({
52008
52072
  ToastSlot.displayName = "ToastSlot";
52009
52073
  }
52010
52074
  });
52011
- function resolveManifestUrl4(manifest, relative) {
52012
- if (relative == null || relative === "") return void 0;
52013
- if (/^https?:\/\//.test(relative)) return relative;
52014
- const base = manifest?.baseUrl;
52015
- if (base == null) return relative;
52016
- const cleanBase = base.replace(/\/$/, "");
52017
- const cleanRel = relative.replace(/^\//, "");
52018
- return `${cleanBase}/${cleanRel}`;
52019
- }
52020
52075
  function readPlayer(v) {
52021
52076
  if (v == null || typeof v !== "object") return void 0;
52022
52077
  const o = v;
@@ -52069,10 +52124,10 @@ function TopDownShooterBoard({
52069
52124
  const wave = propWave ?? num(board.wave, 1);
52070
52125
  const lives = propLives ?? num(board.lives, 3);
52071
52126
  const result = propResult ?? (str(board.result) || "none");
52072
- const playerSprite = resolveManifestUrl4(assetManifest, assetManifest?.units?.player);
52073
- const enemySprite = resolveManifestUrl4(assetManifest, assetManifest?.units?.enemy);
52074
- const projectileSprite = resolveManifestUrl4(assetManifest, assetManifest?.features?.projectile);
52075
- const backgroundSprite = resolveManifestUrl4(assetManifest, assetManifest?.background);
52127
+ const playerSprite = assetManifest?.units?.player?.url;
52128
+ const enemySprite = assetManifest?.units?.enemy?.url;
52129
+ const projectileSprite = assetManifest?.features?.projectile?.url;
52130
+ const backgroundSprite = assetManifest?.background;
52076
52131
  const spriteUrls = useMemo(
52077
52132
  () => [playerSprite, enemySprite, projectileSprite].filter((u) => u != null),
52078
52133
  [playerSprite, enemySprite, projectileSprite]
@@ -52239,7 +52294,6 @@ function TopDownShooterBoard({
52239
52294
  width,
52240
52295
  height,
52241
52296
  backgroundImage: backgroundSprite,
52242
- assetBaseUrl: assetManifest?.baseUrl,
52243
52297
  onDraw
52244
52298
  }
52245
52299
  ),
@@ -52364,15 +52418,6 @@ var init_TopDownShooterTemplate = __esm({
52364
52418
  TopDownShooterTemplate.displayName = "TopDownShooterTemplate";
52365
52419
  }
52366
52420
  });
52367
- function resolveManifestUrl5(manifest, relative) {
52368
- if (relative == null) return void 0;
52369
- if (/^https?:\/\//.test(relative)) return relative;
52370
- const base = manifest?.baseUrl;
52371
- if (base == null) return relative;
52372
- const cleanBase = base.replace(/\/$/, "");
52373
- const cleanRel = relative.replace(/^\//, "");
52374
- return `${cleanBase}/${cleanRel}`;
52375
- }
52376
52421
  function buildDefaultTDTiles() {
52377
52422
  const pathSet = new Set(DEFAULT_TD_PATH.map((p2) => `${p2.x},${p2.y}`));
52378
52423
  const tiles = [];
@@ -52392,18 +52437,18 @@ function buildDefaultTDTiles() {
52392
52437
  function tilesToIso2(tiles, manifest) {
52393
52438
  return tiles.map((t) => {
52394
52439
  const key = t.terrain ?? "ground";
52395
- const sprite = t.terrainSprite ?? resolveManifestUrl5(manifest, manifest?.terrains?.[key]) ?? resolveManifestUrl5(manifest, manifest?.terrains?.ground);
52440
+ const terrainSprite = t.terrainSprite != null ? makeAsset(t.terrainSprite, "tile") : manifest?.terrains?.[key] ?? manifest?.terrains?.ground;
52396
52441
  return {
52397
52442
  x: t.x,
52398
52443
  y: t.y,
52399
52444
  terrain: t.terrain,
52400
- terrainSprite: sprite,
52445
+ terrainSprite,
52401
52446
  passable: t.passable
52402
52447
  };
52403
52448
  });
52404
52449
  }
52405
52450
  function creepsToUnits(creeps, manifest) {
52406
- const sprite = resolveManifestUrl5(manifest, manifest?.units?.creep);
52451
+ const sprite = manifest?.units?.creep;
52407
52452
  return creeps.map((c) => ({
52408
52453
  id: c.id,
52409
52454
  position: { x: c.x, y: c.y },
@@ -52421,14 +52466,14 @@ function heroToUnit(hero, manifest) {
52421
52466
  position: { x: hero.x, y: hero.y },
52422
52467
  name: "Hero",
52423
52468
  team: "player",
52424
- sprite: resolveManifestUrl5(manifest, manifest?.units?.hero),
52469
+ sprite: manifest?.units?.hero,
52425
52470
  unitType: "hero",
52426
52471
  health: 1,
52427
52472
  maxHealth: 1
52428
52473
  };
52429
52474
  }
52430
52475
  function towersToFeatures(towers, manifest) {
52431
- const sprite = resolveManifestUrl5(manifest, manifest?.features?.tower);
52476
+ const sprite = manifest?.features?.tower;
52432
52477
  return towers.map((t) => ({
52433
52478
  id: t.id,
52434
52479
  x: t.x,
@@ -52626,7 +52671,6 @@ function TowerDefenseBoard({
52626
52671
  tiles: isoTiles,
52627
52672
  units: isoUnits,
52628
52673
  features: towerFeatures,
52629
- assetBaseUrl: assetManifest?.baseUrl,
52630
52674
  assetManifest,
52631
52675
  validMoves,
52632
52676
  hoveredTile,
@@ -52670,6 +52714,7 @@ var TD_GRID_W, TD_GRID_H, DEFAULT_TD_PATH, DEFAULT_TD_TILES;
52670
52714
  var init_TowerDefenseBoard = __esm({
52671
52715
  "components/game/organisms/TowerDefenseBoard.tsx"() {
52672
52716
  "use client";
52717
+ init_makeAsset();
52673
52718
  init_cn();
52674
52719
  init_useEventBus();
52675
52720
  init_Box();
@@ -52999,15 +53044,6 @@ var init_UncontrolledBattleBoard = __esm({
52999
53044
  UncontrolledBattleBoard.displayName = "UncontrolledBattleBoard";
53000
53045
  }
53001
53046
  });
53002
- function resolveManifestUrl6(manifest, relative) {
53003
- if (relative == null) return void 0;
53004
- if (/^https?:\/\//.test(relative)) return relative;
53005
- const base = manifest?.baseUrl;
53006
- if (base == null) return relative;
53007
- const cleanBase = base.replace(/\/$/, "");
53008
- const cleanRel = relative.replace(/^\//, "");
53009
- return `${cleanBase}/${cleanRel}`;
53010
- }
53011
53047
  function VisualNovelBoard({
53012
53048
  entity,
53013
53049
  nodes: propNodes,
@@ -53042,11 +53078,11 @@ function VisualNovelBoard({
53042
53078
  const currentNodeId = propCurrentNodeId ?? (str(board.currentNodeId) || nodes[0]?.id);
53043
53079
  const currentNode = nodes.find((n) => n.id === currentNodeId) ?? nodes[0];
53044
53080
  const backgroundImage = useMemo(
53045
- () => resolveManifestUrl6(assetManifest, assetManifest?.backgrounds?.[currentNode?.backgroundKey ?? ""]),
53081
+ () => assetManifest?.backgrounds?.[currentNode?.backgroundKey ?? ""],
53046
53082
  [assetManifest, currentNode?.backgroundKey]
53047
53083
  );
53048
53084
  const portraitUrl = useMemo(
53049
- () => resolveManifestUrl6(assetManifest, assetManifest?.portraits?.[currentNode?.portraitKey ?? ""]),
53085
+ () => assetManifest?.portraits?.[currentNode?.portraitKey ?? ""],
53050
53086
  [assetManifest, currentNode?.portraitKey]
53051
53087
  );
53052
53088
  const dialogueChoices = useMemo(
@@ -53220,7 +53256,7 @@ function buildDefaultWorldTiles() {
53220
53256
  for (let x = 0; x < WORLD_GRID_W; x++) {
53221
53257
  const isBorder = x === 0 || y === 0 || x === WORLD_GRID_W - 1 || y === WORLD_GRID_H - 1;
53222
53258
  const def = isBorder ? WORLD_TERRAIN_DEFS[3] : WORLD_TERRAIN_DEFS[(x * 5 + y * 3 + (x ^ y)) % (WORLD_TERRAIN_DEFS.length - 1)];
53223
- tiles.push({ x, y, terrain: def.terrain, terrainSprite: def.sprite, passable: def.passable });
53259
+ tiles.push({ x, y, terrain: def.terrain, terrainSprite: makeAsset(def.sprite, "tile"), passable: def.passable });
53224
53260
  }
53225
53261
  }
53226
53262
  return tiles;
@@ -53264,7 +53300,12 @@ function WorldMapBoard({
53264
53300
  const resolved = boardEntity(entity);
53265
53301
  const entityUnits = rows(resolved?.units);
53266
53302
  const entityTiles = rows(resolved?.tiles);
53267
- const features = propFeatures ?? rows(resolved?.features);
53303
+ const features = propFeatures ?? rows(resolved?.features).map((r) => ({
53304
+ id: r.id == null ? void 0 : str(r.id),
53305
+ x: num(r.x),
53306
+ y: num(r.y),
53307
+ type: str(r.type)
53308
+ }));
53268
53309
  const selectedHeroId = resolved?.selectedHeroId ?? null;
53269
53310
  const assetManifest = propAssetManifest ?? resolved?.assetManifest;
53270
53311
  const backgroundImage = resolved?.backgroundImage;
@@ -53274,7 +53315,7 @@ function WorldMapBoard({
53274
53315
  x: num(t.x),
53275
53316
  y: num(t.y),
53276
53317
  terrain: str(t.terrain),
53277
- terrainSprite: t.terrainSprite == null ? void 0 : str(t.terrainSprite),
53318
+ terrainSprite: t.terrainSprite == null ? void 0 : makeAsset(str(t.terrainSprite), "tile"),
53278
53319
  passable: t.passable !== false
53279
53320
  })),
53280
53321
  [entityTiles]
@@ -53290,7 +53331,7 @@ function WorldMapBoard({
53290
53331
  team: str(u.team) === "enemy" ? "enemy" : "player",
53291
53332
  health: num(u.health) || 100,
53292
53333
  maxHealth: num(u.maxHealth) || 100,
53293
- sprite: u.sprite == null ? void 0 : str(u.sprite)
53334
+ sprite: u.sprite == null ? void 0 : makeAsset(str(u.sprite), "player")
53294
53335
  })),
53295
53336
  [entityUnits, propUnits]
53296
53337
  );
@@ -53472,7 +53513,6 @@ function WorldMapBoard({
53472
53513
  onTileHover: (x, y) => setHoveredTile({ x, y }),
53473
53514
  onTileLeave: () => setHoveredTile(null),
53474
53515
  scale,
53475
- assetBaseUrl: assetManifest?.baseUrl,
53476
53516
  assetManifest,
53477
53517
  backgroundImage,
53478
53518
  effectSpriteUrls,
@@ -53495,6 +53535,7 @@ var WORLD_CDN, WORLD_GRID_W, WORLD_GRID_H, WORLD_TERRAIN_DEFS, DEFAULT_WORLD_TIL
53495
53535
  var init_WorldMapBoard = __esm({
53496
53536
  "components/game/organisms/WorldMapBoard.tsx"() {
53497
53537
  "use client";
53538
+ init_makeAsset();
53498
53539
  init_cn();
53499
53540
  init_useEventBus();
53500
53541
  init_Stack();
@@ -53548,62 +53589,66 @@ function WorldMapTemplate({
53548
53589
  }
53549
53590
  );
53550
53591
  }
53551
- var CDN5, DEFAULT_WORLDMAP_TILES, DEFAULT_WORLDMAP_UNITS, DEFAULT_WORLDMAP_FEATURES, DEFAULT_WORLDMAP_MANIFEST;
53592
+ var CDN5, mountain, water, grass, road, DEFAULT_WORLDMAP_TILES, DEFAULT_WORLDMAP_UNITS, DEFAULT_WORLDMAP_FEATURES, DEFAULT_WORLDMAP_MANIFEST;
53552
53593
  var init_WorldMapTemplate = __esm({
53553
53594
  "components/game/templates/WorldMapTemplate.tsx"() {
53554
53595
  init_WorldMapBoard();
53596
+ init_makeAsset();
53555
53597
  CDN5 = "https://almadar-kflow-assets.web.app/shared";
53598
+ mountain = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png`, "tile");
53599
+ water = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png`, "tile");
53600
+ grass = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`, "tile");
53601
+ road = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png`, "tile");
53556
53602
  DEFAULT_WORLDMAP_TILES = [
53557
- { x: 0, y: 0, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53558
- { x: 1, y: 0, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53559
- { x: 2, y: 0, terrain: "water", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png` },
53560
- { x: 3, y: 0, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53561
- { x: 4, y: 0, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53562
- { x: 0, y: 1, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53563
- { x: 1, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53564
- { x: 2, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53565
- { x: 3, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53566
- { x: 4, y: 1, terrain: "water", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png` },
53567
- { x: 0, y: 2, terrain: "water", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png` },
53568
- { x: 1, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53569
- { x: 2, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png` },
53570
- { x: 3, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53571
- { x: 4, y: 2, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53572
- { x: 0, y: 3, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53573
- { x: 1, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53574
- { x: 2, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53575
- { x: 3, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png` },
53576
- { x: 4, y: 3, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53577
- { x: 0, y: 4, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53578
- { x: 1, y: 4, terrain: "water", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png` },
53579
- { x: 2, y: 4, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53580
- { x: 3, y: 4, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53581
- { x: 4, y: 4, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` }
53603
+ { x: 0, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53604
+ { x: 1, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53605
+ { x: 2, y: 0, terrain: "water", passable: false, terrainSprite: water },
53606
+ { x: 3, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53607
+ { x: 4, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53608
+ { x: 0, y: 1, terrain: "mountain", passable: false, terrainSprite: mountain },
53609
+ { x: 1, y: 1, terrain: "grass", passable: true, terrainSprite: grass },
53610
+ { x: 2, y: 1, terrain: "grass", passable: true, terrainSprite: grass },
53611
+ { x: 3, y: 1, terrain: "grass", passable: true, terrainSprite: grass },
53612
+ { x: 4, y: 1, terrain: "water", passable: false, terrainSprite: water },
53613
+ { x: 0, y: 2, terrain: "water", passable: false, terrainSprite: water },
53614
+ { x: 1, y: 2, terrain: "grass", passable: true, terrainSprite: grass },
53615
+ { x: 2, y: 2, terrain: "grass", passable: true, terrainSprite: road },
53616
+ { x: 3, y: 2, terrain: "grass", passable: true, terrainSprite: grass },
53617
+ { x: 4, y: 2, terrain: "mountain", passable: false, terrainSprite: mountain },
53618
+ { x: 0, y: 3, terrain: "mountain", passable: false, terrainSprite: mountain },
53619
+ { x: 1, y: 3, terrain: "grass", passable: true, terrainSprite: grass },
53620
+ { x: 2, y: 3, terrain: "grass", passable: true, terrainSprite: grass },
53621
+ { x: 3, y: 3, terrain: "grass", passable: true, terrainSprite: road },
53622
+ { x: 4, y: 3, terrain: "mountain", passable: false, terrainSprite: mountain },
53623
+ { x: 0, y: 4, terrain: "mountain", passable: false, terrainSprite: mountain },
53624
+ { x: 1, y: 4, terrain: "water", passable: false, terrainSprite: water },
53625
+ { x: 2, y: 4, terrain: "grass", passable: true, terrainSprite: grass },
53626
+ { x: 3, y: 4, terrain: "mountain", passable: false, terrainSprite: mountain },
53627
+ { x: 4, y: 4, terrain: "mountain", passable: false, terrainSprite: mountain }
53582
53628
  ];
53583
53629
  DEFAULT_WORLDMAP_UNITS = [
53584
- { 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` },
53585
- { 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` }
53630
+ { 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") },
53631
+ { 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") }
53586
53632
  ];
53587
53633
  DEFAULT_WORLDMAP_FEATURES = [
53588
- { id: "f1", x: 2, y: 2, type: "capital", sprite: `${CDN5}/scenes/world/capital.png` },
53589
- { id: "f2", x: 4, y: 2, type: "power_node", sprite: `${CDN5}/world-map/power_node.png` }
53634
+ { id: "f1", x: 2, y: 2, type: "capital", sprite: makeAsset(`${CDN5}/scenes/world/capital.png`, "decoration") },
53635
+ { id: "f2", x: 4, y: 2, type: "power_node", sprite: makeAsset(`${CDN5}/world-map/power_node.png`, "decoration") }
53590
53636
  ];
53591
53637
  DEFAULT_WORLDMAP_MANIFEST = {
53592
- baseUrl: CDN5,
53593
- terrains: {
53594
- grass: "/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png",
53595
- water: "/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png",
53596
- mountain: "/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png",
53597
- road: "/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png"
53598
- },
53638
+ terrains: makeAssetMap({
53639
+ grass: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`,
53640
+ water: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png`,
53641
+ mountain: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png`,
53642
+ road: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png`
53643
+ }, "tile"),
53599
53644
  units: {
53600
- hero: "/sprite-sheets/amir-sprite-sheet-se.png",
53601
- scout: "/sprite-sheets/archivist-sprite-sheet-se.png"
53645
+ hero: makeAsset(`${CDN5}/sprite-sheets/amir-sprite-sheet-se.png`, "player"),
53646
+ scout: makeAsset(`${CDN5}/sprite-sheets/archivist-sprite-sheet-se.png`, "npc")
53602
53647
  },
53603
- features: {
53604
- capital: "/scenes/world/capital.png",
53605
- power_node: "/world-map/power_node.png"
53606
- }
53648
+ features: makeAssetMap({
53649
+ capital: `${CDN5}/scenes/world/capital.png`,
53650
+ power_node: `${CDN5}/world-map/power_node.png`
53651
+ }, "decoration")
53607
53652
  };
53608
53653
  WorldMapTemplate.displayName = "WorldMapTemplate";
53609
53654
  }