refactor: tighten backend and logic boundaries

This commit is contained in:
2026-08-15 06:46:52 +00:00
parent 7b02ff155f
commit 35d8824b95
86 changed files with 820 additions and 1872 deletions
-13
View File
@@ -754,26 +754,13 @@ export const createItemActionModules = <TriggerState extends GeneralTriggerState
});
export type { ItemModule, ItemModuleExport, ItemSlot } from './types.js';
export {
canAcquireItem,
isInventoryEnabled,
listEquippedItemKeys,
consumeItemRemain,
getItemRemain,
setItemRemain,
} from './utils.js';
export {
cloneItemInventory,
consumeEquippedItemCharge,
createItemInventoryFromSlots,
ensureItemInventory,
equipNewItem,
getEquippedItemInstance,
parseItemInventory,
projectItemSlots,
readItemInventory,
readItemInventoryFromMeta,
removeEquippedItem,
serializeItemInventory,
withSerializedItemInventory,
} from './inventory.js';
+1 -79
View File
@@ -1,33 +1,5 @@
import type { ScenarioConfig } from '@sammo-ts/logic/scenario/types.js';
import type { General, GeneralTriggerState } from '@sammo-ts/logic/domain/entities.js';
import type { ItemModule } from './types.js';
import {
consumeEquippedItemCharge,
ensureItemInventory,
getEquippedItemInstance,
readItemInventory,
} from './inventory.js';
const toBoolean = (value: unknown): boolean => {
if (typeof value === 'boolean') {
return value;
}
if (typeof value === 'number') {
return value > 0;
}
if (typeof value === 'string') {
const normalized = value.trim().toLowerCase();
return normalized === 'true' || normalized === 'yes' || normalized === '1';
}
return false;
};
export const isInventoryEnabled = (config: ScenarioConfig): boolean => {
const constConfig = config.const ?? {};
return toBoolean(
constConfig['allowInventory'] ?? constConfig['inventoryEnabled'] ?? constConfig['enableInventory']
);
};
import { consumeEquippedItemCharge, readItemInventory } from './inventory.js';
export const listEquippedItemKeys = <TriggerState extends GeneralTriggerState>(
general: General<TriggerState>
@@ -49,32 +21,6 @@ export const listEquippedItemKeys = <TriggerState extends GeneralTriggerState>(
return result;
};
export const getItemRemain = <TriggerState extends GeneralTriggerState>(
general: General<TriggerState>,
itemKey: string
): number | null => {
const instance = getEquippedItemInstance(general, 'item');
const value = instance?.itemKey === itemKey ? instance.state.charges : undefined;
return typeof value === 'number' && value > 0 ? value : null;
};
export const setItemRemain = <TriggerState extends GeneralTriggerState>(
general: General<TriggerState>,
itemKey: string,
remain: number | null
): void => {
ensureItemInventory(general);
const instance = getEquippedItemInstance(general, 'item');
if (!instance || instance.itemKey !== itemKey) {
return;
}
if (remain === null || remain <= 0) {
delete instance.state.charges;
return;
}
instance.state.charges = remain;
};
export const consumeItemRemain = <TriggerState extends GeneralTriggerState>(
general: General<TriggerState>,
itemKey: string,
@@ -82,27 +28,3 @@ export const consumeItemRemain = <TriggerState extends GeneralTriggerState>(
): boolean => {
return consumeEquippedItemCharge(general, 'item', itemKey, fallbackRemain);
};
export const canAcquireItem = <TriggerState extends GeneralTriggerState>(options: {
general: General<TriggerState>;
item: ItemModule;
config: ScenarioConfig;
registry: Map<string, ItemModule>;
}): boolean => {
const { general, item, config, registry } = options;
if (!item.unique) {
return true;
}
if (isInventoryEnabled(config)) {
return true;
}
const slotItemKey = general.role.items[item.slot];
if (!slotItemKey) {
return true;
}
const slotItem = registry.get(slotItemKey);
if (!slotItem) {
return true;
}
return !slotItem.unique;
};