0ad/binaries/data/mods/public/simulation/components/tests/test_EntityLimits.js
Dunedan 93ce94655d
Use @stylistic/brace-style for eslint
Up to now `eslint-plugin-brace-rules` was used to enforce a common brace
style for JavaScript code. This plugin was however updated the last time
over 9 years ago and will be incompatible with ESLint v10, as that
[removes `context.getSourceCode()`][1], the plugin relies on.

To keep the eslint config working with ESLint v10, this replaces
`eslint-plugin-brace-rules` with the [`@stylistic/brace-style`][2] rule
from `@stylistic/eslint-plugin`, a package we already use.

While `@stylistic/brace-style` doesn't offer an option to format braces
in exactly the same way as before, the "allman" style seems to be the
one closest to the existing code.

[1]: https://eslint.org/blog/2025/11/eslint-v10.0.0-alpha.0-released/#removed-deprecated-rule-context-members
[2]: https://eslint.style/rules/brace-style
2026-01-12 21:33:52 +01:00

206 lines
8 KiB
JavaScript

Engine.LoadComponentScript("interfaces/BuildRestrictions.js");
Engine.LoadComponentScript("interfaces/EntityLimits.js");
Engine.LoadComponentScript("interfaces/Foundation.js");
Engine.LoadComponentScript("interfaces/TrainingRestrictions.js");
Engine.LoadComponentScript("interfaces/Player.js");
Engine.LoadComponentScript("EntityLimits.js");
const template ={
"Limits": {
"Tower": 5,
"Wonder": 1,
"Hero": 2,
"Champion": 1
},
"LimitChangers": {
"Tower": { "Monument": 1 }
},
"LimitRemovers": {
"Tower": { "RequiredTechs": { "_string": "TechA" } },
"Hero": { "RequiredClasses": { "_string": "Aegis" } }
}
};
AddMock(10, IID_Player, {
"GetPlayerID": id => 1
});
AddMock(SYSTEM_ENTITY, IID_GuiInterface, {
"PushNotification": () => {}
});
const cmpEntityLimits = ConstructComponent(10, "EntityLimits", template);
// Test getters
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetCounts(), { "Tower": 0, "Wonder": 0, "Hero": 0, "Champion": 0 });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetLimits(), { "Tower": 5, "Wonder": 1, "Hero": 2, "Champion": 1 });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetLimitChangers(), { "Tower": { "Monument": 1 } });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetMatchCounts(), {});
// Test training restrictions
TS_ASSERT(cmpEntityLimits.AllowedToTrain("Hero"));
TS_ASSERT(cmpEntityLimits.AllowedToTrain("Hero", 1));
TS_ASSERT(cmpEntityLimits.AllowedToTrain("Hero", 2));
for (let ent = 60; ent < 63; ++ent)
{
AddMock(ent, IID_TrainingRestrictions, {
"GetCategory": () => "Hero"
});
}
cmpEntityLimits.OnGlobalOwnershipChanged({ "entity": 60, "from": INVALID_PLAYER, "to": 1 });
cmpEntityLimits.OnGlobalOwnershipChanged({ "entity": 61, "from": 2, "to": 1 });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetCounts(), { "Tower": 0, "Wonder": 0, "Hero": 2, "Champion": 0 });
TS_ASSERT(cmpEntityLimits.AllowedToTrain("Hero"));
TS_ASSERT(!cmpEntityLimits.AllowedToTrain("Hero", 1));
// Restrictions can be enforced
cmpEntityLimits.OnGlobalOwnershipChanged({ "entity": 62, "from": INVALID_PLAYER, "to": 1 });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetCounts(), { "Tower": 0, "Wonder": 0, "Hero": 3, "Champion": 0 });
for (let ent = 60; ent < 63; ++ent)
cmpEntityLimits.OnGlobalOwnershipChanged({ "entity": ent, "from": 1, "to": INVALID_PLAYER });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetCounts(), { "Tower": 0, "Wonder": 0, "Hero": 0, "Champion": 0 });
// Test building restrictions
AddMock(70, IID_BuildRestrictions, {
"GetCategory": () => "Wonder"
});
cmpEntityLimits.OnGlobalOwnershipChanged({ "entity": 70, "from": 3, "to": 1 });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetCounts(), { "Tower": 0, "Wonder": 1, "Hero": 0, "Champion": 0 });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetLimits(), { "Tower": 5, "Wonder": 1, "Hero": 2, "Champion": 1 });
// AllowedToBuild is used after foundation placement, which are meant to be replaced
TS_ASSERT(cmpEntityLimits.AllowedToBuild("Wonder"));
cmpEntityLimits.OnGlobalOwnershipChanged({ "entity": 70, "from": 1, "to": INVALID_PLAYER });
// Test limit changers
AddMock(80, IID_Identity, {
"GetClassesList": () => ["Monument"]
});
AddMock(81, IID_Identity, {
"GetClassesList": () => ["Monument"]
});
cmpEntityLimits.OnGlobalOwnershipChanged({ "entity": 80, "from": INVALID_PLAYER, "to": 1 });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetCounts(), { "Tower": 0, "Wonder": 0, "Hero": 0, "Champion": 0 });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetLimits(), { "Tower": 5 + 1, "Wonder": 1, "Hero": 2, "Champion": 1 });
cmpEntityLimits.OnGlobalOwnershipChanged({ "entity": 81, "from": 1, "to": INVALID_PLAYER });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetCounts(), { "Tower": 0, "Wonder": 0, "Hero": 0, "Champion": 0 });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetLimits(), { "Tower": 5, "Wonder": 1, "Hero": 2, "Champion": 1 });
// Foundations don't change limits
AddMock(81, IID_Foundation, {});
cmpEntityLimits.OnGlobalOwnershipChanged({ "entity": 81, "from": INVALID_PLAYER, "to": 1 });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetCounts(), { "Tower": 0, "Wonder": 0, "Hero": 0, "Champion": 0 });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetLimits(), { "Tower": 5, "Wonder": 1, "Hero": 2, "Champion": 1 });
cmpEntityLimits.OnGlobalOwnershipChanged({ "entity": 81, "from": 1, "to": INVALID_PLAYER });
// Test limit removers by classes
AddMock(90, IID_Identity, {
"GetClassesList": () => ["Aegis"]
});
cmpEntityLimits.OnGlobalOwnershipChanged({ "entity": 90, "from": INVALID_PLAYER, "to": 1 });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetLimits(), { "Tower": 5, "Wonder": 1, "Hero": undefined, "Champion": 1 });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetCounts(), { "Tower": 0, "Wonder": 0, "Hero": 0, "Champion": 0 });
AddMock(91, IID_TrainingRestrictions, {
"GetCategory": () => "Hero"
});
cmpEntityLimits.OnGlobalOwnershipChanged({ "entity": 91, "from": INVALID_PLAYER, "to": 1 });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetLimits(), { "Tower": 5, "Wonder": 1, "Hero": undefined, "Champion": 1 });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetCounts(), { "Tower": 0, "Wonder": 0, "Hero": 1, "Champion": 0 });
cmpEntityLimits.OnGlobalOwnershipChanged({ "entity": 90, "from": 1, "to": INVALID_PLAYER });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetLimits(), { "Tower": 5, "Wonder": 1, "Hero": 2, "Champion": 1 });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetCounts(), { "Tower": 0, "Wonder": 0, "Hero": 1, "Champion": 0 });
// Edge case
AddMock(92, IID_TrainingRestrictions, {
"GetCategory": () => "Hero"
});
AddMock(92, IID_Identity, {
"GetClassesList": () => ["Aegis"]
});
cmpEntityLimits.OnGlobalOwnershipChanged({ "entity": 92, "from": INVALID_PLAYER, "to": 1 });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetLimits(), { "Tower": 5, "Wonder": 1, "Hero": undefined, "Champion": 1 });
TS_ASSERT(cmpEntityLimits.AllowedToTrain("Hero", 157));
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetCounts(), { "Tower": 0, "Wonder": 0, "Hero": 2, "Champion": 0 });
cmpEntityLimits.OnGlobalOwnershipChanged({ "entity": 91, "from": 1, "to": INVALID_PLAYER });
cmpEntityLimits.OnGlobalOwnershipChanged({ "entity": 92, "from": 1, "to": INVALID_PLAYER });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetLimits(), { "Tower": 5, "Wonder": 1, "Hero": 2, "Champion": 1 });
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetCounts(), { "Tower": 0, "Wonder": 0, "Hero": 0, "Champion": 0 });
// Test AllowedToReplace
AddMock(SYSTEM_ENTITY, IID_TemplateManager, {
"GetTemplate": name =>
{
switch (name)
{
case "templateA":
return { "TrainingRestrictions": { "Category": "Champion" } };
case "templateB":
return { "TrainingRestrictions": { "Category": "Hero" } };
case "templateC":
return { "BuildRestrictions": { "Category": "Wonder" } };
case "templateD":
return { "BuildRestrictions": { "Category": "Tower" } };
default:
return null;
}
},
"GetCurrentTemplateName": id =>
{
switch (id)
{
case 100:
return "templateA";
case 101:
return "templateB";
case 102:
return "templateC";
case 103:
return "templateD";
default:
return null;
}
}
});
cmpEntityLimits.ChangeCount("Champion", 1);
TS_ASSERT(cmpEntityLimits.AllowedToReplace(100, "templateA"));
TS_ASSERT(!cmpEntityLimits.AllowedToReplace(101, "templateA"));
cmpEntityLimits.ChangeCount("Champion", -1);
cmpEntityLimits.ChangeCount("Tower", 5);
TS_ASSERT(!cmpEntityLimits.AllowedToReplace(102, "templateD"));
TS_ASSERT(cmpEntityLimits.AllowedToReplace(103, "templateD"));
cmpEntityLimits.ChangeCount("Tower", -5);
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetCounts(), { "Tower": 0, "Wonder": 0, "Hero": 0, "Champion": 0 });
// Test limit removers by tech
cmpEntityLimits.UpdateLimitsFromTech("TechB");
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetLimits(), { "Tower": 5, "Wonder": 1, "Hero": 2, "Champion": 1 });
cmpEntityLimits.UpdateLimitsFromTech("TechA");
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetLimits(), { "Tower": undefined, "Wonder": 1, "Hero": 2, "Champion": 1 });
cmpEntityLimits.UpdateLimitsFromTech("TechA");
TS_ASSERT_UNEVAL_EQUALS(cmpEntityLimits.GetLimits(), { "Tower": undefined, "Wonder": 1, "Hero": 2, "Champion": 1 });