fix: break circular dependency between combat-descent and non-combat-room actions
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 1m2s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 1m2s
This commit is contained in:
@@ -1,4 +1,11 @@
|
|||||||
# Circular Dependencies
|
# Circular Dependencies
|
||||||
Generated: 2026-06-04T16:54:47.153Z
|
Generated: 2026-06-04T17:28:40.127Z
|
||||||
|
Found: 1 circular chain(s) — these MUST be fixed before modifying involved files.
|
||||||
|
|
||||||
No circular dependencies found. ✅
|
1. 1) stores/combat-descent-actions.ts > stores/non-combat-room-actions.ts
|
||||||
|
|
||||||
|
## How to fix
|
||||||
|
1. Identify which import in the chain can be extracted to a shared types/utils file.
|
||||||
|
2. Move the shared type or function there.
|
||||||
|
3. Both files import from the new shared module instead of each other.
|
||||||
|
4. Run: bunx madge --circular src/lib/game (should return clean)
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"_meta": {
|
"_meta": {
|
||||||
"generated": "2026-06-04T16:54:45.269Z",
|
"generated": "2026-06-04T17:28:38.180Z",
|
||||||
"description": "Import dependency graph for src/lib/game. Keys are files, values are arrays of files they import.",
|
"description": "Import dependency graph for src/lib/game. Keys are files, values are arrays of files they import.",
|
||||||
"usage": "To find what a file affects, search for its path in the VALUES. To find what a file depends on, look at its KEY entry."
|
"usage": "To find what a file affects, search for its path in the VALUES. To find what a file depends on, look at its KEY entry."
|
||||||
},
|
},
|
||||||
@@ -550,9 +550,9 @@
|
|||||||
"stores/combat-descent-actions.ts": [
|
"stores/combat-descent-actions.ts": [
|
||||||
"data/guardian-encounters.ts",
|
"data/guardian-encounters.ts",
|
||||||
"stores/combat-state.types.ts",
|
"stores/combat-state.types.ts",
|
||||||
"stores/discipline-slice.ts",
|
|
||||||
"stores/golem-combat-actions.ts",
|
"stores/golem-combat-actions.ts",
|
||||||
"stores/manaStore.ts",
|
"stores/manaStore.ts",
|
||||||
|
"stores/non-combat-room-actions.ts",
|
||||||
"stores/prestigeStore.ts",
|
"stores/prestigeStore.ts",
|
||||||
"utils/spire-utils.ts"
|
"utils/spire-utils.ts"
|
||||||
],
|
],
|
||||||
@@ -564,6 +564,7 @@
|
|||||||
"stores/combat-actions.ts",
|
"stores/combat-actions.ts",
|
||||||
"stores/combat-descent-actions.ts",
|
"stores/combat-descent-actions.ts",
|
||||||
"stores/combat-state.types.ts",
|
"stores/combat-state.types.ts",
|
||||||
|
"stores/non-combat-room-actions.ts",
|
||||||
"types.ts",
|
"types.ts",
|
||||||
"utils/activity-log.ts",
|
"utils/activity-log.ts",
|
||||||
"utils/index.ts",
|
"utils/index.ts",
|
||||||
@@ -729,6 +730,14 @@
|
|||||||
"utils/result.ts",
|
"utils/result.ts",
|
||||||
"utils/safe-persist.ts"
|
"utils/safe-persist.ts"
|
||||||
],
|
],
|
||||||
|
"stores/non-combat-room-actions.ts": [
|
||||||
|
"constants.ts",
|
||||||
|
"stores/attunementStore.ts",
|
||||||
|
"stores/combat-descent-actions.ts",
|
||||||
|
"stores/combat-state.types.ts",
|
||||||
|
"stores/discipline-slice.ts",
|
||||||
|
"stores/manaStore.ts"
|
||||||
|
],
|
||||||
"stores/pipelines/combat-tick.ts": [
|
"stores/pipelines/combat-tick.ts": [
|
||||||
"constants.ts",
|
"constants.ts",
|
||||||
"data/guardian-encounters.ts",
|
"data/guardian-encounters.ts",
|
||||||
@@ -887,7 +896,9 @@
|
|||||||
"utils/spire-utils.ts": [
|
"utils/spire-utils.ts": [
|
||||||
"constants.ts",
|
"constants.ts",
|
||||||
"data/guardian-encounters.ts",
|
"data/guardian-encounters.ts",
|
||||||
|
"data/loot-drops.ts",
|
||||||
"types.ts",
|
"types.ts",
|
||||||
|
"types/game.ts",
|
||||||
"utils/enemy-utils.ts",
|
"utils/enemy-utils.ts",
|
||||||
"utils/floor-utils.ts"
|
"utils/floor-utils.ts"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
import type { GameAction, SpellState, FloorState, GolemancyState, ActivityLogEntry, AchievementState, EquipmentSpellState, ActivityEventType, ActiveGolem, EnemyState, EquipmentInstance } from '../types';
|
import type { GameAction, SpellState, FloorState, GolemancyState, ActivityLogEntry, AchievementState, EquipmentSpellState, ActivityEventType, ActiveGolem, EnemyState, EquipmentInstance } from '../types';
|
||||||
|
|
||||||
|
/** Signature for the advanceRoomOrFloor callback to break circular dependency */
|
||||||
|
export type AdvanceRoomFn = (get: () => CombatStore, set: (s: Partial<CombatState>) => void) => void;
|
||||||
|
|
||||||
// ─── Combat State (data only) ─────────────────────────────────────────────────
|
// ─── Combat State (data only) ─────────────────────────────────────────────────
|
||||||
|
|
||||||
export interface CombatState {
|
export interface CombatState {
|
||||||
@@ -118,9 +121,9 @@ export interface CombatActions {
|
|||||||
/** Grant discipline XP scaled by floor, then advance */
|
/** Grant discipline XP scaled by floor, then advance */
|
||||||
onEnterLibraryRoom: () => void;
|
onEnterLibraryRoom: () => void;
|
||||||
/** Tick non-combat room progress (called from game tick pipeline) */
|
/** Tick non-combat room progress (called from game tick pipeline) */
|
||||||
tickNonCombatRoom: (hours: number) => void;
|
tickNonCombatRoom: (hours: number, advance: AdvanceRoomFn) => void;
|
||||||
/** Skip current non-combat room (library, recovery, treasure) */
|
/** Skip current non-combat room (library, recovery, treasure) */
|
||||||
skipNonCombatRoom: () => void;
|
skipNonCombatRoom: (advance: AdvanceRoomFn) => void;
|
||||||
/** Stay 1 hour longer in library or recovery room */
|
/** Stay 1 hour longer in library or recovery room */
|
||||||
stayLongerInRoom: () => void;
|
stayLongerInRoom: () => void;
|
||||||
|
|
||||||
|
|||||||
@@ -220,8 +220,8 @@ export const useCombatStore = create<CombatStore>()(
|
|||||||
advanceRoomOrFloor: () => advanceRoomOrFloor(get, set),
|
advanceRoomOrFloor: () => advanceRoomOrFloor(get, set),
|
||||||
onEnterRoomDescend: () => onEnterRoomDescend(get, set),
|
onEnterRoomDescend: () => onEnterRoomDescend(get, set),
|
||||||
onEnterLibraryRoom: () => onEnterLibraryRoom(get, set),
|
onEnterLibraryRoom: () => onEnterLibraryRoom(get, set),
|
||||||
tickNonCombatRoom: (hours: number) => tickNonCombatRoom(get, set, hours),
|
tickNonCombatRoom: (hours: number) => tickNonCombatRoom(get, set, hours, advanceRoomOrFloor),
|
||||||
skipNonCombatRoom: () => skipNonCombatRoom(get, set),
|
skipNonCombatRoom: () => skipNonCombatRoom(get, set, advanceRoomOrFloor),
|
||||||
stayLongerInRoom: () => stayLongerInRoom(get, set),
|
stayLongerInRoom: () => stayLongerInRoom(get, set),
|
||||||
|
|
||||||
// Golemancy
|
// Golemancy
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import { useDisciplineStore } from './discipline-slice';
|
|||||||
import { useManaStore } from './manaStore';
|
import { useManaStore } from './manaStore';
|
||||||
import { useAttunementStore } from './attunementStore';
|
import { useAttunementStore } from './attunementStore';
|
||||||
import { PUZZLE_ROOMS } from '../constants';
|
import { PUZZLE_ROOMS } from '../constants';
|
||||||
import { advanceRoomOrFloor } from './combat-descent-actions';
|
|
||||||
|
|
||||||
type GetFn = () => CombatStore;
|
type GetFn = () => CombatStore;
|
||||||
type SetFn = (state: Partial<CombatState>) => void;
|
type SetFn = (state: Partial<CombatState>) => void;
|
||||||
|
type AdvanceFn = (get: GetFn, set: SetFn) => void;
|
||||||
|
|
||||||
// ─── Room Entry Handlers ──────────────────────────────────────────────────────
|
// ─── Room Entry Handlers ──────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -105,22 +105,22 @@ export function onEnterPuzzleRoom(get: GetFn, set: SetFn): void {
|
|||||||
|
|
||||||
// ─── Tick Handlers ────────────────────────────────────────────────────────────
|
// ─── Tick Handlers ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
export function tickNonCombatRoom(get: GetFn, set: SetFn, hours: number): void {
|
export function tickNonCombatRoom(get: GetFn, set: SetFn, hours: number, advance: AdvanceFn): void {
|
||||||
const s = get();
|
const s = get();
|
||||||
const rt = s.currentRoom.roomType as string;
|
const rt = s.currentRoom.roomType as string;
|
||||||
|
|
||||||
if (rt === 'library') {
|
if (rt === 'library') {
|
||||||
tickLibraryRoom(get, set, hours);
|
tickLibraryRoom(get, set, hours, advance);
|
||||||
} else if (rt === 'recovery') {
|
} else if (rt === 'recovery') {
|
||||||
tickRecoveryRoom(get, set, hours);
|
tickRecoveryRoom(get, set, hours, advance);
|
||||||
} else if (rt === 'treasure') {
|
} else if (rt === 'treasure') {
|
||||||
tickTreasureRoom(get, set, hours);
|
tickTreasureRoom(get, set, hours, advance);
|
||||||
} else if (rt === 'puzzle') {
|
} else if (rt === 'puzzle') {
|
||||||
tickPuzzleRoom(get, set, hours);
|
tickPuzzleRoom(get, set, hours, advance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function tickLibraryRoom(get: GetFn, set: SetFn, hours: number): void {
|
function tickLibraryRoom(get: GetFn, set: SetFn, hours: number, advance: AdvanceFn): void {
|
||||||
const s = get();
|
const s = get();
|
||||||
const room = s.currentRoom;
|
const room = s.currentRoom;
|
||||||
const progress = (room.libraryProgress || 0) + hours;
|
const progress = (room.libraryProgress || 0) + hours;
|
||||||
@@ -150,13 +150,13 @@ function tickLibraryRoom(get: GetFn, set: SetFn, hours: number): void {
|
|||||||
|
|
||||||
if (progress >= required) {
|
if (progress >= required) {
|
||||||
set({ currentRoom: { ...room, libraryProgress: progress } });
|
set({ currentRoom: { ...room, libraryProgress: progress } });
|
||||||
advanceRoomOrFloor(get, set);
|
advance(get, set);
|
||||||
} else {
|
} else {
|
||||||
set({ currentRoom: { ...room, libraryProgress: progress } });
|
set({ currentRoom: { ...room, libraryProgress: progress } });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function tickRecoveryRoom(get: GetFn, set: SetFn, hours: number): void {
|
function tickRecoveryRoom(get: GetFn, set: SetFn, hours: number, advance: AdvanceFn): void {
|
||||||
const s = get();
|
const s = get();
|
||||||
const room = s.currentRoom;
|
const room = s.currentRoom;
|
||||||
const progress = (room.recoveryProgress || 0) + hours;
|
const progress = (room.recoveryProgress || 0) + hours;
|
||||||
@@ -164,13 +164,13 @@ function tickRecoveryRoom(get: GetFn, set: SetFn, hours: number): void {
|
|||||||
|
|
||||||
if (progress >= required) {
|
if (progress >= required) {
|
||||||
set({ currentRoom: { ...room, recoveryProgress: progress } });
|
set({ currentRoom: { ...room, recoveryProgress: progress } });
|
||||||
advanceRoomOrFloor(get, set);
|
advance(get, set);
|
||||||
} else {
|
} else {
|
||||||
set({ currentRoom: { ...room, recoveryProgress: progress } });
|
set({ currentRoom: { ...room, recoveryProgress: progress } });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function tickTreasureRoom(get: GetFn, set: SetFn, hours: number): void {
|
function tickTreasureRoom(get: GetFn, set: SetFn, hours: number, advance: AdvanceFn): void {
|
||||||
const s = get();
|
const s = get();
|
||||||
const room = s.currentRoom;
|
const room = s.currentRoom;
|
||||||
const progress = (room.treasureProgress || 0) + hours;
|
const progress = (room.treasureProgress || 0) + hours;
|
||||||
@@ -228,13 +228,13 @@ function tickTreasureRoom(get: GetFn, set: SetFn, hours: number): void {
|
|||||||
|
|
||||||
if (progress >= required) {
|
if (progress >= required) {
|
||||||
set({ currentRoom: { ...room, treasureProgress: progress, treasureLootClaimed: Array.from(claimedSet) } });
|
set({ currentRoom: { ...room, treasureProgress: progress, treasureLootClaimed: Array.from(claimedSet) } });
|
||||||
advanceRoomOrFloor(get, set);
|
advance(get, set);
|
||||||
} else {
|
} else {
|
||||||
set({ currentRoom: { ...room, treasureProgress: progress, treasureLootClaimed: Array.from(claimedSet) } });
|
set({ currentRoom: { ...room, treasureProgress: progress, treasureLootClaimed: Array.from(claimedSet) } });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function tickPuzzleRoom(get: GetFn, set: SetFn, hours: number): void {
|
function tickPuzzleRoom(get: GetFn, set: SetFn, hours: number, advance: AdvanceFn): void {
|
||||||
const s = get();
|
const s = get();
|
||||||
const room = s.currentRoom;
|
const room = s.currentRoom;
|
||||||
const progress = (room.puzzleProgress || 0) + hours;
|
const progress = (room.puzzleProgress || 0) + hours;
|
||||||
@@ -243,7 +243,7 @@ function tickPuzzleRoom(get: GetFn, set: SetFn, hours: number): void {
|
|||||||
if (progress >= required) {
|
if (progress >= required) {
|
||||||
set({ currentRoom: { ...room, puzzleProgress: progress } });
|
set({ currentRoom: { ...room, puzzleProgress: progress } });
|
||||||
get().addActivityLog('puzzle_solved', `Puzzle solved on Floor ${s.currentFloor}!`);
|
get().addActivityLog('puzzle_solved', `Puzzle solved on Floor ${s.currentFloor}!`);
|
||||||
advanceRoomOrFloor(get, set);
|
advance(get, set);
|
||||||
} else {
|
} else {
|
||||||
set({ currentRoom: { ...room, puzzleProgress: progress } });
|
set({ currentRoom: { ...room, puzzleProgress: progress } });
|
||||||
}
|
}
|
||||||
@@ -251,12 +251,12 @@ function tickPuzzleRoom(get: GetFn, set: SetFn, hours: number): void {
|
|||||||
|
|
||||||
// ─── Player Actions ───────────────────────────────────────────────────────────
|
// ─── Player Actions ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
export function skipNonCombatRoom(get: GetFn, set: SetFn): void {
|
export function skipNonCombatRoom(get: GetFn, set: SetFn, advance: AdvanceFn): void {
|
||||||
const s = get();
|
const s = get();
|
||||||
const rt = s.currentRoom.roomType as string;
|
const rt = s.currentRoom.roomType as string;
|
||||||
if (rt === 'library' || rt === 'recovery' || rt === 'treasure') {
|
if (rt === 'library' || rt === 'recovery' || rt === 'treasure') {
|
||||||
get().addActivityLog('floor_transition', `Skipped ${rt} room on Floor ${s.currentFloor}`);
|
get().addActivityLog('floor_transition', `Skipped ${rt} room on Floor ${s.currentFloor}`);
|
||||||
advanceRoomOrFloor(get, set);
|
advance(get, set);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user