@almadar/ui 5.72.0 → 5.73.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/avl/index.cjs +402 -362
  2. package/dist/avl/index.js +402 -362
  3. package/dist/components/game/atoms/ActionButton.d.ts +3 -3
  4. package/dist/components/game/atoms/ChoiceButton.d.ts +3 -3
  5. package/dist/components/game/atoms/ComboCounter.d.ts +3 -3
  6. package/dist/components/game/atoms/ControlButton.d.ts +3 -3
  7. package/dist/components/game/atoms/DamageNumber.d.ts +3 -3
  8. package/dist/components/game/atoms/DialogueBubble.d.ts +3 -3
  9. package/dist/components/game/atoms/ItemSlot.d.ts +3 -3
  10. package/dist/components/game/atoms/ResourceCounter.d.ts +3 -3
  11. package/dist/components/game/atoms/ScoreDisplay.d.ts +3 -3
  12. package/dist/components/game/atoms/Sprite.d.ts +3 -20
  13. package/dist/components/game/atoms/StateIndicator.d.ts +2 -2
  14. package/dist/components/game/atoms/StatusEffect.d.ts +3 -3
  15. package/dist/components/game/atoms/TurnIndicator.d.ts +3 -3
  16. package/dist/components/game/atoms/WaypointMarker.d.ts +3 -3
  17. package/dist/components/game/molecules/CardHand.d.ts +2 -2
  18. package/dist/components/game/molecules/DialogueBox.d.ts +3 -3
  19. package/dist/components/game/molecules/EnemyPlate.d.ts +3 -3
  20. package/dist/components/game/molecules/GameCanvas2D.d.ts +3 -3
  21. package/dist/components/game/molecules/HealthPanel.d.ts +3 -3
  22. package/dist/components/game/molecules/IsometricCanvas.d.ts +8 -12
  23. package/dist/components/game/molecules/PowerupSlots.d.ts +3 -3
  24. package/dist/components/game/molecules/StatBadge.d.ts +5 -5
  25. package/dist/components/game/molecules/TurnPanel.d.ts +3 -3
  26. package/dist/components/game/molecules/three/index.cjs +51 -28
  27. package/dist/components/game/molecules/three/index.js +51 -28
  28. package/dist/components/game/molecules/useUnitSpriteAtlas.d.ts +3 -10
  29. package/dist/components/game/organisms/BattleBoard.d.ts +5 -6
  30. package/dist/components/game/organisms/CardBattlerBoard.d.ts +3 -4
  31. package/dist/components/game/organisms/CastleBoard.d.ts +5 -6
  32. package/dist/components/game/organisms/CityBuilderBoard.d.ts +6 -7
  33. package/dist/components/game/organisms/FishingBoard.d.ts +4 -6
  34. package/dist/components/game/organisms/PlatformerBoard.d.ts +5 -5
  35. package/dist/components/game/organisms/RoguelikeBoard.d.ts +4 -5
  36. package/dist/components/game/organisms/TopDownShooterBoard.d.ts +5 -6
  37. package/dist/components/game/organisms/TowerDefenseBoard.d.ts +5 -6
  38. package/dist/components/game/organisms/VisualNovelBoard.d.ts +4 -5
  39. package/dist/components/game/organisms/WorldMapBoard.d.ts +5 -6
  40. package/dist/components/game/organisms/types/effects.d.ts +7 -8
  41. package/dist/components/game/organisms/types/isometric.d.ts +8 -8
  42. package/dist/components/game/organisms/types/spriteAnimation.d.ts +3 -4
  43. package/dist/components/game/organisms/utils/makeAsset.d.ts +5 -0
  44. package/dist/components/game/templates/PlatformerTemplate.d.ts +5 -4
  45. package/dist/components/game/templates/game3dAssetManifest.d.ts +6 -8
  46. package/dist/components/index.cjs +417 -363
  47. package/dist/components/index.js +417 -363
  48. package/dist/providers/index.cjs +402 -362
  49. package/dist/providers/index.js +402 -362
  50. package/dist/runtime/index.cjs +402 -362
  51. package/dist/runtime/index.js +402 -362
  52. package/package.json +2 -2
@@ -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";
@@ -44585,7 +44659,6 @@ function HexStrategyBoard({
44585
44659
  units,
44586
44660
  features,
44587
44661
  assetManifest,
44588
- assetBaseUrl,
44589
44662
  scale,
44590
44663
  showMinimap,
44591
44664
  enableCamera,
@@ -44627,7 +44700,6 @@ function HolidayRunnerBoard({
44627
44700
  units,
44628
44701
  features,
44629
44702
  assetManifest,
44630
- assetBaseUrl,
44631
44703
  scale,
44632
44704
  showMinimap,
44633
44705
  enableCamera,
@@ -45422,7 +45494,6 @@ function MatchPuzzleBoard({
45422
45494
  units,
45423
45495
  features,
45424
45496
  assetManifest,
45425
- assetBaseUrl,
45426
45497
  scale,
45427
45498
  showMinimap,
45428
45499
  enableCamera,
@@ -45683,7 +45754,6 @@ function MinigolfBoard({
45683
45754
  units,
45684
45755
  features,
45685
45756
  assetManifest,
45686
- assetBaseUrl,
45687
45757
  scale,
45688
45758
  showMinimap,
45689
45759
  enableCamera,
@@ -45989,7 +46059,6 @@ function PirateBoard({
45989
46059
  units,
45990
46060
  features,
45991
46061
  assetManifest,
45992
- assetBaseUrl,
45993
46062
  scale,
45994
46063
  showMinimap,
45995
46064
  enableCamera,
@@ -46110,8 +46179,8 @@ function PlatformerBoard({
46110
46179
  canvasHeight,
46111
46180
  followCamera: true,
46112
46181
  bgColor,
46113
- playerSprite,
46114
- tileSprites,
46182
+ playerSprite: playerSprite?.url,
46183
+ tileSprites: tileSprites ? Object.fromEntries(Object.entries(tileSprites).map(([k, a]) => [k, a.url])) : void 0,
46115
46184
  leftEvent,
46116
46185
  rightEvent,
46117
46186
  jumpEvent,
@@ -46176,7 +46245,7 @@ function PlatformerTemplate({
46176
46245
  worldHeight = 400,
46177
46246
  canvasWidth = 800,
46178
46247
  canvasHeight = 400,
46179
- playerSprite = `${CDN3}/characters/platformChar_idle.png`,
46248
+ playerSprite = makeAsset(`${CDN3}/characters/platformChar_idle.png`, "player"),
46180
46249
  tileSprites = DEFAULT_TILE_SPRITES,
46181
46250
  bgColor = "#5c94fc",
46182
46251
  gameEndEvent = "GAME_END",
@@ -46229,13 +46298,14 @@ var init_PlatformerTemplate = __esm({
46229
46298
  init_PlatformerBoard();
46230
46299
  init_GameHud();
46231
46300
  init_ScoreBoard();
46301
+ init_makeAsset();
46232
46302
  CDN3 = "https://almadar-kflow-assets.web.app/shared/platformer";
46233
- DEFAULT_TILE_SPRITES = {
46303
+ DEFAULT_TILE_SPRITES = makeAssetMap({
46234
46304
  ground: `${CDN3}/tiles/platformPack_tile001.png`,
46235
46305
  platform: `${CDN3}/tiles/platformPack_tile004.png`,
46236
46306
  hazard: `${CDN3}/tiles/platformPack_tile017.png`,
46237
46307
  goal: `${CDN3}/tiles/platformPack_tile007.png`
46238
- };
46308
+ }, "tile");
46239
46309
  DEFAULT_PLATFORMS = [
46240
46310
  { x: 0, y: 368, width: 800, height: 32, type: "ground" },
46241
46311
  { x: 150, y: 280, width: 160, height: 16, type: "platform" },
@@ -46391,7 +46461,6 @@ function RacingBoard({
46391
46461
  units,
46392
46462
  features,
46393
46463
  assetManifest,
46394
- assetBaseUrl,
46395
46464
  scale,
46396
46465
  showMinimap,
46397
46466
  enableCamera,
@@ -46410,27 +46479,18 @@ var init_RacingBoard = __esm({
46410
46479
  RacingBoard.displayName = "RacingBoard";
46411
46480
  }
46412
46481
  });
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
46482
  function dungeonTerrain(x, y, stairsX, stairsY, manifest) {
46423
46483
  const isBorder = x === 0 || y === 0 || x === DUNGEON_GRID_W - 1 || y === DUNGEON_GRID_H - 1;
46424
46484
  const isPillar = x % 4 === 0 && y % 4 === 0 && !isBorder;
46425
46485
  const isWall = isBorder || isPillar;
46426
46486
  const terrains = manifest?.terrains;
46427
46487
  if (x === stairsX && y === stairsY) {
46428
- return { terrain: "stairs", passable: true, terrainSprite: resolveManifestUrl3(manifest, terrains?.stairs) };
46488
+ return { terrain: "stairs", passable: true, terrainSprite: terrains?.stairs };
46429
46489
  }
46430
46490
  if (isWall) {
46431
- return { terrain: "wall", passable: false, terrainSprite: resolveManifestUrl3(manifest, terrains?.wall) };
46491
+ return { terrain: "wall", passable: false, terrainSprite: terrains?.wall };
46432
46492
  }
46433
- return { terrain: "floor", passable: true, terrainSprite: resolveManifestUrl3(manifest, terrains?.floor) };
46493
+ return { terrain: "floor", passable: true, terrainSprite: terrains?.floor };
46434
46494
  }
46435
46495
  function buildDefaultDungeonTiles(stairsX, stairsY, manifest) {
46436
46496
  const tiles = [];
@@ -46474,7 +46534,7 @@ function RoguelikeBoard({
46474
46534
  x: num(r.x),
46475
46535
  y: num(r.y),
46476
46536
  terrain: r.terrain == null ? void 0 : str(r.terrain),
46477
- terrainSprite: r.terrainSprite == null ? void 0 : str(r.terrainSprite),
46537
+ terrainSprite: r.terrainSprite == null ? void 0 : makeAsset(str(r.terrainSprite), "tile"),
46478
46538
  passable: r.passable !== false
46479
46539
  })),
46480
46540
  [board.tiles]
@@ -46554,7 +46614,7 @@ function RoguelikeBoard({
46554
46614
  health: playerHp,
46555
46615
  maxHealth: playerMaxHp,
46556
46616
  unitType: "player",
46557
- sprite: resolveManifestUrl3(assetManifest, assetManifest?.units?.player)
46617
+ sprite: assetManifest?.units?.player
46558
46618
  },
46559
46619
  ...liveEnemies.map((e) => ({
46560
46620
  id: e.id,
@@ -46564,7 +46624,7 @@ function RoguelikeBoard({
46564
46624
  health: e.hp,
46565
46625
  maxHealth: 6,
46566
46626
  unitType: "enemy",
46567
- sprite: resolveManifestUrl3(assetManifest, assetManifest?.units?.enemy)
46627
+ sprite: assetManifest?.units?.enemy
46568
46628
  }))
46569
46629
  ];
46570
46630
  }, [player, enemies, playerHp, playerMaxHp, assetManifest, t]);
@@ -46574,7 +46634,7 @@ function RoguelikeBoard({
46574
46634
  x: it.x,
46575
46635
  y: it.y,
46576
46636
  type: it.kind,
46577
- sprite: resolveManifestUrl3(assetManifest, assetManifest?.features?.[it.kind])
46637
+ sprite: assetManifest?.features?.[it.kind]
46578
46638
  })),
46579
46639
  [items, assetManifest]
46580
46640
  );
@@ -46635,7 +46695,6 @@ function RoguelikeBoard({
46635
46695
  onTileHover: (x, y) => setHoveredTile({ x, y }),
46636
46696
  onTileLeave: () => setHoveredTile(null),
46637
46697
  scale,
46638
- assetBaseUrl: assetManifest?.baseUrl,
46639
46698
  assetManifest,
46640
46699
  unitScale,
46641
46700
  spriteHeightRatio,
@@ -46695,6 +46754,7 @@ var init_RoguelikeBoard = __esm({
46695
46754
  init_Stack();
46696
46755
  init_IsometricCanvas();
46697
46756
  init_boardEntity();
46757
+ init_makeAsset();
46698
46758
  DUNGEON_GRID_W = 16;
46699
46759
  DUNGEON_GRID_H = 16;
46700
46760
  DEFAULT_ENEMIES = [
@@ -46745,55 +46805,59 @@ function RoguelikeTemplate({
46745
46805
  }
46746
46806
  );
46747
46807
  }
46748
- var CDN4, DEFAULT_ROGUELIKE_TILES, DEFAULT_ROGUELIKE_MANIFEST;
46808
+ var CDN4, wall, floor, tiles2, stairs, DEFAULT_ROGUELIKE_TILES, DEFAULT_ROGUELIKE_MANIFEST;
46749
46809
  var init_RoguelikeTemplate = __esm({
46750
46810
  "components/game/templates/RoguelikeTemplate.tsx"() {
46751
46811
  init_RoguelikeBoard();
46812
+ init_makeAsset();
46752
46813
  CDN4 = "https://almadar-kflow-assets.web.app/shared";
46814
+ wall = makeAsset(`${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png`, "tile");
46815
+ floor = makeAsset(`${CDN4}/isometric-dungeon/Isometric/dirt_E.png`, "tile");
46816
+ tiles2 = makeAsset(`${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png`, "tile");
46817
+ stairs = makeAsset(`${CDN4}/isometric-dungeon/Isometric/stairs_E.png`, "tile");
46753
46818
  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` }
46819
+ { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
46820
+ { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
46821
+ { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
46822
+ { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
46823
+ { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
46824
+ { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: wall },
46825
+ { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: floor },
46826
+ { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: floor },
46827
+ { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: floor },
46828
+ { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: wall },
46829
+ { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: wall },
46830
+ { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: tiles2 },
46831
+ { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: tiles2 },
46832
+ { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: floor },
46833
+ { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: wall },
46834
+ { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: wall },
46835
+ { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: floor },
46836
+ { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: tiles2 },
46837
+ { x: 3, y: 3, terrain: "stairs", passable: true, terrainSprite: stairs },
46838
+ { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: wall },
46839
+ { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
46840
+ { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
46841
+ { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
46842
+ { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
46843
+ { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: wall }
46779
46844
  ];
46780
46845
  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
- },
46846
+ terrains: makeAssetMap({
46847
+ floor: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png`,
46848
+ wall: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png`,
46849
+ stairs: `${CDN4}/isometric-dungeon/Isometric/stairs_E.png`,
46850
+ planks: `${CDN4}/isometric-dungeon/Isometric/planks_E.png`
46851
+ }, "tile"),
46788
46852
  units: {
46789
- player: "/isometric-dungeon/Characters/Male/Male_0_Idle0.png",
46790
- enemy: "/sprite-sheets/shadow-legion-sprite-sheet-sw.png"
46853
+ player: makeAsset(`${CDN4}/isometric-dungeon/Characters/Male/Male_0_Idle0.png`, "player"),
46854
+ enemy: makeAsset(`${CDN4}/sprite-sheets/shadow-legion-sprite-sheet-sw.png`, "enemy")
46791
46855
  },
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
- }
46856
+ features: makeAssetMap({
46857
+ health_potion: `${CDN4}/isometric-dungeon/Isometric/chestClosed_E.png`,
46858
+ sword: `${CDN4}/isometric-dungeon/Isometric/barrel_E.png`,
46859
+ shield: `${CDN4}/isometric-dungeon/Isometric/barrel_E.png`
46860
+ }, "item")
46797
46861
  };
46798
46862
  RoguelikeTemplate.displayName = "RoguelikeTemplate";
46799
46863
  }
@@ -49667,7 +49731,6 @@ function SokobanBoard({
49667
49731
  units,
49668
49732
  features,
49669
49733
  assetManifest,
49670
- assetBaseUrl,
49671
49734
  scale,
49672
49735
  showMinimap,
49673
49736
  enableCamera,
@@ -49709,7 +49772,6 @@ function SpaceShmupBoard({
49709
49772
  units,
49710
49773
  features,
49711
49774
  assetManifest,
49712
- assetBaseUrl,
49713
49775
  scale,
49714
49776
  showMinimap,
49715
49777
  enableCamera,
@@ -49751,7 +49813,6 @@ function SpaceStationBoard({
49751
49813
  units,
49752
49814
  features,
49753
49815
  assetManifest,
49754
- assetBaseUrl,
49755
49816
  scale,
49756
49817
  showMinimap,
49757
49818
  enableCamera,
@@ -49886,7 +49947,6 @@ function SportsBoard({
49886
49947
  units,
49887
49948
  features,
49888
49949
  assetManifest,
49889
- assetBaseUrl,
49890
49950
  scale,
49891
49951
  showMinimap,
49892
49952
  enableCamera,
@@ -51730,7 +51790,6 @@ function TanksBoard({
51730
51790
  units,
51731
51791
  features,
51732
51792
  assetManifest,
51733
- assetBaseUrl,
51734
51793
  scale,
51735
51794
  showMinimap,
51736
51795
  enableCamera,
@@ -52008,15 +52067,6 @@ var init_ToastSlot = __esm({
52008
52067
  ToastSlot.displayName = "ToastSlot";
52009
52068
  }
52010
52069
  });
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
52070
  function readPlayer(v) {
52021
52071
  if (v == null || typeof v !== "object") return void 0;
52022
52072
  const o = v;
@@ -52069,10 +52119,10 @@ function TopDownShooterBoard({
52069
52119
  const wave = propWave ?? num(board.wave, 1);
52070
52120
  const lives = propLives ?? num(board.lives, 3);
52071
52121
  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);
52122
+ const playerSprite = assetManifest?.units?.player?.url;
52123
+ const enemySprite = assetManifest?.units?.enemy?.url;
52124
+ const projectileSprite = assetManifest?.features?.projectile?.url;
52125
+ const backgroundSprite = assetManifest?.background;
52076
52126
  const spriteUrls = useMemo(
52077
52127
  () => [playerSprite, enemySprite, projectileSprite].filter((u) => u != null),
52078
52128
  [playerSprite, enemySprite, projectileSprite]
@@ -52239,7 +52289,6 @@ function TopDownShooterBoard({
52239
52289
  width,
52240
52290
  height,
52241
52291
  backgroundImage: backgroundSprite,
52242
- assetBaseUrl: assetManifest?.baseUrl,
52243
52292
  onDraw
52244
52293
  }
52245
52294
  ),
@@ -52364,15 +52413,6 @@ var init_TopDownShooterTemplate = __esm({
52364
52413
  TopDownShooterTemplate.displayName = "TopDownShooterTemplate";
52365
52414
  }
52366
52415
  });
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
52416
  function buildDefaultTDTiles() {
52377
52417
  const pathSet = new Set(DEFAULT_TD_PATH.map((p2) => `${p2.x},${p2.y}`));
52378
52418
  const tiles = [];
@@ -52392,18 +52432,18 @@ function buildDefaultTDTiles() {
52392
52432
  function tilesToIso2(tiles, manifest) {
52393
52433
  return tiles.map((t) => {
52394
52434
  const key = t.terrain ?? "ground";
52395
- const sprite = t.terrainSprite ?? resolveManifestUrl5(manifest, manifest?.terrains?.[key]) ?? resolveManifestUrl5(manifest, manifest?.terrains?.ground);
52435
+ const terrainSprite = t.terrainSprite != null ? makeAsset(t.terrainSprite, "tile") : manifest?.terrains?.[key] ?? manifest?.terrains?.ground;
52396
52436
  return {
52397
52437
  x: t.x,
52398
52438
  y: t.y,
52399
52439
  terrain: t.terrain,
52400
- terrainSprite: sprite,
52440
+ terrainSprite,
52401
52441
  passable: t.passable
52402
52442
  };
52403
52443
  });
52404
52444
  }
52405
52445
  function creepsToUnits(creeps, manifest) {
52406
- const sprite = resolveManifestUrl5(manifest, manifest?.units?.creep);
52446
+ const sprite = manifest?.units?.creep;
52407
52447
  return creeps.map((c) => ({
52408
52448
  id: c.id,
52409
52449
  position: { x: c.x, y: c.y },
@@ -52421,14 +52461,14 @@ function heroToUnit(hero, manifest) {
52421
52461
  position: { x: hero.x, y: hero.y },
52422
52462
  name: "Hero",
52423
52463
  team: "player",
52424
- sprite: resolveManifestUrl5(manifest, manifest?.units?.hero),
52464
+ sprite: manifest?.units?.hero,
52425
52465
  unitType: "hero",
52426
52466
  health: 1,
52427
52467
  maxHealth: 1
52428
52468
  };
52429
52469
  }
52430
52470
  function towersToFeatures(towers, manifest) {
52431
- const sprite = resolveManifestUrl5(manifest, manifest?.features?.tower);
52471
+ const sprite = manifest?.features?.tower;
52432
52472
  return towers.map((t) => ({
52433
52473
  id: t.id,
52434
52474
  x: t.x,
@@ -52626,7 +52666,6 @@ function TowerDefenseBoard({
52626
52666
  tiles: isoTiles,
52627
52667
  units: isoUnits,
52628
52668
  features: towerFeatures,
52629
- assetBaseUrl: assetManifest?.baseUrl,
52630
52669
  assetManifest,
52631
52670
  validMoves,
52632
52671
  hoveredTile,
@@ -52670,6 +52709,7 @@ var TD_GRID_W, TD_GRID_H, DEFAULT_TD_PATH, DEFAULT_TD_TILES;
52670
52709
  var init_TowerDefenseBoard = __esm({
52671
52710
  "components/game/organisms/TowerDefenseBoard.tsx"() {
52672
52711
  "use client";
52712
+ init_makeAsset();
52673
52713
  init_cn();
52674
52714
  init_useEventBus();
52675
52715
  init_Box();
@@ -52999,15 +53039,6 @@ var init_UncontrolledBattleBoard = __esm({
52999
53039
  UncontrolledBattleBoard.displayName = "UncontrolledBattleBoard";
53000
53040
  }
53001
53041
  });
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
53042
  function VisualNovelBoard({
53012
53043
  entity,
53013
53044
  nodes: propNodes,
@@ -53042,11 +53073,11 @@ function VisualNovelBoard({
53042
53073
  const currentNodeId = propCurrentNodeId ?? (str(board.currentNodeId) || nodes[0]?.id);
53043
53074
  const currentNode = nodes.find((n) => n.id === currentNodeId) ?? nodes[0];
53044
53075
  const backgroundImage = useMemo(
53045
- () => resolveManifestUrl6(assetManifest, assetManifest?.backgrounds?.[currentNode?.backgroundKey ?? ""]),
53076
+ () => assetManifest?.backgrounds?.[currentNode?.backgroundKey ?? ""],
53046
53077
  [assetManifest, currentNode?.backgroundKey]
53047
53078
  );
53048
53079
  const portraitUrl = useMemo(
53049
- () => resolveManifestUrl6(assetManifest, assetManifest?.portraits?.[currentNode?.portraitKey ?? ""]),
53080
+ () => assetManifest?.portraits?.[currentNode?.portraitKey ?? ""],
53050
53081
  [assetManifest, currentNode?.portraitKey]
53051
53082
  );
53052
53083
  const dialogueChoices = useMemo(
@@ -53220,7 +53251,7 @@ function buildDefaultWorldTiles() {
53220
53251
  for (let x = 0; x < WORLD_GRID_W; x++) {
53221
53252
  const isBorder = x === 0 || y === 0 || x === WORLD_GRID_W - 1 || y === WORLD_GRID_H - 1;
53222
53253
  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 });
53254
+ tiles.push({ x, y, terrain: def.terrain, terrainSprite: makeAsset(def.sprite, "tile"), passable: def.passable });
53224
53255
  }
53225
53256
  }
53226
53257
  return tiles;
@@ -53264,7 +53295,12 @@ function WorldMapBoard({
53264
53295
  const resolved = boardEntity(entity);
53265
53296
  const entityUnits = rows(resolved?.units);
53266
53297
  const entityTiles = rows(resolved?.tiles);
53267
- const features = propFeatures ?? rows(resolved?.features);
53298
+ const features = propFeatures ?? rows(resolved?.features).map((r) => ({
53299
+ id: r.id == null ? void 0 : str(r.id),
53300
+ x: num(r.x),
53301
+ y: num(r.y),
53302
+ type: str(r.type)
53303
+ }));
53268
53304
  const selectedHeroId = resolved?.selectedHeroId ?? null;
53269
53305
  const assetManifest = propAssetManifest ?? resolved?.assetManifest;
53270
53306
  const backgroundImage = resolved?.backgroundImage;
@@ -53274,7 +53310,7 @@ function WorldMapBoard({
53274
53310
  x: num(t.x),
53275
53311
  y: num(t.y),
53276
53312
  terrain: str(t.terrain),
53277
- terrainSprite: t.terrainSprite == null ? void 0 : str(t.terrainSprite),
53313
+ terrainSprite: t.terrainSprite == null ? void 0 : makeAsset(str(t.terrainSprite), "tile"),
53278
53314
  passable: t.passable !== false
53279
53315
  })),
53280
53316
  [entityTiles]
@@ -53290,7 +53326,7 @@ function WorldMapBoard({
53290
53326
  team: str(u.team) === "enemy" ? "enemy" : "player",
53291
53327
  health: num(u.health) || 100,
53292
53328
  maxHealth: num(u.maxHealth) || 100,
53293
- sprite: u.sprite == null ? void 0 : str(u.sprite)
53329
+ sprite: u.sprite == null ? void 0 : makeAsset(str(u.sprite), "player")
53294
53330
  })),
53295
53331
  [entityUnits, propUnits]
53296
53332
  );
@@ -53472,7 +53508,6 @@ function WorldMapBoard({
53472
53508
  onTileHover: (x, y) => setHoveredTile({ x, y }),
53473
53509
  onTileLeave: () => setHoveredTile(null),
53474
53510
  scale,
53475
- assetBaseUrl: assetManifest?.baseUrl,
53476
53511
  assetManifest,
53477
53512
  backgroundImage,
53478
53513
  effectSpriteUrls,
@@ -53495,6 +53530,7 @@ var WORLD_CDN, WORLD_GRID_W, WORLD_GRID_H, WORLD_TERRAIN_DEFS, DEFAULT_WORLD_TIL
53495
53530
  var init_WorldMapBoard = __esm({
53496
53531
  "components/game/organisms/WorldMapBoard.tsx"() {
53497
53532
  "use client";
53533
+ init_makeAsset();
53498
53534
  init_cn();
53499
53535
  init_useEventBus();
53500
53536
  init_Stack();
@@ -53548,62 +53584,66 @@ function WorldMapTemplate({
53548
53584
  }
53549
53585
  );
53550
53586
  }
53551
- var CDN5, DEFAULT_WORLDMAP_TILES, DEFAULT_WORLDMAP_UNITS, DEFAULT_WORLDMAP_FEATURES, DEFAULT_WORLDMAP_MANIFEST;
53587
+ var CDN5, mountain, water, grass, road, DEFAULT_WORLDMAP_TILES, DEFAULT_WORLDMAP_UNITS, DEFAULT_WORLDMAP_FEATURES, DEFAULT_WORLDMAP_MANIFEST;
53552
53588
  var init_WorldMapTemplate = __esm({
53553
53589
  "components/game/templates/WorldMapTemplate.tsx"() {
53554
53590
  init_WorldMapBoard();
53591
+ init_makeAsset();
53555
53592
  CDN5 = "https://almadar-kflow-assets.web.app/shared";
53593
+ mountain = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png`, "tile");
53594
+ water = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png`, "tile");
53595
+ grass = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`, "tile");
53596
+ road = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png`, "tile");
53556
53597
  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` }
53598
+ { x: 0, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53599
+ { x: 1, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53600
+ { x: 2, y: 0, terrain: "water", passable: false, terrainSprite: water },
53601
+ { x: 3, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53602
+ { x: 4, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53603
+ { x: 0, y: 1, terrain: "mountain", passable: false, terrainSprite: mountain },
53604
+ { x: 1, y: 1, terrain: "grass", passable: true, terrainSprite: grass },
53605
+ { x: 2, y: 1, terrain: "grass", passable: true, terrainSprite: grass },
53606
+ { x: 3, y: 1, terrain: "grass", passable: true, terrainSprite: grass },
53607
+ { x: 4, y: 1, terrain: "water", passable: false, terrainSprite: water },
53608
+ { x: 0, y: 2, terrain: "water", passable: false, terrainSprite: water },
53609
+ { x: 1, y: 2, terrain: "grass", passable: true, terrainSprite: grass },
53610
+ { x: 2, y: 2, terrain: "grass", passable: true, terrainSprite: road },
53611
+ { x: 3, y: 2, terrain: "grass", passable: true, terrainSprite: grass },
53612
+ { x: 4, y: 2, terrain: "mountain", passable: false, terrainSprite: mountain },
53613
+ { x: 0, y: 3, terrain: "mountain", passable: false, terrainSprite: mountain },
53614
+ { x: 1, y: 3, terrain: "grass", passable: true, terrainSprite: grass },
53615
+ { x: 2, y: 3, terrain: "grass", passable: true, terrainSprite: grass },
53616
+ { x: 3, y: 3, terrain: "grass", passable: true, terrainSprite: road },
53617
+ { x: 4, y: 3, terrain: "mountain", passable: false, terrainSprite: mountain },
53618
+ { x: 0, y: 4, terrain: "mountain", passable: false, terrainSprite: mountain },
53619
+ { x: 1, y: 4, terrain: "water", passable: false, terrainSprite: water },
53620
+ { x: 2, y: 4, terrain: "grass", passable: true, terrainSprite: grass },
53621
+ { x: 3, y: 4, terrain: "mountain", passable: false, terrainSprite: mountain },
53622
+ { x: 4, y: 4, terrain: "mountain", passable: false, terrainSprite: mountain }
53582
53623
  ];
53583
53624
  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` }
53625
+ { 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") },
53626
+ { 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
53627
  ];
53587
53628
  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` }
53629
+ { id: "f1", x: 2, y: 2, type: "capital", sprite: makeAsset(`${CDN5}/scenes/world/capital.png`, "decoration") },
53630
+ { id: "f2", x: 4, y: 2, type: "power_node", sprite: makeAsset(`${CDN5}/world-map/power_node.png`, "decoration") }
53590
53631
  ];
53591
53632
  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
- },
53633
+ terrains: makeAssetMap({
53634
+ grass: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`,
53635
+ water: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png`,
53636
+ mountain: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png`,
53637
+ road: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png`
53638
+ }, "tile"),
53599
53639
  units: {
53600
- hero: "/sprite-sheets/amir-sprite-sheet-se.png",
53601
- scout: "/sprite-sheets/archivist-sprite-sheet-se.png"
53640
+ hero: makeAsset(`${CDN5}/sprite-sheets/amir-sprite-sheet-se.png`, "player"),
53641
+ scout: makeAsset(`${CDN5}/sprite-sheets/archivist-sprite-sheet-se.png`, "npc")
53602
53642
  },
53603
- features: {
53604
- capital: "/scenes/world/capital.png",
53605
- power_node: "/world-map/power_node.png"
53606
- }
53643
+ features: makeAssetMap({
53644
+ capital: `${CDN5}/scenes/world/capital.png`,
53645
+ power_node: `${CDN5}/world-map/power_node.png`
53646
+ }, "decoration")
53607
53647
  };
53608
53648
  WorldMapTemplate.displayName = "WorldMapTemplate";
53609
53649
  }