Skip to content

Commit

Permalink
[ALIFE] Alife management simplification / sharding manager. (#107)
Browse files Browse the repository at this point in the history
Signed-off-by: Neloreck <[email protected]>
  • Loading branch information
Neloreck authored Nov 30, 2024
1 parent 65a3281 commit 95bd96e
Show file tree
Hide file tree
Showing 116 changed files with 2,111 additions and 1,617 deletions.
11 changes: 7 additions & 4 deletions src/engine/core/animation/predicates/animpoint_predicates.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { EStalkerState } from "@/engine/core/animation/types";
import { registry } from "@/engine/core/database";
import { IAnimpointActionDescriptor } from "@/engine/core/schemes/stalker/animpoint/animpoint_types";
import { getObjectSmartTerrain } from "@/engine/core/utils/position";
import { getObjectTerrain } from "@/engine/core/utils/position";
import { food } from "@/engine/lib/constants/items/food";
import { misc } from "@/engine/lib/constants/items/misc";
import { GameObject, LuaArray, Optional, TName } from "@/engine/lib/types";
Expand Down Expand Up @@ -86,17 +86,17 @@ function animpointPredicateHarmonica(object: GameObject, isInCamp?: Optional<boo
* todo;
*/
function animpointPredicateWeapon(object: GameObject): boolean {
const smartTerrainName: Optional<TName> = getObjectSmartTerrain(object)?.name() as Optional<TName>;
const terrainName: Optional<TName> = getObjectTerrain(object)?.name() as Optional<TName>;

if (smartTerrainName && registry.noCombatSmartTerrains.get(smartTerrainName)) {
if (terrainName && registry.noCombatSmartTerrains.get(terrainName)) {
return false;
}

return true;
}

/**
* todo;
* todo: Move to config file
*/
const eatableVisuals: LuaTable<TName, boolean> = $fromObject<TName, boolean>({
["actors\\stalker_hero\\stalker_hero_1"]: true,
Expand Down Expand Up @@ -155,6 +155,9 @@ const eatableVisuals: LuaTable<TName, boolean> = $fromObject<TName, boolean>({
["actors\\stalker_neutral\\stalker_neutral_nauchniy_face_2"]: true,
});

/**
* todo: Move to config file
*/
const harmonicaVisuals: LuaTable<TName, boolean> = $fromObject<TName, boolean>({
["actors\\stalker_hero\\stalker_hero_1"]: true,
["actors\\stalker_hero\\stalker_hero_novice_1"]: true,
Expand Down
2 changes: 1 addition & 1 deletion src/engine/core/binders/creature/ActorBinder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
} from "@/engine/core/database";
import { EGameEvent, EventsManager } from "@/engine/core/managers/events";
import { SaveManager } from "@/engine/core/managers/save";
import { TSimulationObject } from "@/engine/core/managers/simulation";
import { TSimulationObject } from "@/engine/core/managers/simulation/simulation_types";
import { ISchemeDeimosState, SchemeDeimos } from "@/engine/core/schemes/restrictor/sr_deimos";
import { setStableAlifeObjectsUpdate } from "@/engine/core/utils/alife";
import { MAX_ALIFE_ID } from "@/engine/lib/constants/memory";
Expand Down
8 changes: 4 additions & 4 deletions src/engine/core/binders/physic/CampfireBinder.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { LuabindClass, object_binder } from "xray16";

import { getManager, registerSmartTerrainCampfire, unRegisterSmartTerrainCampfire } from "@/engine/core/database";
import { SimulationManager } from "@/engine/core/managers/simulation/SimulationManager";
import { registerSmartTerrainCampfire, unRegisterSmartTerrainCampfire } from "@/engine/core/database";
import { getSimulationTerrainByName } from "@/engine/core/managers/simulation/utils";
import { SmartTerrain } from "@/engine/core/objects/smart_terrain";
import { Optional, ServerObject } from "@/engine/lib/types";

Expand All @@ -20,9 +20,9 @@ export class CampfireBinder extends object_binder {

// logger.format("Register: %s", object.name());

const [smartTerrainName] = string.gsub(this.object.name(), "_campfire_%d*", "");
const [terrainName] = string.gsub(this.object.name(), "_campfire_%d*", "");

this.terrain = getManager(SimulationManager).getSmartTerrainByName(smartTerrainName);
this.terrain = getSimulationTerrainByName(terrainName);

if (this.terrain) {
registerSmartTerrainCampfire(this.terrain, this.object);
Expand Down
41 changes: 20 additions & 21 deletions src/engine/core/database/smart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import { GameObject, Optional, TName, TNumberId, ZoneCampfire } from "@/engine/l
* Register smart terrain object.
*
* @param object - smart terrain client game object
* @param smartTerrain - smart terrain server game object
* @param terrain - smart terrain server game object
* @returns object state representation in registry
*/
export function registerSmartTerrain(object: GameObject, smartTerrain: SmartTerrain): IRegistryObjectState {
registry.smartTerrains.set(smartTerrain.id, smartTerrain);
export function registerSmartTerrain(object: GameObject, terrain: SmartTerrain): IRegistryObjectState {
registry.smartTerrains.set(terrain.id, terrain);

return registerZone(object);
}
Expand All @@ -24,11 +24,11 @@ export function registerSmartTerrain(object: GameObject, smartTerrain: SmartTerr
* Unregister smart terrain object.
*
* @param object - smart terrain client game object
* @param smartTerrain - smart terrain server game object
* @param terrain - smart terrain server game object
*/
export function unregisterSmartTerrain(object: GameObject, smartTerrain: SmartTerrain): void {
export function unregisterSmartTerrain(object: GameObject, terrain: SmartTerrain): void {
unregisterZone(object);
registry.smartTerrains.delete(smartTerrain.id);
registry.smartTerrains.delete(terrain.id);
}

/**
Expand All @@ -52,40 +52,39 @@ export function unregisterSmartCover(smartCover: SmartCover): void {
/**
* Register smart terrain campfire object.
*
* @param smartTerrain - smart terrain object to register for
* @param terrain - smart terrain object to register for
* @param object - game object to register as campfire
*/
export function registerSmartTerrainCampfire(smartTerrain: SmartTerrain, object: GameObject): void {
const smartTerrainName: TName = smartTerrain.name();
export function registerSmartTerrainCampfire(terrain: SmartTerrain, object: GameObject): void {
const terrainName: TName = terrain.name();
const campfire: ZoneCampfire = object.get_campfire();

campfire.turn_off();

if (registry.smartTerrainsCampfires.get(smartTerrainName) === null) {
registry.smartTerrainsCampfires.set(smartTerrainName, new LuaTable());
if (registry.smartTerrainsCampfires.get(terrainName) === null) {
registry.smartTerrainsCampfires.set(terrainName, new LuaTable());
}

registry.smartTerrainsCampfires.get(smartTerrainName).set(object.id(), campfire);
registry.smartTerrainsCampfires.get(terrainName).set(object.id(), campfire);

registerObject(object);
}

/**
* Unregister smart terrain campfire object.
*
* @param smartTerrain - smart terrain object to unregister for
* @param terrain - smart terrain object to unregister for
* @param object - game object to unregister as campfire
*/
export function unRegisterSmartTerrainCampfire(smartTerrain: SmartTerrain, object: GameObject): void {
const smartTerrainName: TName = smartTerrain.name();
const smartTerrainList: Optional<LuaTable<TNumberId, ZoneCampfire>> =
registry.smartTerrainsCampfires.get(smartTerrainName);
export function unRegisterSmartTerrainCampfire(terrain: SmartTerrain, object: GameObject): void {
const terrainName: TName = terrain.name();
const terrainList: Optional<LuaTable<TNumberId, ZoneCampfire>> = registry.smartTerrainsCampfires.get(terrainName);

if (smartTerrainList !== null) {
smartTerrainList.delete(object.id());
if (terrainList !== null) {
terrainList.delete(object.id());

if (isEmpty(smartTerrainList)) {
registry.smartTerrainsCampfires.delete(smartTerrainName);
if (isEmpty(terrainList)) {
registry.smartTerrainsCampfires.delete(terrainName);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/engine/core/managers/death/ReleaseBodyManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ describe("ReleaseBodyManager", () => {
EPacketDataType.U16,
EPacketDataType.U16,
]);
expect(processor.dataList).toEqual([4, 10, 11, 12, 13, 5120, 6]);
expect(processor.dataList).toEqual([4, 10, 11, 12, 13, 5, 6]);

disposeManager(ReleaseBodyManager);

Expand Down Expand Up @@ -171,7 +171,7 @@ describe("ReleaseBodyManager", () => {
EPacketDataType.U16,
EPacketDataType.U16,
]);
expect(processor.dataList).toEqual([2, 10, 11, 5120, 4]);
expect(processor.dataList).toEqual([2, 10, 11, 5, 4]);

disposeManager(ReleaseBodyManager);

Expand Down
59 changes: 30 additions & 29 deletions src/engine/core/managers/map/utils/map_spot_terrain.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { beforeEach, describe, expect, it, jest } from "@jest/globals";
import { level } from "xray16";

import { getManager, registerStoryLink } from "@/engine/core/database";
import { registerStoryLink } from "@/engine/core/database";
import { mapDisplayConfig } from "@/engine/core/managers/map/MapDisplayConfig";
import {
getTerrainMapSpotHint,
removeTerrainMapSpot,
updateTerrainMapSpot,
updateTerrainsMapSpotDisplay,
} from "@/engine/core/managers/map/utils/map_spot_terrain";
import { ESimulationTerrainRole, ISmartTerrainDescriptor, SimulationManager } from "@/engine/core/managers/simulation";
import { ESimulationTerrainRole, ISmartTerrainDescriptor } from "@/engine/core/managers/simulation";
import { getSimulationTerrainDescriptorById } from "@/engine/core/managers/simulation/utils";
import { getSmartTerrainNameCaption, SmartTerrain } from "@/engine/core/objects/smart_terrain";
import { createObjectJobDescriptor } from "@/engine/core/objects/smart_terrain/job";
import { Squad } from "@/engine/core/objects/squad";
Expand Down Expand Up @@ -184,23 +185,23 @@ describe("getSmartTerrainMapDisplayHint util", () => {
});

it("should correctly generate map hints without debug", () => {
const smartTerrain: SmartTerrain = new SmartTerrain("test_init");
const terrain: SmartTerrain = new SmartTerrain("test_init");

expect(getTerrainMapSpotHint(smartTerrain)).toBe(getSmartTerrainNameCaption(smartTerrain));
expect(getTerrainMapSpotHint(terrain)).toBe(getSmartTerrainNameCaption(terrain));
});

it("should correctly generate map hints with debug and defaults", () => {
mockRegisteredActor();

const smartTerrain: SmartTerrain = MockSmartTerrain.mockRegistered("test_smart");
const terrain: SmartTerrain = MockSmartTerrain.mockRegistered("test_smart");

smartTerrain.isSimulationAvailableConditionList = parseConditionsList(FALSE);
smartTerrain.isRespawnPoint = false;
terrain.isSimulationAvailableConditionList = parseConditionsList(FALSE);
terrain.isRespawnPoint = false;

forgeConfig.DEBUG.IS_SIMULATION_ENABLED = true;

expect(getTerrainMapSpotHint(smartTerrain).replaceAll("\\n", "\n")).toBe(
`[translated_st_test_smart_name] (${smartTerrain.name()}) (${smartTerrain.id})
expect(getTerrainMapSpotHint(terrain).replaceAll("\\n", "\n")).toBe(
`[translated_st_test_smart_name] (${terrain.name()}) (${terrain.id})
available = false
online = true
simulation_role = default
Expand All @@ -219,7 +220,7 @@ working = 0
it("getSmartTerrainMapDisplayHint should correctly generate map hints with debug and some custom values", () => {
mockRegisteredActor();

const smartTerrain: SmartTerrain = MockSmartTerrain.mockRegistered("test_smart");
const terrain: SmartTerrain = MockSmartTerrain.mockRegistered("test_smart");
const squads: Array<Squad> = [
MockSquad.mock(),
MockSquad.mock(),
Expand All @@ -231,36 +232,36 @@ working = 0

forgeConfig.DEBUG.IS_SIMULATION_ENABLED = true;

smartTerrain.isRespawnPoint = true;
smartTerrain.simulationProperties = $fromObject<TName, TRate>({ a: 1, b: 2 });
(smartTerrain as AnyObject).online = true;
smartTerrain.simulationRole = ESimulationTerrainRole.SURGE;
smartTerrain.squadId = 155;
smartTerrain.maxStayingSquadsCount = 10;
smartTerrain.stayingObjectsCount = 3;
terrain.isRespawnPoint = true;
terrain.simulationProperties = $fromObject<TName, TRate>({ a: 1, b: 2 });
(terrain as AnyObject).online = true;
terrain.simulationRole = ESimulationTerrainRole.SURGE;
terrain.squadId = 155;
terrain.maxStayingSquadsCount = 10;
terrain.stayingObjectsCount = 3;

smartTerrain.lastRespawnUpdatedAt = MockCTime.mock(2015, 2, 14, 14, 25, 30, 100);
smartTerrain.spawnedSquadsList.set("test-1", { num: 3 });
smartTerrain.spawnedSquadsList.set("test-2", { num: 3 });
terrain.lastRespawnUpdatedAt = MockCTime.mock(2015, 2, 14, 14, 25, 30, 100);
terrain.spawnedSquadsList.set("test-1", { num: 3 });
terrain.spawnedSquadsList.set("test-2", { num: 3 });

smartTerrain.spawnSquadsConfiguration.set("test-1", { num: parseConditionsList("3"), squads: new LuaTable() });
smartTerrain.spawnSquadsConfiguration.set("test-2", { num: parseConditionsList("3"), squads: new LuaTable() });
terrain.spawnSquadsConfiguration.set("test-1", { num: parseConditionsList("3"), squads: new LuaTable() });
terrain.spawnSquadsConfiguration.set("test-2", { num: parseConditionsList("3"), squads: new LuaTable() });

smartTerrain.objectByJobSection.set("some-job", 4000);
smartTerrain.objectJobDescriptors.set(4000, createObjectJobDescriptor(MockAlifeHumanStalker.mock({ id: 4000 })));
smartTerrain.arrivingObjects.set(4001, MockAlifeHumanStalker.mock({ id: 4001 }));
terrain.objectByJobSection.set("some-job", 4000);
terrain.objectJobDescriptors.set(4000, createObjectJobDescriptor(MockAlifeHumanStalker.mock({ id: 4000 })));
terrain.arrivingObjects.set(4001, MockAlifeHumanStalker.mock({ id: 4001 }));

const descriptor: ISmartTerrainDescriptor = getManager(SimulationManager).getSmartTerrainDescriptor(
smartTerrain.id
const descriptor: ISmartTerrainDescriptor = getSimulationTerrainDescriptorById(
terrain.id
) as ISmartTerrainDescriptor;

descriptor.assignedSquadsCount = 6;

squads.forEach((it) => descriptor.assignedSquads.set(it.id, it));
squads.forEach((it, index) => jest.spyOn(it, "getScriptedSimulationTarget").mockImplementation(() => index));

expect(getTerrainMapSpotHint(smartTerrain).replaceAll("\\n", "\n")).toBe(
`[translated_st_test_smart_name] (${smartTerrain.name()}) (${smartTerrain.id})
expect(getTerrainMapSpotHint(terrain).replaceAll("\\n", "\n")).toBe(
`[translated_st_test_smart_name] (${terrain.name()}) (${terrain.id})
available = true
online = true
simulation_role = surge
Expand Down
8 changes: 3 additions & 5 deletions src/engine/core/managers/map/utils/map_spot_terrain.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { game, level } from "xray16";

import { getManagerByName, getObjectIdByStoryId, registry } from "@/engine/core/database";
import { getObjectIdByStoryId, registry } from "@/engine/core/database";
import { mapDisplayConfig } from "@/engine/core/managers/map/MapDisplayConfig";
import { ISmartTerrainDescriptor } from "@/engine/core/managers/simulation/simulation_types";
import { SimulationManager } from "@/engine/core/managers/simulation/SimulationManager";
import { getSimulationTerrainDescriptorById } from "@/engine/core/managers/simulation/utils/simulation_data";
import { SmartTerrain } from "@/engine/core/objects/smart_terrain/SmartTerrain";
import { smartTerrainConfig } from "@/engine/core/objects/smart_terrain/SmartTerrainConfig";
import { getSmartTerrainNameCaption } from "@/engine/core/objects/smart_terrain/utils/smart_terrain_generic_utils";
Expand Down Expand Up @@ -90,9 +90,7 @@ export function removeTerrainMapSpot(terrain: SmartTerrain): void {
*/
export function getTerrainMapSpotHint(terrain: SmartTerrain): TLabel {
if (forgeConfig.DEBUG.IS_SIMULATION_ENABLED) {
const terrainDescriptor: ISmartTerrainDescriptor = (
getManagerByName<SimulationManager>("SimulationManager") as SimulationManager
).getSmartTerrainDescriptor(terrain.id)!;
const terrainDescriptor: ISmartTerrainDescriptor = getSimulationTerrainDescriptorById(terrain.id)!;

let caption: TLabel = string.format(
"[%s] (%s) (%s)\\navailable = %s\\nonline = %s\\nsimulation_role = %s\\nsquad_id = %s\\ncapacity = %s\\%s\\n",
Expand Down
12 changes: 6 additions & 6 deletions src/engine/core/managers/notifications/NotificationManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
} from "@/engine/core/managers/notifications/notifications_types";
import { notificationsConfig } from "@/engine/core/managers/notifications/NotificationsConfig";
import { ISmartTerrainDescriptor } from "@/engine/core/managers/simulation/simulation_types";
import { SimulationManager } from "@/engine/core/managers/simulation/SimulationManager";
import { getSimulationTerrainDescriptorById } from "@/engine/core/managers/simulation/utils";
import { SoundManager } from "@/engine/core/managers/sounds/SoundManager";
import { ETaskState } from "@/engine/core/managers/tasks/types";
import { Stalker } from "@/engine/core/objects/creature/Stalker";
Expand Down Expand Up @@ -307,12 +307,12 @@ export class NotificationManager extends AbstractManager {

// todo: Probably name and number id problem? Not real condition?
if (point) {
const smartDescriptor: Optional<ISmartTerrainDescriptor> = getManager(
SimulationManager
).getSmartTerrainDescriptor(point as TNumberId);
const terrainDescriptor: Optional<ISmartTerrainDescriptor> = getSimulationTerrainDescriptorById(
point as TNumberId
);

pointName = smartDescriptor
? getSmartTerrainNameCaption(smartDescriptor.smartTerrain)
pointName = terrainDescriptor
? getSmartTerrainNameCaption(terrainDescriptor.terrain)
: game.translate_string(point as TName);
}

Expand Down
14 changes: 12 additions & 2 deletions src/engine/core/managers/simulation/SimulationConfig.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import { ini_file } from "xray16";

import { IniFile } from "@/engine/lib/types";
import type { ISmartTerrainDescriptor } from "@/engine/core/managers/simulation/simulation_types";
import type { SmartTerrain } from "@/engine/core/objects/smart_terrain";
import type { Squad } from "@/engine/core/objects/squad";
import type { IniFile, LuaArray, TName, TNumberId } from "@/engine/lib/types";

export const SIMULATION_LTX: IniFile = new ini_file("managers\\simulation\\simulation.ltx");
export const SIMULATION_OBJECTS_PROPERTIES_LTX: IniFile = new ini_file(
"managers\\simulation\\simulation_objects_props.ltx"
);

export const simulationConfig = {};
export const simulationConfig = {
IS_SIMULATION_INITIALIZED: false,
TERRAINS: new LuaTable<TName, SmartTerrain>(),
TERRAIN_DESCRIPTORS: new LuaTable<TNumberId, ISmartTerrainDescriptor>(),
SQUADS: new LuaTable<TNumberId, Squad>(),
// Squads assigned to smart terrains before initialization of terrains.
TEMPORARY_ASSIGNED_SQUADS: new LuaTable<TNumberId, LuaArray<Squad>>(),
};
Loading

0 comments on commit 95bd96e

Please sign in to comment.