Updated trader example to use mongo Ids

This commit is contained in:
Dev 2024-09-21 17:40:49 +01:00
parent b7d81c52d3
commit 6b7c9bd8e3
32 changed files with 87 additions and 60 deletions

View File

@ -1,7 +1,7 @@
{ {
"name": "ScopesAndTypes", "name": "ScopesAndTypes",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "BundleLoading", "name": "BundleLoading",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "ClassExtensionOverride", "name": "ClassExtensionOverride",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "13.1AddTraderWithAssortJSON", "name": "13.1AddTraderWithAssortJSON",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,5 +1,5 @@
{ {
"_id": "cat", "_id": "66eeef8b2a166b73d2066a7e",
"working": true, "working": true,
"availableInRaid": false, "availableInRaid": false,
"items_buy": { "items_buy": {
@ -14,7 +14,7 @@
"name": "Cat", "name": "Cat",
"surname": " ", "surname": " ",
"nickname": "Maxwell", "nickname": "Maxwell",
"location": "Here is the cat shop", "location": "Downtown tarkov",
"avatar": "/files/trader/avatar/cat.jpg", "avatar": "/files/trader/avatar/cat.jpg",
"balance_rub": 5000000, "balance_rub": 5000000,
"balance_dol": 0, "balance_dol": 0,

View File

@ -1,7 +1,7 @@
{ {
"name": "13AddTrader", "name": "13AddTrader",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -16,7 +16,7 @@ import { Money } from "@spt/models/enums/Money";
import { Traders } from "@spt/models/enums/Traders"; import { Traders } from "@spt/models/enums/Traders";
import { HashUtil } from "@spt/utils/HashUtil"; import { HashUtil } from "@spt/utils/HashUtil";
// New trader settings // Get trader settings
import * as baseJson from "../db/base.json"; import * as baseJson from "../db/base.json";
import { TraderHelper } from "./traderHelpers"; import { TraderHelper } from "./traderHelpers";
@ -29,8 +29,14 @@ class SampleTrader implements IPreSptLoadMod, IPostDBLoadMod {
private traderHelper: TraderHelper; private traderHelper: TraderHelper;
private fluentAssortCreator: FluentAssortCreator; private fluentAssortCreator: FluentAssortCreator;
private traderBase;
private traderNickname: string;
constructor() { constructor() {
this.mod = "13AddTrader"; // Set name of mod so we can log it to console later this.mod = "13AddTrader"; // Set name of mod so we can log it to console later
// Get base json from /db/ folder
this.traderBase = baseJson;
this.traderNickname = "Cat"
} }
/** /**
@ -50,17 +56,21 @@ class SampleTrader implements IPreSptLoadMod, IPostDBLoadMod {
const traderConfig: ITraderConfig = configServer.getConfig<ITraderConfig>(ConfigTypes.TRADER); const traderConfig: ITraderConfig = configServer.getConfig<ITraderConfig>(ConfigTypes.TRADER);
const ragfairConfig = configServer.getConfig<IRagfairConfig>(ConfigTypes.RAGFAIR); const ragfairConfig = configServer.getConfig<IRagfairConfig>(ConfigTypes.RAGFAIR);
// IMPORTANT - YOUR TRADER NEEDS A UNIQUE MONGO-ID, ASK IN DISCORD IF YOU DONT KNOW WHAT THAT IS
// GOOGLE "mongoid generator"
this.traderBase._id = "66eeef8b2a166b73d2066a7e";
// Create helper class and use it to register our traders image/icon + set its stock refresh time // Create helper class and use it to register our traders image/icon + set its stock refresh time
this.traderHelper = new TraderHelper(); this.traderHelper = new TraderHelper();
this.fluentAssortCreator = new FluentAssortCreator(hashUtil, this.logger); this.fluentAssortCreator = new FluentAssortCreator(hashUtil, this.logger);
this.traderHelper.registerProfileImage(baseJson, this.mod, preSptModLoader, imageRouter, "cat.jpg"); this.traderHelper.registerProfileImage(this.traderBase, this.mod, preSptModLoader, imageRouter, "cat.jpg");
this.traderHelper.setTraderUpdateTime(traderConfig, baseJson, 3600, 4000); this.traderHelper.setTraderUpdateTime(traderConfig, this.traderBase, 3600, 4000);
// Add trader to trader enum // Add trader to trader enum
Traders[baseJson._id] = baseJson._id; Traders[this.traderBase._id] = this.traderBase._id;
// Add trader to flea market // Add trader to flea market
ragfairConfig.traders[baseJson._id] = true; ragfairConfig.traders[this.traderBase._id] = true;
this.logger.debug(`[${this.mod}] preSpt Loaded`); this.logger.debug(`[${this.mod}] preSpt Loaded`);
} }
@ -74,14 +84,13 @@ class SampleTrader implements IPreSptLoadMod, IPostDBLoadMod {
// Resolve SPT classes we'll use // Resolve SPT classes we'll use
const databaseServer: DatabaseServer = container.resolve<DatabaseServer>("DatabaseServer"); const databaseServer: DatabaseServer = container.resolve<DatabaseServer>("DatabaseServer");
const configServer: ConfigServer = container.resolve<ConfigServer>("ConfigServer");
const jsonUtil: JsonUtil = container.resolve<JsonUtil>("JsonUtil"); const jsonUtil: JsonUtil = container.resolve<JsonUtil>("JsonUtil");
// Get a reference to the database tables // Get a reference to the database tables
const tables = databaseServer.getTables(); const tables = databaseServer.getTables();
// Add new trader to the trader dictionary in DatabaseServer - has no assorts (items) yet // Add new trader to the trader dictionary in DatabaseServer - has no assorts (items) yet
this.traderHelper.addTraderToDb(baseJson, tables, jsonUtil); this.traderHelper.addTraderToDb(this.traderBase, tables, jsonUtil);
// Add milk // Add milk
@ -91,7 +100,7 @@ class SampleTrader implements IPreSptLoadMod, IPostDBLoadMod {
.addBuyRestriction(10) .addBuyRestriction(10)
.addMoneyCost(Money.ROUBLES, 2000) .addMoneyCost(Money.ROUBLES, 2000)
.addLoyaltyLevel(1) .addLoyaltyLevel(1)
.export(tables.traders[baseJson._id]); .export(tables.traders[this.traderBase._id]);
// Add 3x bitcoin + salewa for milk barter // Add 3x bitcoin + salewa for milk barter
this.fluentAssortCreator this.fluentAssortCreator
@ -100,30 +109,37 @@ class SampleTrader implements IPreSptLoadMod, IPostDBLoadMod {
.addBarterCost(ItemTpl.BARTER_PHYSICAL_BITCOIN, 3) .addBarterCost(ItemTpl.BARTER_PHYSICAL_BITCOIN, 3)
.addBarterCost(ItemTpl.MEDKIT_SALEWA_FIRST_AID_KIT, 1) .addBarterCost(ItemTpl.MEDKIT_SALEWA_FIRST_AID_KIT, 1)
.addLoyaltyLevel(1) .addLoyaltyLevel(1)
.export(tables.traders[baseJson._id]); .export(tables.traders[this.traderBase._id]);
// Add glock as money purchase // Add glock as a money purchase
this.fluentAssortCreator this.fluentAssortCreator
.createComplexAssortItem(this.traderHelper.createGlock()) .createComplexAssortItem(this.traderHelper.createGlock())
.addUnlimitedStackCount() .addUnlimitedStackCount()
.addMoneyCost(Money.ROUBLES, 20000) .addMoneyCost(Money.ROUBLES, 20000)
.addBuyRestriction(3) .addBuyRestriction(3)
.addLoyaltyLevel(1) .addLoyaltyLevel(1)
.export(tables.traders[baseJson._id]); .export(tables.traders[this.traderBase._id]);
// Add mp133 preset as mayo barter // Add mp133 preset as a barter for mayonase
this.fluentAssortCreator this.fluentAssortCreator
.createComplexAssortItem(tables.globals.ItemPresets["584148f2245977598f1ad387"]._items) // Weapon preset id comes from globals.json .createComplexAssortItem(tables.globals.ItemPresets["584148f2245977598f1ad387"]._items) // Weapon preset id comes from globals.json
.addStackCount(200) .addStackCount(200)
.addBarterCost(ItemTpl.FOOD_JAR_OF_DEVILDOG_MAYO, 1) .addBarterCost(ItemTpl.FOOD_JAR_OF_DEVILDOG_MAYO, 1)
.addBuyRestriction(3) .addBuyRestriction(3)
.addLoyaltyLevel(1) .addLoyaltyLevel(1)
.export(tables.traders[baseJson._id]); .export(tables.traders[this.traderBase._id]);
// Add trader to locale file, ensures trader text shows properly on screen // Add trader to locale file, ensures trader text shows properly on screen
// WARNING: adds the same text to ALL locales (e.g. chinese/french/english) // WARNING: adds the same text to ALL locales (e.g. chinese/french/english)
this.traderHelper.addTraderToLocales(baseJson, tables, baseJson.name, "Cat", baseJson.nickname, baseJson.location, "This is the cat shop"); this.traderHelper.addTraderToLocales(
this.traderBase,
tables,
this.traderBase.name,
this.traderNickname,
this.traderBase.nickname,
this.traderBase.location,
`This is the ${this.traderNickname} shop`);
this.logger.debug(`[${this.mod}] postDb Loaded`); this.logger.debug(`[${this.mod}] postDb Loaded`);
} }

View File

@ -0,0 +1,10 @@
export enum NewItemIds {
GLOCK_BASE = "66eeef3b2a166b73d2066a74",
GLOCK_BARREL = "66eeef3b2a166b73d2066a75",
GLOCK_RECIEVER = "66eeef3b2a166b73d2066a76",
GLOCK_COMPENSATOR = "66eeef3b2a166b73d2066a77",
GLOCK_PISTOL_GRIP = "66eeef3b2a166b73d2066a78",
GLOCK_REAR_SIGHT = "66eeef3b2a166b73d2066a79",
GLOCK_FRONT_SIGHT = "66eeef3b2a166b73d2066a7a",
GLOCK_MAGAZINE = "66eeef3b2a166b73d2066a7b"
}

View File

@ -5,6 +5,7 @@ import { ITraderConfig, UpdateTime } from "@spt/models/spt/config/ITraderConfig"
import { IDatabaseTables } from "@spt/models/spt/server/IDatabaseTables"; import { IDatabaseTables } from "@spt/models/spt/server/IDatabaseTables";
import { ImageRouter } from "@spt/routers/ImageRouter"; import { ImageRouter } from "@spt/routers/ImageRouter";
import { JsonUtil } from "@spt/utils/JsonUtil"; import { JsonUtil } from "@spt/utils/JsonUtil";
import { NewItemIds } from "./newitemIds";
export class TraderHelper { export class TraderHelper {
/** /**
@ -89,63 +90,63 @@ export class TraderHelper {
// Add the base first // Add the base first
glock.push({ // Add the base weapon first glock.push({ // Add the base weapon first
_id: "glockBase", // Ids dont matter, as long as they are unique (can use hashUtil.generate() if you dont want to type every id by hand) _id: NewItemIds.GLOCK_BASE, // Ids matter, MUST BE UNIQUE See mod.ts for more details
_tpl: "5a7ae0c351dfba0017554310", // This is the weapons tpl, found on: https://db.sp-tarkov.com/search _tpl: "5a7ae0c351dfba0017554310", // This is the weapons tpl, found on: https://db.sp-tarkov.com/search
}); });
// Add barrel // Add barrel
glock.push({ glock.push({
_id: "glockbarrel", _id: NewItemIds.GLOCK_BARREL,
_tpl: "5a6b60158dc32e000a31138b", _tpl: "5a6b60158dc32e000a31138b",
parentId: "glockBase", // This is a sub item, you need to define its parent its attached to / inserted into parentId: NewItemIds.GLOCK_BASE, // This is a sub item, you need to define its parent its attached to / inserted into
slotId: "mod_barrel", // Required for mods, you need to define what 'role' they have slotId: "mod_barrel", // Required for mods, you need to define what 'slot' the mod will fill on the weapon
}); });
// Add reciever // Add reciever
glock.push({ glock.push({
_id: "glockReciever", _id: NewItemIds.GLOCK_RECIEVER,
_tpl: "5a9685b1a2750c0032157104", _tpl: "5a9685b1a2750c0032157104",
parentId: "glockBase", parentId: NewItemIds.GLOCK_BASE,
slotId: "mod_reciever", slotId: "mod_reciever",
}); });
// Add compensator // Add compensator
glock.push({ glock.push({
_id: "glockCompensator", _id: NewItemIds.GLOCK_COMPENSATOR,
_tpl: "5a7b32a2e899ef00135e345a", _tpl: "5a7b32a2e899ef00135e345a",
parentId: "glockReciever", // The parent of this mod is the reciever NOT weapon, be careful to get the correct parent parentId: NewItemIds.GLOCK_RECIEVER, // The parent of this mod is the reciever NOT weapon, be careful to get the correct parent
slotId: "mod_muzzle", slotId: "mod_muzzle",
}); });
// Add Pistol grip // Add Pistol grip
glock.push({ glock.push({
_id: "glockPistolGrip", _id: NewItemIds.GLOCK_PISTOL_GRIP,
_tpl: "5a7b4960e899ef197b331a2d", _tpl: "5a7b4960e899ef197b331a2d",
parentId: "glockBase", parentId: NewItemIds.GLOCK_BASE,
slotId: "mod_pistol_grip", slotId: "mod_pistol_grip",
}); });
// Add front sight // Add front sight
glock.push({ glock.push({
_id: "glockRearSight", _id: NewItemIds.GLOCK_FRONT_SIGHT,
_tpl: "5a6f5d528dc32e00094b97d9", _tpl: "5a6f5d528dc32e00094b97d9",
parentId: "glockReciever", parentId: NewItemIds.GLOCK_RECIEVER,
slotId: "mod_sight_rear", slotId: "mod_sight_rear",
}); });
// Add rear sight // Add rear sight
glock.push({ glock.push({
_id: "glockFrontSight", _id: NewItemIds.GLOCK_REAR_SIGHT,
_tpl: "5a6f58f68dc32e000a311390", _tpl: "5a6f58f68dc32e000a311390",
parentId: "glockReciever", parentId: NewItemIds.GLOCK_RECIEVER,
slotId: "mod_sight_front", slotId: "mod_sight_front",
}); });
// Add magazine // Add magazine
glock.push({ glock.push({
_id: "glockMagazine", _id: NewItemIds.GLOCK_MAGAZINE,
_tpl: "630769c4962d0247b029dc60", _tpl: "630769c4962d0247b029dc60",
parentId: "glockBase", parentId: NewItemIds.GLOCK_BASE,
slotId: "mod_magazine", slotId: "mod_magazine",
}); });

View File

@ -1,7 +1,7 @@
{ {
"name": "AfterDBLoadHook", "name": "AfterDBLoadHook",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "HttpListenerExample", "name": "HttpListenerExample",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "ImporterUtil", "name": "ImporterUtil",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "AsyncWithDependency1", "name": "AsyncWithDependency1",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "AsyncWithDependency2", "name": "AsyncWithDependency2",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "CustomItemService-modified", "name": "CustomItemService-modified",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "CustomItemService", "name": "CustomItemService",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "UseExternalLibraries", "name": "UseExternalLibraries",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "LogToConsole", "name": "LogToConsole",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "CustomChatBot", "name": "CustomChatBot",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "CustomCommandoCommand", "name": "CustomCommandoCommand",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "CustomAkiCommand", "name": "CustomAkiCommand",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "CustomAbstractChatBot", "name": "CustomAbstractChatBot",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "WebSocket", "name": "WebSocket",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "EditDatabase", "name": "EditDatabase",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "GetSptConfigFile", "name": "GetSptConfigFile",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "UseACustomJson5OrJsonCConfigFile", "name": "UseACustomJson5OrJsonCConfigFile",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "UseACustomConfigFile", "name": "UseACustomConfigFile",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "ReplaceMethod", "name": "ReplaceMethod",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "ReferenceAnotherClass", "name": "ReferenceAnotherClass",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "OnLoadHook", "name": "OnLoadHook",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "OnUpdateHook", "name": "OnUpdateHook",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],

View File

@ -1,7 +1,7 @@
{ {
"name": "RouterHooks", "name": "RouterHooks",
"version": "1.0.0", "version": "1.0.0",
"sptVersion": "~3.9", "sptVersion": "~3.10",
"loadBefore": [], "loadBefore": [],
"loadAfter": [], "loadAfter": [],
"incompatibilities": [], "incompatibilities": [],