Skip to content

Commit

Permalink
[SYNC] Extending unit tests / mocks for testing. (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
Neloreck authored Jul 8, 2023
2 parents 9e5014d + 519e644 commit 8417797
Show file tree
Hide file tree
Showing 123 changed files with 3,014 additions and 1,006 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: build-and-test

on:
push:
branches: [ "master", "dev" ]
branches: [ "main", "dev" ]
pull_request:
branches: [ "master", "dev" ]
branches: [ "main", "dev" ]

jobs:
test:
Expand Down
8 changes: 4 additions & 4 deletions src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ This directory contains the source code for the XRF engine modification template

## engine

Contains engine source code.
Script engine source code.

## fixtures

Contains code related to test mocks and utilities.
Test mocks and utilities.

## resources

Contains all assets that should be copied to the target root folder when building the engine modification.
Assets that should be copied to the target root folder when building the engine modification.

## typedefs

Contains all types definitions used in project.
Types definitions used in project.
25 changes: 25 additions & 0 deletions src/engine/core/database/story_objects.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
getObjectIdByStoryId,
getServerObjectByStoryId,
getStoryIdByObjectId,
isStoryObject,
isStoryObjectExisting,
registerObjectStoryLinks,
registerStoryLink,
unregisterStoryLinkByObjectId,
Expand Down Expand Up @@ -68,4 +70,27 @@ describe("'story_objects' module of the database", () => {
unregisterObject(clientObject);
unregisterStoryLinkByStoryId("test-sid");
});

it("'isStoryObjectExisting' should correctly check if object is existing", () => {
expect(isStoryObjectExisting("test-sid")).toBe(false);

const serverObject: ServerObject = mockServerAlifeObject();

registerStoryLink(serverObject.id, "test-sid");

expect(isStoryObjectExisting("test-sid")).toBe(true);
});

it("'isStoryObject' should correctly check if object is existing", () => {
const serverObject: ServerObject = mockServerAlifeObject();
const clientObject: ClientObject = mockClientGameObject({ id: () => serverObject.id });

expect(isStoryObject(serverObject)).toBe(false);
expect(isStoryObject(clientObject)).toBe(false);

registerStoryLink(serverObject.id, "is-story-object-example");

expect(isStoryObject(serverObject)).toBe(true);
expect(isStoryObject(clientObject)).toBe(true);
});
});
37 changes: 36 additions & 1 deletion src/engine/core/database/story_objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,16 @@ import { SYSTEM_INI } from "@/engine/core/database/ini_registry";
import { registry } from "@/engine/core/database/registry";
import { abort, assert } from "@/engine/core/utils/assertion";
import { readIniString } from "@/engine/core/utils/ini/ini_read";
import { ClientObject, IniFile, Optional, ServerObject, TName, TNumberId, TStringId } from "@/engine/lib/types";
import {
AnyGameObject,
ClientObject,
IniFile,
Optional,
ServerObject,
TName,
TNumberId,
TStringId,
} from "@/engine/lib/types";

/**
* Register story object link based on ini configuration.
Expand Down Expand Up @@ -86,6 +95,32 @@ export function unregisterStoryLinkByStoryId(storyId: TStringId): void {
}
}

/**
* Check whether object has story link.
*
* @param object - object to check
* @returns whether provided object has linked story id.
*/
export function isStoryObject(object: AnyGameObject): boolean {
if (type(object.id) === "function") {
return registry.storyLink.sidById.has((object as ClientObject).id());
} else {
return registry.storyLink.sidById.has((object as ServerObject).id);
}
}

/**
* Check whether story object exists.
*
* @param storyId - story ID to check existing
* @returns whether story object exists
*/
export function isStoryObjectExisting(storyId: TStringId): boolean {
const objectId: Optional<TNumberId> = registry.storyLink.idBySid.get(storyId);

return objectId === null ? false : alife().object(objectId) !== null;
}

/**
* Get object story ID by provided game object ID.
*
Expand Down
12 changes: 6 additions & 6 deletions src/engine/core/managers/interaction/SimulationBoardManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { abort } from "@/engine/core/utils/assertion";
import { parseStringsList } from "@/engine/core/utils/ini";
import { LuaLogger } from "@/engine/core/utils/logging";
import { evaluateSimulationPriority } from "@/engine/core/utils/object/object_alife";
import { changeTeamSquadGroup } from "@/engine/core/utils/object/object_set";
import { setObjectTeamSquadGroup } from "@/engine/core/utils/object/object_set";
import { setSquadRelationToActor } from "@/engine/core/utils/relation";
import { TCommunity } from "@/engine/lib/constants/communities";
import { levels, TLevel } from "@/engine/lib/constants/levels";
Expand Down Expand Up @@ -360,7 +360,7 @@ export class SimulationBoardManager extends AbstractCoreManager {

const smartTerrainDescriptor: ISmartTerrainDescriptor = this.smartTerrains.get(smartTerrainId);

if (squad.enteredSmartTerrainId !== null) {
if (squad.enteredSmartTerrainId) {
abort("Couldn't enter smart, still in old one. Squad: [%s]", squad.name());
}

Expand All @@ -382,12 +382,12 @@ export class SimulationBoardManager extends AbstractCoreManager {
object = alife().object(object.id)!;

// todo: Check, probably magic or unused code with duplicated changeTeam calls.
changeTeamSquadGroup(object, object.team, object.squad, groupId);
setObjectTeamSquadGroup(object, object.team, object.squad, groupId);

const squad: Optional<Squad> = alife().object<Squad>(object.group_id);

if (squad === null) {
return changeTeamSquadGroup(object, object.team, 0, object.group);
return setObjectTeamSquadGroup(object, object.team, 0, object.group);
}

let smartTerrain: Optional<SmartTerrain> = null;
Expand All @@ -399,7 +399,7 @@ export class SimulationBoardManager extends AbstractCoreManager {
}

if (smartTerrain === null) {
return changeTeamSquadGroup(object, object.team, 0, object.group);
return setObjectTeamSquadGroup(object, object.team, 0, object.group);
}

let objectSquadId: TNumberId = 0;
Expand All @@ -408,7 +408,7 @@ export class SimulationBoardManager extends AbstractCoreManager {
objectSquadId = smartTerrain.squadId;
}

changeTeamSquadGroup(object, object.team, objectSquadId, object.group);
setObjectTeamSquadGroup(object, object.team, objectSquadId, object.group);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/engine/core/managers/interaction/TravelManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { createAutoSave } from "@/engine/core/utils/game/game_save";
import { parseConditionsList, pickSectionFromCondList, TConditionList } from "@/engine/core/utils/ini";
import { LuaLogger } from "@/engine/core/utils/logging";
import {
getAlifeCharacterCommunity,
getObjectCommunity,
getObjectSmartTerrain,
getObjectSquad,
getServerDistanceBetween,
Expand Down Expand Up @@ -240,7 +240,7 @@ export class TravelManager extends AbstractCoreManager {
if (targetClsId === clsid.script_actor) {
abort("Actor talking with squad, which chasing actor.");
} else if (targetClsId === clsid.online_offline_group_s) {
return "dm_" + communities.stalker + "_chasing_squad_" + getAlifeCharacterCommunity(targetSquadObject as Squad);
return "dm_" + communities.stalker + "_chasing_squad_" + getObjectCommunity(targetSquadObject as Squad);
} else if (targetClsId === clsid.smart_terrain) {
const smartName: TName = targetSquadObject.name();
const smartDescription: TLabel = this.smartDescriptionsByName.get(smartName);
Expand Down
6 changes: 3 additions & 3 deletions src/engine/core/managers/interaction/dialog/DialogManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
import { assert } from "@/engine/core/utils/assertion";
import { parseInfoPortions, parseStringsList } from "@/engine/core/utils/ini";
import { LuaLogger } from "@/engine/core/utils/logging";
import { getCharacterCommunity, isObjectWounded } from "@/engine/core/utils/object";
import { getObjectCommunity, isObjectWounded } from "@/engine/core/utils/object";
import { hasAlifeInfo } from "@/engine/core/utils/object/object_info_portion";
import { FALSE, TRUE } from "@/engine/lib/constants/words";
import {
Expand Down Expand Up @@ -308,7 +308,7 @@ export class DialogManager extends AbstractCoreManager {
fComm = true;
} else {
for (const i of $range(1, PTIDSubtable.npc_community.length())) {
if (PTIDSubtable.npc_community.get(i) === getCharacterCommunity(object)) {
if (PTIDSubtable.npc_community.get(i) === getObjectCommunity(object)) {
priority = priority + 2;
fComm = true;
break;
Expand Down Expand Up @@ -339,7 +339,7 @@ export class DialogManager extends AbstractCoreManager {
priority = priority + 1;
} else {
for (const i of $range(1, PTIDSubtable.actor_community.length())) {
if (PTIDSubtable.actor_community.get(i) === getCharacterCommunity(registry.actor)) {
if (PTIDSubtable.actor_community.get(i) === getObjectCommunity(registry.actor)) {
priority = priority + 2;
break;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { alife, game } from "xray16";
import { alife, clsid, game } from "xray16";

import { getObjectIdByStoryId, registry } from "@/engine/core/database";
import { AbstractCoreManager } from "@/engine/core/managers/base/AbstractCoreManager";
Expand Down Expand Up @@ -29,7 +29,7 @@ import { GlobalSoundManager } from "@/engine/core/managers/sounds/GlobalSoundMan
import { Stalker } from "@/engine/core/objects";
import { abort, assert } from "@/engine/core/utils/assertion";
import { LuaLogger } from "@/engine/core/utils/logging";
import { isObjectWounded, isStalkerClassId } from "@/engine/core/utils/object";
import { isObjectWounded } from "@/engine/core/utils/object";
import { getInventoryNameForItemSection } from "@/engine/core/utils/object/object_spawn";
import { captions, TCaption } from "@/engine/lib/constants/captions/captions";
import { scriptSounds } from "@/engine/lib/constants/sound/script_sounds";
Expand Down Expand Up @@ -338,7 +338,7 @@ export class NotificationManager extends AbstractCoreManager {

let textureName: TTexture = textures.ui_iconsTotal_grouping;

if (object !== null && isStalkerClassId(object.clsid())) {
if (object !== null && (object.clsid() === clsid.script_stalker || object.clsid() === clsid.stalker)) {
textureName = object.character_icon();
} else if (notificationManagerIcons[faction as TNotificationIconKey]) {
textureName = notificationManagerIcons[faction as TNotificationIconKey];
Expand Down
4 changes: 2 additions & 2 deletions src/engine/core/managers/sounds/GlobalSoundManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { EPlayableSound } from "@/engine/core/objects/sounds/types";
import { abort, assert, assertDefined } from "@/engine/core/utils/assertion";
import { readIniString } from "@/engine/core/utils/ini";
import { LuaLogger } from "@/engine/core/utils/logging";
import { getCharacterCommunity } from "@/engine/core/utils/object/object_get";
import { getObjectCommunity } from "@/engine/core/utils/object/object_get";
import { getTableSize, resetTable } from "@/engine/core/utils/table";
import {
ClientObject,
Expand All @@ -44,7 +44,7 @@ export class GlobalSoundManager extends AbstractCoreManager {
public static initializeObjectSounds(object: ClientObject): void {
for (const [key, sound] of registry.sounds.themes) {
if (sound.type === NpcSound.type) {
if ((sound as NpcSound).availableCommunities.has(getCharacterCommunity(object))) {
if ((sound as NpcSound).availableCommunities.has(getObjectCommunity(object))) {
(sound as NpcSound).initializeObject(object);
}
}
Expand Down
14 changes: 7 additions & 7 deletions src/engine/core/managers/world/DropManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import { abort } from "@/engine/core/utils/assertion";
import { parseNumbersList, parseStringsList } from "@/engine/core/utils/ini";
import { LuaLogger } from "@/engine/core/utils/logging";
import {
getCharacterCommunity,
isAmmoItem,
getObjectCommunity,
isAmmoSection,
isArtefact,
isExcludedFromLootDropItem,
isExcludedFromLootDropItemSection,
isGrenade,
isLootableItem,
isLootableItemSection,
isWeapon,
setItemCondition,
spawnItemsForObject,
Expand Down Expand Up @@ -196,7 +196,7 @@ export class DropManager extends AbstractCoreManager {
}

const spawnItems: Optional<LuaTable<TInventoryItem, TProbability>> = this.itemsByCommunity.get(
getCharacterCommunity(object)
getObjectCommunity(object)
);

if (spawnItems === null) {
Expand Down Expand Up @@ -233,7 +233,7 @@ export class DropManager extends AbstractCoreManager {
return;
}

if (isExcludedFromLootDropItem(item)) {
if (isExcludedFromLootDropItemSection(section)) {
alife().release(alife().object(item.id()), true);

return;
Expand Down Expand Up @@ -269,7 +269,7 @@ export class DropManager extends AbstractCoreManager {
return;
}

if (isLootableItem(item) && !isAmmoItem(item)) {
if (isLootableItemSection(item.section()) && !isAmmoSection(item.section())) {
logger.info("Keep item, misc lootable:", object.name(), item.name(), section);

return;
Expand Down
13 changes: 4 additions & 9 deletions src/engine/core/managers/world/SurgeManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { alife, game, hit, level } from "xray16";
import {
closeLoadMarker,
closeSaveMarker,
isStoryObject,
openLoadMarker,
openSaveMarker,
registry,
Expand All @@ -25,13 +26,7 @@ import { createAutoSave } from "@/engine/core/utils/game/game_save";
import { readTimeFromPacket, writeTimeToPacket } from "@/engine/core/utils/game/game_time";
import { parseConditionsList, pickSectionFromCondList, TConditionList } from "@/engine/core/utils/ini";
import { LuaLogger } from "@/engine/core/utils/logging";
import {
isArtefact,
isImmuneToSurge,
isObjectOnLevel,
isStoryObject,
isSurgeEnabledOnLevel,
} from "@/engine/core/utils/object";
import { isArtefact, isImmuneToSurgeObject, isObjectOnLevel, isSurgeEnabledOnLevel } from "@/engine/core/utils/object";
import { disableInfo, giveInfo, hasAlifeInfo } from "@/engine/core/utils/object/object_info_portion";
import { createVector } from "@/engine/core/utils/vector";
import { surgeConfig } from "@/engine/lib/configs/SurgeConfig";
Expand Down Expand Up @@ -490,7 +485,7 @@ export class SurgeManager extends AbstractCoreManager {
logger.info("Releasing squads:", simulationBoardManager.getSquads().length());

for (const [squadId, squad] of simulationBoardManager.getSquads()) {
if (isObjectOnLevel(squad, levelName) && !isImmuneToSurge(squad) && !isStoryObject(squad)) {
if (isObjectOnLevel(squad, levelName) && !isImmuneToSurgeObject(squad) && !isStoryObject(squad)) {
for (const member of squad.squad_members()) {
if (!isStoryObject(member.object)) {
if (this.canReleaseSquad(squad)) {
Expand Down Expand Up @@ -571,7 +566,7 @@ export class SurgeManager extends AbstractCoreManager {
const activeCovers: LuaArray<ClientObject> = this.getCoverObjects();

for (const [squadId, squad] of simulationBoardManager.getSquads()) {
if (isObjectOnLevel(squad, levelName) && !isImmuneToSurge(squad)) {
if (isObjectOnLevel(squad, levelName) && !isImmuneToSurgeObject(squad)) {
for (const member of squad.squad_members()) {
let isInCover: boolean = false;

Expand Down
9 changes: 5 additions & 4 deletions src/engine/core/objects/binders/creature/MonsterBinder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ import { ESchemeEvent, IBaseSchemeState } from "@/engine/core/schemes";
import { SchemeHear } from "@/engine/core/schemes/hear/SchemeHear";
import { pickSectionFromCondList, TConditionList } from "@/engine/core/utils/ini";
import { LuaLogger } from "@/engine/core/utils/logging";
import { action, getObjectSquad } from "@/engine/core/utils/object";
import { getObjectSquad } from "@/engine/core/utils/object";
import {
emitSchemeEvent,
isMonsterScriptCaptured,
scriptCaptureMonster,
scriptCommandMonster,
scriptReleaseMonster,
trySwitchToAnotherSection,
} from "@/engine/core/utils/scheme";
Expand Down Expand Up @@ -124,14 +125,14 @@ export class MonsterBinder extends object_binder {
scriptCaptureMonster(this.object, true);

if (squad.commander_id() === this.object.id()) {
action(this.object, new move(move.walk_with_leader, targetPosition), new cond(cond.move_end));
scriptCommandMonster(this.object, new move(move.walk_with_leader, targetPosition), new cond(cond.move_end));
} else {
const commanderPosition: Vector = alife().object(squad.commander_id())!.position;

if (commanderPosition.distance_to_sqr(this.object.position()) > 100) {
action(this.object, new move(move.run_with_leader, targetPosition), new cond(cond.move_end));
scriptCommandMonster(this.object, new move(move.run_with_leader, targetPosition), new cond(cond.move_end));
} else {
action(this.object, new move(move.walk_with_leader, targetPosition), new cond(cond.move_end));
scriptCommandMonster(this.object, new move(move.walk_with_leader, targetPosition), new cond(cond.move_end));
}
}

Expand Down
Loading

0 comments on commit 8417797

Please sign in to comment.