feat: Zod를 사용한 월드 상태 구성 및 메타 타입 추가, 사용자 ID 처리 개선
This commit is contained in:
@@ -1,12 +1,7 @@
|
||||
export type JsonValue =
|
||||
| null
|
||||
| boolean
|
||||
| number
|
||||
| string
|
||||
| JsonValue[]
|
||||
| { [key: string]: JsonValue };
|
||||
import type { GamePrisma, LogCategory, LogScope } from './gamePrisma.js';
|
||||
|
||||
export type InputJsonValue = JsonValue;
|
||||
export type JsonValue = GamePrisma.JsonValue;
|
||||
export type InputJsonValue = GamePrisma.InputJsonValue;
|
||||
|
||||
export interface TurnEngineWorldStateRow {
|
||||
id: number;
|
||||
@@ -148,7 +143,7 @@ export interface TurnEngineGeneralUpdateInput {
|
||||
name: string;
|
||||
nationId: number;
|
||||
cityId: number;
|
||||
troopId: number | null;
|
||||
troopId: number;
|
||||
leadership: number;
|
||||
strength: number;
|
||||
intel: number;
|
||||
@@ -181,7 +176,7 @@ export interface TurnEngineGeneralCreateManyInput {
|
||||
name: string;
|
||||
nationId: number;
|
||||
cityId: number;
|
||||
troopId?: number | null;
|
||||
troopId?: number;
|
||||
npcState: number;
|
||||
leadership: number;
|
||||
strength: number;
|
||||
@@ -323,8 +318,8 @@ export interface TurnEngineEventCreateManyInput {
|
||||
}
|
||||
|
||||
export interface TurnEngineLogEntryCreateManyInput {
|
||||
scope: string;
|
||||
category: string;
|
||||
scope: LogScope;
|
||||
category: LogCategory;
|
||||
subType: string | null;
|
||||
year: number;
|
||||
month: number;
|
||||
@@ -387,7 +382,12 @@ export interface TurnEngineDatabaseClient {
|
||||
data: TurnEngineDiplomacyCreateManyInput[];
|
||||
}): Promise<unknown>;
|
||||
update(args: {
|
||||
where: { srcNationId: number; destNationId: number };
|
||||
where: {
|
||||
srcNationId_destNationId: {
|
||||
srcNationId: number;
|
||||
destNationId: number;
|
||||
};
|
||||
};
|
||||
data: TurnEngineDiplomacyUpdateInput;
|
||||
}): Promise<unknown>;
|
||||
deleteMany(args?: unknown): Promise<unknown>;
|
||||
@@ -416,36 +416,13 @@ export interface TurnEngineDatabaseClient {
|
||||
}): Promise<unknown>;
|
||||
};
|
||||
generalTurn: {
|
||||
findMany(args?: {
|
||||
where?: { generalId?: number };
|
||||
orderBy?: { turnIdx: 'asc' | 'desc' }[];
|
||||
}): Promise<TurnEngineGeneralTurnRow[]>;
|
||||
deleteMany(args: { where: { generalId: number } }): Promise<unknown>;
|
||||
createMany(args: {
|
||||
data: Array<{
|
||||
generalId: number;
|
||||
turnIdx: number;
|
||||
actionCode: string;
|
||||
arg: InputJsonValue;
|
||||
}>;
|
||||
}): Promise<unknown>;
|
||||
findMany(args?: unknown): Promise<TurnEngineGeneralTurnRow[]>;
|
||||
deleteMany(args?: unknown): Promise<unknown>;
|
||||
createMany(args?: unknown): Promise<unknown>;
|
||||
};
|
||||
nationTurn: {
|
||||
findMany(args?: {
|
||||
where?: { nationId?: number; officerLevel?: number };
|
||||
orderBy?: { turnIdx: 'asc' | 'desc' }[];
|
||||
}): Promise<TurnEngineNationTurnRow[]>;
|
||||
deleteMany(args: {
|
||||
where: { nationId: number; officerLevel: number };
|
||||
}): Promise<unknown>;
|
||||
createMany(args: {
|
||||
data: Array<{
|
||||
nationId: number;
|
||||
officerLevel: number;
|
||||
turnIdx: number;
|
||||
actionCode: string;
|
||||
arg: InputJsonValue;
|
||||
}>;
|
||||
}): Promise<unknown>;
|
||||
findMany(args?: unknown): Promise<TurnEngineNationTurnRow[]>;
|
||||
deleteMany(args?: unknown): Promise<unknown>;
|
||||
createMany(args?: unknown): Promise<unknown>;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,6 +15,6 @@ export interface TurnCommandModule<TSpec extends TurnCommandSpecBase = TurnComma
|
||||
commandSpec: TSpec;
|
||||
ActionDefinition: new (...args: any[]) => GeneralActionDefinition;
|
||||
ActionResolver?: new (...args: any[]) => GeneralActionResolver;
|
||||
CommandResolver?: new (...args: any[]) => unknown;
|
||||
CommandResolver?: new (...args: any[]) => any;
|
||||
actionContextBuilder?: ActionContextBuilder;
|
||||
}
|
||||
|
||||
@@ -29,11 +29,13 @@ export interface CityDevelopmentEnvironment {
|
||||
amount?: number;
|
||||
}
|
||||
|
||||
type NumberKeys<T> = { [K in keyof T]: T[K] extends number ? K : never }[keyof T];
|
||||
|
||||
export interface CityDevelopmentConfig {
|
||||
key: string;
|
||||
name: string;
|
||||
statKey: keyof City;
|
||||
maxKey: keyof City;
|
||||
statKey: NumberKeys<City>;
|
||||
maxKey: NumberKeys<City>;
|
||||
label: string;
|
||||
baseAmount: number;
|
||||
}
|
||||
@@ -74,8 +76,8 @@ export class CityDevelopmentActionDefinition<
|
||||
occupiedCity(),
|
||||
suppliedCity(),
|
||||
remainCityCapacityByMax(
|
||||
String(this.config.statKey),
|
||||
String(this.config.maxKey),
|
||||
this.config.statKey,
|
||||
this.config.maxKey,
|
||||
this.config.label
|
||||
),
|
||||
reqGeneralGold(getRequiredGold),
|
||||
@@ -105,7 +107,7 @@ export class CityDevelopmentActionDefinition<
|
||||
const costGold = this.env.develCost ?? 0;
|
||||
|
||||
// 직접 수정 (Immer Draft)
|
||||
(city as any)[this.config.statKey] = nextValue;
|
||||
city[this.config.statKey] = nextValue;
|
||||
general.gold = Math.max(0, general.gold - costGold);
|
||||
|
||||
const logMessage = `${this.config.label}이 ${nextValue - current} 증가했습니다.`;
|
||||
|
||||
@@ -143,7 +143,7 @@ export const suppliedDestCity = (): Constraint => ({
|
||||
});
|
||||
|
||||
export const remainCityCapacity = (
|
||||
key: string,
|
||||
key: keyof City,
|
||||
label: string
|
||||
): Constraint => ({
|
||||
name: 'RemainCityCapacity',
|
||||
@@ -158,11 +158,10 @@ export const remainCityCapacity = (
|
||||
const req: RequirementKey = { kind: 'city', id: ctx.cityId };
|
||||
return unknownOrDeny(ctx, [req], '도시 정보가 없습니다.');
|
||||
}
|
||||
const record = city as unknown as Record<string, number | undefined>;
|
||||
const maxKey = `${key}_max`;
|
||||
const current = record[key];
|
||||
const max = record[maxKey];
|
||||
if (current === undefined || max === undefined) {
|
||||
const maxKey = `${String(key)}Max` as keyof City;
|
||||
const current = city[key];
|
||||
const max = city[maxKey];
|
||||
if (typeof current !== 'number' || typeof max !== 'number') {
|
||||
return unknownOrDeny(ctx, [], '도시 정보가 없습니다.');
|
||||
}
|
||||
if (current < max) {
|
||||
@@ -173,8 +172,8 @@ export const remainCityCapacity = (
|
||||
});
|
||||
|
||||
export const remainCityCapacityByMax = (
|
||||
key: string,
|
||||
maxKey: string,
|
||||
key: keyof City,
|
||||
maxKey: keyof City,
|
||||
label: string
|
||||
): Constraint => ({
|
||||
name: 'RemainCityCapacityByMax',
|
||||
@@ -189,10 +188,9 @@ export const remainCityCapacityByMax = (
|
||||
const req: RequirementKey = { kind: 'city', id: ctx.cityId };
|
||||
return unknownOrDeny(ctx, [req], '도시 정보가 없습니다.');
|
||||
}
|
||||
const record = city as unknown as Record<string, number | undefined>;
|
||||
const current = record[key];
|
||||
const max = record[maxKey];
|
||||
if (current === undefined || max === undefined) {
|
||||
const current = city[key];
|
||||
const max = city[maxKey];
|
||||
if (typeof current !== 'number' || typeof max !== 'number') {
|
||||
return unknownOrDeny(ctx, [], '도시 정보가 없습니다.');
|
||||
}
|
||||
if (current < max) {
|
||||
@@ -203,7 +201,7 @@ export const remainCityCapacityByMax = (
|
||||
});
|
||||
|
||||
export const reqCityCapacity = (
|
||||
key: string,
|
||||
key: keyof City,
|
||||
label: string,
|
||||
required: number | string
|
||||
): Constraint => ({
|
||||
@@ -219,16 +217,15 @@ export const reqCityCapacity = (
|
||||
const req: RequirementKey = { kind: 'city', id: ctx.cityId };
|
||||
return unknownOrDeny(ctx, [req], '도시 정보가 없습니다.');
|
||||
}
|
||||
const record = city as unknown as Record<string, number | undefined>;
|
||||
const current = record[key];
|
||||
if (current === undefined) {
|
||||
const current = city[key];
|
||||
if (typeof current !== 'number') {
|
||||
return unknownOrDeny(ctx, [], '도시 정보가 없습니다.');
|
||||
}
|
||||
if (typeof required === 'string') {
|
||||
const ratio = parsePercent(required);
|
||||
const maxKey = `${key}Max`;
|
||||
const max = record[maxKey];
|
||||
if (ratio === null || max === undefined) {
|
||||
const maxKey = `${String(key)}Max` as keyof City;
|
||||
const max = city[maxKey];
|
||||
if (ratio === null || typeof max !== 'number') {
|
||||
return unknownOrDeny(ctx, [], '도시 정보가 없습니다.');
|
||||
}
|
||||
if (current >= max * ratio) {
|
||||
@@ -256,7 +253,7 @@ export const reqCityTrust = (minTrust: number): Constraint => ({
|
||||
}
|
||||
const trust =
|
||||
readMetaNumberFromUnknown(
|
||||
city.meta as Record<string, unknown>,
|
||||
city.meta,
|
||||
'trust'
|
||||
) ?? null;
|
||||
if (trust === null) {
|
||||
|
||||
Reference in New Issue
Block a user