@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
@@ -7002,7 +7002,7 @@ function ScoreDisplay({
7002
7002
  assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
7003
7003
  "img",
7004
7004
  {
7005
- src: assetUrl,
7005
+ src: assetUrl.url,
7006
7006
  alt: "",
7007
7007
  width: 20,
7008
7008
  height: 20,
@@ -7027,7 +7027,11 @@ var init_ScoreDisplay = __esm({
7027
7027
  lg: "text-2xl",
7028
7028
  xl: "text-4xl"
7029
7029
  };
7030
- DEFAULT_ASSET_URL = "https://almadar-kflow-assets.web.app/shared/effects/particles/star_01.png";
7030
+ DEFAULT_ASSET_URL = {
7031
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/star_01.png",
7032
+ role: "effect",
7033
+ category: "effect"
7034
+ };
7031
7035
  ScoreDisplay.displayName = "ScoreDisplay";
7032
7036
  }
7033
7037
  });
@@ -7103,7 +7107,7 @@ function ControlButton({
7103
7107
  children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
7104
7108
  "img",
7105
7109
  {
7106
- src: assetUrl,
7110
+ src: assetUrl.url,
7107
7111
  alt: "",
7108
7112
  width: 24,
7109
7113
  height: 24,
@@ -7143,7 +7147,11 @@ var init_ControlButton = __esm({
7143
7147
  secondary: "bg-secondary text-secondary-foreground border-border hover:bg-secondary-hover",
7144
7148
  ghost: "bg-transparent text-foreground border-border hover:bg-muted"
7145
7149
  };
7146
- DEFAULT_ASSET_URL2 = "https://almadar-kflow-assets.web.app/shared/effects/particles/circle_01.png";
7150
+ DEFAULT_ASSET_URL2 = {
7151
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/circle_01.png",
7152
+ role: "effect",
7153
+ category: "effect"
7154
+ };
7147
7155
  ControlButton.displayName = "ControlButton";
7148
7156
  }
7149
7157
  });
@@ -7182,7 +7190,7 @@ var init_spriteAnimation = __esm({
7182
7190
  }
7183
7191
  });
7184
7192
  function Sprite({
7185
- spritesheet = "https://almadar-kflow-assets.web.app/shared/isometric-blocks/Spritesheet/allTiles_sheet.png",
7193
+ spritesheet = DEFAULT_SPRITESHEET,
7186
7194
  frameWidth = 64,
7187
7195
  frameHeight = 64,
7188
7196
  frame = 0,
@@ -7235,7 +7243,7 @@ function Sprite({
7235
7243
  position: "absolute",
7236
7244
  width: frameWidth,
7237
7245
  height: frameHeight,
7238
- backgroundImage: `url(${spritesheet})`,
7246
+ backgroundImage: `url(${spritesheet.url})`,
7239
7247
  backgroundPosition,
7240
7248
  backgroundRepeat: "no-repeat",
7241
7249
  imageRendering: "pixelated",
@@ -7248,11 +7256,17 @@ function Sprite({
7248
7256
  }
7249
7257
  );
7250
7258
  }
7259
+ var DEFAULT_SPRITESHEET;
7251
7260
  var init_Sprite = __esm({
7252
7261
  "components/game/atoms/Sprite.tsx"() {
7253
7262
  "use client";
7254
7263
  init_useEventBus();
7255
7264
  init_spriteAnimation();
7265
+ DEFAULT_SPRITESHEET = {
7266
+ url: "https://almadar-kflow-assets.web.app/shared/isometric-blocks/Spritesheet/allTiles_sheet.png",
7267
+ role: "tile",
7268
+ category: "tile"
7269
+ };
7256
7270
  }
7257
7271
  });
7258
7272
  function StateIndicator({
@@ -7282,7 +7296,7 @@ function StateIndicator({
7282
7296
  /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
7283
7297
  "img",
7284
7298
  {
7285
- src: assetUrl,
7299
+ src: assetUrl.url,
7286
7300
  alt: displayLabel,
7287
7301
  width: 16,
7288
7302
  height: 16,
@@ -7301,7 +7315,11 @@ var init_StateIndicator = __esm({
7301
7315
  init_Box();
7302
7316
  init_Icon();
7303
7317
  init_cn();
7304
- DEFAULT_ASSET_URL3 = "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png";
7318
+ DEFAULT_ASSET_URL3 = {
7319
+ url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
7320
+ role: "effect",
7321
+ category: "item"
7322
+ };
7305
7323
  DEFAULT_STATE_STYLES = {
7306
7324
  idle: { icon: "\u23F8", bgClass: "bg-muted" },
7307
7325
  active: { icon: "\u25B6", bgClass: "bg-success" },
@@ -7399,7 +7417,7 @@ function ResourceCounter({
7399
7417
  assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
7400
7418
  "img",
7401
7419
  {
7402
- src: assetUrl,
7420
+ src: assetUrl.url,
7403
7421
  alt: label,
7404
7422
  width: sizes.img,
7405
7423
  height: sizes.img,
@@ -7432,7 +7450,11 @@ var init_ResourceCounter = __esm({
7432
7450
  error: "text-error",
7433
7451
  muted: "text-muted-foreground"
7434
7452
  };
7435
- DEFAULT_ASSET_URL4 = "https://almadar-kflow-assets.web.app/shared/world-map/gold_mine.png";
7453
+ DEFAULT_ASSET_URL4 = {
7454
+ url: "https://almadar-kflow-assets.web.app/shared/world-map/gold_mine.png",
7455
+ role: "effect",
7456
+ category: "world"
7457
+ };
7436
7458
  sizeMap5 = {
7437
7459
  sm: { wrapper: "text-xs gap-1 px-1.5 py-0.5", icon: "text-sm", img: 16 },
7438
7460
  md: { wrapper: "text-sm gap-1.5 px-2 py-1", icon: "text-base", img: 20 },
@@ -7478,7 +7500,7 @@ function ItemSlot({
7478
7500
  assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
7479
7501
  "img",
7480
7502
  {
7481
- src: assetUrl,
7503
+ src: assetUrl?.url,
7482
7504
  alt: label,
7483
7505
  width: px,
7484
7506
  height: px,
@@ -7526,7 +7548,11 @@ var init_ItemSlot = __esm({
7526
7548
  epic: "shadow-lg",
7527
7549
  legendary: "shadow-lg"
7528
7550
  };
7529
- DEFAULT_ASSET_URL5 = "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png";
7551
+ DEFAULT_ASSET_URL5 = {
7552
+ url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
7553
+ role: "effect",
7554
+ category: "item"
7555
+ };
7530
7556
  assetSizeMap = {
7531
7557
  sm: 28,
7532
7558
  md: 40,
@@ -7572,7 +7598,7 @@ function TurnIndicator({
7572
7598
  assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
7573
7599
  "img",
7574
7600
  {
7575
- src: assetUrl,
7601
+ src: assetUrl.url,
7576
7602
  alt: "",
7577
7603
  width: 12,
7578
7604
  height: 12,
@@ -7595,7 +7621,11 @@ var init_TurnIndicator = __esm({
7595
7621
  md: { wrapper: "text-sm gap-2 px-3 py-1", dot: "w-2 h-2" },
7596
7622
  lg: { wrapper: "text-base gap-2.5 px-4 py-1.5", dot: "w-2.5 h-2.5" }
7597
7623
  };
7598
- DEFAULT_ASSET_URL6 = "https://almadar-kflow-assets.web.app/shared/effects/particles/symbol_01.png";
7624
+ DEFAULT_ASSET_URL6 = {
7625
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/symbol_01.png",
7626
+ role: "effect",
7627
+ category: "effect"
7628
+ };
7599
7629
  TurnIndicator.displayName = "TurnIndicator";
7600
7630
  }
7601
7631
  });
@@ -7634,7 +7664,7 @@ function ComboCounter({
7634
7664
  assetUrl && /* @__PURE__ */ jsxRuntime.jsx(
7635
7665
  "img",
7636
7666
  {
7637
- src: assetUrl,
7667
+ src: assetUrl.url,
7638
7668
  alt: "combo",
7639
7669
  width: 24,
7640
7670
  height: 24,
@@ -7660,7 +7690,11 @@ var DEFAULT_ASSET_URL7, sizeMap8;
7660
7690
  var init_ComboCounter = __esm({
7661
7691
  "components/game/atoms/ComboCounter.tsx"() {
7662
7692
  init_cn();
7663
- DEFAULT_ASSET_URL7 = "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png";
7693
+ DEFAULT_ASSET_URL7 = {
7694
+ url: "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png",
7695
+ role: "effect",
7696
+ category: "effect"
7697
+ };
7664
7698
  sizeMap8 = {
7665
7699
  sm: { combo: "text-lg", label: "text-xs", multiplier: "text-xs" },
7666
7700
  md: { combo: "text-2xl", label: "text-xs", multiplier: "text-sm" },
@@ -7780,7 +7814,7 @@ function WaypointMarker({
7780
7814
  children: completed ? checkIcon : assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
7781
7815
  "img",
7782
7816
  {
7783
- src: assetUrl,
7817
+ src: assetUrl.url,
7784
7818
  alt: label,
7785
7819
  width: sizes.img,
7786
7820
  height: sizes.img,
@@ -7809,7 +7843,11 @@ var init_WaypointMarker = __esm({
7809
7843
  "components/game/atoms/WaypointMarker.tsx"() {
7810
7844
  init_cn();
7811
7845
  init_Icon();
7812
- DEFAULT_ASSET_URL8 = "https://almadar-kflow-assets.web.app/shared/world-map/battle_marker.png";
7846
+ DEFAULT_ASSET_URL8 = {
7847
+ url: "https://almadar-kflow-assets.web.app/shared/world-map/battle_marker.png",
7848
+ role: "effect",
7849
+ category: "world"
7850
+ };
7813
7851
  sizeMap10 = {
7814
7852
  sm: { dot: "w-4 h-4", ring: "w-6 h-6", label: "text-xs mt-1", img: 12 },
7815
7853
  md: { dot: "w-6 h-6", ring: "w-8 h-8", label: "text-sm mt-1.5", img: 18 },
@@ -7850,7 +7888,7 @@ function StatusEffect({
7850
7888
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("flex items-center justify-center", sizes.icon), children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
7851
7889
  "img",
7852
7890
  {
7853
- src: assetUrl,
7891
+ src: assetUrl.url,
7854
7892
  alt: label,
7855
7893
  width: sizes.img,
7856
7894
  height: sizes.img,
@@ -7889,7 +7927,11 @@ var init_StatusEffect = __esm({
7889
7927
  "components/game/atoms/StatusEffect.tsx"() {
7890
7928
  init_cn();
7891
7929
  init_Icon();
7892
- DEFAULT_ASSET_URL9 = "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png";
7930
+ DEFAULT_ASSET_URL9 = {
7931
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png",
7932
+ role: "effect",
7933
+ category: "effect"
7934
+ };
7893
7935
  sizeMap11 = {
7894
7936
  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 },
7895
7937
  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 },
@@ -7927,7 +7969,7 @@ function DamageNumber({
7927
7969
  assetUrl && /* @__PURE__ */ jsxRuntime.jsx(
7928
7970
  "img",
7929
7971
  {
7930
- src: assetUrl,
7972
+ src: assetUrl.url,
7931
7973
  alt: "",
7932
7974
  width: 14,
7933
7975
  height: 14,
@@ -7963,14 +8005,18 @@ var init_DamageNumber = __esm({
7963
8005
  100% { opacity: 0; transform: translateY(-32px) scale(0.8); }
7964
8006
  }
7965
8007
  `;
7966
- DEFAULT_ASSET_URL10 = "https://almadar-kflow-assets.web.app/shared/effects/particles/spark_01.png";
8008
+ DEFAULT_ASSET_URL10 = {
8009
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/spark_01.png",
8010
+ role: "effect",
8011
+ category: "effect"
8012
+ };
7967
8013
  DamageNumber.displayName = "DamageNumber";
7968
8014
  }
7969
8015
  });
7970
8016
  function DialogueBubble({
7971
8017
  speaker = "Hero",
7972
8018
  text = "The dungeon awaits. Choose your path wisely.",
7973
- portrait = "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
8019
+ portrait = DEFAULT_PORTRAIT,
7974
8020
  position = "bottom",
7975
8021
  className
7976
8022
  }) {
@@ -7986,7 +8032,7 @@ function DialogueBubble({
7986
8032
  portrait && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 w-12 h-12 rounded-full overflow-hidden border-2 border-warning/60", children: /* @__PURE__ */ jsxRuntime.jsx(
7987
8033
  "img",
7988
8034
  {
7989
- src: portrait,
8035
+ src: portrait?.url,
7990
8036
  alt: speaker ?? "speaker",
7991
8037
  className: "w-full h-full object-cover"
7992
8038
  }
@@ -7999,9 +8045,15 @@ function DialogueBubble({
7999
8045
  }
8000
8046
  );
8001
8047
  }
8048
+ var DEFAULT_PORTRAIT;
8002
8049
  var init_DialogueBubble = __esm({
8003
8050
  "components/game/atoms/DialogueBubble.tsx"() {
8004
8051
  init_cn();
8052
+ DEFAULT_PORTRAIT = {
8053
+ url: "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
8054
+ role: "effect",
8055
+ category: "character"
8056
+ };
8005
8057
  DialogueBubble.displayName = "DialogueBubble";
8006
8058
  }
8007
8059
  });
@@ -8045,7 +8097,7 @@ function ChoiceButton({
8045
8097
  assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
8046
8098
  "img",
8047
8099
  {
8048
- src: assetUrl,
8100
+ src: assetUrl.url,
8049
8101
  alt: "",
8050
8102
  width: 16,
8051
8103
  height: 16,
@@ -8115,7 +8167,7 @@ function ActionButton({
8115
8167
  assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
8116
8168
  "img",
8117
8169
  {
8118
- src: assetUrl,
8170
+ src: assetUrl.url,
8119
8171
  alt: "",
8120
8172
  width: 16,
8121
8173
  height: 16,
@@ -8159,7 +8211,11 @@ var init_ActionButton = __esm({
8159
8211
  secondary: "bg-secondary text-secondary-foreground hover:bg-secondary-hover border-border",
8160
8212
  danger: "bg-error text-error-foreground hover:bg-error/90 border-error"
8161
8213
  };
8162
- DEFAULT_ASSET_URL11 = "https://almadar-kflow-assets.web.app/shared/effects/particles/slash_01.png";
8214
+ DEFAULT_ASSET_URL11 = {
8215
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/slash_01.png",
8216
+ role: "effect",
8217
+ category: "effect"
8218
+ };
8163
8219
  ActionButton.displayName = "ActionButton";
8164
8220
  }
8165
8221
  });
@@ -10746,12 +10802,7 @@ var init_useCanvasGestures = __esm({
10746
10802
  }
10747
10803
  });
10748
10804
  function unitAtlasUrl(unit) {
10749
- if (unit.spriteSheet) return unit.spriteSheet;
10750
- const sprite = unit.sprite;
10751
- if (!sprite) return null;
10752
- const match = /^(.*-sprite-sheet)(?:-(?:se|sw))?(?:-v\d+)?\.png$/.exec(sprite);
10753
- if (!match) return null;
10754
- return `${match[1]}.json`;
10805
+ return unit.spriteSheet?.url ?? null;
10755
10806
  }
10756
10807
  function resolveSheetUrl(atlasUrl, relativeSheetPath) {
10757
10808
  try {
@@ -10947,7 +10998,6 @@ function IsometricCanvas({
10947
10998
  // Tuning
10948
10999
  diamondTopY: diamondTopYProp,
10949
11000
  // Remote asset loading
10950
- assetBaseUrl,
10951
11001
  assetManifest
10952
11002
  }) {
10953
11003
  const tilesProp = Array.isArray(_tilesPropRaw) ? _tilesPropRaw : [];
@@ -11029,54 +11079,48 @@ function IsometricCanvas({
11029
11079
  const attackTargetSet = React87.useMemo(() => {
11030
11080
  return new Set(attackTargets.map((p2) => `${p2.x},${p2.y}`));
11031
11081
  }, [attackTargets]);
11032
- const resolveManifestUrl7 = React87.useCallback((relativePath) => {
11033
- if (!relativePath) return void 0;
11034
- if (assetBaseUrl) return `${assetBaseUrl.replace(/\/$/, "")}${relativePath.startsWith("/") ? "" : "/"}${relativePath}`;
11035
- return relativePath;
11036
- }, [assetBaseUrl]);
11037
11082
  const spriteUrls = React87.useMemo(() => {
11038
11083
  const urls = [];
11039
11084
  for (const tile of sortedTiles) {
11040
- if (tile.terrainSprite) urls.push(tile.terrainSprite);
11085
+ if (tile.terrainSprite) urls.push(tile.terrainSprite.url);
11041
11086
  else if (getTerrainSprite) {
11042
11087
  const url = getTerrainSprite(tile.terrain ?? "");
11043
11088
  if (url) urls.push(url);
11044
11089
  } else {
11045
- const url = resolveManifestUrl7(assetManifest?.terrains?.[tile.terrain ?? ""]);
11090
+ const url = assetManifest?.terrains?.[tile.terrain ?? ""]?.url;
11046
11091
  if (url) urls.push(url);
11047
11092
  }
11048
11093
  }
11049
11094
  for (const feature of features) {
11050
- if (feature.sprite) urls.push(feature.sprite);
11095
+ if (feature.sprite) urls.push(feature.sprite.url);
11051
11096
  else if (getFeatureSprite) {
11052
11097
  const url = getFeatureSprite(feature.type);
11053
11098
  if (url) urls.push(url);
11054
11099
  } else {
11055
- const url = resolveManifestUrl7(assetManifest?.features?.[feature.type]);
11100
+ const url = assetManifest?.features?.[feature.type]?.url;
11056
11101
  if (url) urls.push(url);
11057
11102
  }
11058
11103
  }
11059
11104
  for (const unit of units) {
11060
- if (unit.sprite) urls.push(unit.sprite);
11105
+ if (unit.sprite) urls.push(unit.sprite.url);
11061
11106
  else if (getUnitSprite) {
11062
11107
  const url = getUnitSprite(unit);
11063
11108
  if (url) urls.push(url);
11064
11109
  } else if (unit.unitType) {
11065
- const url = resolveManifestUrl7(assetManifest?.units?.[unit.unitType]);
11110
+ const url = assetManifest?.units?.[unit.unitType]?.url;
11066
11111
  if (url) urls.push(url);
11067
11112
  }
11068
11113
  }
11069
11114
  if (assetManifest?.effects) {
11070
- for (const path of Object.values(assetManifest.effects)) {
11071
- const url = resolveManifestUrl7(path);
11072
- if (url) urls.push(url);
11115
+ for (const asset of Object.values(assetManifest.effects)) {
11116
+ if (asset.url) urls.push(asset.url);
11073
11117
  }
11074
11118
  }
11075
11119
  if (effectSpriteUrls) urls.push(...effectSpriteUrls);
11076
11120
  if (atlasSheetUrls.length) urls.push(...atlasSheetUrls);
11077
11121
  if (backgroundImage) urls.push(backgroundImage);
11078
11122
  return [...new Set(urls.filter(Boolean))];
11079
- }, [sortedTiles, features, units, getTerrainSprite, getFeatureSprite, getUnitSprite, effectSpriteUrls, atlasSheetUrls, backgroundImage, assetManifest, resolveManifestUrl7]);
11123
+ }, [sortedTiles, features, units, getTerrainSprite, getFeatureSprite, getUnitSprite, effectSpriteUrls, atlasSheetUrls, backgroundImage, assetManifest]);
11080
11124
  const { getImage, pendingCount: _imagePendingCount } = useImageCache(spriteUrls);
11081
11125
  React87.useEffect(() => {
11082
11126
  if (typeof window === "undefined") return;
@@ -11101,14 +11145,14 @@ function IsometricCanvas({
11101
11145
  lerpToTarget
11102
11146
  } = useCamera();
11103
11147
  const resolveTerrainSpriteUrl = React87.useCallback((tile) => {
11104
- return tile.terrainSprite || getTerrainSprite?.(tile.terrain ?? "") || resolveManifestUrl7(assetManifest?.terrains?.[tile.terrain ?? ""]);
11105
- }, [getTerrainSprite, assetManifest, resolveManifestUrl7]);
11148
+ return tile.terrainSprite?.url || getTerrainSprite?.(tile.terrain ?? "") || assetManifest?.terrains?.[tile.terrain ?? ""]?.url;
11149
+ }, [getTerrainSprite, assetManifest]);
11106
11150
  const resolveFeatureSpriteUrl = React87.useCallback((featureType) => {
11107
- return getFeatureSprite?.(featureType) || resolveManifestUrl7(assetManifest?.features?.[featureType]);
11108
- }, [getFeatureSprite, assetManifest, resolveManifestUrl7]);
11151
+ return getFeatureSprite?.(featureType) || assetManifest?.features?.[featureType]?.url;
11152
+ }, [getFeatureSprite, assetManifest]);
11109
11153
  const resolveUnitSpriteUrl = React87.useCallback((unit) => {
11110
- return unit.sprite || getUnitSprite?.(unit) || (unit.unitType ? resolveManifestUrl7(assetManifest?.units?.[unit.unitType]) : void 0);
11111
- }, [getUnitSprite, assetManifest, resolveManifestUrl7]);
11154
+ return unit.sprite?.url || getUnitSprite?.(unit) || (unit.unitType ? assetManifest?.units?.[unit.unitType]?.url : void 0);
11155
+ }, [getUnitSprite, assetManifest]);
11112
11156
  const miniMapTiles = React87.useMemo(() => {
11113
11157
  if (!showMinimap) return [];
11114
11158
  return sortedTiles.map((t2) => ({
@@ -11255,7 +11299,7 @@ function IsometricCanvas({
11255
11299
  if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
11256
11300
  continue;
11257
11301
  }
11258
- const spriteUrl = feature.sprite || resolveFeatureSpriteUrl(feature.type);
11302
+ const spriteUrl = feature.sprite?.url || resolveFeatureSpriteUrl(feature.type);
11259
11303
  const img = spriteUrl ? getImage(spriteUrl) : null;
11260
11304
  const centerX = pos.x + scaledTileWidth / 2;
11261
11305
  const featureGroundY = pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
@@ -11304,12 +11348,12 @@ function IsometricCanvas({
11304
11348
  const img = unitSpriteUrl ? getImage(unitSpriteUrl) : null;
11305
11349
  const unitDrawH = scaledFloorHeight * spriteHeightRatio * unitScale;
11306
11350
  const maxUnitW = scaledTileWidth * spriteMaxWidthRatio * unitScale;
11351
+ const unitIsSheet = unit.sprite?.dimension === "2d" && (unit.sprite?.animations?.length ?? 0) > 0;
11307
11352
  const SHEET_ROWS = 5;
11308
11353
  const sheetFrameW = img ? img.naturalWidth / SHEET_COLUMNS : 0;
11309
11354
  const sheetFrameH = img ? img.naturalHeight / SHEET_ROWS : 0;
11310
- const imgIsSheet = img ? img.naturalWidth % SHEET_COLUMNS === 0 && img.naturalHeight % SHEET_ROWS === 0 && Math.abs(sheetFrameW - sheetFrameH) < 2 : false;
11311
- const frameW = imgIsSheet ? sheetFrameW : img?.naturalWidth ?? 1;
11312
- const frameH = imgIsSheet ? sheetFrameH : img?.naturalHeight ?? 1;
11355
+ const frameW = unitIsSheet ? sheetFrameW : img?.naturalWidth ?? 1;
11356
+ const frameH = unitIsSheet ? sheetFrameH : img?.naturalHeight ?? 1;
11313
11357
  const ar = frameW / (frameH || 1);
11314
11358
  let drawH = unitDrawH;
11315
11359
  let drawW = unitDrawH * ar;
@@ -11324,7 +11368,7 @@ function IsometricCanvas({
11324
11368
  ctx.save();
11325
11369
  ctx.globalAlpha = 0.25;
11326
11370
  if (img) {
11327
- if (imgIsSheet) {
11371
+ if (unitIsSheet) {
11328
11372
  ctx.drawImage(img, 0, 0, sheetFrameW, sheetFrameH, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
11329
11373
  } else {
11330
11374
  ctx.drawImage(img, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
@@ -11372,7 +11416,7 @@ function IsometricCanvas({
11372
11416
  } else if (img) {
11373
11417
  const spriteY = groundY - drawH - breatheOffset;
11374
11418
  const drawUnit = (x) => {
11375
- if (imgIsSheet) {
11419
+ if (unitIsSheet) {
11376
11420
  ctx.drawImage(img, 0, 0, sheetFrameW, sheetFrameH, x, spriteY, drawW, drawH);
11377
11421
  } else {
11378
11422
  ctx.drawImage(img, x, spriteY, drawW, drawH);
@@ -11399,7 +11443,7 @@ function IsometricCanvas({
11399
11443
  }
11400
11444
  }
11401
11445
  for (const fx of effects) {
11402
- const spriteUrl = resolveManifestUrl7(assetManifest?.effects?.[fx.key]);
11446
+ const spriteUrl = assetManifest?.effects?.[fx.key]?.url;
11403
11447
  if (!spriteUrl) continue;
11404
11448
  const img = getImage(spriteUrl);
11405
11449
  if (!img) continue;
@@ -11443,7 +11487,6 @@ function IsometricCanvas({
11443
11487
  backgroundImage,
11444
11488
  cameraRef,
11445
11489
  unitScale,
11446
- resolveManifestUrl7,
11447
11490
  assetManifest
11448
11491
  ]);
11449
11492
  React87.useEffect(() => {
@@ -11721,6 +11764,42 @@ var init_boardEntity = __esm({
11721
11764
  "components/game/organisms/boardEntity.ts"() {
11722
11765
  }
11723
11766
  });
11767
+
11768
+ // components/game/organisms/utils/makeAsset.ts
11769
+ function makeAsset(url, role, overrides = {}) {
11770
+ const defaults = ROLE_DEFAULTS[role] ?? { dimension: "2d", animations: ["static"], aspect: "1:1" };
11771
+ return {
11772
+ url,
11773
+ role,
11774
+ category: url.split("/").pop()?.replace(/\.[^.]+$/, "") ?? role,
11775
+ ...defaults,
11776
+ ...overrides
11777
+ };
11778
+ }
11779
+ function makeAssetMap(record, role, overrides = {}) {
11780
+ const result = {};
11781
+ for (const [key, url] of Object.entries(record)) {
11782
+ result[key] = makeAsset(url, role, overrides);
11783
+ }
11784
+ return result;
11785
+ }
11786
+ var ROLE_DEFAULTS;
11787
+ var init_makeAsset = __esm({
11788
+ "components/game/organisms/utils/makeAsset.ts"() {
11789
+ ROLE_DEFAULTS = {
11790
+ tile: { dimension: "2d", animations: ["static"], aspect: "1:1" },
11791
+ decoration: { dimension: "2d", animations: ["static"], aspect: "1:1" },
11792
+ effect: { dimension: "2d", animations: ["static"], aspect: "1:1" },
11793
+ item: { dimension: "2d", animations: ["static"], aspect: "5:7" },
11794
+ player: { dimension: "2d", animations: ["idle", "walk", "attack", "hit", "death"], aspect: "1:1" },
11795
+ enemy: { dimension: "2d", animations: ["idle", "walk", "attack", "hit", "death"], aspect: "1:1" },
11796
+ npc: { dimension: "2d", animations: ["idle", "walk", "attack", "hit", "death"], aspect: "1:1" },
11797
+ projectile: { dimension: "2d", animations: ["static"], aspect: "1:1" },
11798
+ vehicle: { dimension: "2d", animations: ["idle", "walk"], aspect: "1:1" },
11799
+ ui: { dimension: "2d", animations: ["static"], aspect: "1:1" }
11800
+ };
11801
+ }
11802
+ });
11724
11803
  function buildDefaultBattleTiles() {
11725
11804
  const tiles = [];
11726
11805
  for (let y = 0; y < BATTLE_GRID_H; y++) {
@@ -11779,14 +11858,14 @@ function BattleBoard({
11779
11858
  if (o === null || typeof o.x !== "number" || typeof o.y !== "number") return [];
11780
11859
  const tile = { x: o.x, y: o.y };
11781
11860
  if (typeof o.terrain === "string") tile.terrain = o.terrain;
11782
- if (typeof o.terrainSprite === "string") tile.terrainSprite = o.terrainSprite;
11861
+ if (typeof o.terrainSprite === "string") tile.terrainSprite = makeAsset(o.terrainSprite, "tile");
11783
11862
  if (typeof o.passable === "boolean") tile.passable = o.passable;
11784
11863
  if (typeof o.movementCost === "number") tile.movementCost = o.movementCost;
11785
11864
  if (typeof o.elevation === "number") tile.elevation = o.elevation;
11786
11865
  if (typeof o.type === "string") tile.type = o.type;
11787
11866
  if (typeof o.tileType === "string") tile.tileType = o.tileType;
11788
11867
  if (typeof o.id === "string") tile.id = o.id;
11789
- if (typeof o.modelUrl === "string") tile.modelUrl = o.modelUrl;
11868
+ if (typeof o.modelUrl === "string") tile.modelUrl = makeAsset(o.modelUrl, "decoration", { dimension: "3d" });
11790
11869
  return [tile];
11791
11870
  }) : []);
11792
11871
  const tiles = rawTiles.length === 0 ? DEFAULT_BATTLE_TILES : rawTiles;
@@ -11795,10 +11874,10 @@ function BattleBoard({
11795
11874
  if (o === null || typeof o.type !== "string" || typeof o.x !== "number" || typeof o.y !== "number") return [];
11796
11875
  const feat = { type: o.type, x: o.x, y: o.y };
11797
11876
  if (typeof o.id === "string") feat.id = o.id;
11798
- if (typeof o.sprite === "string") feat.sprite = o.sprite;
11877
+ if (typeof o.sprite === "string") feat.sprite = makeAsset(o.sprite, "decoration");
11799
11878
  if (typeof o.color === "string") feat.color = o.color;
11800
11879
  if (typeof o.elevation === "number") feat.elevation = o.elevation;
11801
- if (typeof o.assetUrl === "string") feat.assetUrl = o.assetUrl;
11880
+ if (typeof o.assetUrl === "string") feat.assetUrl = makeAsset(o.assetUrl, "decoration", { dimension: "3d" });
11802
11881
  return [feat];
11803
11882
  }) : []);
11804
11883
  const boardWidth = num(board.gridWidth ?? board.boardWidth, BATTLE_GRID_W);
@@ -11914,7 +11993,7 @@ function BattleBoard({
11914
11993
  maxHealth: num(unit.maxHealth),
11915
11994
  unitType: unit.unitType == null ? void 0 : str(unit.unitType),
11916
11995
  heroId: unit.heroId == null ? void 0 : str(unit.heroId),
11917
- sprite: unit.sprite == null ? void 0 : str(unit.sprite),
11996
+ sprite: unit.sprite == null ? void 0 : makeAsset(str(unit.sprite), "npc"),
11918
11997
  traits: unitTraits?.map((tr) => ({
11919
11998
  name: tr.name,
11920
11999
  currentState: tr.currentState,
@@ -12064,7 +12143,6 @@ function BattleBoard({
12064
12143
  onTileHover: (x, y) => setHoveredTile({ x, y }),
12065
12144
  onTileLeave: () => setHoveredTile(null),
12066
12145
  scale,
12067
- assetBaseUrl: assetManifest?.baseUrl,
12068
12146
  assetManifest,
12069
12147
  backgroundImage,
12070
12148
  onDrawEffects,
@@ -12142,15 +12220,16 @@ var init_BattleBoard = __esm({
12142
12220
  init_IsometricCanvas();
12143
12221
  init_boardEntity();
12144
12222
  init_isometric();
12223
+ init_makeAsset();
12145
12224
  BATTLE_CDN = "https://almadar-kflow-assets.web.app/shared";
12146
12225
  BATTLE_GRID_W = 16;
12147
12226
  BATTLE_GRID_H = 16;
12148
12227
  BATTLE_TERRAIN_SPRITES = [
12149
- `${BATTLE_CDN}/isometric-dungeon/Isometric/dirt_E.png`,
12150
- `${BATTLE_CDN}/isometric-dungeon/Isometric/dirtTiles_E.png`,
12151
- `${BATTLE_CDN}/isometric-dungeon/Isometric/planks_E.png`,
12152
- `${BATTLE_CDN}/isometric-dungeon/Isometric/stoneTile_E.png`,
12153
- `${BATTLE_CDN}/isometric-dungeon/Isometric/stoneInset_E.png`
12228
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/dirt_E.png`, "tile"),
12229
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/dirtTiles_E.png`, "tile"),
12230
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/planks_E.png`, "tile"),
12231
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/stoneTile_E.png`, "tile"),
12232
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/stoneInset_E.png`, "tile")
12154
12233
  ];
12155
12234
  DEFAULT_BATTLE_TILES = buildDefaultBattleTiles();
12156
12235
  BattleBoard.displayName = "BattleBoard";
@@ -12189,61 +12268,64 @@ function BattleTemplate({
12189
12268
  }
12190
12269
  );
12191
12270
  }
12192
- var CDN, DEFAULT_BATTLE_TILES2, DEFAULT_BATTLE_UNITS, DEFAULT_BATTLE_FEATURES, DEFAULT_BATTLE_MANIFEST;
12271
+ var CDN, STONE, DIRT, GRASS, DEFAULT_BATTLE_TILES2, DEFAULT_BATTLE_UNITS, DEFAULT_BATTLE_FEATURES, DEFAULT_BATTLE_MANIFEST;
12193
12272
  var init_BattleTemplate = __esm({
12194
12273
  "components/game/templates/BattleTemplate.tsx"() {
12195
12274
  init_BattleBoard();
12275
+ init_makeAsset();
12196
12276
  CDN = "https://almadar-kflow-assets.web.app/shared";
12277
+ STONE = makeAsset(`${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png`, "tile");
12278
+ DIRT = makeAsset(`${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png`, "tile");
12279
+ GRASS = makeAsset(`${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png`, "tile");
12197
12280
  DEFAULT_BATTLE_TILES2 = [
12198
- { x: 0, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12199
- { x: 1, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12200
- { x: 2, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12201
- { x: 3, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12202
- { x: 4, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12203
- { x: 0, y: 1, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12204
- { x: 1, y: 1, terrain: "dirt", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png` },
12205
- { x: 2, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12206
- { x: 3, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12207
- { x: 4, y: 1, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12208
- { x: 0, y: 2, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12209
- { x: 1, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12210
- { x: 2, y: 2, terrain: "dirt", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png` },
12211
- { x: 3, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12212
- { x: 4, y: 2, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12213
- { x: 0, y: 3, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12214
- { x: 1, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12215
- { x: 2, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12216
- { x: 3, y: 3, terrain: "dirt", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png` },
12217
- { x: 4, y: 3, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12218
- { x: 0, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12219
- { x: 1, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12220
- { x: 2, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12221
- { x: 3, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12222
- { x: 4, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` }
12281
+ { x: 0, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12282
+ { x: 1, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12283
+ { x: 2, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12284
+ { x: 3, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12285
+ { x: 4, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12286
+ { x: 0, y: 1, terrain: "stone", passable: false, terrainSprite: STONE },
12287
+ { x: 1, y: 1, terrain: "dirt", passable: true, terrainSprite: DIRT },
12288
+ { x: 2, y: 1, terrain: "grass", passable: true, terrainSprite: GRASS },
12289
+ { x: 3, y: 1, terrain: "grass", passable: true, terrainSprite: GRASS },
12290
+ { x: 4, y: 1, terrain: "stone", passable: false, terrainSprite: STONE },
12291
+ { x: 0, y: 2, terrain: "stone", passable: false, terrainSprite: STONE },
12292
+ { x: 1, y: 2, terrain: "grass", passable: true, terrainSprite: GRASS },
12293
+ { x: 2, y: 2, terrain: "dirt", passable: true, terrainSprite: DIRT },
12294
+ { x: 3, y: 2, terrain: "grass", passable: true, terrainSprite: GRASS },
12295
+ { x: 4, y: 2, terrain: "stone", passable: false, terrainSprite: STONE },
12296
+ { x: 0, y: 3, terrain: "stone", passable: false, terrainSprite: STONE },
12297
+ { x: 1, y: 3, terrain: "grass", passable: true, terrainSprite: GRASS },
12298
+ { x: 2, y: 3, terrain: "grass", passable: true, terrainSprite: GRASS },
12299
+ { x: 3, y: 3, terrain: "dirt", passable: true, terrainSprite: DIRT },
12300
+ { x: 4, y: 3, terrain: "stone", passable: false, terrainSprite: STONE },
12301
+ { x: 0, y: 4, terrain: "stone", passable: false, terrainSprite: STONE },
12302
+ { x: 1, y: 4, terrain: "stone", passable: false, terrainSprite: STONE },
12303
+ { x: 2, y: 4, terrain: "stone", passable: false, terrainSprite: STONE },
12304
+ { x: 3, y: 4, terrain: "stone", passable: false, terrainSprite: STONE },
12305
+ { x: 4, y: 4, terrain: "stone", passable: false, terrainSprite: STONE }
12223
12306
  ];
12224
12307
  DEFAULT_BATTLE_UNITS = [
12225
- { 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` },
12226
- { 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` }
12308
+ { 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") },
12309
+ { 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") }
12227
12310
  ];
12228
12311
  DEFAULT_BATTLE_FEATURES = [
12229
- { id: "f1", x: 2, y: 2, type: "gold_mine", sprite: `${CDN}/world-map/gold_mine.png` },
12230
- { id: "f2", x: 3, y: 1, type: "portal", sprite: `${CDN}/world-map/portal_open.png` }
12312
+ { id: "f1", x: 2, y: 2, type: "gold_mine", sprite: makeAsset(`${CDN}/world-map/gold_mine.png`, "decoration") },
12313
+ { id: "f2", x: 3, y: 1, type: "portal", sprite: makeAsset(`${CDN}/world-map/portal_open.png`, "decoration") }
12231
12314
  ];
12232
12315
  DEFAULT_BATTLE_MANIFEST = {
12233
- baseUrl: CDN,
12234
- terrains: {
12235
- stone: "/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png",
12236
- dirt: "/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png",
12237
- grass: "/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png"
12238
- },
12239
- units: {
12240
- worker: "/sprite-sheets/amir-sprite-sheet-se.png",
12241
- guardian: "/sprite-sheets/destroyer-sprite-sheet-sw.png"
12242
- },
12243
- features: {
12244
- gold_mine: "/world-map/gold_mine.png",
12245
- portal: "/world-map/portal_open.png"
12246
- }
12316
+ terrains: makeAssetMap({
12317
+ stone: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png`,
12318
+ dirt: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png`,
12319
+ grass: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png`
12320
+ }, "tile"),
12321
+ units: makeAssetMap({
12322
+ worker: `${CDN}/sprite-sheets/amir-sprite-sheet-se.png`,
12323
+ guardian: `${CDN}/sprite-sheets/destroyer-sprite-sheet-sw.png`
12324
+ }, "npc"),
12325
+ features: makeAssetMap({
12326
+ gold_mine: `${CDN}/world-map/gold_mine.png`,
12327
+ portal: `${CDN}/world-map/portal_open.png`
12328
+ }, "decoration")
12247
12329
  };
12248
12330
  BattleTemplate.displayName = "BattleTemplate";
12249
12331
  }
@@ -14458,7 +14540,6 @@ function BoardgameBoard({
14458
14540
  units,
14459
14541
  features,
14460
14542
  assetManifest,
14461
- assetBaseUrl,
14462
14543
  scale,
14463
14544
  showMinimap,
14464
14545
  enableCamera,
@@ -19528,7 +19609,7 @@ function CardHand({
19528
19609
  /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex-1 flex items-center justify-center w-full", children: card.iconUrl ? /* @__PURE__ */ jsxRuntime.jsx(
19529
19610
  "img",
19530
19611
  {
19531
- src: card.iconUrl,
19612
+ src: card.iconUrl.url,
19532
19613
  alt: card.title ?? card.id,
19533
19614
  width: art,
19534
19615
  height: art,
@@ -19586,15 +19667,6 @@ var init_CardHand = __esm({
19586
19667
  CardHand.displayName = "CardHand";
19587
19668
  }
19588
19669
  });
19589
- function resolveManifestUrl(manifest, relative) {
19590
- if (relative == null) return void 0;
19591
- if (/^https?:\/\//.test(relative)) return relative;
19592
- const base = manifest?.baseUrl;
19593
- if (base == null) return relative;
19594
- const cleanBase = base.replace(/\/$/, "");
19595
- const cleanRel = relative.replace(/^\//, "");
19596
- return `${cleanBase}/${cleanRel}`;
19597
- }
19598
19670
  function rowToCard(r) {
19599
19671
  return {
19600
19672
  id: str(r.id),
@@ -19608,7 +19680,7 @@ function rowToCard(r) {
19608
19680
  function toHandCards(cards, manifest, mana) {
19609
19681
  return cards.map((c) => {
19610
19682
  const key = c.iconKey ?? c.id;
19611
- const iconUrl = resolveManifestUrl(manifest, manifest?.cards?.[key]);
19683
+ const iconUrl = manifest?.cards?.[key];
19612
19684
  return {
19613
19685
  id: c.id,
19614
19686
  iconUrl,
@@ -20722,7 +20794,6 @@ function CastleBoard({
20722
20794
  onTileHover: (x, y) => setHoveredTile({ x, y }),
20723
20795
  onTileLeave: () => setHoveredTile(null),
20724
20796
  scale,
20725
- assetBaseUrl: assetManifest?.baseUrl,
20726
20797
  assetManifest,
20727
20798
  backgroundImage
20728
20799
  }
@@ -20798,60 +20869,63 @@ function CastleTemplate({
20798
20869
  }
20799
20870
  );
20800
20871
  }
20801
- var CDN2, DEFAULT_CASTLE_TILES, DEFAULT_CASTLE_UNITS, DEFAULT_CASTLE_FEATURES, DEFAULT_CASTLE_MANIFEST;
20872
+ var CDN2, WALL, FLOOR, FLOOR_CENTER, DEFAULT_CASTLE_TILES, DEFAULT_CASTLE_UNITS, DEFAULT_CASTLE_FEATURES, DEFAULT_CASTLE_MANIFEST;
20802
20873
  var init_CastleTemplate = __esm({
20803
20874
  "components/game/templates/CastleTemplate.tsx"() {
20804
20875
  init_CastleBoard();
20876
+ init_makeAsset();
20805
20877
  CDN2 = "https://almadar-kflow-assets.web.app/shared";
20878
+ WALL = makeAsset(`${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png`, "tile");
20879
+ FLOOR = makeAsset(`${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`, "tile");
20880
+ FLOOR_CENTER = makeAsset(`${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_09.png`, "tile");
20806
20881
  DEFAULT_CASTLE_TILES = [
20807
- { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20808
- { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20809
- { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20810
- { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20811
- { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20812
- { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20813
- { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20814
- { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20815
- { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20816
- { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20817
- { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20818
- { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20819
- { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_09.png` },
20820
- { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20821
- { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20822
- { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20823
- { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20824
- { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20825
- { x: 3, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20826
- { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20827
- { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20828
- { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20829
- { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20830
- { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20831
- { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` }
20882
+ { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
20883
+ { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
20884
+ { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
20885
+ { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
20886
+ { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
20887
+ { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: WALL },
20888
+ { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: FLOOR },
20889
+ { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: FLOOR },
20890
+ { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: FLOOR },
20891
+ { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: WALL },
20892
+ { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: WALL },
20893
+ { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: FLOOR },
20894
+ { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: FLOOR_CENTER },
20895
+ { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: FLOOR },
20896
+ { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: WALL },
20897
+ { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: WALL },
20898
+ { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: FLOOR },
20899
+ { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: FLOOR },
20900
+ { x: 3, y: 3, terrain: "floor", passable: true, terrainSprite: FLOOR },
20901
+ { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: WALL },
20902
+ { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: WALL },
20903
+ { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: WALL },
20904
+ { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: WALL },
20905
+ { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: WALL },
20906
+ { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: WALL }
20832
20907
  ];
20833
20908
  DEFAULT_CASTLE_UNITS = [
20834
- { 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` },
20835
- { 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` }
20909
+ { 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") },
20910
+ { 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") }
20836
20911
  ];
20837
20912
  DEFAULT_CASTLE_FEATURES = [
20838
- { id: "f1", x: 2, y: 2, type: "chest", sprite: `${CDN2}/world-map/treasure_chest_closed.png` },
20839
- { id: "f2", x: 3, y: 1, type: "crystal", sprite: `${CDN2}/world-map/resonance_crystal.png` }
20913
+ { id: "f1", x: 2, y: 2, type: "chest", sprite: makeAsset(`${CDN2}/world-map/treasure_chest_closed.png`, "decoration") },
20914
+ { id: "f2", x: 3, y: 1, type: "crystal", sprite: makeAsset(`${CDN2}/world-map/resonance_crystal.png`, "decoration") }
20840
20915
  ];
20841
20916
  DEFAULT_CASTLE_MANIFEST = {
20842
- baseUrl: CDN2,
20843
- terrains: {
20844
- wall: "/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png",
20845
- floor: "/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png"
20846
- },
20847
- units: {
20848
- worker: "/sprite-sheets/coordinator-sprite-sheet-se.png",
20849
- guardian: "/sprite-sheets/forger-sprite-sheet-se.png"
20850
- },
20851
- features: {
20852
- chest: "/world-map/treasure_chest_closed.png",
20853
- crystal: "/world-map/resonance_crystal.png"
20854
- }
20917
+ terrains: makeAssetMap({
20918
+ wall: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png`,
20919
+ floor: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`
20920
+ }, "tile"),
20921
+ units: makeAssetMap({
20922
+ worker: `${CDN2}/sprite-sheets/coordinator-sprite-sheet-se.png`,
20923
+ guardian: `${CDN2}/sprite-sheets/forger-sprite-sheet-se.png`
20924
+ }, "player"),
20925
+ features: makeAssetMap({
20926
+ chest: `${CDN2}/world-map/treasure_chest_closed.png`,
20927
+ crystal: `${CDN2}/world-map/resonance_crystal.png`
20928
+ }, "decoration")
20855
20929
  };
20856
20930
  CastleTemplate.displayName = "CastleTemplate";
20857
20931
  }
@@ -21839,15 +21913,6 @@ var init_ChatBar = __esm({
21839
21913
  ChatBar.displayName = "ChatBar";
21840
21914
  }
21841
21915
  });
21842
- function resolveManifestUrl2(manifest, relative) {
21843
- if (relative == null) return void 0;
21844
- if (/^https?:\/\//.test(relative)) return relative;
21845
- const base = manifest?.baseUrl;
21846
- if (base == null) return relative;
21847
- const cleanBase = base.replace(/\/$/, "");
21848
- const cleanRel = relative.replace(/^\//, "");
21849
- return `${cleanBase}/${cleanRel}`;
21850
- }
21851
21916
  function buildDefaultCBTiles() {
21852
21917
  const tiles = [];
21853
21918
  for (let y = 0; y < CB_GRID_H; y++) {
@@ -21862,12 +21927,12 @@ function buildDefaultCBTiles() {
21862
21927
  function tilesToIso(tiles, manifest) {
21863
21928
  return tiles.map((t) => {
21864
21929
  const key = t.terrain ?? "grass";
21865
- const sprite = t.terrainSprite ?? resolveManifestUrl2(manifest, manifest?.terrains?.[key]) ?? resolveManifestUrl2(manifest, manifest?.terrains?.grass);
21930
+ const terrainSprite = t.terrainSprite ?? manifest?.terrains?.[key] ?? manifest?.terrains?.grass;
21866
21931
  return {
21867
21932
  x: t.x,
21868
21933
  y: t.y,
21869
21934
  terrain: t.terrain,
21870
- terrainSprite: sprite,
21935
+ terrainSprite,
21871
21936
  passable: t.passable
21872
21937
  };
21873
21938
  });
@@ -21878,7 +21943,7 @@ function buildingsToFeatures(buildings, manifest) {
21878
21943
  x: b.x,
21879
21944
  y: b.y,
21880
21945
  type: b.type,
21881
- sprite: resolveManifestUrl2(manifest, manifest?.features?.[b.type])
21946
+ sprite: manifest?.features?.[b.type]
21882
21947
  }));
21883
21948
  }
21884
21949
  function CityBuilderBoard({
@@ -21910,7 +21975,7 @@ function CityBuilderBoard({
21910
21975
  x: num(r.x),
21911
21976
  y: num(r.y),
21912
21977
  terrain: r.terrain == null ? void 0 : str(r.terrain),
21913
- terrainSprite: r.terrainSprite == null ? void 0 : str(r.terrainSprite),
21978
+ terrainSprite: r.terrainSprite == null ? void 0 : makeAsset(str(r.terrainSprite), "tile"),
21914
21979
  passable: r.passable !== false
21915
21980
  })),
21916
21981
  [board.tiles]
@@ -22019,7 +22084,6 @@ function CityBuilderBoard({
22019
22084
  {
22020
22085
  tiles: isoTiles,
22021
22086
  features: buildingFeatures,
22022
- assetBaseUrl: assetManifest?.baseUrl,
22023
22087
  assetManifest,
22024
22088
  validMoves,
22025
22089
  hoveredTile,
@@ -22054,6 +22118,7 @@ var CB_GRID_W, CB_GRID_H, DEFAULT_BUILD_TYPES, DEFAULT_CB_TILES;
22054
22118
  var init_CityBuilderBoard = __esm({
22055
22119
  "components/game/organisms/CityBuilderBoard.tsx"() {
22056
22120
  "use client";
22121
+ init_makeAsset();
22057
22122
  init_cn();
22058
22123
  init_useEventBus();
22059
22124
  init_Box();
@@ -28048,7 +28113,7 @@ function StatBadge({
28048
28113
  resolvedAsset ? /* @__PURE__ */ jsxRuntime.jsx(
28049
28114
  "img",
28050
28115
  {
28051
- src: resolvedAsset,
28116
+ src: resolvedAsset.url,
28052
28117
  alt: "",
28053
28118
  width: 16,
28054
28119
  height: 16,
@@ -28355,7 +28420,7 @@ function GameCanvas2D({
28355
28420
  tickEvent,
28356
28421
  drawEvent,
28357
28422
  fps = 60,
28358
- backgroundImage = "",
28423
+ backgroundImage,
28359
28424
  assetBaseUrl,
28360
28425
  className
28361
28426
  }) {
@@ -28419,7 +28484,7 @@ function GameCanvas2D({
28419
28484
  emitRef.current(tickEventRef.current, { dt, frame });
28420
28485
  }
28421
28486
  if (backgroundImageRef.current) {
28422
- const bgImg = loadImage(backgroundImageRef.current);
28487
+ const bgImg = loadImage(backgroundImageRef.current.url);
28423
28488
  if (bgImg) {
28424
28489
  ctx.drawImage(bgImg, 0, 0, widthRef.current, heightRef.current);
28425
28490
  } else {
@@ -28790,7 +28855,7 @@ function EnemyPlate({
28790
28855
  assetUrl && /* @__PURE__ */ jsxRuntime.jsx(
28791
28856
  "img",
28792
28857
  {
28793
- src: assetUrl,
28858
+ src: assetUrl.url,
28794
28859
  alt: name,
28795
28860
  width: 24,
28796
28861
  height: 24,
@@ -29132,7 +29197,7 @@ function DialogueBox({
29132
29197
  "div",
29133
29198
  {
29134
29199
  className: "fixed inset-0 z-20 bg-center bg-cover bg-no-repeat",
29135
- style: { backgroundImage: `url(${backgroundImage})` },
29200
+ style: { backgroundImage: `url(${backgroundImage?.url})` },
29136
29201
  "aria-hidden": "true"
29137
29202
  }
29138
29203
  ),
@@ -29147,7 +29212,7 @@ function DialogueBox({
29147
29212
  children: /* @__PURE__ */ jsxRuntime.jsx(
29148
29213
  "img",
29149
29214
  {
29150
- src: portraitUrl,
29215
+ src: portraitUrl?.url,
29151
29216
  alt: dialogue.speaker,
29152
29217
  className: "h-full w-auto object-contain drop-shadow-2xl"
29153
29218
  }
@@ -41453,7 +41518,6 @@ var init_FeatureGridOrganism = __esm({
41453
41518
  });
41454
41519
  function FishingBoard({
41455
41520
  backgroundImage,
41456
- assetBaseUrl,
41457
41521
  scale = 1,
41458
41522
  showMinimap = false,
41459
41523
  enableCamera = true,
@@ -41471,8 +41535,7 @@ function FishingBoard({
41471
41535
  {
41472
41536
  width,
41473
41537
  height,
41474
- backgroundImage: backgroundImage ?? "",
41475
- assetBaseUrl,
41538
+ backgroundImage,
41476
41539
  fps: 60,
41477
41540
  className: "w-full h-full"
41478
41541
  }
@@ -43691,7 +43754,7 @@ var init_GameCanvas3D2 = __esm({
43691
43754
  children: /* @__PURE__ */ jsxRuntime.jsx(
43692
43755
  ModelLoader,
43693
43756
  {
43694
- url: tile.modelUrl,
43757
+ url: tile.modelUrl.url,
43695
43758
  scale: 0.95,
43696
43759
  fallbackGeometry: "box",
43697
43760
  castShadow: true,
@@ -43756,7 +43819,7 @@ var init_GameCanvas3D2 = __esm({
43756
43819
  /* @__PURE__ */ jsxRuntime.jsx(
43757
43820
  ModelLoader,
43758
43821
  {
43759
- url: unit.modelUrl,
43822
+ url: unit.modelUrl.url,
43760
43823
  scale: modelScale,
43761
43824
  fallbackGeometry: "box",
43762
43825
  castShadow: true
@@ -43816,7 +43879,7 @@ var init_GameCanvas3D2 = __esm({
43816
43879
  return /* @__PURE__ */ jsxRuntime.jsx(
43817
43880
  ModelLoader,
43818
43881
  {
43819
- url: feature.assetUrl,
43882
+ url: feature.assetUrl.url,
43820
43883
  position,
43821
43884
  scale: 0.5,
43822
43885
  rotation: [0, feature.rotation ?? 0, 0],
@@ -44037,7 +44100,18 @@ function GameBoard3D({
44037
44100
  const row = boardEntity(entity);
44038
44101
  const eventBus = useEventBus();
44039
44102
  const entityUnits = row ? rows(row.units) : [];
44040
- const units = entityUnits;
44103
+ const units = entityUnits.map((r) => ({
44104
+ id: str(r.id),
44105
+ x: num(r.x),
44106
+ y: num(r.y),
44107
+ z: num(r.z),
44108
+ faction: str(r.faction) || "neutral",
44109
+ team: str(r.team) || str(r.faction) || "neutral",
44110
+ unitType: r.unitType == null ? void 0 : str(r.unitType),
44111
+ name: r.name == null ? void 0 : str(r.name),
44112
+ health: r.health == null ? void 0 : num(r.health),
44113
+ maxHealth: r.maxHealth == null ? void 0 : num(r.maxHealth)
44114
+ }));
44041
44115
  const selectedUnitId = row ? str(row.selectedUnitId) || null : null;
44042
44116
  const phase = row ? str(row.phase) : "observation";
44043
44117
  const result = row ? str(row.result) : "none";
@@ -44632,7 +44706,6 @@ function HexStrategyBoard({
44632
44706
  units,
44633
44707
  features,
44634
44708
  assetManifest,
44635
- assetBaseUrl,
44636
44709
  scale,
44637
44710
  showMinimap,
44638
44711
  enableCamera,
@@ -44674,7 +44747,6 @@ function HolidayRunnerBoard({
44674
44747
  units,
44675
44748
  features,
44676
44749
  assetManifest,
44677
- assetBaseUrl,
44678
44750
  scale,
44679
44751
  showMinimap,
44680
44752
  enableCamera,
@@ -45469,7 +45541,6 @@ function MatchPuzzleBoard({
45469
45541
  units,
45470
45542
  features,
45471
45543
  assetManifest,
45472
- assetBaseUrl,
45473
45544
  scale,
45474
45545
  showMinimap,
45475
45546
  enableCamera,
@@ -45730,7 +45801,6 @@ function MinigolfBoard({
45730
45801
  units,
45731
45802
  features,
45732
45803
  assetManifest,
45733
- assetBaseUrl,
45734
45804
  scale,
45735
45805
  showMinimap,
45736
45806
  enableCamera,
@@ -46036,7 +46106,6 @@ function PirateBoard({
46036
46106
  units,
46037
46107
  features,
46038
46108
  assetManifest,
46039
- assetBaseUrl,
46040
46109
  scale,
46041
46110
  showMinimap,
46042
46111
  enableCamera,
@@ -46157,8 +46226,8 @@ function PlatformerBoard({
46157
46226
  canvasHeight,
46158
46227
  followCamera: true,
46159
46228
  bgColor,
46160
- playerSprite,
46161
- tileSprites,
46229
+ playerSprite: playerSprite?.url,
46230
+ tileSprites: tileSprites ? Object.fromEntries(Object.entries(tileSprites).map(([k, a]) => [k, a.url])) : void 0,
46162
46231
  leftEvent,
46163
46232
  rightEvent,
46164
46233
  jumpEvent,
@@ -46223,7 +46292,7 @@ function PlatformerTemplate({
46223
46292
  worldHeight = 400,
46224
46293
  canvasWidth = 800,
46225
46294
  canvasHeight = 400,
46226
- playerSprite = `${CDN3}/characters/platformChar_idle.png`,
46295
+ playerSprite = makeAsset(`${CDN3}/characters/platformChar_idle.png`, "player"),
46227
46296
  tileSprites = DEFAULT_TILE_SPRITES,
46228
46297
  bgColor = "#5c94fc",
46229
46298
  gameEndEvent = "GAME_END",
@@ -46276,13 +46345,14 @@ var init_PlatformerTemplate = __esm({
46276
46345
  init_PlatformerBoard();
46277
46346
  init_GameHud();
46278
46347
  init_ScoreBoard();
46348
+ init_makeAsset();
46279
46349
  CDN3 = "https://almadar-kflow-assets.web.app/shared/platformer";
46280
- DEFAULT_TILE_SPRITES = {
46350
+ DEFAULT_TILE_SPRITES = makeAssetMap({
46281
46351
  ground: `${CDN3}/tiles/platformPack_tile001.png`,
46282
46352
  platform: `${CDN3}/tiles/platformPack_tile004.png`,
46283
46353
  hazard: `${CDN3}/tiles/platformPack_tile017.png`,
46284
46354
  goal: `${CDN3}/tiles/platformPack_tile007.png`
46285
- };
46355
+ }, "tile");
46286
46356
  DEFAULT_PLATFORMS = [
46287
46357
  { x: 0, y: 368, width: 800, height: 32, type: "ground" },
46288
46358
  { x: 150, y: 280, width: 160, height: 16, type: "platform" },
@@ -46438,7 +46508,6 @@ function RacingBoard({
46438
46508
  units,
46439
46509
  features,
46440
46510
  assetManifest,
46441
- assetBaseUrl,
46442
46511
  scale,
46443
46512
  showMinimap,
46444
46513
  enableCamera,
@@ -46457,27 +46526,18 @@ var init_RacingBoard = __esm({
46457
46526
  RacingBoard.displayName = "RacingBoard";
46458
46527
  }
46459
46528
  });
46460
- function resolveManifestUrl3(manifest, relative) {
46461
- if (relative == null) return void 0;
46462
- if (/^https?:\/\//.test(relative)) return relative;
46463
- const base = manifest?.baseUrl;
46464
- if (base == null) return relative;
46465
- const cleanBase = base.replace(/\/$/, "");
46466
- const cleanRel = relative.replace(/^\//, "");
46467
- return `${cleanBase}/${cleanRel}`;
46468
- }
46469
46529
  function dungeonTerrain(x, y, stairsX, stairsY, manifest) {
46470
46530
  const isBorder = x === 0 || y === 0 || x === DUNGEON_GRID_W - 1 || y === DUNGEON_GRID_H - 1;
46471
46531
  const isPillar = x % 4 === 0 && y % 4 === 0 && !isBorder;
46472
46532
  const isWall = isBorder || isPillar;
46473
46533
  const terrains = manifest?.terrains;
46474
46534
  if (x === stairsX && y === stairsY) {
46475
- return { terrain: "stairs", passable: true, terrainSprite: resolveManifestUrl3(manifest, terrains?.stairs) };
46535
+ return { terrain: "stairs", passable: true, terrainSprite: terrains?.stairs };
46476
46536
  }
46477
46537
  if (isWall) {
46478
- return { terrain: "wall", passable: false, terrainSprite: resolveManifestUrl3(manifest, terrains?.wall) };
46538
+ return { terrain: "wall", passable: false, terrainSprite: terrains?.wall };
46479
46539
  }
46480
- return { terrain: "floor", passable: true, terrainSprite: resolveManifestUrl3(manifest, terrains?.floor) };
46540
+ return { terrain: "floor", passable: true, terrainSprite: terrains?.floor };
46481
46541
  }
46482
46542
  function buildDefaultDungeonTiles(stairsX, stairsY, manifest) {
46483
46543
  const tiles = [];
@@ -46521,7 +46581,7 @@ function RoguelikeBoard({
46521
46581
  x: num(r.x),
46522
46582
  y: num(r.y),
46523
46583
  terrain: r.terrain == null ? void 0 : str(r.terrain),
46524
- terrainSprite: r.terrainSprite == null ? void 0 : str(r.terrainSprite),
46584
+ terrainSprite: r.terrainSprite == null ? void 0 : makeAsset(str(r.terrainSprite), "tile"),
46525
46585
  passable: r.passable !== false
46526
46586
  })),
46527
46587
  [board.tiles]
@@ -46601,7 +46661,7 @@ function RoguelikeBoard({
46601
46661
  health: playerHp,
46602
46662
  maxHealth: playerMaxHp,
46603
46663
  unitType: "player",
46604
- sprite: resolveManifestUrl3(assetManifest, assetManifest?.units?.player)
46664
+ sprite: assetManifest?.units?.player
46605
46665
  },
46606
46666
  ...liveEnemies.map((e) => ({
46607
46667
  id: e.id,
@@ -46611,7 +46671,7 @@ function RoguelikeBoard({
46611
46671
  health: e.hp,
46612
46672
  maxHealth: 6,
46613
46673
  unitType: "enemy",
46614
- sprite: resolveManifestUrl3(assetManifest, assetManifest?.units?.enemy)
46674
+ sprite: assetManifest?.units?.enemy
46615
46675
  }))
46616
46676
  ];
46617
46677
  }, [player, enemies, playerHp, playerMaxHp, assetManifest, t]);
@@ -46621,7 +46681,7 @@ function RoguelikeBoard({
46621
46681
  x: it.x,
46622
46682
  y: it.y,
46623
46683
  type: it.kind,
46624
- sprite: resolveManifestUrl3(assetManifest, assetManifest?.features?.[it.kind])
46684
+ sprite: assetManifest?.features?.[it.kind]
46625
46685
  })),
46626
46686
  [items, assetManifest]
46627
46687
  );
@@ -46682,7 +46742,6 @@ function RoguelikeBoard({
46682
46742
  onTileHover: (x, y) => setHoveredTile({ x, y }),
46683
46743
  onTileLeave: () => setHoveredTile(null),
46684
46744
  scale,
46685
- assetBaseUrl: assetManifest?.baseUrl,
46686
46745
  assetManifest,
46687
46746
  unitScale,
46688
46747
  spriteHeightRatio,
@@ -46742,6 +46801,7 @@ var init_RoguelikeBoard = __esm({
46742
46801
  init_Stack();
46743
46802
  init_IsometricCanvas();
46744
46803
  init_boardEntity();
46804
+ init_makeAsset();
46745
46805
  DUNGEON_GRID_W = 16;
46746
46806
  DUNGEON_GRID_H = 16;
46747
46807
  DEFAULT_ENEMIES = [
@@ -46792,55 +46852,59 @@ function RoguelikeTemplate({
46792
46852
  }
46793
46853
  );
46794
46854
  }
46795
- var CDN4, DEFAULT_ROGUELIKE_TILES, DEFAULT_ROGUELIKE_MANIFEST;
46855
+ var CDN4, wall, floor, tiles2, stairs, DEFAULT_ROGUELIKE_TILES, DEFAULT_ROGUELIKE_MANIFEST;
46796
46856
  var init_RoguelikeTemplate = __esm({
46797
46857
  "components/game/templates/RoguelikeTemplate.tsx"() {
46798
46858
  init_RoguelikeBoard();
46859
+ init_makeAsset();
46799
46860
  CDN4 = "https://almadar-kflow-assets.web.app/shared";
46861
+ wall = makeAsset(`${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png`, "tile");
46862
+ floor = makeAsset(`${CDN4}/isometric-dungeon/Isometric/dirt_E.png`, "tile");
46863
+ tiles2 = makeAsset(`${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png`, "tile");
46864
+ stairs = makeAsset(`${CDN4}/isometric-dungeon/Isometric/stairs_E.png`, "tile");
46800
46865
  DEFAULT_ROGUELIKE_TILES = [
46801
- { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46802
- { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46803
- { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46804
- { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46805
- { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46806
- { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46807
- { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
46808
- { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
46809
- { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
46810
- { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46811
- { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46812
- { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
46813
- { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
46814
- { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
46815
- { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46816
- { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46817
- { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
46818
- { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
46819
- { x: 3, y: 3, terrain: "stairs", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stairs_E.png` },
46820
- { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46821
- { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46822
- { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46823
- { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46824
- { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46825
- { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` }
46866
+ { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
46867
+ { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
46868
+ { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
46869
+ { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
46870
+ { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
46871
+ { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: wall },
46872
+ { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: floor },
46873
+ { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: floor },
46874
+ { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: floor },
46875
+ { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: wall },
46876
+ { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: wall },
46877
+ { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: tiles2 },
46878
+ { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: tiles2 },
46879
+ { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: floor },
46880
+ { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: wall },
46881
+ { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: wall },
46882
+ { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: floor },
46883
+ { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: tiles2 },
46884
+ { x: 3, y: 3, terrain: "stairs", passable: true, terrainSprite: stairs },
46885
+ { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: wall },
46886
+ { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
46887
+ { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
46888
+ { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
46889
+ { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
46890
+ { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: wall }
46826
46891
  ];
46827
46892
  DEFAULT_ROGUELIKE_MANIFEST = {
46828
- baseUrl: CDN4,
46829
- terrains: {
46830
- floor: "/isometric-dungeon/Isometric/dirt_E.png",
46831
- wall: "/isometric-dungeon/Isometric/stoneInset_E.png",
46832
- stairs: "/isometric-dungeon/Isometric/stairs_E.png",
46833
- planks: "/isometric-dungeon/Isometric/planks_E.png"
46834
- },
46893
+ terrains: makeAssetMap({
46894
+ floor: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png`,
46895
+ wall: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png`,
46896
+ stairs: `${CDN4}/isometric-dungeon/Isometric/stairs_E.png`,
46897
+ planks: `${CDN4}/isometric-dungeon/Isometric/planks_E.png`
46898
+ }, "tile"),
46835
46899
  units: {
46836
- player: "/isometric-dungeon/Characters/Male/Male_0_Idle0.png",
46837
- enemy: "/sprite-sheets/shadow-legion-sprite-sheet-sw.png"
46900
+ player: makeAsset(`${CDN4}/isometric-dungeon/Characters/Male/Male_0_Idle0.png`, "player"),
46901
+ enemy: makeAsset(`${CDN4}/sprite-sheets/shadow-legion-sprite-sheet-sw.png`, "enemy")
46838
46902
  },
46839
- features: {
46840
- health_potion: "/isometric-dungeon/Isometric/chestClosed_E.png",
46841
- sword: "/isometric-dungeon/Isometric/barrel_E.png",
46842
- shield: "/isometric-dungeon/Isometric/barrel_E.png"
46843
- }
46903
+ features: makeAssetMap({
46904
+ health_potion: `${CDN4}/isometric-dungeon/Isometric/chestClosed_E.png`,
46905
+ sword: `${CDN4}/isometric-dungeon/Isometric/barrel_E.png`,
46906
+ shield: `${CDN4}/isometric-dungeon/Isometric/barrel_E.png`
46907
+ }, "item")
46844
46908
  };
46845
46909
  RoguelikeTemplate.displayName = "RoguelikeTemplate";
46846
46910
  }
@@ -49714,7 +49778,6 @@ function SokobanBoard({
49714
49778
  units,
49715
49779
  features,
49716
49780
  assetManifest,
49717
- assetBaseUrl,
49718
49781
  scale,
49719
49782
  showMinimap,
49720
49783
  enableCamera,
@@ -49756,7 +49819,6 @@ function SpaceShmupBoard({
49756
49819
  units,
49757
49820
  features,
49758
49821
  assetManifest,
49759
- assetBaseUrl,
49760
49822
  scale,
49761
49823
  showMinimap,
49762
49824
  enableCamera,
@@ -49798,7 +49860,6 @@ function SpaceStationBoard({
49798
49860
  units,
49799
49861
  features,
49800
49862
  assetManifest,
49801
- assetBaseUrl,
49802
49863
  scale,
49803
49864
  showMinimap,
49804
49865
  enableCamera,
@@ -49933,7 +49994,6 @@ function SportsBoard({
49933
49994
  units,
49934
49995
  features,
49935
49996
  assetManifest,
49936
- assetBaseUrl,
49937
49997
  scale,
49938
49998
  showMinimap,
49939
49999
  enableCamera,
@@ -51777,7 +51837,6 @@ function TanksBoard({
51777
51837
  units,
51778
51838
  features,
51779
51839
  assetManifest,
51780
- assetBaseUrl,
51781
51840
  scale,
51782
51841
  showMinimap,
51783
51842
  enableCamera,
@@ -52055,15 +52114,6 @@ var init_ToastSlot = __esm({
52055
52114
  ToastSlot.displayName = "ToastSlot";
52056
52115
  }
52057
52116
  });
52058
- function resolveManifestUrl4(manifest, relative) {
52059
- if (relative == null || relative === "") return void 0;
52060
- if (/^https?:\/\//.test(relative)) return relative;
52061
- const base = manifest?.baseUrl;
52062
- if (base == null) return relative;
52063
- const cleanBase = base.replace(/\/$/, "");
52064
- const cleanRel = relative.replace(/^\//, "");
52065
- return `${cleanBase}/${cleanRel}`;
52066
- }
52067
52117
  function readPlayer(v) {
52068
52118
  if (v == null || typeof v !== "object") return void 0;
52069
52119
  const o = v;
@@ -52116,10 +52166,10 @@ function TopDownShooterBoard({
52116
52166
  const wave = propWave ?? num(board.wave, 1);
52117
52167
  const lives = propLives ?? num(board.lives, 3);
52118
52168
  const result = propResult ?? (str(board.result) || "none");
52119
- const playerSprite = resolveManifestUrl4(assetManifest, assetManifest?.units?.player);
52120
- const enemySprite = resolveManifestUrl4(assetManifest, assetManifest?.units?.enemy);
52121
- const projectileSprite = resolveManifestUrl4(assetManifest, assetManifest?.features?.projectile);
52122
- const backgroundSprite = resolveManifestUrl4(assetManifest, assetManifest?.background);
52169
+ const playerSprite = assetManifest?.units?.player?.url;
52170
+ const enemySprite = assetManifest?.units?.enemy?.url;
52171
+ const projectileSprite = assetManifest?.features?.projectile?.url;
52172
+ const backgroundSprite = assetManifest?.background;
52123
52173
  const spriteUrls = React87.useMemo(
52124
52174
  () => [playerSprite, enemySprite, projectileSprite].filter((u) => u != null),
52125
52175
  [playerSprite, enemySprite, projectileSprite]
@@ -52286,7 +52336,6 @@ function TopDownShooterBoard({
52286
52336
  width,
52287
52337
  height,
52288
52338
  backgroundImage: backgroundSprite,
52289
- assetBaseUrl: assetManifest?.baseUrl,
52290
52339
  onDraw
52291
52340
  }
52292
52341
  ),
@@ -52411,15 +52460,6 @@ var init_TopDownShooterTemplate = __esm({
52411
52460
  TopDownShooterTemplate.displayName = "TopDownShooterTemplate";
52412
52461
  }
52413
52462
  });
52414
- function resolveManifestUrl5(manifest, relative) {
52415
- if (relative == null) return void 0;
52416
- if (/^https?:\/\//.test(relative)) return relative;
52417
- const base = manifest?.baseUrl;
52418
- if (base == null) return relative;
52419
- const cleanBase = base.replace(/\/$/, "");
52420
- const cleanRel = relative.replace(/^\//, "");
52421
- return `${cleanBase}/${cleanRel}`;
52422
- }
52423
52463
  function buildDefaultTDTiles() {
52424
52464
  const pathSet = new Set(DEFAULT_TD_PATH.map((p2) => `${p2.x},${p2.y}`));
52425
52465
  const tiles = [];
@@ -52439,18 +52479,18 @@ function buildDefaultTDTiles() {
52439
52479
  function tilesToIso2(tiles, manifest) {
52440
52480
  return tiles.map((t) => {
52441
52481
  const key = t.terrain ?? "ground";
52442
- const sprite = t.terrainSprite ?? resolveManifestUrl5(manifest, manifest?.terrains?.[key]) ?? resolveManifestUrl5(manifest, manifest?.terrains?.ground);
52482
+ const terrainSprite = t.terrainSprite != null ? makeAsset(t.terrainSprite, "tile") : manifest?.terrains?.[key] ?? manifest?.terrains?.ground;
52443
52483
  return {
52444
52484
  x: t.x,
52445
52485
  y: t.y,
52446
52486
  terrain: t.terrain,
52447
- terrainSprite: sprite,
52487
+ terrainSprite,
52448
52488
  passable: t.passable
52449
52489
  };
52450
52490
  });
52451
52491
  }
52452
52492
  function creepsToUnits(creeps, manifest) {
52453
- const sprite = resolveManifestUrl5(manifest, manifest?.units?.creep);
52493
+ const sprite = manifest?.units?.creep;
52454
52494
  return creeps.map((c) => ({
52455
52495
  id: c.id,
52456
52496
  position: { x: c.x, y: c.y },
@@ -52468,14 +52508,14 @@ function heroToUnit(hero, manifest) {
52468
52508
  position: { x: hero.x, y: hero.y },
52469
52509
  name: "Hero",
52470
52510
  team: "player",
52471
- sprite: resolveManifestUrl5(manifest, manifest?.units?.hero),
52511
+ sprite: manifest?.units?.hero,
52472
52512
  unitType: "hero",
52473
52513
  health: 1,
52474
52514
  maxHealth: 1
52475
52515
  };
52476
52516
  }
52477
52517
  function towersToFeatures(towers, manifest) {
52478
- const sprite = resolveManifestUrl5(manifest, manifest?.features?.tower);
52518
+ const sprite = manifest?.features?.tower;
52479
52519
  return towers.map((t) => ({
52480
52520
  id: t.id,
52481
52521
  x: t.x,
@@ -52673,7 +52713,6 @@ function TowerDefenseBoard({
52673
52713
  tiles: isoTiles,
52674
52714
  units: isoUnits,
52675
52715
  features: towerFeatures,
52676
- assetBaseUrl: assetManifest?.baseUrl,
52677
52716
  assetManifest,
52678
52717
  validMoves,
52679
52718
  hoveredTile,
@@ -52717,6 +52756,7 @@ var TD_GRID_W, TD_GRID_H, DEFAULT_TD_PATH, DEFAULT_TD_TILES;
52717
52756
  var init_TowerDefenseBoard = __esm({
52718
52757
  "components/game/organisms/TowerDefenseBoard.tsx"() {
52719
52758
  "use client";
52759
+ init_makeAsset();
52720
52760
  init_cn();
52721
52761
  init_useEventBus();
52722
52762
  init_Box();
@@ -53046,15 +53086,6 @@ var init_UncontrolledBattleBoard = __esm({
53046
53086
  UncontrolledBattleBoard.displayName = "UncontrolledBattleBoard";
53047
53087
  }
53048
53088
  });
53049
- function resolveManifestUrl6(manifest, relative) {
53050
- if (relative == null) return void 0;
53051
- if (/^https?:\/\//.test(relative)) return relative;
53052
- const base = manifest?.baseUrl;
53053
- if (base == null) return relative;
53054
- const cleanBase = base.replace(/\/$/, "");
53055
- const cleanRel = relative.replace(/^\//, "");
53056
- return `${cleanBase}/${cleanRel}`;
53057
- }
53058
53089
  function VisualNovelBoard({
53059
53090
  entity,
53060
53091
  nodes: propNodes,
@@ -53089,11 +53120,11 @@ function VisualNovelBoard({
53089
53120
  const currentNodeId = propCurrentNodeId ?? (str(board.currentNodeId) || nodes[0]?.id);
53090
53121
  const currentNode = nodes.find((n) => n.id === currentNodeId) ?? nodes[0];
53091
53122
  const backgroundImage = React87.useMemo(
53092
- () => resolveManifestUrl6(assetManifest, assetManifest?.backgrounds?.[currentNode?.backgroundKey ?? ""]),
53123
+ () => assetManifest?.backgrounds?.[currentNode?.backgroundKey ?? ""],
53093
53124
  [assetManifest, currentNode?.backgroundKey]
53094
53125
  );
53095
53126
  const portraitUrl = React87.useMemo(
53096
- () => resolveManifestUrl6(assetManifest, assetManifest?.portraits?.[currentNode?.portraitKey ?? ""]),
53127
+ () => assetManifest?.portraits?.[currentNode?.portraitKey ?? ""],
53097
53128
  [assetManifest, currentNode?.portraitKey]
53098
53129
  );
53099
53130
  const dialogueChoices = React87.useMemo(
@@ -53267,7 +53298,7 @@ function buildDefaultWorldTiles() {
53267
53298
  for (let x = 0; x < WORLD_GRID_W; x++) {
53268
53299
  const isBorder = x === 0 || y === 0 || x === WORLD_GRID_W - 1 || y === WORLD_GRID_H - 1;
53269
53300
  const def = isBorder ? WORLD_TERRAIN_DEFS[3] : WORLD_TERRAIN_DEFS[(x * 5 + y * 3 + (x ^ y)) % (WORLD_TERRAIN_DEFS.length - 1)];
53270
- tiles.push({ x, y, terrain: def.terrain, terrainSprite: def.sprite, passable: def.passable });
53301
+ tiles.push({ x, y, terrain: def.terrain, terrainSprite: makeAsset(def.sprite, "tile"), passable: def.passable });
53271
53302
  }
53272
53303
  }
53273
53304
  return tiles;
@@ -53311,7 +53342,12 @@ function WorldMapBoard({
53311
53342
  const resolved = boardEntity(entity);
53312
53343
  const entityUnits = rows(resolved?.units);
53313
53344
  const entityTiles = rows(resolved?.tiles);
53314
- const features = propFeatures ?? rows(resolved?.features);
53345
+ const features = propFeatures ?? rows(resolved?.features).map((r) => ({
53346
+ id: r.id == null ? void 0 : str(r.id),
53347
+ x: num(r.x),
53348
+ y: num(r.y),
53349
+ type: str(r.type)
53350
+ }));
53315
53351
  const selectedHeroId = resolved?.selectedHeroId ?? null;
53316
53352
  const assetManifest = propAssetManifest ?? resolved?.assetManifest;
53317
53353
  const backgroundImage = resolved?.backgroundImage;
@@ -53321,7 +53357,7 @@ function WorldMapBoard({
53321
53357
  x: num(t.x),
53322
53358
  y: num(t.y),
53323
53359
  terrain: str(t.terrain),
53324
- terrainSprite: t.terrainSprite == null ? void 0 : str(t.terrainSprite),
53360
+ terrainSprite: t.terrainSprite == null ? void 0 : makeAsset(str(t.terrainSprite), "tile"),
53325
53361
  passable: t.passable !== false
53326
53362
  })),
53327
53363
  [entityTiles]
@@ -53337,7 +53373,7 @@ function WorldMapBoard({
53337
53373
  team: str(u.team) === "enemy" ? "enemy" : "player",
53338
53374
  health: num(u.health) || 100,
53339
53375
  maxHealth: num(u.maxHealth) || 100,
53340
- sprite: u.sprite == null ? void 0 : str(u.sprite)
53376
+ sprite: u.sprite == null ? void 0 : makeAsset(str(u.sprite), "player")
53341
53377
  })),
53342
53378
  [entityUnits, propUnits]
53343
53379
  );
@@ -53519,7 +53555,6 @@ function WorldMapBoard({
53519
53555
  onTileHover: (x, y) => setHoveredTile({ x, y }),
53520
53556
  onTileLeave: () => setHoveredTile(null),
53521
53557
  scale,
53522
- assetBaseUrl: assetManifest?.baseUrl,
53523
53558
  assetManifest,
53524
53559
  backgroundImage,
53525
53560
  effectSpriteUrls,
@@ -53542,6 +53577,7 @@ var WORLD_CDN, WORLD_GRID_W, WORLD_GRID_H, WORLD_TERRAIN_DEFS, DEFAULT_WORLD_TIL
53542
53577
  var init_WorldMapBoard = __esm({
53543
53578
  "components/game/organisms/WorldMapBoard.tsx"() {
53544
53579
  "use client";
53580
+ init_makeAsset();
53545
53581
  init_cn();
53546
53582
  init_useEventBus();
53547
53583
  init_Stack();
@@ -53595,62 +53631,66 @@ function WorldMapTemplate({
53595
53631
  }
53596
53632
  );
53597
53633
  }
53598
- var CDN5, DEFAULT_WORLDMAP_TILES, DEFAULT_WORLDMAP_UNITS, DEFAULT_WORLDMAP_FEATURES, DEFAULT_WORLDMAP_MANIFEST;
53634
+ var CDN5, mountain, water, grass, road, DEFAULT_WORLDMAP_TILES, DEFAULT_WORLDMAP_UNITS, DEFAULT_WORLDMAP_FEATURES, DEFAULT_WORLDMAP_MANIFEST;
53599
53635
  var init_WorldMapTemplate = __esm({
53600
53636
  "components/game/templates/WorldMapTemplate.tsx"() {
53601
53637
  init_WorldMapBoard();
53638
+ init_makeAsset();
53602
53639
  CDN5 = "https://almadar-kflow-assets.web.app/shared";
53640
+ mountain = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png`, "tile");
53641
+ water = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png`, "tile");
53642
+ grass = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`, "tile");
53643
+ road = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png`, "tile");
53603
53644
  DEFAULT_WORLDMAP_TILES = [
53604
- { x: 0, y: 0, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53605
- { x: 1, y: 0, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53606
- { x: 2, y: 0, terrain: "water", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png` },
53607
- { x: 3, y: 0, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53608
- { x: 4, y: 0, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53609
- { x: 0, y: 1, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53610
- { x: 1, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53611
- { x: 2, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53612
- { x: 3, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53613
- { x: 4, y: 1, terrain: "water", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png` },
53614
- { x: 0, y: 2, terrain: "water", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png` },
53615
- { x: 1, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53616
- { x: 2, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png` },
53617
- { x: 3, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53618
- { x: 4, y: 2, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53619
- { x: 0, y: 3, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53620
- { x: 1, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53621
- { x: 2, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53622
- { x: 3, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png` },
53623
- { x: 4, y: 3, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53624
- { x: 0, y: 4, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53625
- { x: 1, y: 4, terrain: "water", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png` },
53626
- { x: 2, y: 4, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53627
- { x: 3, y: 4, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53628
- { x: 4, y: 4, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` }
53645
+ { x: 0, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53646
+ { x: 1, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53647
+ { x: 2, y: 0, terrain: "water", passable: false, terrainSprite: water },
53648
+ { x: 3, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53649
+ { x: 4, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53650
+ { x: 0, y: 1, terrain: "mountain", passable: false, terrainSprite: mountain },
53651
+ { x: 1, y: 1, terrain: "grass", passable: true, terrainSprite: grass },
53652
+ { x: 2, y: 1, terrain: "grass", passable: true, terrainSprite: grass },
53653
+ { x: 3, y: 1, terrain: "grass", passable: true, terrainSprite: grass },
53654
+ { x: 4, y: 1, terrain: "water", passable: false, terrainSprite: water },
53655
+ { x: 0, y: 2, terrain: "water", passable: false, terrainSprite: water },
53656
+ { x: 1, y: 2, terrain: "grass", passable: true, terrainSprite: grass },
53657
+ { x: 2, y: 2, terrain: "grass", passable: true, terrainSprite: road },
53658
+ { x: 3, y: 2, terrain: "grass", passable: true, terrainSprite: grass },
53659
+ { x: 4, y: 2, terrain: "mountain", passable: false, terrainSprite: mountain },
53660
+ { x: 0, y: 3, terrain: "mountain", passable: false, terrainSprite: mountain },
53661
+ { x: 1, y: 3, terrain: "grass", passable: true, terrainSprite: grass },
53662
+ { x: 2, y: 3, terrain: "grass", passable: true, terrainSprite: grass },
53663
+ { x: 3, y: 3, terrain: "grass", passable: true, terrainSprite: road },
53664
+ { x: 4, y: 3, terrain: "mountain", passable: false, terrainSprite: mountain },
53665
+ { x: 0, y: 4, terrain: "mountain", passable: false, terrainSprite: mountain },
53666
+ { x: 1, y: 4, terrain: "water", passable: false, terrainSprite: water },
53667
+ { x: 2, y: 4, terrain: "grass", passable: true, terrainSprite: grass },
53668
+ { x: 3, y: 4, terrain: "mountain", passable: false, terrainSprite: mountain },
53669
+ { x: 4, y: 4, terrain: "mountain", passable: false, terrainSprite: mountain }
53629
53670
  ];
53630
53671
  DEFAULT_WORLDMAP_UNITS = [
53631
- { 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` },
53632
- { 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` }
53672
+ { 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") },
53673
+ { 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") }
53633
53674
  ];
53634
53675
  DEFAULT_WORLDMAP_FEATURES = [
53635
- { id: "f1", x: 2, y: 2, type: "capital", sprite: `${CDN5}/scenes/world/capital.png` },
53636
- { id: "f2", x: 4, y: 2, type: "power_node", sprite: `${CDN5}/world-map/power_node.png` }
53676
+ { id: "f1", x: 2, y: 2, type: "capital", sprite: makeAsset(`${CDN5}/scenes/world/capital.png`, "decoration") },
53677
+ { id: "f2", x: 4, y: 2, type: "power_node", sprite: makeAsset(`${CDN5}/world-map/power_node.png`, "decoration") }
53637
53678
  ];
53638
53679
  DEFAULT_WORLDMAP_MANIFEST = {
53639
- baseUrl: CDN5,
53640
- terrains: {
53641
- grass: "/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png",
53642
- water: "/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png",
53643
- mountain: "/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png",
53644
- road: "/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png"
53645
- },
53680
+ terrains: makeAssetMap({
53681
+ grass: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`,
53682
+ water: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png`,
53683
+ mountain: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png`,
53684
+ road: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png`
53685
+ }, "tile"),
53646
53686
  units: {
53647
- hero: "/sprite-sheets/amir-sprite-sheet-se.png",
53648
- scout: "/sprite-sheets/archivist-sprite-sheet-se.png"
53687
+ hero: makeAsset(`${CDN5}/sprite-sheets/amir-sprite-sheet-se.png`, "player"),
53688
+ scout: makeAsset(`${CDN5}/sprite-sheets/archivist-sprite-sheet-se.png`, "npc")
53649
53689
  },
53650
- features: {
53651
- capital: "/scenes/world/capital.png",
53652
- power_node: "/world-map/power_node.png"
53653
- }
53690
+ features: makeAssetMap({
53691
+ capital: `${CDN5}/scenes/world/capital.png`,
53692
+ power_node: `${CDN5}/world-map/power_node.png`
53693
+ }, "decoration")
53654
53694
  };
53655
53695
  WorldMapTemplate.displayName = "WorldMapTemplate";
53656
53696
  }