@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
@@ -6913,7 +6913,7 @@ function ScoreDisplay({
6913
6913
  assetUrl ? /* @__PURE__ */ jsx(
6914
6914
  "img",
6915
6915
  {
6916
- src: assetUrl,
6916
+ src: assetUrl.url,
6917
6917
  alt: "",
6918
6918
  width: 20,
6919
6919
  height: 20,
@@ -6938,7 +6938,11 @@ var init_ScoreDisplay = __esm({
6938
6938
  lg: "text-2xl",
6939
6939
  xl: "text-4xl"
6940
6940
  };
6941
- DEFAULT_ASSET_URL = "https://almadar-kflow-assets.web.app/shared/effects/particles/star_01.png";
6941
+ DEFAULT_ASSET_URL = {
6942
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/star_01.png",
6943
+ role: "effect",
6944
+ category: "effect"
6945
+ };
6942
6946
  ScoreDisplay.displayName = "ScoreDisplay";
6943
6947
  }
6944
6948
  });
@@ -7014,7 +7018,7 @@ function ControlButton({
7014
7018
  children: assetUrl ? /* @__PURE__ */ jsx(
7015
7019
  "img",
7016
7020
  {
7017
- src: assetUrl,
7021
+ src: assetUrl.url,
7018
7022
  alt: "",
7019
7023
  width: 24,
7020
7024
  height: 24,
@@ -7054,7 +7058,11 @@ var init_ControlButton = __esm({
7054
7058
  secondary: "bg-secondary text-secondary-foreground border-border hover:bg-secondary-hover",
7055
7059
  ghost: "bg-transparent text-foreground border-border hover:bg-muted"
7056
7060
  };
7057
- DEFAULT_ASSET_URL2 = "https://almadar-kflow-assets.web.app/shared/effects/particles/circle_01.png";
7061
+ DEFAULT_ASSET_URL2 = {
7062
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/circle_01.png",
7063
+ role: "effect",
7064
+ category: "effect"
7065
+ };
7058
7066
  ControlButton.displayName = "ControlButton";
7059
7067
  }
7060
7068
  });
@@ -7093,7 +7101,7 @@ var init_spriteAnimation = __esm({
7093
7101
  }
7094
7102
  });
7095
7103
  function Sprite({
7096
- spritesheet = "https://almadar-kflow-assets.web.app/shared/isometric-blocks/Spritesheet/allTiles_sheet.png",
7104
+ spritesheet = DEFAULT_SPRITESHEET,
7097
7105
  frameWidth = 64,
7098
7106
  frameHeight = 64,
7099
7107
  frame = 0,
@@ -7146,7 +7154,7 @@ function Sprite({
7146
7154
  position: "absolute",
7147
7155
  width: frameWidth,
7148
7156
  height: frameHeight,
7149
- backgroundImage: `url(${spritesheet})`,
7157
+ backgroundImage: `url(${spritesheet.url})`,
7150
7158
  backgroundPosition,
7151
7159
  backgroundRepeat: "no-repeat",
7152
7160
  imageRendering: "pixelated",
@@ -7159,11 +7167,17 @@ function Sprite({
7159
7167
  }
7160
7168
  );
7161
7169
  }
7170
+ var DEFAULT_SPRITESHEET;
7162
7171
  var init_Sprite = __esm({
7163
7172
  "components/game/atoms/Sprite.tsx"() {
7164
7173
  "use client";
7165
7174
  init_useEventBus();
7166
7175
  init_spriteAnimation();
7176
+ DEFAULT_SPRITESHEET = {
7177
+ url: "https://almadar-kflow-assets.web.app/shared/isometric-blocks/Spritesheet/allTiles_sheet.png",
7178
+ role: "tile",
7179
+ category: "tile"
7180
+ };
7167
7181
  }
7168
7182
  });
7169
7183
  function StateIndicator({
@@ -7193,7 +7207,7 @@ function StateIndicator({
7193
7207
  /* @__PURE__ */ jsx(Box, { as: "span", children: assetUrl ? /* @__PURE__ */ jsx(
7194
7208
  "img",
7195
7209
  {
7196
- src: assetUrl,
7210
+ src: assetUrl.url,
7197
7211
  alt: displayLabel,
7198
7212
  width: 16,
7199
7213
  height: 16,
@@ -7212,7 +7226,11 @@ var init_StateIndicator = __esm({
7212
7226
  init_Box();
7213
7227
  init_Icon();
7214
7228
  init_cn();
7215
- DEFAULT_ASSET_URL3 = "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png";
7229
+ DEFAULT_ASSET_URL3 = {
7230
+ url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
7231
+ role: "effect",
7232
+ category: "item"
7233
+ };
7216
7234
  DEFAULT_STATE_STYLES = {
7217
7235
  idle: { icon: "\u23F8", bgClass: "bg-muted" },
7218
7236
  active: { icon: "\u25B6", bgClass: "bg-success" },
@@ -7310,7 +7328,7 @@ function ResourceCounter({
7310
7328
  assetUrl ? /* @__PURE__ */ jsx(
7311
7329
  "img",
7312
7330
  {
7313
- src: assetUrl,
7331
+ src: assetUrl.url,
7314
7332
  alt: label,
7315
7333
  width: sizes.img,
7316
7334
  height: sizes.img,
@@ -7343,7 +7361,11 @@ var init_ResourceCounter = __esm({
7343
7361
  error: "text-error",
7344
7362
  muted: "text-muted-foreground"
7345
7363
  };
7346
- DEFAULT_ASSET_URL4 = "https://almadar-kflow-assets.web.app/shared/world-map/gold_mine.png";
7364
+ DEFAULT_ASSET_URL4 = {
7365
+ url: "https://almadar-kflow-assets.web.app/shared/world-map/gold_mine.png",
7366
+ role: "effect",
7367
+ category: "world"
7368
+ };
7347
7369
  sizeMap5 = {
7348
7370
  sm: { wrapper: "text-xs gap-1 px-1.5 py-0.5", icon: "text-sm", img: 16 },
7349
7371
  md: { wrapper: "text-sm gap-1.5 px-2 py-1", icon: "text-base", img: 20 },
@@ -7389,7 +7411,7 @@ function ItemSlot({
7389
7411
  assetUrl ? /* @__PURE__ */ jsx(
7390
7412
  "img",
7391
7413
  {
7392
- src: assetUrl,
7414
+ src: assetUrl?.url,
7393
7415
  alt: label,
7394
7416
  width: px,
7395
7417
  height: px,
@@ -7437,7 +7459,11 @@ var init_ItemSlot = __esm({
7437
7459
  epic: "shadow-lg",
7438
7460
  legendary: "shadow-lg"
7439
7461
  };
7440
- DEFAULT_ASSET_URL5 = "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png";
7462
+ DEFAULT_ASSET_URL5 = {
7463
+ url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
7464
+ role: "effect",
7465
+ category: "item"
7466
+ };
7441
7467
  assetSizeMap = {
7442
7468
  sm: 28,
7443
7469
  md: 40,
@@ -7483,7 +7509,7 @@ function TurnIndicator({
7483
7509
  assetUrl ? /* @__PURE__ */ jsx(
7484
7510
  "img",
7485
7511
  {
7486
- src: assetUrl,
7512
+ src: assetUrl.url,
7487
7513
  alt: "",
7488
7514
  width: 12,
7489
7515
  height: 12,
@@ -7506,7 +7532,11 @@ var init_TurnIndicator = __esm({
7506
7532
  md: { wrapper: "text-sm gap-2 px-3 py-1", dot: "w-2 h-2" },
7507
7533
  lg: { wrapper: "text-base gap-2.5 px-4 py-1.5", dot: "w-2.5 h-2.5" }
7508
7534
  };
7509
- DEFAULT_ASSET_URL6 = "https://almadar-kflow-assets.web.app/shared/effects/particles/symbol_01.png";
7535
+ DEFAULT_ASSET_URL6 = {
7536
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/symbol_01.png",
7537
+ role: "effect",
7538
+ category: "effect"
7539
+ };
7510
7540
  TurnIndicator.displayName = "TurnIndicator";
7511
7541
  }
7512
7542
  });
@@ -7545,7 +7575,7 @@ function ComboCounter({
7545
7575
  assetUrl && /* @__PURE__ */ jsx(
7546
7576
  "img",
7547
7577
  {
7548
- src: assetUrl,
7578
+ src: assetUrl.url,
7549
7579
  alt: "combo",
7550
7580
  width: 24,
7551
7581
  height: 24,
@@ -7571,7 +7601,11 @@ var DEFAULT_ASSET_URL7, sizeMap8;
7571
7601
  var init_ComboCounter = __esm({
7572
7602
  "components/game/atoms/ComboCounter.tsx"() {
7573
7603
  init_cn();
7574
- DEFAULT_ASSET_URL7 = "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png";
7604
+ DEFAULT_ASSET_URL7 = {
7605
+ url: "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png",
7606
+ role: "effect",
7607
+ category: "effect"
7608
+ };
7575
7609
  sizeMap8 = {
7576
7610
  sm: { combo: "text-lg", label: "text-xs", multiplier: "text-xs" },
7577
7611
  md: { combo: "text-2xl", label: "text-xs", multiplier: "text-sm" },
@@ -7691,7 +7725,7 @@ function WaypointMarker({
7691
7725
  children: completed ? checkIcon : assetUrl ? /* @__PURE__ */ jsx(
7692
7726
  "img",
7693
7727
  {
7694
- src: assetUrl,
7728
+ src: assetUrl.url,
7695
7729
  alt: label,
7696
7730
  width: sizes.img,
7697
7731
  height: sizes.img,
@@ -7720,7 +7754,11 @@ var init_WaypointMarker = __esm({
7720
7754
  "components/game/atoms/WaypointMarker.tsx"() {
7721
7755
  init_cn();
7722
7756
  init_Icon();
7723
- DEFAULT_ASSET_URL8 = "https://almadar-kflow-assets.web.app/shared/world-map/battle_marker.png";
7757
+ DEFAULT_ASSET_URL8 = {
7758
+ url: "https://almadar-kflow-assets.web.app/shared/world-map/battle_marker.png",
7759
+ role: "effect",
7760
+ category: "world"
7761
+ };
7724
7762
  sizeMap10 = {
7725
7763
  sm: { dot: "w-4 h-4", ring: "w-6 h-6", label: "text-xs mt-1", img: 12 },
7726
7764
  md: { dot: "w-6 h-6", ring: "w-8 h-8", label: "text-sm mt-1.5", img: 18 },
@@ -7761,7 +7799,7 @@ function StatusEffect({
7761
7799
  /* @__PURE__ */ jsx("span", { className: cn("flex items-center justify-center", sizes.icon), children: assetUrl ? /* @__PURE__ */ jsx(
7762
7800
  "img",
7763
7801
  {
7764
- src: assetUrl,
7802
+ src: assetUrl.url,
7765
7803
  alt: label,
7766
7804
  width: sizes.img,
7767
7805
  height: sizes.img,
@@ -7800,7 +7838,11 @@ var init_StatusEffect = __esm({
7800
7838
  "components/game/atoms/StatusEffect.tsx"() {
7801
7839
  init_cn();
7802
7840
  init_Icon();
7803
- DEFAULT_ASSET_URL9 = "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png";
7841
+ DEFAULT_ASSET_URL9 = {
7842
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png",
7843
+ role: "effect",
7844
+ category: "effect"
7845
+ };
7804
7846
  sizeMap11 = {
7805
7847
  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 },
7806
7848
  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 },
@@ -7838,7 +7880,7 @@ function DamageNumber({
7838
7880
  assetUrl && /* @__PURE__ */ jsx(
7839
7881
  "img",
7840
7882
  {
7841
- src: assetUrl,
7883
+ src: assetUrl.url,
7842
7884
  alt: "",
7843
7885
  width: 14,
7844
7886
  height: 14,
@@ -7874,14 +7916,18 @@ var init_DamageNumber = __esm({
7874
7916
  100% { opacity: 0; transform: translateY(-32px) scale(0.8); }
7875
7917
  }
7876
7918
  `;
7877
- DEFAULT_ASSET_URL10 = "https://almadar-kflow-assets.web.app/shared/effects/particles/spark_01.png";
7919
+ DEFAULT_ASSET_URL10 = {
7920
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/spark_01.png",
7921
+ role: "effect",
7922
+ category: "effect"
7923
+ };
7878
7924
  DamageNumber.displayName = "DamageNumber";
7879
7925
  }
7880
7926
  });
7881
7927
  function DialogueBubble({
7882
7928
  speaker = "Hero",
7883
7929
  text = "The dungeon awaits. Choose your path wisely.",
7884
- portrait = "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
7930
+ portrait = DEFAULT_PORTRAIT,
7885
7931
  position = "bottom",
7886
7932
  className
7887
7933
  }) {
@@ -7897,7 +7943,7 @@ function DialogueBubble({
7897
7943
  portrait && /* @__PURE__ */ jsx("div", { className: "flex-shrink-0 w-12 h-12 rounded-full overflow-hidden border-2 border-warning/60", children: /* @__PURE__ */ jsx(
7898
7944
  "img",
7899
7945
  {
7900
- src: portrait,
7946
+ src: portrait?.url,
7901
7947
  alt: speaker ?? "speaker",
7902
7948
  className: "w-full h-full object-cover"
7903
7949
  }
@@ -7910,9 +7956,15 @@ function DialogueBubble({
7910
7956
  }
7911
7957
  );
7912
7958
  }
7959
+ var DEFAULT_PORTRAIT;
7913
7960
  var init_DialogueBubble = __esm({
7914
7961
  "components/game/atoms/DialogueBubble.tsx"() {
7915
7962
  init_cn();
7963
+ DEFAULT_PORTRAIT = {
7964
+ url: "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
7965
+ role: "effect",
7966
+ category: "character"
7967
+ };
7916
7968
  DialogueBubble.displayName = "DialogueBubble";
7917
7969
  }
7918
7970
  });
@@ -7956,7 +8008,7 @@ function ChoiceButton({
7956
8008
  assetUrl ? /* @__PURE__ */ jsx(
7957
8009
  "img",
7958
8010
  {
7959
- src: assetUrl,
8011
+ src: assetUrl.url,
7960
8012
  alt: "",
7961
8013
  width: 16,
7962
8014
  height: 16,
@@ -8026,7 +8078,7 @@ function ActionButton({
8026
8078
  assetUrl ? /* @__PURE__ */ jsx(
8027
8079
  "img",
8028
8080
  {
8029
- src: assetUrl,
8081
+ src: assetUrl.url,
8030
8082
  alt: "",
8031
8083
  width: 16,
8032
8084
  height: 16,
@@ -8070,7 +8122,11 @@ var init_ActionButton = __esm({
8070
8122
  secondary: "bg-secondary text-secondary-foreground hover:bg-secondary-hover border-border",
8071
8123
  danger: "bg-error text-error-foreground hover:bg-error/90 border-error"
8072
8124
  };
8073
- DEFAULT_ASSET_URL11 = "https://almadar-kflow-assets.web.app/shared/effects/particles/slash_01.png";
8125
+ DEFAULT_ASSET_URL11 = {
8126
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/slash_01.png",
8127
+ role: "effect",
8128
+ category: "effect"
8129
+ };
8074
8130
  ActionButton.displayName = "ActionButton";
8075
8131
  }
8076
8132
  });
@@ -11001,12 +11057,7 @@ var init_useCanvasGestures = __esm({
11001
11057
  }
11002
11058
  });
11003
11059
  function unitAtlasUrl(unit) {
11004
- if (unit.spriteSheet) return unit.spriteSheet;
11005
- const sprite = unit.sprite;
11006
- if (!sprite) return null;
11007
- const match = /^(.*-sprite-sheet)(?:-(?:se|sw))?(?:-v\d+)?\.png$/.exec(sprite);
11008
- if (!match) return null;
11009
- return `${match[1]}.json`;
11060
+ return unit.spriteSheet?.url ?? null;
11010
11061
  }
11011
11062
  function resolveSheetUrl(atlasUrl, relativeSheetPath) {
11012
11063
  try {
@@ -11202,7 +11253,6 @@ function IsometricCanvas({
11202
11253
  // Tuning
11203
11254
  diamondTopY: diamondTopYProp,
11204
11255
  // Remote asset loading
11205
- assetBaseUrl,
11206
11256
  assetManifest
11207
11257
  }) {
11208
11258
  const tilesProp = Array.isArray(_tilesPropRaw) ? _tilesPropRaw : [];
@@ -11284,54 +11334,48 @@ function IsometricCanvas({
11284
11334
  const attackTargetSet = useMemo(() => {
11285
11335
  return new Set(attackTargets.map((p2) => `${p2.x},${p2.y}`));
11286
11336
  }, [attackTargets]);
11287
- const resolveManifestUrl7 = useCallback((relativePath) => {
11288
- if (!relativePath) return void 0;
11289
- if (assetBaseUrl) return `${assetBaseUrl.replace(/\/$/, "")}${relativePath.startsWith("/") ? "" : "/"}${relativePath}`;
11290
- return relativePath;
11291
- }, [assetBaseUrl]);
11292
11337
  const spriteUrls = useMemo(() => {
11293
11338
  const urls = [];
11294
11339
  for (const tile of sortedTiles) {
11295
- if (tile.terrainSprite) urls.push(tile.terrainSprite);
11340
+ if (tile.terrainSprite) urls.push(tile.terrainSprite.url);
11296
11341
  else if (getTerrainSprite) {
11297
11342
  const url = getTerrainSprite(tile.terrain ?? "");
11298
11343
  if (url) urls.push(url);
11299
11344
  } else {
11300
- const url = resolveManifestUrl7(assetManifest?.terrains?.[tile.terrain ?? ""]);
11345
+ const url = assetManifest?.terrains?.[tile.terrain ?? ""]?.url;
11301
11346
  if (url) urls.push(url);
11302
11347
  }
11303
11348
  }
11304
11349
  for (const feature of features) {
11305
- if (feature.sprite) urls.push(feature.sprite);
11350
+ if (feature.sprite) urls.push(feature.sprite.url);
11306
11351
  else if (getFeatureSprite) {
11307
11352
  const url = getFeatureSprite(feature.type);
11308
11353
  if (url) urls.push(url);
11309
11354
  } else {
11310
- const url = resolveManifestUrl7(assetManifest?.features?.[feature.type]);
11355
+ const url = assetManifest?.features?.[feature.type]?.url;
11311
11356
  if (url) urls.push(url);
11312
11357
  }
11313
11358
  }
11314
11359
  for (const unit of units) {
11315
- if (unit.sprite) urls.push(unit.sprite);
11360
+ if (unit.sprite) urls.push(unit.sprite.url);
11316
11361
  else if (getUnitSprite) {
11317
11362
  const url = getUnitSprite(unit);
11318
11363
  if (url) urls.push(url);
11319
11364
  } else if (unit.unitType) {
11320
- const url = resolveManifestUrl7(assetManifest?.units?.[unit.unitType]);
11365
+ const url = assetManifest?.units?.[unit.unitType]?.url;
11321
11366
  if (url) urls.push(url);
11322
11367
  }
11323
11368
  }
11324
11369
  if (assetManifest?.effects) {
11325
- for (const path of Object.values(assetManifest.effects)) {
11326
- const url = resolveManifestUrl7(path);
11327
- if (url) urls.push(url);
11370
+ for (const asset of Object.values(assetManifest.effects)) {
11371
+ if (asset.url) urls.push(asset.url);
11328
11372
  }
11329
11373
  }
11330
11374
  if (effectSpriteUrls) urls.push(...effectSpriteUrls);
11331
11375
  if (atlasSheetUrls.length) urls.push(...atlasSheetUrls);
11332
11376
  if (backgroundImage) urls.push(backgroundImage);
11333
11377
  return [...new Set(urls.filter(Boolean))];
11334
- }, [sortedTiles, features, units, getTerrainSprite, getFeatureSprite, getUnitSprite, effectSpriteUrls, atlasSheetUrls, backgroundImage, assetManifest, resolveManifestUrl7]);
11378
+ }, [sortedTiles, features, units, getTerrainSprite, getFeatureSprite, getUnitSprite, effectSpriteUrls, atlasSheetUrls, backgroundImage, assetManifest]);
11335
11379
  const { getImage, pendingCount: _imagePendingCount } = useImageCache(spriteUrls);
11336
11380
  useEffect(() => {
11337
11381
  if (typeof window === "undefined") return;
@@ -11356,14 +11400,14 @@ function IsometricCanvas({
11356
11400
  lerpToTarget
11357
11401
  } = useCamera();
11358
11402
  const resolveTerrainSpriteUrl = useCallback((tile) => {
11359
- return tile.terrainSprite || getTerrainSprite?.(tile.terrain ?? "") || resolveManifestUrl7(assetManifest?.terrains?.[tile.terrain ?? ""]);
11360
- }, [getTerrainSprite, assetManifest, resolveManifestUrl7]);
11403
+ return tile.terrainSprite?.url || getTerrainSprite?.(tile.terrain ?? "") || assetManifest?.terrains?.[tile.terrain ?? ""]?.url;
11404
+ }, [getTerrainSprite, assetManifest]);
11361
11405
  const resolveFeatureSpriteUrl = useCallback((featureType) => {
11362
- return getFeatureSprite?.(featureType) || resolveManifestUrl7(assetManifest?.features?.[featureType]);
11363
- }, [getFeatureSprite, assetManifest, resolveManifestUrl7]);
11406
+ return getFeatureSprite?.(featureType) || assetManifest?.features?.[featureType]?.url;
11407
+ }, [getFeatureSprite, assetManifest]);
11364
11408
  const resolveUnitSpriteUrl = useCallback((unit) => {
11365
- return unit.sprite || getUnitSprite?.(unit) || (unit.unitType ? resolveManifestUrl7(assetManifest?.units?.[unit.unitType]) : void 0);
11366
- }, [getUnitSprite, assetManifest, resolveManifestUrl7]);
11409
+ return unit.sprite?.url || getUnitSprite?.(unit) || (unit.unitType ? assetManifest?.units?.[unit.unitType]?.url : void 0);
11410
+ }, [getUnitSprite, assetManifest]);
11367
11411
  const miniMapTiles = useMemo(() => {
11368
11412
  if (!showMinimap) return [];
11369
11413
  return sortedTiles.map((t2) => ({
@@ -11510,7 +11554,7 @@ function IsometricCanvas({
11510
11554
  if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
11511
11555
  continue;
11512
11556
  }
11513
- const spriteUrl = feature.sprite || resolveFeatureSpriteUrl(feature.type);
11557
+ const spriteUrl = feature.sprite?.url || resolveFeatureSpriteUrl(feature.type);
11514
11558
  const img = spriteUrl ? getImage(spriteUrl) : null;
11515
11559
  const centerX = pos.x + scaledTileWidth / 2;
11516
11560
  const featureGroundY = pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
@@ -11559,12 +11603,12 @@ function IsometricCanvas({
11559
11603
  const img = unitSpriteUrl ? getImage(unitSpriteUrl) : null;
11560
11604
  const unitDrawH = scaledFloorHeight * spriteHeightRatio * unitScale;
11561
11605
  const maxUnitW = scaledTileWidth * spriteMaxWidthRatio * unitScale;
11606
+ const unitIsSheet = unit.sprite?.dimension === "2d" && (unit.sprite?.animations?.length ?? 0) > 0;
11562
11607
  const SHEET_ROWS = 5;
11563
11608
  const sheetFrameW = img ? img.naturalWidth / SHEET_COLUMNS : 0;
11564
11609
  const sheetFrameH = img ? img.naturalHeight / SHEET_ROWS : 0;
11565
- const imgIsSheet = img ? img.naturalWidth % SHEET_COLUMNS === 0 && img.naturalHeight % SHEET_ROWS === 0 && Math.abs(sheetFrameW - sheetFrameH) < 2 : false;
11566
- const frameW = imgIsSheet ? sheetFrameW : img?.naturalWidth ?? 1;
11567
- const frameH = imgIsSheet ? sheetFrameH : img?.naturalHeight ?? 1;
11610
+ const frameW = unitIsSheet ? sheetFrameW : img?.naturalWidth ?? 1;
11611
+ const frameH = unitIsSheet ? sheetFrameH : img?.naturalHeight ?? 1;
11568
11612
  const ar = frameW / (frameH || 1);
11569
11613
  let drawH = unitDrawH;
11570
11614
  let drawW = unitDrawH * ar;
@@ -11579,7 +11623,7 @@ function IsometricCanvas({
11579
11623
  ctx.save();
11580
11624
  ctx.globalAlpha = 0.25;
11581
11625
  if (img) {
11582
- if (imgIsSheet) {
11626
+ if (unitIsSheet) {
11583
11627
  ctx.drawImage(img, 0, 0, sheetFrameW, sheetFrameH, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
11584
11628
  } else {
11585
11629
  ctx.drawImage(img, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
@@ -11627,7 +11671,7 @@ function IsometricCanvas({
11627
11671
  } else if (img) {
11628
11672
  const spriteY = groundY - drawH - breatheOffset;
11629
11673
  const drawUnit = (x) => {
11630
- if (imgIsSheet) {
11674
+ if (unitIsSheet) {
11631
11675
  ctx.drawImage(img, 0, 0, sheetFrameW, sheetFrameH, x, spriteY, drawW, drawH);
11632
11676
  } else {
11633
11677
  ctx.drawImage(img, x, spriteY, drawW, drawH);
@@ -11654,7 +11698,7 @@ function IsometricCanvas({
11654
11698
  }
11655
11699
  }
11656
11700
  for (const fx of effects) {
11657
- const spriteUrl = resolveManifestUrl7(assetManifest?.effects?.[fx.key]);
11701
+ const spriteUrl = assetManifest?.effects?.[fx.key]?.url;
11658
11702
  if (!spriteUrl) continue;
11659
11703
  const img = getImage(spriteUrl);
11660
11704
  if (!img) continue;
@@ -11698,7 +11742,6 @@ function IsometricCanvas({
11698
11742
  backgroundImage,
11699
11743
  cameraRef,
11700
11744
  unitScale,
11701
- resolveManifestUrl7,
11702
11745
  assetManifest
11703
11746
  ]);
11704
11747
  useEffect(() => {
@@ -11976,6 +12019,42 @@ var init_boardEntity = __esm({
11976
12019
  "components/game/organisms/boardEntity.ts"() {
11977
12020
  }
11978
12021
  });
12022
+
12023
+ // components/game/organisms/utils/makeAsset.ts
12024
+ function makeAsset(url, role, overrides = {}) {
12025
+ const defaults = ROLE_DEFAULTS[role] ?? { dimension: "2d", animations: ["static"], aspect: "1:1" };
12026
+ return {
12027
+ url,
12028
+ role,
12029
+ category: url.split("/").pop()?.replace(/\.[^.]+$/, "") ?? role,
12030
+ ...defaults,
12031
+ ...overrides
12032
+ };
12033
+ }
12034
+ function makeAssetMap(record, role, overrides = {}) {
12035
+ const result = {};
12036
+ for (const [key, url] of Object.entries(record)) {
12037
+ result[key] = makeAsset(url, role, overrides);
12038
+ }
12039
+ return result;
12040
+ }
12041
+ var ROLE_DEFAULTS;
12042
+ var init_makeAsset = __esm({
12043
+ "components/game/organisms/utils/makeAsset.ts"() {
12044
+ ROLE_DEFAULTS = {
12045
+ tile: { dimension: "2d", animations: ["static"], aspect: "1:1" },
12046
+ decoration: { dimension: "2d", animations: ["static"], aspect: "1:1" },
12047
+ effect: { dimension: "2d", animations: ["static"], aspect: "1:1" },
12048
+ item: { dimension: "2d", animations: ["static"], aspect: "5:7" },
12049
+ player: { dimension: "2d", animations: ["idle", "walk", "attack", "hit", "death"], aspect: "1:1" },
12050
+ enemy: { dimension: "2d", animations: ["idle", "walk", "attack", "hit", "death"], aspect: "1:1" },
12051
+ npc: { dimension: "2d", animations: ["idle", "walk", "attack", "hit", "death"], aspect: "1:1" },
12052
+ projectile: { dimension: "2d", animations: ["static"], aspect: "1:1" },
12053
+ vehicle: { dimension: "2d", animations: ["idle", "walk"], aspect: "1:1" },
12054
+ ui: { dimension: "2d", animations: ["static"], aspect: "1:1" }
12055
+ };
12056
+ }
12057
+ });
11979
12058
  function buildDefaultBattleTiles() {
11980
12059
  const tiles = [];
11981
12060
  for (let y = 0; y < BATTLE_GRID_H; y++) {
@@ -12034,14 +12113,14 @@ function BattleBoard({
12034
12113
  if (o === null || typeof o.x !== "number" || typeof o.y !== "number") return [];
12035
12114
  const tile = { x: o.x, y: o.y };
12036
12115
  if (typeof o.terrain === "string") tile.terrain = o.terrain;
12037
- if (typeof o.terrainSprite === "string") tile.terrainSprite = o.terrainSprite;
12116
+ if (typeof o.terrainSprite === "string") tile.terrainSprite = makeAsset(o.terrainSprite, "tile");
12038
12117
  if (typeof o.passable === "boolean") tile.passable = o.passable;
12039
12118
  if (typeof o.movementCost === "number") tile.movementCost = o.movementCost;
12040
12119
  if (typeof o.elevation === "number") tile.elevation = o.elevation;
12041
12120
  if (typeof o.type === "string") tile.type = o.type;
12042
12121
  if (typeof o.tileType === "string") tile.tileType = o.tileType;
12043
12122
  if (typeof o.id === "string") tile.id = o.id;
12044
- if (typeof o.modelUrl === "string") tile.modelUrl = o.modelUrl;
12123
+ if (typeof o.modelUrl === "string") tile.modelUrl = makeAsset(o.modelUrl, "decoration", { dimension: "3d" });
12045
12124
  return [tile];
12046
12125
  }) : []);
12047
12126
  const tiles = rawTiles.length === 0 ? DEFAULT_BATTLE_TILES : rawTiles;
@@ -12050,10 +12129,10 @@ function BattleBoard({
12050
12129
  if (o === null || typeof o.type !== "string" || typeof o.x !== "number" || typeof o.y !== "number") return [];
12051
12130
  const feat = { type: o.type, x: o.x, y: o.y };
12052
12131
  if (typeof o.id === "string") feat.id = o.id;
12053
- if (typeof o.sprite === "string") feat.sprite = o.sprite;
12132
+ if (typeof o.sprite === "string") feat.sprite = makeAsset(o.sprite, "decoration");
12054
12133
  if (typeof o.color === "string") feat.color = o.color;
12055
12134
  if (typeof o.elevation === "number") feat.elevation = o.elevation;
12056
- if (typeof o.assetUrl === "string") feat.assetUrl = o.assetUrl;
12135
+ if (typeof o.assetUrl === "string") feat.assetUrl = makeAsset(o.assetUrl, "decoration", { dimension: "3d" });
12057
12136
  return [feat];
12058
12137
  }) : []);
12059
12138
  const boardWidth = num(board.gridWidth ?? board.boardWidth, BATTLE_GRID_W);
@@ -12169,7 +12248,7 @@ function BattleBoard({
12169
12248
  maxHealth: num(unit.maxHealth),
12170
12249
  unitType: unit.unitType == null ? void 0 : str(unit.unitType),
12171
12250
  heroId: unit.heroId == null ? void 0 : str(unit.heroId),
12172
- sprite: unit.sprite == null ? void 0 : str(unit.sprite),
12251
+ sprite: unit.sprite == null ? void 0 : makeAsset(str(unit.sprite), "npc"),
12173
12252
  traits: unitTraits?.map((tr) => ({
12174
12253
  name: tr.name,
12175
12254
  currentState: tr.currentState,
@@ -12319,7 +12398,6 @@ function BattleBoard({
12319
12398
  onTileHover: (x, y) => setHoveredTile({ x, y }),
12320
12399
  onTileLeave: () => setHoveredTile(null),
12321
12400
  scale,
12322
- assetBaseUrl: assetManifest?.baseUrl,
12323
12401
  assetManifest,
12324
12402
  backgroundImage,
12325
12403
  onDrawEffects,
@@ -12397,15 +12475,16 @@ var init_BattleBoard = __esm({
12397
12475
  init_IsometricCanvas();
12398
12476
  init_boardEntity();
12399
12477
  init_isometric();
12478
+ init_makeAsset();
12400
12479
  BATTLE_CDN = "https://almadar-kflow-assets.web.app/shared";
12401
12480
  BATTLE_GRID_W = 16;
12402
12481
  BATTLE_GRID_H = 16;
12403
12482
  BATTLE_TERRAIN_SPRITES = [
12404
- `${BATTLE_CDN}/isometric-dungeon/Isometric/dirt_E.png`,
12405
- `${BATTLE_CDN}/isometric-dungeon/Isometric/dirtTiles_E.png`,
12406
- `${BATTLE_CDN}/isometric-dungeon/Isometric/planks_E.png`,
12407
- `${BATTLE_CDN}/isometric-dungeon/Isometric/stoneTile_E.png`,
12408
- `${BATTLE_CDN}/isometric-dungeon/Isometric/stoneInset_E.png`
12483
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/dirt_E.png`, "tile"),
12484
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/dirtTiles_E.png`, "tile"),
12485
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/planks_E.png`, "tile"),
12486
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/stoneTile_E.png`, "tile"),
12487
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/stoneInset_E.png`, "tile")
12409
12488
  ];
12410
12489
  DEFAULT_BATTLE_TILES = buildDefaultBattleTiles();
12411
12490
  BattleBoard.displayName = "BattleBoard";
@@ -12444,61 +12523,64 @@ function BattleTemplate({
12444
12523
  }
12445
12524
  );
12446
12525
  }
12447
- var CDN, DEFAULT_BATTLE_TILES2, DEFAULT_BATTLE_UNITS, DEFAULT_BATTLE_FEATURES, DEFAULT_BATTLE_MANIFEST;
12526
+ var CDN, STONE, DIRT, GRASS, DEFAULT_BATTLE_TILES2, DEFAULT_BATTLE_UNITS, DEFAULT_BATTLE_FEATURES, DEFAULT_BATTLE_MANIFEST;
12448
12527
  var init_BattleTemplate = __esm({
12449
12528
  "components/game/templates/BattleTemplate.tsx"() {
12450
12529
  init_BattleBoard();
12530
+ init_makeAsset();
12451
12531
  CDN = "https://almadar-kflow-assets.web.app/shared";
12532
+ STONE = makeAsset(`${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png`, "tile");
12533
+ DIRT = makeAsset(`${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png`, "tile");
12534
+ GRASS = makeAsset(`${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png`, "tile");
12452
12535
  DEFAULT_BATTLE_TILES2 = [
12453
- { x: 0, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12454
- { x: 1, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12455
- { x: 2, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12456
- { x: 3, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12457
- { x: 4, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12458
- { x: 0, y: 1, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12459
- { x: 1, y: 1, terrain: "dirt", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png` },
12460
- { x: 2, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12461
- { x: 3, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12462
- { x: 4, y: 1, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12463
- { x: 0, y: 2, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12464
- { x: 1, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12465
- { x: 2, y: 2, terrain: "dirt", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png` },
12466
- { x: 3, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12467
- { x: 4, y: 2, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12468
- { x: 0, y: 3, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12469
- { x: 1, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12470
- { x: 2, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12471
- { x: 3, y: 3, terrain: "dirt", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png` },
12472
- { x: 4, y: 3, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12473
- { x: 0, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12474
- { x: 1, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12475
- { x: 2, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12476
- { x: 3, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12477
- { x: 4, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` }
12536
+ { x: 0, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12537
+ { x: 1, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12538
+ { x: 2, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12539
+ { x: 3, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12540
+ { x: 4, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12541
+ { x: 0, y: 1, terrain: "stone", passable: false, terrainSprite: STONE },
12542
+ { x: 1, y: 1, terrain: "dirt", passable: true, terrainSprite: DIRT },
12543
+ { x: 2, y: 1, terrain: "grass", passable: true, terrainSprite: GRASS },
12544
+ { x: 3, y: 1, terrain: "grass", passable: true, terrainSprite: GRASS },
12545
+ { x: 4, y: 1, terrain: "stone", passable: false, terrainSprite: STONE },
12546
+ { x: 0, y: 2, terrain: "stone", passable: false, terrainSprite: STONE },
12547
+ { x: 1, y: 2, terrain: "grass", passable: true, terrainSprite: GRASS },
12548
+ { x: 2, y: 2, terrain: "dirt", passable: true, terrainSprite: DIRT },
12549
+ { x: 3, y: 2, terrain: "grass", passable: true, terrainSprite: GRASS },
12550
+ { x: 4, y: 2, terrain: "stone", passable: false, terrainSprite: STONE },
12551
+ { x: 0, y: 3, terrain: "stone", passable: false, terrainSprite: STONE },
12552
+ { x: 1, y: 3, terrain: "grass", passable: true, terrainSprite: GRASS },
12553
+ { x: 2, y: 3, terrain: "grass", passable: true, terrainSprite: GRASS },
12554
+ { x: 3, y: 3, terrain: "dirt", passable: true, terrainSprite: DIRT },
12555
+ { x: 4, y: 3, terrain: "stone", passable: false, terrainSprite: STONE },
12556
+ { x: 0, y: 4, terrain: "stone", passable: false, terrainSprite: STONE },
12557
+ { x: 1, y: 4, terrain: "stone", passable: false, terrainSprite: STONE },
12558
+ { x: 2, y: 4, terrain: "stone", passable: false, terrainSprite: STONE },
12559
+ { x: 3, y: 4, terrain: "stone", passable: false, terrainSprite: STONE },
12560
+ { x: 4, y: 4, terrain: "stone", passable: false, terrainSprite: STONE }
12478
12561
  ];
12479
12562
  DEFAULT_BATTLE_UNITS = [
12480
- { 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` },
12481
- { 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` }
12563
+ { 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") },
12564
+ { 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") }
12482
12565
  ];
12483
12566
  DEFAULT_BATTLE_FEATURES = [
12484
- { id: "f1", x: 2, y: 2, type: "gold_mine", sprite: `${CDN}/world-map/gold_mine.png` },
12485
- { id: "f2", x: 3, y: 1, type: "portal", sprite: `${CDN}/world-map/portal_open.png` }
12567
+ { id: "f1", x: 2, y: 2, type: "gold_mine", sprite: makeAsset(`${CDN}/world-map/gold_mine.png`, "decoration") },
12568
+ { id: "f2", x: 3, y: 1, type: "portal", sprite: makeAsset(`${CDN}/world-map/portal_open.png`, "decoration") }
12486
12569
  ];
12487
12570
  DEFAULT_BATTLE_MANIFEST = {
12488
- baseUrl: CDN,
12489
- terrains: {
12490
- stone: "/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png",
12491
- dirt: "/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png",
12492
- grass: "/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png"
12493
- },
12494
- units: {
12495
- worker: "/sprite-sheets/amir-sprite-sheet-se.png",
12496
- guardian: "/sprite-sheets/destroyer-sprite-sheet-sw.png"
12497
- },
12498
- features: {
12499
- gold_mine: "/world-map/gold_mine.png",
12500
- portal: "/world-map/portal_open.png"
12501
- }
12571
+ terrains: makeAssetMap({
12572
+ stone: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png`,
12573
+ dirt: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png`,
12574
+ grass: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png`
12575
+ }, "tile"),
12576
+ units: makeAssetMap({
12577
+ worker: `${CDN}/sprite-sheets/amir-sprite-sheet-se.png`,
12578
+ guardian: `${CDN}/sprite-sheets/destroyer-sprite-sheet-sw.png`
12579
+ }, "npc"),
12580
+ features: makeAssetMap({
12581
+ gold_mine: `${CDN}/world-map/gold_mine.png`,
12582
+ portal: `${CDN}/world-map/portal_open.png`
12583
+ }, "decoration")
12502
12584
  };
12503
12585
  BattleTemplate.displayName = "BattleTemplate";
12504
12586
  }
@@ -14713,7 +14795,6 @@ function BoardgameBoard({
14713
14795
  units,
14714
14796
  features,
14715
14797
  assetManifest,
14716
- assetBaseUrl,
14717
14798
  scale,
14718
14799
  showMinimap,
14719
14800
  enableCamera,
@@ -19783,7 +19864,7 @@ function CardHand({
19783
19864
  /* @__PURE__ */ jsx(Box, { className: "flex-1 flex items-center justify-center w-full", children: card.iconUrl ? /* @__PURE__ */ jsx(
19784
19865
  "img",
19785
19866
  {
19786
- src: card.iconUrl,
19867
+ src: card.iconUrl.url,
19787
19868
  alt: card.title ?? card.id,
19788
19869
  width: art,
19789
19870
  height: art,
@@ -19841,15 +19922,6 @@ var init_CardHand = __esm({
19841
19922
  CardHand.displayName = "CardHand";
19842
19923
  }
19843
19924
  });
19844
- function resolveManifestUrl(manifest, relative) {
19845
- if (relative == null) return void 0;
19846
- if (/^https?:\/\//.test(relative)) return relative;
19847
- const base = manifest?.baseUrl;
19848
- if (base == null) return relative;
19849
- const cleanBase = base.replace(/\/$/, "");
19850
- const cleanRel = relative.replace(/^\//, "");
19851
- return `${cleanBase}/${cleanRel}`;
19852
- }
19853
19925
  function rowToCard(r) {
19854
19926
  return {
19855
19927
  id: str(r.id),
@@ -19863,7 +19935,7 @@ function rowToCard(r) {
19863
19935
  function toHandCards(cards, manifest, mana) {
19864
19936
  return cards.map((c) => {
19865
19937
  const key = c.iconKey ?? c.id;
19866
- const iconUrl = resolveManifestUrl(manifest, manifest?.cards?.[key]);
19938
+ const iconUrl = manifest?.cards?.[key];
19867
19939
  return {
19868
19940
  id: c.id,
19869
19941
  iconUrl,
@@ -20977,7 +21049,6 @@ function CastleBoard({
20977
21049
  onTileHover: (x, y) => setHoveredTile({ x, y }),
20978
21050
  onTileLeave: () => setHoveredTile(null),
20979
21051
  scale,
20980
- assetBaseUrl: assetManifest?.baseUrl,
20981
21052
  assetManifest,
20982
21053
  backgroundImage
20983
21054
  }
@@ -21053,60 +21124,63 @@ function CastleTemplate({
21053
21124
  }
21054
21125
  );
21055
21126
  }
21056
- var CDN2, DEFAULT_CASTLE_TILES, DEFAULT_CASTLE_UNITS, DEFAULT_CASTLE_FEATURES, DEFAULT_CASTLE_MANIFEST;
21127
+ var CDN2, WALL, FLOOR, FLOOR_CENTER, DEFAULT_CASTLE_TILES, DEFAULT_CASTLE_UNITS, DEFAULT_CASTLE_FEATURES, DEFAULT_CASTLE_MANIFEST;
21057
21128
  var init_CastleTemplate = __esm({
21058
21129
  "components/game/templates/CastleTemplate.tsx"() {
21059
21130
  init_CastleBoard();
21131
+ init_makeAsset();
21060
21132
  CDN2 = "https://almadar-kflow-assets.web.app/shared";
21133
+ WALL = makeAsset(`${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png`, "tile");
21134
+ FLOOR = makeAsset(`${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`, "tile");
21135
+ FLOOR_CENTER = makeAsset(`${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_09.png`, "tile");
21061
21136
  DEFAULT_CASTLE_TILES = [
21062
- { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21063
- { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21064
- { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21065
- { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21066
- { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21067
- { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21068
- { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
21069
- { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
21070
- { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
21071
- { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21072
- { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21073
- { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
21074
- { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_09.png` },
21075
- { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
21076
- { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21077
- { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21078
- { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
21079
- { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
21080
- { x: 3, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
21081
- { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21082
- { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21083
- { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21084
- { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21085
- { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
21086
- { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` }
21137
+ { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
21138
+ { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
21139
+ { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
21140
+ { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
21141
+ { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
21142
+ { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: WALL },
21143
+ { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: FLOOR },
21144
+ { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: FLOOR },
21145
+ { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: FLOOR },
21146
+ { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: WALL },
21147
+ { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: WALL },
21148
+ { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: FLOOR },
21149
+ { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: FLOOR_CENTER },
21150
+ { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: FLOOR },
21151
+ { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: WALL },
21152
+ { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: WALL },
21153
+ { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: FLOOR },
21154
+ { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: FLOOR },
21155
+ { x: 3, y: 3, terrain: "floor", passable: true, terrainSprite: FLOOR },
21156
+ { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: WALL },
21157
+ { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: WALL },
21158
+ { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: WALL },
21159
+ { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: WALL },
21160
+ { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: WALL },
21161
+ { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: WALL }
21087
21162
  ];
21088
21163
  DEFAULT_CASTLE_UNITS = [
21089
- { 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` },
21090
- { 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` }
21164
+ { 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") },
21165
+ { 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") }
21091
21166
  ];
21092
21167
  DEFAULT_CASTLE_FEATURES = [
21093
- { id: "f1", x: 2, y: 2, type: "chest", sprite: `${CDN2}/world-map/treasure_chest_closed.png` },
21094
- { id: "f2", x: 3, y: 1, type: "crystal", sprite: `${CDN2}/world-map/resonance_crystal.png` }
21168
+ { id: "f1", x: 2, y: 2, type: "chest", sprite: makeAsset(`${CDN2}/world-map/treasure_chest_closed.png`, "decoration") },
21169
+ { id: "f2", x: 3, y: 1, type: "crystal", sprite: makeAsset(`${CDN2}/world-map/resonance_crystal.png`, "decoration") }
21095
21170
  ];
21096
21171
  DEFAULT_CASTLE_MANIFEST = {
21097
- baseUrl: CDN2,
21098
- terrains: {
21099
- wall: "/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png",
21100
- floor: "/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png"
21101
- },
21102
- units: {
21103
- worker: "/sprite-sheets/coordinator-sprite-sheet-se.png",
21104
- guardian: "/sprite-sheets/forger-sprite-sheet-se.png"
21105
- },
21106
- features: {
21107
- chest: "/world-map/treasure_chest_closed.png",
21108
- crystal: "/world-map/resonance_crystal.png"
21109
- }
21172
+ terrains: makeAssetMap({
21173
+ wall: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png`,
21174
+ floor: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`
21175
+ }, "tile"),
21176
+ units: makeAssetMap({
21177
+ worker: `${CDN2}/sprite-sheets/coordinator-sprite-sheet-se.png`,
21178
+ guardian: `${CDN2}/sprite-sheets/forger-sprite-sheet-se.png`
21179
+ }, "player"),
21180
+ features: makeAssetMap({
21181
+ chest: `${CDN2}/world-map/treasure_chest_closed.png`,
21182
+ crystal: `${CDN2}/world-map/resonance_crystal.png`
21183
+ }, "decoration")
21110
21184
  };
21111
21185
  CastleTemplate.displayName = "CastleTemplate";
21112
21186
  }
@@ -22094,15 +22168,6 @@ var init_ChatBar = __esm({
22094
22168
  ChatBar.displayName = "ChatBar";
22095
22169
  }
22096
22170
  });
22097
- function resolveManifestUrl2(manifest, relative) {
22098
- if (relative == null) return void 0;
22099
- if (/^https?:\/\//.test(relative)) return relative;
22100
- const base = manifest?.baseUrl;
22101
- if (base == null) return relative;
22102
- const cleanBase = base.replace(/\/$/, "");
22103
- const cleanRel = relative.replace(/^\//, "");
22104
- return `${cleanBase}/${cleanRel}`;
22105
- }
22106
22171
  function buildDefaultCBTiles() {
22107
22172
  const tiles = [];
22108
22173
  for (let y = 0; y < CB_GRID_H; y++) {
@@ -22117,12 +22182,12 @@ function buildDefaultCBTiles() {
22117
22182
  function tilesToIso(tiles, manifest) {
22118
22183
  return tiles.map((t) => {
22119
22184
  const key = t.terrain ?? "grass";
22120
- const sprite = t.terrainSprite ?? resolveManifestUrl2(manifest, manifest?.terrains?.[key]) ?? resolveManifestUrl2(manifest, manifest?.terrains?.grass);
22185
+ const terrainSprite = t.terrainSprite ?? manifest?.terrains?.[key] ?? manifest?.terrains?.grass;
22121
22186
  return {
22122
22187
  x: t.x,
22123
22188
  y: t.y,
22124
22189
  terrain: t.terrain,
22125
- terrainSprite: sprite,
22190
+ terrainSprite,
22126
22191
  passable: t.passable
22127
22192
  };
22128
22193
  });
@@ -22133,7 +22198,7 @@ function buildingsToFeatures(buildings, manifest) {
22133
22198
  x: b.x,
22134
22199
  y: b.y,
22135
22200
  type: b.type,
22136
- sprite: resolveManifestUrl2(manifest, manifest?.features?.[b.type])
22201
+ sprite: manifest?.features?.[b.type]
22137
22202
  }));
22138
22203
  }
22139
22204
  function CityBuilderBoard({
@@ -22165,7 +22230,7 @@ function CityBuilderBoard({
22165
22230
  x: num(r.x),
22166
22231
  y: num(r.y),
22167
22232
  terrain: r.terrain == null ? void 0 : str(r.terrain),
22168
- terrainSprite: r.terrainSprite == null ? void 0 : str(r.terrainSprite),
22233
+ terrainSprite: r.terrainSprite == null ? void 0 : makeAsset(str(r.terrainSprite), "tile"),
22169
22234
  passable: r.passable !== false
22170
22235
  })),
22171
22236
  [board.tiles]
@@ -22274,7 +22339,6 @@ function CityBuilderBoard({
22274
22339
  {
22275
22340
  tiles: isoTiles,
22276
22341
  features: buildingFeatures,
22277
- assetBaseUrl: assetManifest?.baseUrl,
22278
22342
  assetManifest,
22279
22343
  validMoves,
22280
22344
  hoveredTile,
@@ -22309,6 +22373,7 @@ var CB_GRID_W, CB_GRID_H, DEFAULT_BUILD_TYPES, DEFAULT_CB_TILES;
22309
22373
  var init_CityBuilderBoard = __esm({
22310
22374
  "components/game/organisms/CityBuilderBoard.tsx"() {
22311
22375
  "use client";
22376
+ init_makeAsset();
22312
22377
  init_cn();
22313
22378
  init_useEventBus();
22314
22379
  init_Box();
@@ -28303,7 +28368,7 @@ function StatBadge({
28303
28368
  resolvedAsset ? /* @__PURE__ */ jsx(
28304
28369
  "img",
28305
28370
  {
28306
- src: resolvedAsset,
28371
+ src: resolvedAsset.url,
28307
28372
  alt: "",
28308
28373
  width: 16,
28309
28374
  height: 16,
@@ -28610,7 +28675,7 @@ function GameCanvas2D({
28610
28675
  tickEvent,
28611
28676
  drawEvent,
28612
28677
  fps = 60,
28613
- backgroundImage = "",
28678
+ backgroundImage,
28614
28679
  assetBaseUrl,
28615
28680
  className
28616
28681
  }) {
@@ -28674,7 +28739,7 @@ function GameCanvas2D({
28674
28739
  emitRef.current(tickEventRef.current, { dt, frame });
28675
28740
  }
28676
28741
  if (backgroundImageRef.current) {
28677
- const bgImg = loadImage(backgroundImageRef.current);
28742
+ const bgImg = loadImage(backgroundImageRef.current.url);
28678
28743
  if (bgImg) {
28679
28744
  ctx.drawImage(bgImg, 0, 0, widthRef.current, heightRef.current);
28680
28745
  } else {
@@ -29045,7 +29110,7 @@ function EnemyPlate({
29045
29110
  assetUrl && /* @__PURE__ */ jsx(
29046
29111
  "img",
29047
29112
  {
29048
- src: assetUrl,
29113
+ src: assetUrl.url,
29049
29114
  alt: name,
29050
29115
  width: 24,
29051
29116
  height: 24,
@@ -29387,7 +29452,7 @@ function DialogueBox({
29387
29452
  "div",
29388
29453
  {
29389
29454
  className: "fixed inset-0 z-20 bg-center bg-cover bg-no-repeat",
29390
- style: { backgroundImage: `url(${backgroundImage})` },
29455
+ style: { backgroundImage: `url(${backgroundImage?.url})` },
29391
29456
  "aria-hidden": "true"
29392
29457
  }
29393
29458
  ),
@@ -29402,7 +29467,7 @@ function DialogueBox({
29402
29467
  children: /* @__PURE__ */ jsx(
29403
29468
  "img",
29404
29469
  {
29405
- src: portraitUrl,
29470
+ src: portraitUrl?.url,
29406
29471
  alt: dialogue.speaker,
29407
29472
  className: "h-full w-auto object-contain drop-shadow-2xl"
29408
29473
  }
@@ -41708,7 +41773,6 @@ var init_FeatureGridOrganism = __esm({
41708
41773
  });
41709
41774
  function FishingBoard({
41710
41775
  backgroundImage,
41711
- assetBaseUrl,
41712
41776
  scale = 1,
41713
41777
  showMinimap = false,
41714
41778
  enableCamera = true,
@@ -41726,8 +41790,7 @@ function FishingBoard({
41726
41790
  {
41727
41791
  width,
41728
41792
  height,
41729
- backgroundImage: backgroundImage ?? "",
41730
- assetBaseUrl,
41793
+ backgroundImage,
41731
41794
  fps: 60,
41732
41795
  className: "w-full h-full"
41733
41796
  }
@@ -43946,7 +44009,7 @@ var init_GameCanvas3D2 = __esm({
43946
44009
  children: /* @__PURE__ */ jsx(
43947
44010
  ModelLoader,
43948
44011
  {
43949
- url: tile.modelUrl,
44012
+ url: tile.modelUrl.url,
43950
44013
  scale: 0.95,
43951
44014
  fallbackGeometry: "box",
43952
44015
  castShadow: true,
@@ -44011,7 +44074,7 @@ var init_GameCanvas3D2 = __esm({
44011
44074
  /* @__PURE__ */ jsx(
44012
44075
  ModelLoader,
44013
44076
  {
44014
- url: unit.modelUrl,
44077
+ url: unit.modelUrl.url,
44015
44078
  scale: modelScale,
44016
44079
  fallbackGeometry: "box",
44017
44080
  castShadow: true
@@ -44071,7 +44134,7 @@ var init_GameCanvas3D2 = __esm({
44071
44134
  return /* @__PURE__ */ jsx(
44072
44135
  ModelLoader,
44073
44136
  {
44074
- url: feature.assetUrl,
44137
+ url: feature.assetUrl.url,
44075
44138
  position,
44076
44139
  scale: 0.5,
44077
44140
  rotation: [0, feature.rotation ?? 0, 0],
@@ -44292,7 +44355,18 @@ function GameBoard3D({
44292
44355
  const row = boardEntity(entity);
44293
44356
  const eventBus = useEventBus();
44294
44357
  const entityUnits = row ? rows(row.units) : [];
44295
- const units = entityUnits;
44358
+ const units = entityUnits.map((r) => ({
44359
+ id: str(r.id),
44360
+ x: num(r.x),
44361
+ y: num(r.y),
44362
+ z: num(r.z),
44363
+ faction: str(r.faction) || "neutral",
44364
+ team: str(r.team) || str(r.faction) || "neutral",
44365
+ unitType: r.unitType == null ? void 0 : str(r.unitType),
44366
+ name: r.name == null ? void 0 : str(r.name),
44367
+ health: r.health == null ? void 0 : num(r.health),
44368
+ maxHealth: r.maxHealth == null ? void 0 : num(r.maxHealth)
44369
+ }));
44296
44370
  const selectedUnitId = row ? str(row.selectedUnitId) || null : null;
44297
44371
  const phase = row ? str(row.phase) : "observation";
44298
44372
  const result = row ? str(row.result) : "none";
@@ -44887,7 +44961,6 @@ function HexStrategyBoard({
44887
44961
  units,
44888
44962
  features,
44889
44963
  assetManifest,
44890
- assetBaseUrl,
44891
44964
  scale,
44892
44965
  showMinimap,
44893
44966
  enableCamera,
@@ -44929,7 +45002,6 @@ function HolidayRunnerBoard({
44929
45002
  units,
44930
45003
  features,
44931
45004
  assetManifest,
44932
- assetBaseUrl,
44933
45005
  scale,
44934
45006
  showMinimap,
44935
45007
  enableCamera,
@@ -45724,7 +45796,6 @@ function MatchPuzzleBoard({
45724
45796
  units,
45725
45797
  features,
45726
45798
  assetManifest,
45727
- assetBaseUrl,
45728
45799
  scale,
45729
45800
  showMinimap,
45730
45801
  enableCamera,
@@ -45985,7 +46056,6 @@ function MinigolfBoard({
45985
46056
  units,
45986
46057
  features,
45987
46058
  assetManifest,
45988
- assetBaseUrl,
45989
46059
  scale,
45990
46060
  showMinimap,
45991
46061
  enableCamera,
@@ -46291,7 +46361,6 @@ function PirateBoard({
46291
46361
  units,
46292
46362
  features,
46293
46363
  assetManifest,
46294
- assetBaseUrl,
46295
46364
  scale,
46296
46365
  showMinimap,
46297
46366
  enableCamera,
@@ -46412,8 +46481,8 @@ function PlatformerBoard({
46412
46481
  canvasHeight,
46413
46482
  followCamera: true,
46414
46483
  bgColor,
46415
- playerSprite,
46416
- tileSprites,
46484
+ playerSprite: playerSprite?.url,
46485
+ tileSprites: tileSprites ? Object.fromEntries(Object.entries(tileSprites).map(([k, a]) => [k, a.url])) : void 0,
46417
46486
  leftEvent,
46418
46487
  rightEvent,
46419
46488
  jumpEvent,
@@ -46478,7 +46547,7 @@ function PlatformerTemplate({
46478
46547
  worldHeight = 400,
46479
46548
  canvasWidth = 800,
46480
46549
  canvasHeight = 400,
46481
- playerSprite = `${CDN3}/characters/platformChar_idle.png`,
46550
+ playerSprite = makeAsset(`${CDN3}/characters/platformChar_idle.png`, "player"),
46482
46551
  tileSprites = DEFAULT_TILE_SPRITES,
46483
46552
  bgColor = "#5c94fc",
46484
46553
  gameEndEvent = "GAME_END",
@@ -46531,13 +46600,14 @@ var init_PlatformerTemplate = __esm({
46531
46600
  init_PlatformerBoard();
46532
46601
  init_GameHud();
46533
46602
  init_ScoreBoard();
46603
+ init_makeAsset();
46534
46604
  CDN3 = "https://almadar-kflow-assets.web.app/shared/platformer";
46535
- DEFAULT_TILE_SPRITES = {
46605
+ DEFAULT_TILE_SPRITES = makeAssetMap({
46536
46606
  ground: `${CDN3}/tiles/platformPack_tile001.png`,
46537
46607
  platform: `${CDN3}/tiles/platformPack_tile004.png`,
46538
46608
  hazard: `${CDN3}/tiles/platformPack_tile017.png`,
46539
46609
  goal: `${CDN3}/tiles/platformPack_tile007.png`
46540
- };
46610
+ }, "tile");
46541
46611
  DEFAULT_PLATFORMS = [
46542
46612
  { x: 0, y: 368, width: 800, height: 32, type: "ground" },
46543
46613
  { x: 150, y: 280, width: 160, height: 16, type: "platform" },
@@ -46693,7 +46763,6 @@ function RacingBoard({
46693
46763
  units,
46694
46764
  features,
46695
46765
  assetManifest,
46696
- assetBaseUrl,
46697
46766
  scale,
46698
46767
  showMinimap,
46699
46768
  enableCamera,
@@ -46712,27 +46781,18 @@ var init_RacingBoard = __esm({
46712
46781
  RacingBoard.displayName = "RacingBoard";
46713
46782
  }
46714
46783
  });
46715
- function resolveManifestUrl3(manifest, relative) {
46716
- if (relative == null) return void 0;
46717
- if (/^https?:\/\//.test(relative)) return relative;
46718
- const base = manifest?.baseUrl;
46719
- if (base == null) return relative;
46720
- const cleanBase = base.replace(/\/$/, "");
46721
- const cleanRel = relative.replace(/^\//, "");
46722
- return `${cleanBase}/${cleanRel}`;
46723
- }
46724
46784
  function dungeonTerrain(x, y, stairsX, stairsY, manifest) {
46725
46785
  const isBorder = x === 0 || y === 0 || x === DUNGEON_GRID_W - 1 || y === DUNGEON_GRID_H - 1;
46726
46786
  const isPillar = x % 4 === 0 && y % 4 === 0 && !isBorder;
46727
46787
  const isWall = isBorder || isPillar;
46728
46788
  const terrains = manifest?.terrains;
46729
46789
  if (x === stairsX && y === stairsY) {
46730
- return { terrain: "stairs", passable: true, terrainSprite: resolveManifestUrl3(manifest, terrains?.stairs) };
46790
+ return { terrain: "stairs", passable: true, terrainSprite: terrains?.stairs };
46731
46791
  }
46732
46792
  if (isWall) {
46733
- return { terrain: "wall", passable: false, terrainSprite: resolveManifestUrl3(manifest, terrains?.wall) };
46793
+ return { terrain: "wall", passable: false, terrainSprite: terrains?.wall };
46734
46794
  }
46735
- return { terrain: "floor", passable: true, terrainSprite: resolveManifestUrl3(manifest, terrains?.floor) };
46795
+ return { terrain: "floor", passable: true, terrainSprite: terrains?.floor };
46736
46796
  }
46737
46797
  function buildDefaultDungeonTiles(stairsX, stairsY, manifest) {
46738
46798
  const tiles = [];
@@ -46776,7 +46836,7 @@ function RoguelikeBoard({
46776
46836
  x: num(r.x),
46777
46837
  y: num(r.y),
46778
46838
  terrain: r.terrain == null ? void 0 : str(r.terrain),
46779
- terrainSprite: r.terrainSprite == null ? void 0 : str(r.terrainSprite),
46839
+ terrainSprite: r.terrainSprite == null ? void 0 : makeAsset(str(r.terrainSprite), "tile"),
46780
46840
  passable: r.passable !== false
46781
46841
  })),
46782
46842
  [board.tiles]
@@ -46856,7 +46916,7 @@ function RoguelikeBoard({
46856
46916
  health: playerHp,
46857
46917
  maxHealth: playerMaxHp,
46858
46918
  unitType: "player",
46859
- sprite: resolveManifestUrl3(assetManifest, assetManifest?.units?.player)
46919
+ sprite: assetManifest?.units?.player
46860
46920
  },
46861
46921
  ...liveEnemies.map((e) => ({
46862
46922
  id: e.id,
@@ -46866,7 +46926,7 @@ function RoguelikeBoard({
46866
46926
  health: e.hp,
46867
46927
  maxHealth: 6,
46868
46928
  unitType: "enemy",
46869
- sprite: resolveManifestUrl3(assetManifest, assetManifest?.units?.enemy)
46929
+ sprite: assetManifest?.units?.enemy
46870
46930
  }))
46871
46931
  ];
46872
46932
  }, [player, enemies, playerHp, playerMaxHp, assetManifest, t]);
@@ -46876,7 +46936,7 @@ function RoguelikeBoard({
46876
46936
  x: it.x,
46877
46937
  y: it.y,
46878
46938
  type: it.kind,
46879
- sprite: resolveManifestUrl3(assetManifest, assetManifest?.features?.[it.kind])
46939
+ sprite: assetManifest?.features?.[it.kind]
46880
46940
  })),
46881
46941
  [items, assetManifest]
46882
46942
  );
@@ -46937,7 +46997,6 @@ function RoguelikeBoard({
46937
46997
  onTileHover: (x, y) => setHoveredTile({ x, y }),
46938
46998
  onTileLeave: () => setHoveredTile(null),
46939
46999
  scale,
46940
- assetBaseUrl: assetManifest?.baseUrl,
46941
47000
  assetManifest,
46942
47001
  unitScale,
46943
47002
  spriteHeightRatio,
@@ -46997,6 +47056,7 @@ var init_RoguelikeBoard = __esm({
46997
47056
  init_Stack();
46998
47057
  init_IsometricCanvas();
46999
47058
  init_boardEntity();
47059
+ init_makeAsset();
47000
47060
  DUNGEON_GRID_W = 16;
47001
47061
  DUNGEON_GRID_H = 16;
47002
47062
  DEFAULT_ENEMIES = [
@@ -47047,55 +47107,59 @@ function RoguelikeTemplate({
47047
47107
  }
47048
47108
  );
47049
47109
  }
47050
- var CDN4, DEFAULT_ROGUELIKE_TILES, DEFAULT_ROGUELIKE_MANIFEST;
47110
+ var CDN4, wall, floor, tiles2, stairs, DEFAULT_ROGUELIKE_TILES, DEFAULT_ROGUELIKE_MANIFEST;
47051
47111
  var init_RoguelikeTemplate = __esm({
47052
47112
  "components/game/templates/RoguelikeTemplate.tsx"() {
47053
47113
  init_RoguelikeBoard();
47114
+ init_makeAsset();
47054
47115
  CDN4 = "https://almadar-kflow-assets.web.app/shared";
47116
+ wall = makeAsset(`${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png`, "tile");
47117
+ floor = makeAsset(`${CDN4}/isometric-dungeon/Isometric/dirt_E.png`, "tile");
47118
+ tiles2 = makeAsset(`${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png`, "tile");
47119
+ stairs = makeAsset(`${CDN4}/isometric-dungeon/Isometric/stairs_E.png`, "tile");
47055
47120
  DEFAULT_ROGUELIKE_TILES = [
47056
- { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47057
- { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47058
- { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47059
- { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47060
- { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47061
- { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47062
- { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
47063
- { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
47064
- { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
47065
- { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47066
- { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47067
- { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
47068
- { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
47069
- { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
47070
- { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47071
- { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47072
- { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
47073
- { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
47074
- { x: 3, y: 3, terrain: "stairs", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stairs_E.png` },
47075
- { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47076
- { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47077
- { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47078
- { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47079
- { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
47080
- { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` }
47121
+ { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
47122
+ { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
47123
+ { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
47124
+ { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
47125
+ { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
47126
+ { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: wall },
47127
+ { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: floor },
47128
+ { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: floor },
47129
+ { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: floor },
47130
+ { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: wall },
47131
+ { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: wall },
47132
+ { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: tiles2 },
47133
+ { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: tiles2 },
47134
+ { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: floor },
47135
+ { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: wall },
47136
+ { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: wall },
47137
+ { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: floor },
47138
+ { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: tiles2 },
47139
+ { x: 3, y: 3, terrain: "stairs", passable: true, terrainSprite: stairs },
47140
+ { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: wall },
47141
+ { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
47142
+ { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
47143
+ { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
47144
+ { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
47145
+ { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: wall }
47081
47146
  ];
47082
47147
  DEFAULT_ROGUELIKE_MANIFEST = {
47083
- baseUrl: CDN4,
47084
- terrains: {
47085
- floor: "/isometric-dungeon/Isometric/dirt_E.png",
47086
- wall: "/isometric-dungeon/Isometric/stoneInset_E.png",
47087
- stairs: "/isometric-dungeon/Isometric/stairs_E.png",
47088
- planks: "/isometric-dungeon/Isometric/planks_E.png"
47089
- },
47148
+ terrains: makeAssetMap({
47149
+ floor: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png`,
47150
+ wall: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png`,
47151
+ stairs: `${CDN4}/isometric-dungeon/Isometric/stairs_E.png`,
47152
+ planks: `${CDN4}/isometric-dungeon/Isometric/planks_E.png`
47153
+ }, "tile"),
47090
47154
  units: {
47091
- player: "/isometric-dungeon/Characters/Male/Male_0_Idle0.png",
47092
- enemy: "/sprite-sheets/shadow-legion-sprite-sheet-sw.png"
47155
+ player: makeAsset(`${CDN4}/isometric-dungeon/Characters/Male/Male_0_Idle0.png`, "player"),
47156
+ enemy: makeAsset(`${CDN4}/sprite-sheets/shadow-legion-sprite-sheet-sw.png`, "enemy")
47093
47157
  },
47094
- features: {
47095
- health_potion: "/isometric-dungeon/Isometric/chestClosed_E.png",
47096
- sword: "/isometric-dungeon/Isometric/barrel_E.png",
47097
- shield: "/isometric-dungeon/Isometric/barrel_E.png"
47098
- }
47158
+ features: makeAssetMap({
47159
+ health_potion: `${CDN4}/isometric-dungeon/Isometric/chestClosed_E.png`,
47160
+ sword: `${CDN4}/isometric-dungeon/Isometric/barrel_E.png`,
47161
+ shield: `${CDN4}/isometric-dungeon/Isometric/barrel_E.png`
47162
+ }, "item")
47099
47163
  };
47100
47164
  RoguelikeTemplate.displayName = "RoguelikeTemplate";
47101
47165
  }
@@ -49950,7 +50014,6 @@ function SokobanBoard({
49950
50014
  units,
49951
50015
  features,
49952
50016
  assetManifest,
49953
- assetBaseUrl,
49954
50017
  scale,
49955
50018
  showMinimap,
49956
50019
  enableCamera,
@@ -49992,7 +50055,6 @@ function SpaceShmupBoard({
49992
50055
  units,
49993
50056
  features,
49994
50057
  assetManifest,
49995
- assetBaseUrl,
49996
50058
  scale,
49997
50059
  showMinimap,
49998
50060
  enableCamera,
@@ -50034,7 +50096,6 @@ function SpaceStationBoard({
50034
50096
  units,
50035
50097
  features,
50036
50098
  assetManifest,
50037
- assetBaseUrl,
50038
50099
  scale,
50039
50100
  showMinimap,
50040
50101
  enableCamera,
@@ -50169,7 +50230,6 @@ function SportsBoard({
50169
50230
  units,
50170
50231
  features,
50171
50232
  assetManifest,
50172
- assetBaseUrl,
50173
50233
  scale,
50174
50234
  showMinimap,
50175
50235
  enableCamera,
@@ -52013,7 +52073,6 @@ function TanksBoard({
52013
52073
  units,
52014
52074
  features,
52015
52075
  assetManifest,
52016
- assetBaseUrl,
52017
52076
  scale,
52018
52077
  showMinimap,
52019
52078
  enableCamera,
@@ -52291,15 +52350,6 @@ var init_ToastSlot = __esm({
52291
52350
  ToastSlot.displayName = "ToastSlot";
52292
52351
  }
52293
52352
  });
52294
- function resolveManifestUrl4(manifest, relative) {
52295
- if (relative == null || relative === "") return void 0;
52296
- if (/^https?:\/\//.test(relative)) return relative;
52297
- const base = manifest?.baseUrl;
52298
- if (base == null) return relative;
52299
- const cleanBase = base.replace(/\/$/, "");
52300
- const cleanRel = relative.replace(/^\//, "");
52301
- return `${cleanBase}/${cleanRel}`;
52302
- }
52303
52353
  function readPlayer(v) {
52304
52354
  if (v == null || typeof v !== "object") return void 0;
52305
52355
  const o = v;
@@ -52352,10 +52402,10 @@ function TopDownShooterBoard({
52352
52402
  const wave = propWave ?? num(board.wave, 1);
52353
52403
  const lives = propLives ?? num(board.lives, 3);
52354
52404
  const result = propResult ?? (str(board.result) || "none");
52355
- const playerSprite = resolveManifestUrl4(assetManifest, assetManifest?.units?.player);
52356
- const enemySprite = resolveManifestUrl4(assetManifest, assetManifest?.units?.enemy);
52357
- const projectileSprite = resolveManifestUrl4(assetManifest, assetManifest?.features?.projectile);
52358
- const backgroundSprite = resolveManifestUrl4(assetManifest, assetManifest?.background);
52405
+ const playerSprite = assetManifest?.units?.player?.url;
52406
+ const enemySprite = assetManifest?.units?.enemy?.url;
52407
+ const projectileSprite = assetManifest?.features?.projectile?.url;
52408
+ const backgroundSprite = assetManifest?.background;
52359
52409
  const spriteUrls = useMemo(
52360
52410
  () => [playerSprite, enemySprite, projectileSprite].filter((u) => u != null),
52361
52411
  [playerSprite, enemySprite, projectileSprite]
@@ -52522,7 +52572,6 @@ function TopDownShooterBoard({
52522
52572
  width,
52523
52573
  height,
52524
52574
  backgroundImage: backgroundSprite,
52525
- assetBaseUrl: assetManifest?.baseUrl,
52526
52575
  onDraw
52527
52576
  }
52528
52577
  ),
@@ -52647,15 +52696,6 @@ var init_TopDownShooterTemplate = __esm({
52647
52696
  TopDownShooterTemplate.displayName = "TopDownShooterTemplate";
52648
52697
  }
52649
52698
  });
52650
- function resolveManifestUrl5(manifest, relative) {
52651
- if (relative == null) return void 0;
52652
- if (/^https?:\/\//.test(relative)) return relative;
52653
- const base = manifest?.baseUrl;
52654
- if (base == null) return relative;
52655
- const cleanBase = base.replace(/\/$/, "");
52656
- const cleanRel = relative.replace(/^\//, "");
52657
- return `${cleanBase}/${cleanRel}`;
52658
- }
52659
52699
  function buildDefaultTDTiles() {
52660
52700
  const pathSet = new Set(DEFAULT_TD_PATH.map((p2) => `${p2.x},${p2.y}`));
52661
52701
  const tiles = [];
@@ -52675,18 +52715,18 @@ function buildDefaultTDTiles() {
52675
52715
  function tilesToIso2(tiles, manifest) {
52676
52716
  return tiles.map((t) => {
52677
52717
  const key = t.terrain ?? "ground";
52678
- const sprite = t.terrainSprite ?? resolveManifestUrl5(manifest, manifest?.terrains?.[key]) ?? resolveManifestUrl5(manifest, manifest?.terrains?.ground);
52718
+ const terrainSprite = t.terrainSprite != null ? makeAsset(t.terrainSprite, "tile") : manifest?.terrains?.[key] ?? manifest?.terrains?.ground;
52679
52719
  return {
52680
52720
  x: t.x,
52681
52721
  y: t.y,
52682
52722
  terrain: t.terrain,
52683
- terrainSprite: sprite,
52723
+ terrainSprite,
52684
52724
  passable: t.passable
52685
52725
  };
52686
52726
  });
52687
52727
  }
52688
52728
  function creepsToUnits(creeps, manifest) {
52689
- const sprite = resolveManifestUrl5(manifest, manifest?.units?.creep);
52729
+ const sprite = manifest?.units?.creep;
52690
52730
  return creeps.map((c) => ({
52691
52731
  id: c.id,
52692
52732
  position: { x: c.x, y: c.y },
@@ -52704,14 +52744,14 @@ function heroToUnit(hero, manifest) {
52704
52744
  position: { x: hero.x, y: hero.y },
52705
52745
  name: "Hero",
52706
52746
  team: "player",
52707
- sprite: resolveManifestUrl5(manifest, manifest?.units?.hero),
52747
+ sprite: manifest?.units?.hero,
52708
52748
  unitType: "hero",
52709
52749
  health: 1,
52710
52750
  maxHealth: 1
52711
52751
  };
52712
52752
  }
52713
52753
  function towersToFeatures(towers, manifest) {
52714
- const sprite = resolveManifestUrl5(manifest, manifest?.features?.tower);
52754
+ const sprite = manifest?.features?.tower;
52715
52755
  return towers.map((t) => ({
52716
52756
  id: t.id,
52717
52757
  x: t.x,
@@ -52909,7 +52949,6 @@ function TowerDefenseBoard({
52909
52949
  tiles: isoTiles,
52910
52950
  units: isoUnits,
52911
52951
  features: towerFeatures,
52912
- assetBaseUrl: assetManifest?.baseUrl,
52913
52952
  assetManifest,
52914
52953
  validMoves,
52915
52954
  hoveredTile,
@@ -52953,6 +52992,7 @@ var TD_GRID_W, TD_GRID_H, DEFAULT_TD_PATH, DEFAULT_TD_TILES;
52953
52992
  var init_TowerDefenseBoard = __esm({
52954
52993
  "components/game/organisms/TowerDefenseBoard.tsx"() {
52955
52994
  "use client";
52995
+ init_makeAsset();
52956
52996
  init_cn();
52957
52997
  init_useEventBus();
52958
52998
  init_Box();
@@ -53282,15 +53322,6 @@ var init_UncontrolledBattleBoard = __esm({
53282
53322
  UncontrolledBattleBoard.displayName = "UncontrolledBattleBoard";
53283
53323
  }
53284
53324
  });
53285
- function resolveManifestUrl6(manifest, relative) {
53286
- if (relative == null) return void 0;
53287
- if (/^https?:\/\//.test(relative)) return relative;
53288
- const base = manifest?.baseUrl;
53289
- if (base == null) return relative;
53290
- const cleanBase = base.replace(/\/$/, "");
53291
- const cleanRel = relative.replace(/^\//, "");
53292
- return `${cleanBase}/${cleanRel}`;
53293
- }
53294
53325
  function VisualNovelBoard({
53295
53326
  entity,
53296
53327
  nodes: propNodes,
@@ -53325,11 +53356,11 @@ function VisualNovelBoard({
53325
53356
  const currentNodeId = propCurrentNodeId ?? (str(board.currentNodeId) || nodes[0]?.id);
53326
53357
  const currentNode = nodes.find((n) => n.id === currentNodeId) ?? nodes[0];
53327
53358
  const backgroundImage = useMemo(
53328
- () => resolveManifestUrl6(assetManifest, assetManifest?.backgrounds?.[currentNode?.backgroundKey ?? ""]),
53359
+ () => assetManifest?.backgrounds?.[currentNode?.backgroundKey ?? ""],
53329
53360
  [assetManifest, currentNode?.backgroundKey]
53330
53361
  );
53331
53362
  const portraitUrl = useMemo(
53332
- () => resolveManifestUrl6(assetManifest, assetManifest?.portraits?.[currentNode?.portraitKey ?? ""]),
53363
+ () => assetManifest?.portraits?.[currentNode?.portraitKey ?? ""],
53333
53364
  [assetManifest, currentNode?.portraitKey]
53334
53365
  );
53335
53366
  const dialogueChoices = useMemo(
@@ -53503,7 +53534,7 @@ function buildDefaultWorldTiles() {
53503
53534
  for (let x = 0; x < WORLD_GRID_W; x++) {
53504
53535
  const isBorder = x === 0 || y === 0 || x === WORLD_GRID_W - 1 || y === WORLD_GRID_H - 1;
53505
53536
  const def = isBorder ? WORLD_TERRAIN_DEFS[3] : WORLD_TERRAIN_DEFS[(x * 5 + y * 3 + (x ^ y)) % (WORLD_TERRAIN_DEFS.length - 1)];
53506
- tiles.push({ x, y, terrain: def.terrain, terrainSprite: def.sprite, passable: def.passable });
53537
+ tiles.push({ x, y, terrain: def.terrain, terrainSprite: makeAsset(def.sprite, "tile"), passable: def.passable });
53507
53538
  }
53508
53539
  }
53509
53540
  return tiles;
@@ -53547,7 +53578,12 @@ function WorldMapBoard({
53547
53578
  const resolved = boardEntity(entity);
53548
53579
  const entityUnits = rows(resolved?.units);
53549
53580
  const entityTiles = rows(resolved?.tiles);
53550
- const features = propFeatures ?? rows(resolved?.features);
53581
+ const features = propFeatures ?? rows(resolved?.features).map((r) => ({
53582
+ id: r.id == null ? void 0 : str(r.id),
53583
+ x: num(r.x),
53584
+ y: num(r.y),
53585
+ type: str(r.type)
53586
+ }));
53551
53587
  const selectedHeroId = resolved?.selectedHeroId ?? null;
53552
53588
  const assetManifest = propAssetManifest ?? resolved?.assetManifest;
53553
53589
  const backgroundImage = resolved?.backgroundImage;
@@ -53557,7 +53593,7 @@ function WorldMapBoard({
53557
53593
  x: num(t.x),
53558
53594
  y: num(t.y),
53559
53595
  terrain: str(t.terrain),
53560
- terrainSprite: t.terrainSprite == null ? void 0 : str(t.terrainSprite),
53596
+ terrainSprite: t.terrainSprite == null ? void 0 : makeAsset(str(t.terrainSprite), "tile"),
53561
53597
  passable: t.passable !== false
53562
53598
  })),
53563
53599
  [entityTiles]
@@ -53573,7 +53609,7 @@ function WorldMapBoard({
53573
53609
  team: str(u.team) === "enemy" ? "enemy" : "player",
53574
53610
  health: num(u.health) || 100,
53575
53611
  maxHealth: num(u.maxHealth) || 100,
53576
- sprite: u.sprite == null ? void 0 : str(u.sprite)
53612
+ sprite: u.sprite == null ? void 0 : makeAsset(str(u.sprite), "player")
53577
53613
  })),
53578
53614
  [entityUnits, propUnits]
53579
53615
  );
@@ -53755,7 +53791,6 @@ function WorldMapBoard({
53755
53791
  onTileHover: (x, y) => setHoveredTile({ x, y }),
53756
53792
  onTileLeave: () => setHoveredTile(null),
53757
53793
  scale,
53758
- assetBaseUrl: assetManifest?.baseUrl,
53759
53794
  assetManifest,
53760
53795
  backgroundImage,
53761
53796
  effectSpriteUrls,
@@ -53778,6 +53813,7 @@ var WORLD_CDN, WORLD_GRID_W, WORLD_GRID_H, WORLD_TERRAIN_DEFS, DEFAULT_WORLD_TIL
53778
53813
  var init_WorldMapBoard = __esm({
53779
53814
  "components/game/organisms/WorldMapBoard.tsx"() {
53780
53815
  "use client";
53816
+ init_makeAsset();
53781
53817
  init_cn();
53782
53818
  init_useEventBus();
53783
53819
  init_Stack();
@@ -53831,62 +53867,66 @@ function WorldMapTemplate({
53831
53867
  }
53832
53868
  );
53833
53869
  }
53834
- var CDN5, DEFAULT_WORLDMAP_TILES, DEFAULT_WORLDMAP_UNITS, DEFAULT_WORLDMAP_FEATURES, DEFAULT_WORLDMAP_MANIFEST;
53870
+ var CDN5, mountain, water, grass, road, DEFAULT_WORLDMAP_TILES, DEFAULT_WORLDMAP_UNITS, DEFAULT_WORLDMAP_FEATURES, DEFAULT_WORLDMAP_MANIFEST;
53835
53871
  var init_WorldMapTemplate = __esm({
53836
53872
  "components/game/templates/WorldMapTemplate.tsx"() {
53837
53873
  init_WorldMapBoard();
53874
+ init_makeAsset();
53838
53875
  CDN5 = "https://almadar-kflow-assets.web.app/shared";
53876
+ mountain = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png`, "tile");
53877
+ water = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png`, "tile");
53878
+ grass = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`, "tile");
53879
+ road = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png`, "tile");
53839
53880
  DEFAULT_WORLDMAP_TILES = [
53840
- { x: 0, y: 0, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53841
- { x: 1, y: 0, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53842
- { x: 2, y: 0, terrain: "water", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png` },
53843
- { x: 3, y: 0, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53844
- { x: 4, y: 0, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53845
- { x: 0, y: 1, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53846
- { x: 1, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53847
- { x: 2, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53848
- { x: 3, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53849
- { x: 4, y: 1, terrain: "water", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png` },
53850
- { x: 0, y: 2, terrain: "water", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png` },
53851
- { x: 1, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53852
- { x: 2, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png` },
53853
- { x: 3, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53854
- { x: 4, y: 2, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53855
- { x: 0, y: 3, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53856
- { x: 1, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53857
- { x: 2, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53858
- { x: 3, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png` },
53859
- { x: 4, y: 3, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53860
- { x: 0, y: 4, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53861
- { x: 1, y: 4, terrain: "water", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png` },
53862
- { x: 2, y: 4, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53863
- { x: 3, y: 4, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53864
- { x: 4, y: 4, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` }
53881
+ { x: 0, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53882
+ { x: 1, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53883
+ { x: 2, y: 0, terrain: "water", passable: false, terrainSprite: water },
53884
+ { x: 3, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53885
+ { x: 4, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53886
+ { x: 0, y: 1, terrain: "mountain", passable: false, terrainSprite: mountain },
53887
+ { x: 1, y: 1, terrain: "grass", passable: true, terrainSprite: grass },
53888
+ { x: 2, y: 1, terrain: "grass", passable: true, terrainSprite: grass },
53889
+ { x: 3, y: 1, terrain: "grass", passable: true, terrainSprite: grass },
53890
+ { x: 4, y: 1, terrain: "water", passable: false, terrainSprite: water },
53891
+ { x: 0, y: 2, terrain: "water", passable: false, terrainSprite: water },
53892
+ { x: 1, y: 2, terrain: "grass", passable: true, terrainSprite: grass },
53893
+ { x: 2, y: 2, terrain: "grass", passable: true, terrainSprite: road },
53894
+ { x: 3, y: 2, terrain: "grass", passable: true, terrainSprite: grass },
53895
+ { x: 4, y: 2, terrain: "mountain", passable: false, terrainSprite: mountain },
53896
+ { x: 0, y: 3, terrain: "mountain", passable: false, terrainSprite: mountain },
53897
+ { x: 1, y: 3, terrain: "grass", passable: true, terrainSprite: grass },
53898
+ { x: 2, y: 3, terrain: "grass", passable: true, terrainSprite: grass },
53899
+ { x: 3, y: 3, terrain: "grass", passable: true, terrainSprite: road },
53900
+ { x: 4, y: 3, terrain: "mountain", passable: false, terrainSprite: mountain },
53901
+ { x: 0, y: 4, terrain: "mountain", passable: false, terrainSprite: mountain },
53902
+ { x: 1, y: 4, terrain: "water", passable: false, terrainSprite: water },
53903
+ { x: 2, y: 4, terrain: "grass", passable: true, terrainSprite: grass },
53904
+ { x: 3, y: 4, terrain: "mountain", passable: false, terrainSprite: mountain },
53905
+ { x: 4, y: 4, terrain: "mountain", passable: false, terrainSprite: mountain }
53865
53906
  ];
53866
53907
  DEFAULT_WORLDMAP_UNITS = [
53867
- { 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` },
53868
- { 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` }
53908
+ { 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") },
53909
+ { 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") }
53869
53910
  ];
53870
53911
  DEFAULT_WORLDMAP_FEATURES = [
53871
- { id: "f1", x: 2, y: 2, type: "capital", sprite: `${CDN5}/scenes/world/capital.png` },
53872
- { id: "f2", x: 4, y: 2, type: "power_node", sprite: `${CDN5}/world-map/power_node.png` }
53912
+ { id: "f1", x: 2, y: 2, type: "capital", sprite: makeAsset(`${CDN5}/scenes/world/capital.png`, "decoration") },
53913
+ { id: "f2", x: 4, y: 2, type: "power_node", sprite: makeAsset(`${CDN5}/world-map/power_node.png`, "decoration") }
53873
53914
  ];
53874
53915
  DEFAULT_WORLDMAP_MANIFEST = {
53875
- baseUrl: CDN5,
53876
- terrains: {
53877
- grass: "/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png",
53878
- water: "/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png",
53879
- mountain: "/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png",
53880
- road: "/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png"
53881
- },
53916
+ terrains: makeAssetMap({
53917
+ grass: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`,
53918
+ water: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png`,
53919
+ mountain: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png`,
53920
+ road: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png`
53921
+ }, "tile"),
53882
53922
  units: {
53883
- hero: "/sprite-sheets/amir-sprite-sheet-se.png",
53884
- scout: "/sprite-sheets/archivist-sprite-sheet-se.png"
53923
+ hero: makeAsset(`${CDN5}/sprite-sheets/amir-sprite-sheet-se.png`, "player"),
53924
+ scout: makeAsset(`${CDN5}/sprite-sheets/archivist-sprite-sheet-se.png`, "npc")
53885
53925
  },
53886
- features: {
53887
- capital: "/scenes/world/capital.png",
53888
- power_node: "/world-map/power_node.png"
53889
- }
53926
+ features: makeAssetMap({
53927
+ capital: `${CDN5}/scenes/world/capital.png`,
53928
+ power_node: `${CDN5}/world-map/power_node.png`
53929
+ }, "decoration")
53890
53930
  };
53891
53931
  WorldMapTemplate.displayName = "WorldMapTemplate";
53892
53932
  }