merge: 최신 main을 메인 도시 정보 호환에 통합
This commit is contained in:
@@ -44,6 +44,7 @@ export type WorldStateConfig = z.infer<typeof zWorldStateConfig>;
|
||||
|
||||
export const zWorldStateMeta = z.object({
|
||||
serverId: z.string().optional(),
|
||||
gameIdx: z.number().int().positive().optional(),
|
||||
starttime: z.string().optional(),
|
||||
opentime: z.string().optional(),
|
||||
preopenAt: z.string().optional(),
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
isWarTraitKey,
|
||||
} from '@sammo-ts/logic';
|
||||
import type { InheritBuffType } from '@sammo-ts/logic';
|
||||
import type { ItemSlot } from '@sammo-ts/logic';
|
||||
import { simpleSerialize } from '@sammo-ts/logic/war/utils.js';
|
||||
import { resolveLegacyCompatibleUniqueConfig } from '@sammo-ts/logic/rewards/legacyUniqueItemPool.js';
|
||||
import {
|
||||
@@ -39,6 +40,8 @@ const BUFF_KEYS: InheritBuffType[] = [
|
||||
'warMagicTrialProbOppose',
|
||||
];
|
||||
|
||||
const UNIQUE_ITEM_SLOT_ORDER: readonly ItemSlot[] = ['horse', 'weapon', 'book', 'item'];
|
||||
|
||||
const BUFF_LABELS: Record<InheritBuffType, string> = {
|
||||
warAvoidRatio: '회피 확률 증가',
|
||||
warCriticalRatio: '필살 확률 증가',
|
||||
@@ -79,7 +82,8 @@ const loadAvailableUniqueItems = async (worldState: WorldStateRow) => {
|
||||
const loader = new ItemLoader();
|
||||
const { allItems } = await resolveLegacyCompatibleUniqueConfig(configConst, loader);
|
||||
const enabledKeys: Array<Parameters<ItemLoader['load']>[0]> = [];
|
||||
for (const entries of Object.values(allItems)) {
|
||||
for (const slot of UNIQUE_ITEM_SLOT_ORDER) {
|
||||
const entries = allItems[slot] ?? {};
|
||||
for (const [key, amount] of Object.entries(asRecord(entries))) {
|
||||
if (asNumber(amount, 0) !== 0 && isItemKey(key)) {
|
||||
enabledKeys.push(key);
|
||||
@@ -94,10 +98,11 @@ const loadAvailableUniqueItems = async (worldState: WorldStateRow) => {
|
||||
name: item.name,
|
||||
rawName: item.rawName,
|
||||
info: item.info ?? '',
|
||||
slot: item.slot,
|
||||
};
|
||||
})
|
||||
);
|
||||
return items.sort((left, right) => left.name.localeCompare(right.name, 'ko'));
|
||||
return items;
|
||||
};
|
||||
|
||||
const resolveWorld = async (ctx: { db: { worldState: { findFirst: () => Promise<unknown> } } }) => {
|
||||
|
||||
@@ -53,6 +53,8 @@ export const lobbyRouter = router({
|
||||
|
||||
return {
|
||||
serverId: worldState.meta.serverId?.trim() || ctx.profile?.name || 'game',
|
||||
profile: ctx.profile.id,
|
||||
gameIdx: worldState.meta.gameIdx ?? 1,
|
||||
year: worldState.currentYear,
|
||||
month: worldState.currentMonth,
|
||||
userCnt,
|
||||
|
||||
@@ -218,6 +218,32 @@ describe('inherit router actor and permission boundaries', () => {
|
||||
}
|
||||
);
|
||||
|
||||
it('orders unique auction candidates by Ref slot order and preserves order within each slot', async () => {
|
||||
const fixture = buildContext({
|
||||
configConst: {
|
||||
allItems: {
|
||||
item: { che_보물_도기: 1 },
|
||||
book: { che_서적_07_논어: 1 },
|
||||
weapon: { che_무기_12_칠성검: 1 },
|
||||
horse: {
|
||||
che_명마_07_백마: 1,
|
||||
che_명마_07_기주마: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const status = await appRouter.createCaller(fixture.context).inherit.getStatus();
|
||||
|
||||
expect(status.availableUnique.map(({ key, slot }) => ({ key, slot }))).toEqual([
|
||||
{ key: 'che_명마_07_백마', slot: 'horse' },
|
||||
{ key: 'che_명마_07_기주마', slot: 'horse' },
|
||||
{ key: 'che_무기_12_칠성검', slot: 'weapon' },
|
||||
{ key: 'che_서적_07_논어', slot: 'book' },
|
||||
{ key: 'che_보물_도기', slot: 'item' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('loads the first inheritance-log page without an out-of-range integer cursor', async () => {
|
||||
const createdAt = new Date('2026-07-26T00:00:00Z');
|
||||
const fixture = buildContext({
|
||||
|
||||
@@ -15,6 +15,7 @@ const buildContext = (
|
||||
): GameApiContext =>
|
||||
({
|
||||
auth: null,
|
||||
profile: { id: 'che', scenario: 'default', name: 'che:default' },
|
||||
db: {
|
||||
worldState: {
|
||||
findFirst: vi.fn(async () => ({
|
||||
@@ -75,6 +76,7 @@ describe('lobby season state', () => {
|
||||
buildContext(
|
||||
{
|
||||
serverId: 'che_260819_season',
|
||||
gameIdx: 101,
|
||||
preopenAt: '2026-08-19 22:00:00',
|
||||
opentime: '2026-08-19 23:00:00',
|
||||
scenarioMeta: { title: '【가상모드27-b】 아시아 명장전(비급)' },
|
||||
@@ -103,6 +105,8 @@ describe('lobby season state', () => {
|
||||
|
||||
expect(result).toMatchObject({
|
||||
serverId: 'che_260819_season',
|
||||
profile: 'che',
|
||||
gameIdx: 101,
|
||||
preopenAt: '2026-08-19 22:00:00',
|
||||
opentime: '2026-08-19 23:00:00',
|
||||
scenarioTitle: '【가상모드27-b】 아시아 명장전(비급)',
|
||||
|
||||
Reference in New Issue
Block a user