diff --git a/src/engine/core/utils/ini/config.test.ts b/src/engine/core/utils/ini/config.test.ts index 54f476aa7..89b4bba5d 100644 --- a/src/engine/core/utils/ini/config.test.ts +++ b/src/engine/core/utils/ini/config.test.ts @@ -1,9 +1,12 @@ import { describe, expect, it } from "@jest/globals"; +import { registerStoryLink } from "@/engine/core/database"; import { IBaseSchemeLogic } from "@/engine/core/schemes"; -import { addConditionToList } from "@/engine/core/utils/ini/config"; -import { LuaArray, TIndex } from "@/engine/lib/types"; -import { luaTableToObject } from "@/fixtures/lua/mocks/lua_utils"; +import { addConditionToList, getConfigSwitchConditions, parseConditionsList } from "@/engine/core/utils/ini"; +import { LuaArray, ServerObject, TIndex } from "@/engine/lib/types"; +import { mockBaseSchemeLogic } from "@/fixtures/engine"; +import { luaTableToArray, luaTableToObject } from "@/fixtures/lua"; +import { mockIniFile, mockServerAlifeObject } from "@/fixtures/xray"; describe("'config' utils for ini file", () => { it("'addCondition' util should fill table and return new index", () => { @@ -33,21 +36,220 @@ describe("'config' utils for ini file", () => { expect(firstIndex).toBe(2); expect(secondIndex).toBe(3); - expect(luaTableToObject(list)).toEqual({ - "1": { - condlist: {}, - name: "first", - npc_id: 123, - v1: 1, - v2: null, - }, - "2": { - condlist: {}, - name: "second", - npc_id: 333, - v1: "a", - v2: "b", - }, - }); + expect(luaTableToArray(list)).toEqual([ + luaTableToObject( + mockBaseSchemeLogic({ + name: "first", + npc_id: 123, + v1: 1, + }) + ), + luaTableToObject( + mockBaseSchemeLogic({ + name: "second", + npc_id: 333, + v1: "a", + v2: "b", + }) + ), + ]); + }); + + it("getConfigSwitchConditions correctly parse empty/other ini files conditions", () => { + expect( + getConfigSwitchConditions( + mockIniFile("test.ltx", { + existing: { + on_signal: "true", + }, + }), + "not_existing" + ) + ).toBeNull(); + + expect( + luaTableToObject( + getConfigSwitchConditions( + mockIniFile("test.ltx", { + existing: {}, + }), + "existing" + ) + ) + ).toEqual({}); + + expect( + luaTableToObject( + getConfigSwitchConditions( + mockIniFile("test.ltx", { + existing: { + first: 1, + second: "b", + }, + }), + "existing" + ) + ) + ).toEqual({}); + }); + + it("getConfigSwitchConditions correctly parse different listed conditions", () => { + expect( + luaTableToArray( + getConfigSwitchConditions( + mockIniFile("test.ltx", { + existing: { + another: 1, + something: "else", + on_actor_dist_le: "3 | {=actor_has_weapon} remark", + }, + }), + "existing" + ) + ) + ).toEqual([ + luaTableToObject( + mockBaseSchemeLogic({ + v1: 3, + name: "on_actor_dist_le", + condlist: parseConditionsList("{=actor_has_weapon} remark"), + }) + ), + ]); + + expect( + luaTableToArray( + getConfigSwitchConditions( + mockIniFile("test.ltx", { + existing: { + on_actor_dist_le_nvis: "31 | {=actor_condition} value", + on_actor_dist_ge: "55 | {=another_cond} another", + }, + }), + "existing" + ) + ) + ).toEqual([ + luaTableToObject( + mockBaseSchemeLogic({ + v1: 31, + name: "on_actor_dist_le_nvis", + condlist: parseConditionsList("{=actor_condition} value"), + }) + ), + luaTableToObject( + mockBaseSchemeLogic({ + v1: 55, + name: "on_actor_dist_ge", + condlist: parseConditionsList("{=another_cond} another"), + }) + ), + ]); + + const serverObject: ServerObject = mockServerAlifeObject(); + + registerStoryLink(serverObject.id, "test-cfg-sid"); + + expect( + luaTableToArray( + getConfigSwitchConditions( + mockIniFile("test.ltx", { + existing: { + on_actor_dist_ge_nvis: "100|test1", + on_signal: "anim_end|test2", + on_info: "{+pri_a28_infop} test3", + on_timer: "50|test4", + on_game_timer: "10|test5", + on_actor_in_zone: "zat_b38|test7", + on_actor_not_in_zone: "zat_b38|test8", + on_actor_inside: "test9", + on_actor_outside: "test10", + on_npc_in_zone: "test-cfg-sid|jup_hide_a6|test11", + on_npc_not_in_zone: "test-cfg-sid|jup_hide_a6|test12", + }, + }), + "existing" + ) + ) + ).toEqual([ + luaTableToObject( + mockBaseSchemeLogic({ + v1: 100, + name: "on_actor_dist_ge_nvis", + condlist: parseConditionsList("test1"), + }) + ), + luaTableToObject( + mockBaseSchemeLogic({ + v1: "anim_end", + name: "on_signal", + condlist: parseConditionsList("test2"), + }) + ), + luaTableToObject( + mockBaseSchemeLogic({ + name: "on_info", + condlist: parseConditionsList("{+pri_a28_infop} test3"), + }) + ), + luaTableToObject( + mockBaseSchemeLogic({ + v1: 50, + name: "on_timer", + condlist: parseConditionsList("test4"), + }) + ), + luaTableToObject( + mockBaseSchemeLogic({ + v1: 10, + name: "on_game_timer", + condlist: parseConditionsList("test5"), + }) + ), + luaTableToObject( + mockBaseSchemeLogic({ + v1: "zat_b38", + name: "on_actor_in_zone", + condlist: parseConditionsList("test7"), + }) + ), + luaTableToObject( + mockBaseSchemeLogic({ + v1: "zat_b38", + name: "on_actor_not_in_zone", + condlist: parseConditionsList("test8"), + }) + ), + luaTableToObject( + mockBaseSchemeLogic({ + name: "on_actor_inside", + condlist: parseConditionsList("test9"), + }) + ), + luaTableToObject( + mockBaseSchemeLogic({ + name: "on_actor_outside", + condlist: parseConditionsList("test10"), + }) + ), + luaTableToObject( + mockBaseSchemeLogic({ + v1: "test-cfg-sid", + v2: "jup_hide_a6", + npc_id: serverObject.id, + name: "on_npc_in_zone", + condlist: parseConditionsList("test11"), + }) + ), + luaTableToObject( + mockBaseSchemeLogic({ + v1: "test-cfg-sid", + v2: "jup_hide_a6", + npc_id: serverObject.id, + name: "on_npc_not_in_zone", + condlist: parseConditionsList("test12"), + }) + ), + ]); }); }); diff --git a/src/engine/core/utils/ini/config.ts b/src/engine/core/utils/ini/config.ts index adb41ffdb..c440b57e5 100644 --- a/src/engine/core/utils/ini/config.ts +++ b/src/engine/core/utils/ini/config.ts @@ -273,37 +273,38 @@ export function getObjectConfigOverrides(ini: IniFile, section: TSection, object } /** - * todo - * todo - * todo * Get switch conditions for provided scheme section like `mob_home@2`. * Parses all possible switch cases for checking and switching later if conditions are satisfied. + * + * @param ini - target ini config file + * @param section - section in ini file to read + * @return optional list of scheme logic switcher descriptors */ export function getConfigSwitchConditions(ini: IniFile, section: TSection): Optional> { const conditionsList: LuaArray = new LuaTable(); - let index: TIndex = 1; if (!ini.section_exist(tostring(section))) { return null; } const linesCount: TCount = ini.line_count(section); + let index: TIndex = 1; function addConditions( func: (ini: IniFile, section: TSection, id: TStringId) => Optional, cond: ESchemeCondition ): void { for (const lineNumber of $range(0, linesCount - 1)) { - const [, id, value] = ini.r_line(section, lineNumber, "", ""); - const [searchIndex] = string.find(id, "^" + cond + "%d*$"); + const [, key] = ini.r_line(section, lineNumber, "", ""); + const [searchIndex] = string.find(key, "^" + cond + "%d*$"); if (searchIndex !== null) { - index = addConditionToList(conditionsList, index, func(ini, section, id)); + index = addConditionToList(conditionsList, index, func(ini, section, key)); } } } - // todo: Move conditions to enum. + // todo: Move conditions to enum/switcher object? addConditions(readIniNumberAndConditionList, ESchemeCondition.ON_ACTOR_DISTANCE_LESS_THAN); addConditions(readIniNumberAndConditionList, ESchemeCondition.ON_ACTOR_DISTANCE_LESS_THAN_NOT_VISIBLE); addConditions(readIniNumberAndConditionList, ESchemeCondition.ON_ACTOR_DISTANCE_GREATER_THAN); diff --git a/src/engine/core/utils/scheme/setup.ts b/src/engine/core/utils/scheme/setup.ts index de2988cab..8c9541a20 100644 --- a/src/engine/core/utils/scheme/setup.ts +++ b/src/engine/core/utils/scheme/setup.ts @@ -1,6 +1,6 @@ import { stalker_ids, world_property } from "xray16"; -import { IRegistryObjectState, registry } from "@/engine/core/database"; +import { registry } from "@/engine/core/database"; import { EEvaluatorId, TAbstractSchemeConstructor } from "@/engine/core/schemes"; import { assert } from "@/engine/core/utils/assertion"; import { LuaLogger } from "@/engine/core/utils/logging"; diff --git a/src/fixtures/engine/mocks/scheme.mocks.ts b/src/fixtures/engine/mocks/scheme.mocks.ts index 6ce4297a9..c3ce1c398 100644 --- a/src/fixtures/engine/mocks/scheme.mocks.ts +++ b/src/fixtures/engine/mocks/scheme.mocks.ts @@ -45,6 +45,17 @@ export function mockCondition(base: Partial = {}): IConf }; } +/** + * Mock generic switch condition. + */ +export function mockSwitchCondition({ + section = "test-section", + infop_check = new LuaTable(), + infop_set = new LuaTable(), +}: Partial): IConfigSwitchCondition { + return { infop_check, infop_set, section }; +} + /** * Mock whole condlist. */ diff --git a/src/fixtures/lua/index.ts b/src/fixtures/lua/index.ts index a7d8b03da..ad02d3f42 100644 --- a/src/fixtures/lua/index.ts +++ b/src/fixtures/lua/index.ts @@ -1,2 +1,3 @@ export * from "@/fixtures/lua/mockLuaLib"; +export * from "@/fixtures/lua/mocks"; export * from "@/fixtures/lua/mocks/LuaTable.mock"; diff --git a/src/fixtures/lua/mocks/index.ts b/src/fixtures/lua/mocks/index.ts new file mode 100644 index 000000000..55ea3c0ba --- /dev/null +++ b/src/fixtures/lua/mocks/index.ts @@ -0,0 +1 @@ +export * from "@/fixtures/lua/mocks/lua_utils"; diff --git a/src/fixtures/lua/mocks/lua_utils.ts b/src/fixtures/lua/mocks/lua_utils.ts index c1cfc6a49..1cbf3b951 100644 --- a/src/fixtures/lua/mocks/lua_utils.ts +++ b/src/fixtures/lua/mocks/lua_utils.ts @@ -1,10 +1,10 @@ -import { AnyObject, Optional } from "@/engine/lib/types"; +import { AnyObject, LuaArray, Optional } from "@/engine/lib/types"; import { MockLuaTable } from "@/fixtures/lua/mocks/LuaTable.mock"; /** * todo; */ -export function luaTableToArray(value: LuaTable): Array { +export function luaTableToArray(value: Optional>): Array { if (value instanceof MockLuaTable) { return [...(value as unknown as Map).values()].map((it) => { return mapFromLua(it);