Fixed pretty much all the things that were triggering my OCD #28
@ -8,4 +8,4 @@ Dive into a specific mod folder and follow the instructions in the `README.md` f
|
||||
|
||||
# Mod Upgrade Guide
|
||||
|
||||
Read [Here](https://hub.sp-tarkov.com/doc/entry/51-modding-in-2-4-0/)
|
||||
Read [Here](https://hub.sp-tarkov.com/doc/entry/51-modding-in-spt-3-x-x/)
|
||||
|
@ -1,9 +1,10 @@
|
||||
# Exclude these folders from linting
|
||||
node_modules
|
||||
dist/
|
||||
types/
|
||||
**/node_modules
|
||||
/tmp
|
||||
/dist
|
||||
/types
|
||||
|
||||
# Exclude these filetypes from linting
|
||||
*.json
|
||||
*.txt
|
||||
*.exe
|
||||
*.exe
|
||||
|
@ -95,4 +95,4 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ Some resources to get you started:
|
||||
|
||||
## **Coding Guidelines**
|
||||
|
||||
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"license"`, `"author"`, and `"akiVersion"`.
|
||||
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"akiVersion"`, `"loadBefore"`, `"loadAfter"`, `"incompatibilities"`, `"isBundleMod"`, `"author"`, and `"license"`.
|
||||
|
||||
New to Typescript? Find comprehensive documentation on the [official website](https://www.typescriptlang.org/docs/).
|
||||
|
||||
|
@ -29,11 +29,10 @@
|
||||
* @version v1.0.0
|
||||
*/
|
||||
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import fs from "fs-extra";
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { dirname } from "path";
|
||||
import ignore from "ignore";
|
||||
import archiver from "archiver";
|
||||
import winston from "winston";
|
||||
@ -165,7 +164,7 @@ async function main() {
|
||||
* @returns {string} The absolute path of the current working directory.
|
||||
*/
|
||||
function getCurrentDirectory() {
|
||||
return dirname(fileURLToPath(import.meta.url));
|
||||
return path.dirname(fileURLToPath(import.meta.url));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -225,10 +224,9 @@ function createProjectName(packageJson) {
|
||||
// Remove any non-alphanumeric characters from the author and name.
|
||||
const author = packageJson.author.replace(/\W/g, "");
|
||||
const name = packageJson.name.replace(/\W/g, "");
|
||||
const version = packageJson.version;
|
||||
|
||||
// Ensure the name is lowercase, as per the package.json specification.
|
||||
return `${author}-${name}-${version}`.toLowerCase();
|
||||
return `${author}-${name}`.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,12 +1,13 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint"
|
||||
]
|
||||
}
|
||||
}
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"refringe.spt-id-highlighter"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,12 @@
|
||||
{
|
||||
"name": "ScopesAndTypes",
|
||||
"version": "1.0.0",
|
||||
"main": "src/mod.js",
|
||||
"license": "MIT",
|
||||
"author": "Chomp",
|
||||
"akiVersion": "~3.9",
|
||||
"loadBefore": [],
|
||||
"loadAfter": [],
|
||||
"incompatibilities": [],
|
||||
"contributors": [],
|
||||
"loadBefore": [],
|
||||
"loadAfter": [],
|
||||
"incompatibilities": [],
|
||||
"isBundleMod": false,
|
||||
"main": "src/mod.js",
|
||||
"scripts": {
|
||||
"setup": "npm i",
|
||||
"build": "node ./build.mjs",
|
||||
@ -22,9 +20,11 @@
|
||||
"eslint": "8.57",
|
||||
"fs-extra": "11.2",
|
||||
"ignore": "^5.2",
|
||||
"os": "^0.1",
|
||||
"tsyringe": "4.8.0",
|
||||
"typescript": "5.4",
|
||||
"winston": "3.12"
|
||||
}
|
||||
},
|
||||
"author": "Chomp",
|
||||
"contributors": [],
|
||||
"license": "MIT"
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { Processing } from "./Processing";
|
||||
|
||||
@injectable()
|
||||
export class MyMod
|
||||
export class MyMod
|
||||
{
|
||||
// Since this is a singleton this class will only have 1 object/bean
|
||||
private calls = 0;
|
||||
@ -11,15 +12,15 @@ export class MyMod
|
||||
// All these types are automatically wired when the container resolves the bean creation
|
||||
constructor(
|
||||
@inject("Processing") private processing: Processing,
|
||||
@inject("WinstonLogger") private logger: ILogger
|
||||
@inject("WinstonLogger") private logger: ILogger,
|
||||
)
|
||||
{}
|
||||
|
||||
public runModLogic(): void
|
||||
public runModLogic(): void
|
||||
{
|
||||
this.processing.doProcess();
|
||||
this.logger.info(`This is a singleton bean, so everytime its called the same entity will be returned. This is the call number: ${this.calls}`);
|
||||
this.calls++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,22 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
|
||||
@injectable()
|
||||
export class Processing
|
||||
export class Processing
|
||||
{
|
||||
// Since this is a transient type, this class will have many of this type
|
||||
// Anything left in variables will always be discarded
|
||||
private calls = 0;
|
||||
|
||||
constructor(
|
||||
@inject("WinstonLogger") private logger: ILogger
|
||||
@inject("WinstonLogger") private logger: ILogger,
|
||||
)
|
||||
{}
|
||||
|
||||
public doProcess(): void
|
||||
public doProcess(): void
|
||||
{
|
||||
this.logger.info(`Process was triggered, since this is a singleton the calls value is always 0: ${this.calls}`);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { DependencyContainer, Lifecycle } from "tsyringe";
|
||||
|
||||
import { IPreAkiLoadMod } from "@spt-aki/models/external/IPreAkiLoadMod";
|
||||
import { IPostAkiLoadMod } from "@spt-aki/models/external/IPostAkiLoadMod";
|
||||
import { MyMod } from "./MyMod";
|
||||
@ -12,16 +13,16 @@ class Mod implements IPreAkiLoadMod, IPostAkiLoadMod
|
||||
// This class is registered as a singleton. This means ONE and only ONE bean
|
||||
// of this class will ever exist.
|
||||
container.register<MyMod>("MyMod", MyMod, {lifecycle: Lifecycle.Singleton});
|
||||
|
||||
|
||||
// This class is being registered as default or transient. This means that
|
||||
// every time a class requests a bean of this type a new one will be created
|
||||
container.register<Processing>("Processing", Processing);
|
||||
}
|
||||
|
||||
public postAkiLoad(container: DependencyContainer): void
|
||||
public postAkiLoad(container: DependencyContainer): void
|
||||
{
|
||||
// We will run this in a quick 5 loop to show how singletons and transients work
|
||||
for (let i = 0; i < 5; i++)
|
||||
for (let i = 0; i < 5; i++)
|
||||
{
|
||||
// every resolution will return the same MyMod bean
|
||||
container.resolve<MyMod>("MyMod").runModLogic();
|
||||
@ -29,4 +30,4 @@ class Mod implements IPreAkiLoadMod, IPostAkiLoadMod
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { mod: new Mod() }
|
||||
export const mod = new Mod();
|
||||
|
@ -11,8 +11,8 @@
|
||||
"resolveJsonModule": true,
|
||||
"outDir": "tmp",
|
||||
"paths": {
|
||||
"@spt-aki/*": [ "./types/*" ],
|
||||
"@spt-aki/*": ["./types/*"],
|
||||
},
|
||||
},
|
||||
"exclude": [ "node_modules", "dist", "tmp" ],
|
||||
}
|
||||
"exclude": ["node_modules", "dist", "tmp"],
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
# Exclude these folders from linting
|
||||
node_modules
|
||||
dist/
|
||||
types/
|
||||
**/node_modules
|
||||
/tmp
|
||||
/dist
|
||||
/types
|
||||
|
||||
# Exclude these filetypes from linting
|
||||
*.json
|
||||
*.txt
|
||||
*.exe
|
||||
*.exe
|
||||
|
@ -95,4 +95,4 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ Some resources to get you started:
|
||||
|
||||
## **Coding Guidelines**
|
||||
|
||||
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"license"`, `"author"`, and `"akiVersion"`.
|
||||
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"akiVersion"`, `"loadBefore"`, `"loadAfter"`, `"incompatibilities"`, `"isBundleMod"`, `"author"`, and `"license"`.
|
||||
|
||||
New to Typescript? Find comprehensive documentation on the [official website](https://www.typescriptlang.org/docs/).
|
||||
|
||||
|
@ -29,11 +29,10 @@
|
||||
* @version v1.0.0
|
||||
*/
|
||||
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import fs from "fs-extra";
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { dirname } from "path";
|
||||
import ignore from "ignore";
|
||||
import archiver from "archiver";
|
||||
import winston from "winston";
|
||||
@ -165,7 +164,7 @@ async function main() {
|
||||
* @returns {string} The absolute path of the current working directory.
|
||||
*/
|
||||
function getCurrentDirectory() {
|
||||
return dirname(fileURLToPath(import.meta.url));
|
||||
return path.dirname(fileURLToPath(import.meta.url));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -225,10 +224,9 @@ function createProjectName(packageJson) {
|
||||
// Remove any non-alphanumeric characters from the author and name.
|
||||
const author = packageJson.author.replace(/\W/g, "");
|
||||
const name = packageJson.name.replace(/\W/g, "");
|
||||
const version = packageJson.version;
|
||||
|
||||
// Ensure the name is lowercase, as per the package.json specification.
|
||||
return `${author}-${name}-${version}`.toLowerCase();
|
||||
return `${author}-${name}`.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"manifest": [
|
||||
{
|
||||
"key": "assets/content/weapons/usable_items/item_bottle/textures/client_assets.bundle",
|
||||
"dependencyKeys": []
|
||||
}
|
||||
]
|
||||
}
|
||||
"manifest": [
|
||||
{
|
||||
"key": "assets/content/weapons/usable_items/item_bottle/textures/client_assets.bundle",
|
||||
"dependencyKeys": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint"
|
||||
]
|
||||
}
|
||||
}
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"refringe.spt-id-highlighter"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,12 @@
|
||||
{
|
||||
"name": "BundleLoading",
|
||||
"version": "1.0.0",
|
||||
"author": "Chomp",
|
||||
"license": "MIT",
|
||||
"main": "src/mod.js",
|
||||
"isBundleMod": true,
|
||||
"name": "BundleLoading",
|
||||
"version": "1.0.0",
|
||||
"akiVersion": "~3.9",
|
||||
"loadBefore": [],
|
||||
"loadAfter": [],
|
||||
"incompatibilities": [],
|
||||
"contributors": [],
|
||||
"loadBefore": [],
|
||||
"loadAfter": [],
|
||||
"incompatibilities": [],
|
||||
"isBundleMod": true,
|
||||
"main": "src/mod.js",
|
||||
"scripts": {
|
||||
"setup": "npm i",
|
||||
"build": "node ./build.mjs",
|
||||
@ -23,9 +20,11 @@
|
||||
"eslint": "8.57",
|
||||
"fs-extra": "11.2",
|
||||
"ignore": "^5.2",
|
||||
"os": "^0.1",
|
||||
"tsyringe": "4.8.0",
|
||||
"typescript": "5.4",
|
||||
"winston": "3.12"
|
||||
}
|
||||
},
|
||||
"author": "Chomp",
|
||||
"contributors": [],
|
||||
"license": "MIT"
|
||||
}
|
||||
|
@ -1,16 +1,17 @@
|
||||
import { DependencyContainer } from "tsyringe";
|
||||
|
||||
import { IPostAkiLoadMod } from "@spt-aki/models/external/IPostAkiLoadMod";
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
|
||||
class Mod implements IPostAkiLoadMod
|
||||
{
|
||||
public postAkiLoad(container: DependencyContainer): void
|
||||
public postAkiLoad(container: DependencyContainer): void
|
||||
{
|
||||
// get the logger from the server container
|
||||
// get the logger from the server container
|
||||
const logger = container.resolve<ILogger>("WinstonLogger");
|
||||
|
||||
|
||||
logger.info("Loading: Bundle Loading Sample");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { mod: new Mod() }
|
||||
export const mod = new Mod();
|
||||
|
@ -11,8 +11,8 @@
|
||||
"resolveJsonModule": true,
|
||||
"outDir": "tmp",
|
||||
"paths": {
|
||||
"@spt-aki/*": [ "./types/*" ],
|
||||
"@spt-aki/*": ["./types/*"],
|
||||
},
|
||||
},
|
||||
"exclude": [ "node_modules", "dist", "tmp" ],
|
||||
}
|
||||
"exclude": ["node_modules", "dist", "tmp"],
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
# Exclude these folders from linting
|
||||
node_modules
|
||||
dist/
|
||||
types/
|
||||
**/node_modules
|
||||
/tmp
|
||||
/dist
|
||||
/types
|
||||
|
||||
# Exclude these filetypes from linting
|
||||
*.json
|
||||
*.txt
|
||||
*.exe
|
||||
*.exe
|
||||
|
@ -95,4 +95,4 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ Some resources to get you started:
|
||||
|
||||
## **Coding Guidelines**
|
||||
|
||||
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"license"`, `"author"`, and `"akiVersion"`.
|
||||
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"akiVersion"`, `"loadBefore"`, `"loadAfter"`, `"incompatibilities"`, `"isBundleMod"`, `"author"`, and `"license"`.
|
||||
|
||||
New to Typescript? Find comprehensive documentation on the [official website](https://www.typescriptlang.org/docs/).
|
||||
|
||||
|
@ -29,11 +29,10 @@
|
||||
* @version v1.0.0
|
||||
*/
|
||||
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import fs from "fs-extra";
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { dirname } from "path";
|
||||
import ignore from "ignore";
|
||||
import archiver from "archiver";
|
||||
import winston from "winston";
|
||||
@ -165,7 +164,7 @@ async function main() {
|
||||
* @returns {string} The absolute path of the current working directory.
|
||||
*/
|
||||
function getCurrentDirectory() {
|
||||
return dirname(fileURLToPath(import.meta.url));
|
||||
return path.dirname(fileURLToPath(import.meta.url));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -225,10 +224,9 @@ function createProjectName(packageJson) {
|
||||
// Remove any non-alphanumeric characters from the author and name.
|
||||
const author = packageJson.author.replace(/\W/g, "");
|
||||
const name = packageJson.name.replace(/\W/g, "");
|
||||
const version = packageJson.version;
|
||||
|
||||
// Ensure the name is lowercase, as per the package.json specification.
|
||||
return `${author}-${name}-${version}`.toLowerCase();
|
||||
return `${author}-${name}`.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,12 +1,13 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint"
|
||||
]
|
||||
}
|
||||
}
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"refringe.spt-id-highlighter"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,12 @@
|
||||
{
|
||||
"name": "ClassExtensionOverride",
|
||||
"version": "1.0.0",
|
||||
"main": "src/mod.js",
|
||||
"license": "MIT",
|
||||
"author": "Chomp",
|
||||
"akiVersion": "~3.9",
|
||||
"loadBefore": [],
|
||||
"loadAfter": [],
|
||||
"incompatibilities": [],
|
||||
"contributors": [],
|
||||
"loadBefore": [],
|
||||
"loadAfter": [],
|
||||
"incompatibilities": [],
|
||||
"isBundleMod": false,
|
||||
"main": "src/mod.js",
|
||||
"scripts": {
|
||||
"setup": "npm i",
|
||||
"build": "node ./build.mjs",
|
||||
@ -22,9 +20,11 @@
|
||||
"eslint": "8.57",
|
||||
"fs-extra": "11.2",
|
||||
"ignore": "^5.2",
|
||||
"os": "^0.1",
|
||||
"tsyringe": "4.8.0",
|
||||
"typescript": "5.4",
|
||||
"winston": "3.12"
|
||||
}
|
||||
},
|
||||
"author": "Chomp",
|
||||
"contributors": [],
|
||||
"license": "MIT"
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { LauncherCallbacks } from "@spt-aki/callbacks/LauncherCallbacks";
|
||||
import { LauncherController } from "@spt-aki/controllers/LauncherController";
|
||||
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
|
||||
@ -5,7 +7,6 @@ import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { SaveServer } from "@spt-aki/servers/SaveServer";
|
||||
import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil";
|
||||
import { Watermark } from "@spt-aki/utils/Watermark";
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
// We need to declare this class as injectable, this will add the container
|
||||
// metadata
|
||||
@ -15,12 +16,12 @@ export class MyCustomLauncherCallbacks extends LauncherCallbacks // <<<<=== This
|
||||
{
|
||||
// We need to make sure we use the constructor and pass the dependencies to the parent class!
|
||||
constructor(
|
||||
// @inject() will make sure to find the component with the right token and put them there
|
||||
@inject("HttpResponseUtil") httpResponse: HttpResponseUtil,
|
||||
// @inject() will make sure to find the component with the right token and put them there
|
||||
@inject("HttpResponseUtil") httpResponse: HttpResponseUtil,
|
||||
@inject("LauncherController") launcherController: LauncherController,
|
||||
@inject("SaveServer") saveServer: SaveServer,
|
||||
@inject("Watermark") watermark: Watermark,
|
||||
@inject("WinstonLogger") private logger: ILogger
|
||||
@inject("WinstonLogger") private logger: ILogger,
|
||||
)
|
||||
{
|
||||
// Pass the parent class (LauncherCallbacks) the dependencies it needs to work
|
||||
@ -28,7 +29,7 @@ export class MyCustomLauncherCallbacks extends LauncherCallbacks // <<<<=== This
|
||||
}
|
||||
|
||||
// We override the parent method with the EXACT same signature
|
||||
public override ping(url: string, info: IEmptyRequestData, sessionID: string): string
|
||||
public override ping(url: string, info: IEmptyRequestData, sessionID: string): string
|
||||
{
|
||||
// We are overriding the parent method, so ONLY this method will run, not the parent!
|
||||
// If we wanted to run both, you can always write:
|
||||
@ -39,5 +40,4 @@ export class MyCustomLauncherCallbacks extends LauncherCallbacks // <<<<=== This
|
||||
this.logger.success("Our custom method is dancing baby!");
|
||||
return "Lets dance";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { DependencyContainer } from "tsyringe";
|
||||
|
||||
import { IPreAkiLoadMod } from "@spt-aki/models/external/IPreAkiLoadMod"
|
||||
import { MyCustomLauncherCallbacks } from "./MyCustomLauncherCallbacks";
|
||||
|
||||
@ -9,7 +10,7 @@ class Mod implements IPreAkiLoadMod
|
||||
// you own custom implementations the server will then use.
|
||||
// In this example we will take the LauncherCallbacks class and override the ping() method
|
||||
// for our own custom method that will return "Lets dance" instead of "pong!"
|
||||
|
||||
|
||||
// Perform these actions before server fully loads
|
||||
public preAkiLoad(container: DependencyContainer): void {
|
||||
// Here we register our override for the component and we NEED to use the same
|
||||
@ -18,15 +19,14 @@ class Mod implements IPreAkiLoadMod
|
||||
// https://dev.sp-tarkov.com/SPT-AKI/Server/src/branch/development/project/src/di/Container.ts
|
||||
// In this scenario we want to override LauncherCallbacks, so we find the proper registry:
|
||||
//
|
||||
// depContainer.register<LauncherCallbacks>("LauncherCallbacks", {useClass: LauncherCallbacks});
|
||||
// depContainer.register<LauncherCallbacks>("LauncherCallbacks", { useClass: LauncherCallbacks });
|
||||
//
|
||||
// So what we want to do is register it with EXACTLY the same token
|
||||
container.register<MyCustomLauncherCallbacks>("MyCustomLauncherCallbacks", MyCustomLauncherCallbacks);
|
||||
container.register("LauncherCallbacks", {useToken: "MyCustomLauncherCallbacks"});
|
||||
|
||||
// Now that its registered, the server will automatically find this dependency and use it where ever its needed
|
||||
container.register("LauncherCallbacks", { useToken: "MyCustomLauncherCallbacks" });
|
||||
|
||||
// Now that its registered, the server will automatically find this dependency and use it where ever its needed
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { mod: new Mod() }
|
||||
export const mod = new Mod();
|
||||
|
@ -11,8 +11,8 @@
|
||||
"resolveJsonModule": true,
|
||||
"outDir": "tmp",
|
||||
"paths": {
|
||||
"@spt-aki/*": [ "./types/*" ],
|
||||
"@spt-aki/*": ["./types/*"],
|
||||
},
|
||||
},
|
||||
"exclude": [ "node_modules", "dist", "tmp" ],
|
||||
}
|
||||
"exclude": ["node_modules", "dist", "tmp"],
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
# Exclude these folders from linting
|
||||
node_modules
|
||||
dist/
|
||||
types/
|
||||
**/node_modules
|
||||
/tmp
|
||||
/dist
|
||||
/types
|
||||
|
||||
# Exclude these filetypes from linting
|
||||
*.json
|
||||
*.txt
|
||||
*.exe
|
||||
*.exe
|
||||
|
@ -95,4 +95,4 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ Some resources to get you started:
|
||||
|
||||
## **Coding Guidelines**
|
||||
|
||||
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"license"`, `"author"`, and `"akiVersion"`.
|
||||
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"akiVersion"`, `"loadBefore"`, `"loadAfter"`, `"incompatibilities"`, `"isBundleMod"`, `"author"`, and `"license"`.
|
||||
|
||||
New to Typescript? Find comprehensive documentation on the [official website](https://www.typescriptlang.org/docs/).
|
||||
|
||||
|
@ -29,11 +29,10 @@
|
||||
* @version v1.0.0
|
||||
*/
|
||||
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import fs from "fs-extra";
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { dirname } from "path";
|
||||
import ignore from "ignore";
|
||||
import archiver from "archiver";
|
||||
import winston from "winston";
|
||||
@ -165,7 +164,7 @@ async function main() {
|
||||
* @returns {string} The absolute path of the current working directory.
|
||||
*/
|
||||
function getCurrentDirectory() {
|
||||
return dirname(fileURLToPath(import.meta.url));
|
||||
return path.dirname(fileURLToPath(import.meta.url));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -225,10 +224,9 @@ function createProjectName(packageJson) {
|
||||
// Remove any non-alphanumeric characters from the author and name.
|
||||
const author = packageJson.author.replace(/\W/g, "");
|
||||
const name = packageJson.name.replace(/\W/g, "");
|
||||
const version = packageJson.version;
|
||||
|
||||
// Ensure the name is lowercase, as per the package.json specification.
|
||||
return `${author}-${name}-${version}`.toLowerCase();
|
||||
return `${author}-${name}`.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,12 +1,13 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint"
|
||||
]
|
||||
}
|
||||
}
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"refringe.spt-id-highlighter"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,12 @@
|
||||
{
|
||||
"name": "13AddTrader",
|
||||
"version": "1.0.0",
|
||||
"main": "src/mod.js",
|
||||
"license": "MIT",
|
||||
"author": "Shirito",
|
||||
"akiVersion": "~3.9",
|
||||
"loadBefore": [],
|
||||
"loadAfter": [],
|
||||
"incompatibilities": [],
|
||||
"contributors": [],
|
||||
"loadBefore": [],
|
||||
"loadAfter": [],
|
||||
"incompatibilities": [],
|
||||
"isBundleMod": false,
|
||||
"main": "src/mod.js",
|
||||
"scripts": {
|
||||
"setup": "npm i",
|
||||
"build": "node ./build.mjs",
|
||||
@ -22,9 +20,11 @@
|
||||
"eslint": "8.57",
|
||||
"fs-extra": "11.2",
|
||||
"ignore": "^5.2",
|
||||
"os": "^0.1",
|
||||
"tsyringe": "4.8.0",
|
||||
"typescript": "5.4",
|
||||
"winston": "3.12"
|
||||
}
|
||||
},
|
||||
"author": "Shirito",
|
||||
"contributors": [],
|
||||
"license": "MIT"
|
||||
}
|
||||
|
@ -17,24 +17,24 @@ export class FluentAssortConstructor
|
||||
this.hashUtil = hashutil
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Start selling item with tpl
|
||||
* @param itemTpl Tpl id of the item you want trader to sell
|
||||
* @param itemId Optional - set your own Id, otherwise unique id will be generated
|
||||
*/
|
||||
public createSingleAssortItem(itemTpl: string, itemId = undefined): FluentAssortConstructor
|
||||
public createSingleAssortItem(itemTpl: string, itemId: string = undefined): FluentAssortConstructor
|
||||
{
|
||||
// Create item ready for insertion into assort table
|
||||
const newItemToAdd: Item = {
|
||||
_id: !itemId ? this.hashUtil.generate(): itemId,
|
||||
_id: itemId ?? this.hashUtil.generate(),
|
||||
_tpl: itemTpl,
|
||||
parentId: "hideout", // Should always be "hideout"
|
||||
slotId: "hideout", // Should always be "hideout"
|
||||
upd: {
|
||||
UnlimitedCount: false,
|
||||
StackObjectsCount: 100
|
||||
}
|
||||
StackObjectsCount: 100,
|
||||
},
|
||||
};
|
||||
|
||||
this.itemsToSell.push(newItemToAdd);
|
||||
@ -47,10 +47,7 @@ export class FluentAssortConstructor
|
||||
items[0].parentId = "hideout";
|
||||
items[0].slotId = "hideout";
|
||||
|
||||
if (!items[0].upd)
|
||||
{
|
||||
items[0].upd = {}
|
||||
}
|
||||
items[0].upd ??= {};
|
||||
|
||||
items[0].upd.UnlimitedCount = false;
|
||||
items[0].upd.StackObjectsCount = 100;
|
||||
@ -99,14 +96,12 @@ export class FluentAssortConstructor
|
||||
|
||||
public addMoneyCost(currencyType: Money, amount: number): FluentAssortConstructor
|
||||
{
|
||||
this.barterScheme[this.itemsToSell[0]._id] = [
|
||||
[
|
||||
{
|
||||
count: amount,
|
||||
_tpl: currencyType
|
||||
}
|
||||
]
|
||||
];
|
||||
this.barterScheme[this.itemsToSell[0]._id] = [[
|
||||
{
|
||||
count: amount,
|
||||
_tpl: currencyType,
|
||||
},
|
||||
]];
|
||||
|
||||
return this;
|
||||
}
|
||||
@ -121,8 +116,8 @@ export class FluentAssortConstructor
|
||||
this.barterScheme[sellableItemId] = [[
|
||||
{
|
||||
count: count,
|
||||
_tpl: itemTpl
|
||||
}
|
||||
_tpl: itemTpl,
|
||||
},
|
||||
]];
|
||||
}
|
||||
else
|
||||
@ -139,10 +134,9 @@ export class FluentAssortConstructor
|
||||
// No barter for item, add it fresh
|
||||
this.barterScheme[sellableItemId][0].push({
|
||||
count: count,
|
||||
_tpl: itemTpl
|
||||
})
|
||||
_tpl: itemTpl,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
@ -150,7 +144,7 @@ export class FluentAssortConstructor
|
||||
|
||||
/**
|
||||
* Reset objet ready for reuse
|
||||
* @returns
|
||||
* @returns
|
||||
*/
|
||||
public export(data: ITrader): FluentAssortConstructor
|
||||
{
|
||||
@ -172,4 +166,4 @@ export class FluentAssortConstructor
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,21 +12,22 @@ import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
|
||||
import { ITraderConfig } from "@spt-aki/models/spt/config/ITraderConfig";
|
||||
import { IRagfairConfig } from "@spt-aki/models/spt/config/IRagfairConfig";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
|
||||
// New trader settings
|
||||
import * as baseJson from "../db/base.json";
|
||||
import { TraderHelper } from "./traderHelpers";
|
||||
import { FluentAssortConstructor as FluentAssortCreator } from "./fluentTraderAssortCreator";
|
||||
import { Money } from "@spt-aki/models/enums/Money";
|
||||
import { Traders } from "@spt-aki/models/enums/Traders";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
|
||||
// New trader settings
|
||||
import * as baseJson from "../db/base.json";
|
||||
|
||||
import { TraderHelper } from "./traderHelpers";
|
||||
import { FluentAssortConstructor as FluentAssortCreator } from "./fluentTraderAssortCreator";
|
||||
|
||||
class SampleTrader implements IPreAkiLoadMod, IPostDBLoadMod
|
||||
{
|
||||
private mod: string
|
||||
private logger: ILogger
|
||||
private traderHelper: TraderHelper
|
||||
private fluentAssortCreator: FluentAssortCreator
|
||||
private mod: string;
|
||||
private logger: ILogger;
|
||||
private traderHelper: TraderHelper;
|
||||
private fluentAssortCreator: FluentAssortCreator;
|
||||
|
||||
constructor() {
|
||||
this.mod = "13AddTrader"; // Set name of mod so we can log it to console later
|
||||
@ -64,7 +65,7 @@ class SampleTrader implements IPreAkiLoadMod, IPostDBLoadMod
|
||||
|
||||
this.logger.debug(`[${this.mod}] preAki Loaded`);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Majority of trader-related work occurs after the aki database has been loaded but prior to SPT code being run
|
||||
* @param container Dependency container
|
||||
@ -86,39 +87,43 @@ class SampleTrader implements IPreAkiLoadMod, IPostDBLoadMod
|
||||
|
||||
// Add milk
|
||||
const MILK_ID = "575146b724597720a27126d5"; // Can find item ids in `database\templates\items.json` or with https://db.sp-tarkov.com/search
|
||||
this.fluentAssortCreator.createSingleAssortItem(MILK_ID)
|
||||
.addStackCount(200)
|
||||
.addBuyRestriction(10)
|
||||
.addMoneyCost(Money.ROUBLES, 2000)
|
||||
.addLoyaltyLevel(1)
|
||||
.export(tables.traders[baseJson._id]);
|
||||
this.fluentAssortCreator
|
||||
.createSingleAssortItem(MILK_ID)
|
||||
.addStackCount(200)
|
||||
.addBuyRestriction(10)
|
||||
.addMoneyCost(Money.ROUBLES, 2000)
|
||||
.addLoyaltyLevel(1)
|
||||
.export(tables.traders[baseJson._id]);
|
||||
|
||||
// Add 3x bitcoin + salewa for milk barter
|
||||
const BITCOIN_ID = "59faff1d86f7746c51718c9c"
|
||||
const BITCOIN_ID = "59faff1d86f7746c51718c9c";
|
||||
const SALEWA_ID = "544fb45d4bdc2dee738b4568";
|
||||
this.fluentAssortCreator.createSingleAssortItem(MILK_ID)
|
||||
.addStackCount(100)
|
||||
.addBarterCost(BITCOIN_ID, 3)
|
||||
.addBarterCost(SALEWA_ID, 1)
|
||||
.addLoyaltyLevel(1)
|
||||
.export(tables.traders[baseJson._id]);
|
||||
this.fluentAssortCreator
|
||||
.createSingleAssortItem(MILK_ID)
|
||||
.addStackCount(100)
|
||||
.addBarterCost(BITCOIN_ID, 3)
|
||||
.addBarterCost(SALEWA_ID, 1)
|
||||
.addLoyaltyLevel(1)
|
||||
.export(tables.traders[baseJson._id]);
|
||||
|
||||
|
||||
// Add glock as money purchase
|
||||
this.fluentAssortCreator.createComplexAssortItem(this.traderHelper.createGlock())
|
||||
.addUnlimitedStackCount()
|
||||
.addMoneyCost(Money.ROUBLES, 20000)
|
||||
.addBuyRestriction(3)
|
||||
.addLoyaltyLevel(1)
|
||||
.export(tables.traders[baseJson._id]);
|
||||
this.fluentAssortCreator
|
||||
.createComplexAssortItem(this.traderHelper.createGlock())
|
||||
.addUnlimitedStackCount()
|
||||
.addMoneyCost(Money.ROUBLES, 20000)
|
||||
.addBuyRestriction(3)
|
||||
.addLoyaltyLevel(1)
|
||||
.export(tables.traders[baseJson._id]);
|
||||
|
||||
// Add mp133 preset as mayo barter
|
||||
this.fluentAssortCreator.createComplexAssortItem(tables.globals.ItemPresets["584148f2245977598f1ad387"]._items)
|
||||
.addStackCount(200)
|
||||
.addBarterCost("5bc9b156d4351e00367fbce9", 1)
|
||||
.addBuyRestriction(3)
|
||||
.addLoyaltyLevel(1)
|
||||
.export(tables.traders[baseJson._id]);
|
||||
this.fluentAssortCreator
|
||||
.createComplexAssortItem(tables.globals.ItemPresets["584148f2245977598f1ad387"]._items)
|
||||
.addStackCount(200)
|
||||
.addBarterCost("5bc9b156d4351e00367fbce9", 1)
|
||||
.addBuyRestriction(3)
|
||||
.addLoyaltyLevel(1)
|
||||
.export(tables.traders[baseJson._id]);
|
||||
|
||||
// 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)
|
||||
@ -128,4 +133,4 @@ class SampleTrader implements IPreAkiLoadMod, IPostDBLoadMod
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { mod: new SampleTrader() }
|
||||
export const mod = new SampleTrader();
|
||||
|
@ -11,6 +11,7 @@ export class TraderHelper
|
||||
/**
|
||||
* Add profile picture to our trader
|
||||
* @param baseJson json file for trader (db/base.json)
|
||||
* @param modName mod folder name
|
||||
* @param preAkiModLoader mod loader class - used to get the mods file path
|
||||
* @param imageRouter image router class - used to register the trader image path so we see their image on trader page
|
||||
* @param traderImageName Filename of the trader icon to use
|
||||
@ -19,7 +20,7 @@ export class TraderHelper
|
||||
{
|
||||
// Reference the mod "res" folder
|
||||
const imageFilepath = `./${preAkiModLoader.getModPath(modName)}res`;
|
||||
|
||||
|
||||
// Register a route to point to the profile picture - remember to remove the .jpg from it
|
||||
imageRouter.addRoute(baseJson.avatar.replace(".jpg", ""), `${imageFilepath}/${traderImageName}`);
|
||||
}
|
||||
@ -38,8 +39,9 @@ export class TraderHelper
|
||||
traderId: baseJson._id,
|
||||
seconds: {
|
||||
min: refreshTimeSecondsMin,
|
||||
max: refreshTimeSecondsMax
|
||||
} };
|
||||
max: refreshTimeSecondsMax,
|
||||
},
|
||||
};
|
||||
|
||||
traderConfig.updateTime.push(traderRefreshRecord);
|
||||
}
|
||||
@ -60,15 +62,13 @@ export class TraderHelper
|
||||
questassort: {
|
||||
started: {},
|
||||
success: {},
|
||||
fail: {}
|
||||
} // questassort is empty as trader has no assorts unlocked by quests
|
||||
fail: {},
|
||||
}, // questassort is empty as trader has no assorts unlocked by quests
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create basic data for trader + add empty assorts table for trader
|
||||
* @param tables SPT db
|
||||
* @param jsonUtil SPT JSON utility class
|
||||
* @returns ITraderAssort
|
||||
*/
|
||||
private createAssortTable(): ITraderAssort
|
||||
@ -78,8 +78,8 @@ export class TraderHelper
|
||||
nextResupply: 0,
|
||||
items: [],
|
||||
barter_scheme: {},
|
||||
loyal_level_items: {}
|
||||
}
|
||||
loyal_level_items: {},
|
||||
};
|
||||
|
||||
return assortTable;
|
||||
}
|
||||
@ -96,7 +96,7 @@ export class TraderHelper
|
||||
// Add the base 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)
|
||||
_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
|
||||
@ -104,7 +104,7 @@ export class TraderHelper
|
||||
_id: "glockbarrel",
|
||||
_tpl: "5a6b60158dc32e000a31138b",
|
||||
parentId: "glockBase", // 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 'role' they have
|
||||
});
|
||||
|
||||
// Add reciever
|
||||
@ -112,7 +112,7 @@ export class TraderHelper
|
||||
_id: "glockReciever",
|
||||
_tpl:"5a9685b1a2750c0032157104",
|
||||
parentId: "glockBase",
|
||||
slotId: "mod_reciever"
|
||||
slotId: "mod_reciever",
|
||||
});
|
||||
|
||||
// Add compensator
|
||||
@ -120,7 +120,7 @@ export class TraderHelper
|
||||
_id: "glockCompensator",
|
||||
_tpl:"5a7b32a2e899ef00135e345a",
|
||||
parentId: "glockReciever", // 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
|
||||
@ -128,7 +128,7 @@ export class TraderHelper
|
||||
_id: "glockPistolGrip",
|
||||
_tpl:"5a7b4960e899ef197b331a2d",
|
||||
parentId: "glockBase",
|
||||
slotId: "mod_pistol_grip"
|
||||
slotId: "mod_pistol_grip",
|
||||
});
|
||||
|
||||
// Add front sight
|
||||
@ -136,7 +136,7 @@ export class TraderHelper
|
||||
_id: "glockRearSight",
|
||||
_tpl: "5a6f5d528dc32e00094b97d9",
|
||||
parentId: "glockReciever",
|
||||
slotId: "mod_sight_rear"
|
||||
slotId: "mod_sight_rear",
|
||||
});
|
||||
|
||||
// Add rear sight
|
||||
@ -144,7 +144,7 @@ export class TraderHelper
|
||||
_id: "glockFrontSight",
|
||||
_tpl: "5a6f58f68dc32e000a311390",
|
||||
parentId: "glockReciever",
|
||||
slotId: "mod_sight_front"
|
||||
slotId: "mod_sight_front",
|
||||
});
|
||||
|
||||
// Add magazine
|
||||
@ -152,7 +152,7 @@ export class TraderHelper
|
||||
_id: "glockMagazine",
|
||||
_tpl: "630769c4962d0247b029dc60",
|
||||
parentId: "glockBase",
|
||||
slotId: "mod_magazine"
|
||||
slotId: "mod_magazine",
|
||||
});
|
||||
|
||||
return glock;
|
||||
@ -171,7 +171,8 @@ export class TraderHelper
|
||||
public addTraderToLocales(baseJson: any, tables: IDatabaseTables, fullName: string, firstName: string, nickName: string, location: string, description: string)
|
||||
{
|
||||
// For each language, add locale for the new trader
|
||||
const locales = Object.values(tables.locales.global) as Record<string, string>[];
|
||||
const locales = Object.values(tables.locales.global);
|
||||
|
||||
for (const locale of locales) {
|
||||
locale[`${baseJson._id} FullName`] = fullName;
|
||||
locale[`${baseJson._id} FirstName`] = firstName;
|
||||
@ -180,4 +181,4 @@ export class TraderHelper
|
||||
locale[`${baseJson._id} Description`] = description;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,8 +11,8 @@
|
||||
"resolveJsonModule": true,
|
||||
"outDir": "tmp",
|
||||
"paths": {
|
||||
"@spt-aki/*": [ "./types/*" ],
|
||||
"@spt-aki/*": ["./types/*"],
|
||||
},
|
||||
},
|
||||
"exclude": [ "node_modules", "dist", "tmp" ],
|
||||
}
|
||||
"exclude": ["node_modules", "dist", "tmp"],
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
# Exclude these folders from linting
|
||||
node_modules
|
||||
dist/
|
||||
types/
|
||||
**/node_modules
|
||||
/tmp
|
||||
/dist
|
||||
/types
|
||||
|
||||
# Exclude these filetypes from linting
|
||||
*.json
|
||||
*.txt
|
||||
*.exe
|
||||
*.exe
|
||||
|
@ -95,4 +95,4 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ Some resources to get you started:
|
||||
|
||||
## **Coding Guidelines**
|
||||
|
||||
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"license"`, `"author"`, and `"akiVersion"`.
|
||||
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"akiVersion"`, `"loadBefore"`, `"loadAfter"`, `"incompatibilities"`, `"isBundleMod"`, `"author"`, and `"license"`.
|
||||
|
||||
New to Typescript? Find comprehensive documentation on the [official website](https://www.typescriptlang.org/docs/).
|
||||
|
||||
|
@ -29,11 +29,10 @@
|
||||
* @version v1.0.0
|
||||
*/
|
||||
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import fs from "fs-extra";
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { dirname } from "path";
|
||||
import ignore from "ignore";
|
||||
import archiver from "archiver";
|
||||
import winston from "winston";
|
||||
@ -165,7 +164,7 @@ async function main() {
|
||||
* @returns {string} The absolute path of the current working directory.
|
||||
*/
|
||||
function getCurrentDirectory() {
|
||||
return dirname(fileURLToPath(import.meta.url));
|
||||
return path.dirname(fileURLToPath(import.meta.url));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -225,10 +224,9 @@ function createProjectName(packageJson) {
|
||||
// Remove any non-alphanumeric characters from the author and name.
|
||||
const author = packageJson.author.replace(/\W/g, "");
|
||||
const name = packageJson.name.replace(/\W/g, "");
|
||||
const version = packageJson.version;
|
||||
|
||||
// Ensure the name is lowercase, as per the package.json specification.
|
||||
return `${author}-${name}-${version}`.toLowerCase();
|
||||
return `${author}-${name}`.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,12 +1,13 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint"
|
||||
]
|
||||
}
|
||||
}
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"refringe.spt-id-highlighter"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,12 @@
|
||||
{
|
||||
"name": "AfterDBLoadHook",
|
||||
"version": "1.0.0",
|
||||
"main": "src/mod.js",
|
||||
"license": "MIT",
|
||||
"author": "Chomp",
|
||||
"akiVersion": "~3.9",
|
||||
"loadBefore": [],
|
||||
"loadAfter": [],
|
||||
"incompatibilities": [],
|
||||
"contributors": [],
|
||||
"loadBefore": [],
|
||||
"loadAfter": [],
|
||||
"incompatibilities": [],
|
||||
"isBundleMod": false,
|
||||
"main": "src/mod.js",
|
||||
"scripts": {
|
||||
"setup": "npm i",
|
||||
"build": "node ./build.mjs",
|
||||
@ -22,9 +20,11 @@
|
||||
"eslint": "8.57",
|
||||
"fs-extra": "11.2",
|
||||
"ignore": "^5.2",
|
||||
"os": "^0.1",
|
||||
"tsyringe": "4.8.0",
|
||||
"typescript": "5.4",
|
||||
"winston": "3.12"
|
||||
}
|
||||
},
|
||||
"author": "Chomp",
|
||||
"contributors": [],
|
||||
"license": "MIT"
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ class Mod implements IPreAkiLoadMod, IPostAkiLoadMod, IPostDBLoadMod
|
||||
const logger = container.resolve<ILogger>("WinstonLogger");
|
||||
logger.logWithColor(`Database item table state: ${databaseServer.getTables().templates} (<<< should be undefined)`, LogTextColor.RED, LogBackgroundColor.YELLOW);
|
||||
}
|
||||
|
||||
|
||||
public postDBLoad(container: DependencyContainer): void {
|
||||
// Database will be loaded, this is the fresh state of the DB so NOTHING from the AKI
|
||||
// logic has modified anything yet. This is the DB loaded straight from the JSON files
|
||||
@ -25,7 +25,7 @@ class Mod implements IPreAkiLoadMod, IPostAkiLoadMod, IPostDBLoadMod
|
||||
const logger = container.resolve<ILogger>("WinstonLogger");
|
||||
logger.logWithColor(`Database item size: ${Object.entries(databaseServer.getTables().templates.items).length}`, LogTextColor.RED, LogBackgroundColor.YELLOW);
|
||||
// lets do a quick modification and see how this reflect later on, on the postAkiLoad()
|
||||
|
||||
|
||||
// find the nvgs item by its Id
|
||||
const nvgs = databaseServer.getTables().templates.items["5c0558060db834001b735271"];
|
||||
// Lets log the state before the modification:
|
||||
@ -47,4 +47,4 @@ class Mod implements IPreAkiLoadMod, IPostAkiLoadMod, IPostDBLoadMod
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { mod: new Mod() }
|
||||
export const mod = new Mod();
|
||||
|
@ -11,8 +11,8 @@
|
||||
"resolveJsonModule": true,
|
||||
"outDir": "tmp",
|
||||
"paths": {
|
||||
"@spt-aki/*": [ "./types/*" ],
|
||||
"@spt-aki/*": ["./types/*"],
|
||||
},
|
||||
},
|
||||
"exclude": [ "node_modules", "dist", "tmp" ],
|
||||
}
|
||||
"exclude": ["node_modules", "dist", "tmp"],
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
# Exclude these folders from linting
|
||||
node_modules
|
||||
dist/
|
||||
types/
|
||||
**/node_modules
|
||||
/tmp
|
||||
/dist
|
||||
/types
|
||||
|
||||
# Exclude these filetypes from linting
|
||||
*.json
|
||||
*.txt
|
||||
*.exe
|
||||
*.exe
|
||||
|
@ -95,4 +95,4 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ Some resources to get you started:
|
||||
|
||||
## **Coding Guidelines**
|
||||
|
||||
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"license"`, `"author"`, and `"akiVersion"`.
|
||||
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"akiVersion"`, `"loadBefore"`, `"loadAfter"`, `"incompatibilities"`, `"isBundleMod"`, `"author"`, and `"license"`.
|
||||
|
||||
New to Typescript? Find comprehensive documentation on the [official website](https://www.typescriptlang.org/docs/).
|
||||
|
||||
|
@ -29,11 +29,10 @@
|
||||
* @version v1.0.0
|
||||
*/
|
||||
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import fs from "fs-extra";
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { dirname } from "path";
|
||||
import ignore from "ignore";
|
||||
import archiver from "archiver";
|
||||
import winston from "winston";
|
||||
@ -165,7 +164,7 @@ async function main() {
|
||||
* @returns {string} The absolute path of the current working directory.
|
||||
*/
|
||||
function getCurrentDirectory() {
|
||||
return dirname(fileURLToPath(import.meta.url));
|
||||
return path.dirname(fileURLToPath(import.meta.url));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -225,10 +224,9 @@ function createProjectName(packageJson) {
|
||||
// Remove any non-alphanumeric characters from the author and name.
|
||||
const author = packageJson.author.replace(/\W/g, "");
|
||||
const name = packageJson.name.replace(/\W/g, "");
|
||||
const version = packageJson.version;
|
||||
|
||||
// Ensure the name is lowercase, as per the package.json specification.
|
||||
return `${author}-${name}-${version}`.toLowerCase();
|
||||
return `${author}-${name}`.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,12 +1,13 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint"
|
||||
]
|
||||
}
|
||||
}
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"refringe.spt-id-highlighter"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,12 @@
|
||||
{
|
||||
"name": "HttpListenerExample",
|
||||
"version": "1.0.0",
|
||||
"main": "src/mod.js",
|
||||
"license": "MIT",
|
||||
"author": "Alex",
|
||||
"akiVersion": "~3.9",
|
||||
"loadBefore": [],
|
||||
"loadAfter": [],
|
||||
"incompatibilities": [],
|
||||
"contributors": [],
|
||||
"loadBefore": [],
|
||||
"loadAfter": [],
|
||||
"incompatibilities": [],
|
||||
"isBundleMod": false,
|
||||
"main": "src/mod.js",
|
||||
"scripts": {
|
||||
"setup": "npm i",
|
||||
"build": "node ./build.mjs",
|
||||
@ -22,9 +20,11 @@
|
||||
"eslint": "8.57",
|
||||
"fs-extra": "11.2",
|
||||
"ignore": "^5.2",
|
||||
"os": "^0.1",
|
||||
"tsyringe": "4.8.0",
|
||||
"typescript": "5.4",
|
||||
"winston": "3.12"
|
||||
}
|
||||
},
|
||||
"author": "clodan",
|
||||
"contributors": [],
|
||||
"license": "MIT"
|
||||
}
|
||||
|
@ -1,16 +1,17 @@
|
||||
import { IncomingMessage, ServerResponse } from "node:http";
|
||||
|
||||
import { IHttpListener } from "@spt-aki/servers/http/IHttpListener";
|
||||
import { IncomingMessage, ServerResponse } from "http";
|
||||
|
||||
export class Type2HttpListener implements IHttpListener
|
||||
{
|
||||
public canHandle(sessionId: string, req: IncomingMessage): boolean
|
||||
public canHandle(sessionId: string, req: IncomingMessage): boolean
|
||||
{
|
||||
return req.method === "GET" && req.url?.includes("/type2-custom-url");
|
||||
}
|
||||
public handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void
|
||||
|
||||
public async handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): Promise<void>
|
||||
{
|
||||
resp.writeHead(200, "OK");
|
||||
resp.end("[2] This is the second example of a mod hooking into the HttpServer");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,14 @@
|
||||
import { IncomingMessage, ServerResponse } from "node:http";
|
||||
import { DependencyContainer } from "tsyringe";
|
||||
|
||||
import { IPreAkiLoadMod } from "@spt-aki/models/external/IPreAkiLoadMod";
|
||||
import { HttpListenerModService } from "@spt-aki/services/mod/httpListener/HttpListenerModService";
|
||||
import { IncomingMessage, ServerResponse } from "http";
|
||||
import { Type2HttpListener } from "./Type2HttpListener";
|
||||
|
||||
class Mod implements IPreAkiLoadMod
|
||||
{
|
||||
// Code added here will load BEFORE the server has started loading
|
||||
public preAkiLoad(container: DependencyContainer): void
|
||||
public preAkiLoad(container: DependencyContainer): void
|
||||
{
|
||||
const httpListenerService = container.resolve<HttpListenerModService>("HttpListenerModService");
|
||||
httpListenerService.registerHttpListener("Type1HttpListener", this.canHandleOverride, this.handleOverride)
|
||||
@ -28,4 +29,4 @@ class Mod implements IPreAkiLoadMod
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { mod: new Mod() }
|
||||
export const mod = new Mod();
|
||||
|
@ -11,8 +11,8 @@
|
||||
"resolveJsonModule": true,
|
||||
"outDir": "tmp",
|
||||
"paths": {
|
||||
"@spt-aki/*": [ "./types/*" ],
|
||||
"@spt-aki/*": ["./types/*"],
|
||||
},
|
||||
},
|
||||
"exclude": [ "node_modules", "dist", "tmp" ],
|
||||
}
|
||||
"exclude": ["node_modules", "dist", "tmp"],
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
# Exclude these folders from linting
|
||||
node_modules
|
||||
dist/
|
||||
types/
|
||||
**/node_modules
|
||||
/tmp
|
||||
/dist
|
||||
/types
|
||||
|
||||
# Exclude these filetypes from linting
|
||||
*.json
|
||||
*.txt
|
||||
*.exe
|
||||
*.exe
|
||||
|
@ -95,4 +95,4 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ Some resources to get you started:
|
||||
|
||||
## **Coding Guidelines**
|
||||
|
||||
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"license"`, `"author"`, and `"akiVersion"`.
|
||||
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"akiVersion"`, `"loadBefore"`, `"loadAfter"`, `"incompatibilities"`, `"isBundleMod"`, `"author"`, and `"license"`.
|
||||
|
||||
New to Typescript? Find comprehensive documentation on the [official website](https://www.typescriptlang.org/docs/).
|
||||
|
||||
|
@ -29,11 +29,10 @@
|
||||
* @version v1.0.0
|
||||
*/
|
||||
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import fs from "fs-extra";
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { dirname } from "path";
|
||||
import ignore from "ignore";
|
||||
import archiver from "archiver";
|
||||
import winston from "winston";
|
||||
@ -165,7 +164,7 @@ async function main() {
|
||||
* @returns {string} The absolute path of the current working directory.
|
||||
*/
|
||||
function getCurrentDirectory() {
|
||||
return dirname(fileURLToPath(import.meta.url));
|
||||
return path.dirname(fileURLToPath(import.meta.url));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -225,10 +224,9 @@ function createProjectName(packageJson) {
|
||||
// Remove any non-alphanumeric characters from the author and name.
|
||||
const author = packageJson.author.replace(/\W/g, "");
|
||||
const name = packageJson.name.replace(/\W/g, "");
|
||||
const version = packageJson.version;
|
||||
|
||||
// Ensure the name is lowercase, as per the package.json specification.
|
||||
return `${author}-${name}-${version}`.toLowerCase();
|
||||
return `${author}-${name}`.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,3 +1,3 @@
|
||||
{
|
||||
"myProperty": "wow"
|
||||
}
|
||||
"myProperty": "wow"
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
{
|
||||
"myProperty": "wow inside db"
|
||||
}
|
||||
"myProperty": "wow inside db"
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
{
|
||||
"myProperty": "wow inside db inside moredb"
|
||||
}
|
||||
"myProperty": "wow inside db inside moredb"
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint"
|
||||
]
|
||||
}
|
||||
}
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"refringe.spt-id-highlighter"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,12 @@
|
||||
{
|
||||
"name": "ImporterUtil",
|
||||
"version": "1.0.0",
|
||||
"main": "src/mod.js",
|
||||
"license": "MIT",
|
||||
"author": "Chomp",
|
||||
"akiVersion": "~3.9",
|
||||
"loadBefore": [],
|
||||
"loadAfter": [],
|
||||
"incompatibilities": [],
|
||||
"contributors": [],
|
||||
"loadBefore": [],
|
||||
"loadAfter": [],
|
||||
"incompatibilities": [],
|
||||
"isBundleMod": false,
|
||||
"main": "src/mod.js",
|
||||
"scripts": {
|
||||
"setup": "npm i",
|
||||
"build": "node ./build.mjs",
|
||||
@ -22,9 +20,11 @@
|
||||
"eslint": "8.57",
|
||||
"fs-extra": "11.2",
|
||||
"ignore": "^5.2",
|
||||
"os": "^0.1",
|
||||
"tsyringe": "4.8.0",
|
||||
"typescript": "5.4",
|
||||
"winston": "3.12"
|
||||
}
|
||||
},
|
||||
"author": "Chomp",
|
||||
"contributors": [],
|
||||
"license": "MIT"
|
||||
}
|
||||
|
@ -1,25 +1,26 @@
|
||||
import { DependencyContainer } from "tsyringe";
|
||||
|
||||
import { PreAkiModLoader } from "@spt-aki/loaders/PreAkiModLoader";
|
||||
import { IPreAkiLoadMod } from "@spt-aki/models/external/IPreAkiLoadMod";
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { ImporterUtil } from "@spt-aki/utils/ImporterUtil";
|
||||
import { DependencyContainer } from "tsyringe";
|
||||
import { ConfigsModelBase } from "./model/ConfigsModel";
|
||||
|
||||
class Mod implements IPreAkiLoadMod {
|
||||
public preAkiLoad(container: DependencyContainer): void {
|
||||
// get logger
|
||||
const logger = container.resolve<ILogger>("WinstonLogger");
|
||||
public preAkiLoad(container: DependencyContainer): void {
|
||||
// get logger
|
||||
const logger = container.resolve<ILogger>("WinstonLogger");
|
||||
|
||||
const importerUtil = container.resolve<ImporterUtil>("ImporterUtil");
|
||||
const modImporter = container.resolve<PreAkiModLoader>("PreAkiModLoader");
|
||||
const path = modImporter.getModPath("16ImporterUtil");
|
||||
const importerUtil = container.resolve<ImporterUtil>("ImporterUtil");
|
||||
const modImporter = container.resolve<PreAkiModLoader>("PreAkiModLoader");
|
||||
const path = modImporter.getModPath("16ImporterUtil");
|
||||
|
||||
const configPath = `${path}config/`;
|
||||
const configs = importerUtil.loadRecursive<ConfigsModelBase>(configPath);
|
||||
logger.info(
|
||||
`16ImporterUtil Configurations found: ${JSON.stringify(configs)}`,
|
||||
);
|
||||
}
|
||||
const configPath = `${path}config/`;
|
||||
const configs = importerUtil.loadRecursive<ConfigsModelBase>(configPath);
|
||||
logger.info(
|
||||
`16ImporterUtil Configurations found: ${JSON.stringify(configs)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { mod: new Mod() };
|
||||
export const mod = new Mod();
|
||||
|
@ -1,17 +1,17 @@
|
||||
export class ConfigsModelBase {
|
||||
db: ConfigsModelDb;
|
||||
config: ConfigModel;
|
||||
db: ConfigsModelDb;
|
||||
config: ConfigModel;
|
||||
}
|
||||
|
||||
export class ConfigsModelDb {
|
||||
moredb: ConfigsModelMoreDb;
|
||||
config: ConfigModel;
|
||||
moredb: ConfigsModelMoreDb;
|
||||
config: ConfigModel;
|
||||
}
|
||||
|
||||
export class ConfigsModelMoreDb {
|
||||
config: ConfigModel;
|
||||
config: ConfigModel;
|
||||
}
|
||||
|
||||
export class ConfigModel {
|
||||
myProperty: string;
|
||||
myProperty: string;
|
||||
}
|
||||
|
@ -11,8 +11,8 @@
|
||||
"resolveJsonModule": true,
|
||||
"outDir": "tmp",
|
||||
"paths": {
|
||||
"@spt-aki/*": [ "./types/*" ],
|
||||
"@spt-aki/*": ["./types/*"],
|
||||
},
|
||||
},
|
||||
"exclude": [ "node_modules", "dist", "tmp" ],
|
||||
}
|
||||
"exclude": ["node_modules", "dist", "tmp"],
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
# Exclude these folders from linting
|
||||
node_modules
|
||||
dist/
|
||||
types/
|
||||
**/node_modules
|
||||
/tmp
|
||||
/dist
|
||||
/types
|
||||
|
||||
# Exclude these filetypes from linting
|
||||
*.json
|
||||
*.txt
|
||||
*.exe
|
||||
*.exe
|
||||
|
@ -95,4 +95,4 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ Some resources to get you started:
|
||||
|
||||
## **Coding Guidelines**
|
||||
|
||||
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"license"`, `"author"`, and `"akiVersion"`.
|
||||
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"akiVersion"`, `"loadBefore"`, `"loadAfter"`, `"incompatibilities"`, `"isBundleMod"`, `"author"`, and `"license"`.
|
||||
|
||||
New to Typescript? Find comprehensive documentation on the [official website](https://www.typescriptlang.org/docs/).
|
||||
|
||||
|
@ -29,11 +29,10 @@
|
||||
* @version v1.0.0
|
||||
*/
|
||||
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import fs from "fs-extra";
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { dirname } from "path";
|
||||
import ignore from "ignore";
|
||||
import archiver from "archiver";
|
||||
import winston from "winston";
|
||||
@ -165,7 +164,7 @@ async function main() {
|
||||
* @returns {string} The absolute path of the current working directory.
|
||||
*/
|
||||
function getCurrentDirectory() {
|
||||
return dirname(fileURLToPath(import.meta.url));
|
||||
return path.dirname(fileURLToPath(import.meta.url));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -225,10 +224,9 @@ function createProjectName(packageJson) {
|
||||
// Remove any non-alphanumeric characters from the author and name.
|
||||
const author = packageJson.author.replace(/\W/g, "");
|
||||
const name = packageJson.name.replace(/\W/g, "");
|
||||
const version = packageJson.version;
|
||||
|
||||
// Ensure the name is lowercase, as per the package.json specification.
|
||||
return `${author}-${name}-${version}`.toLowerCase();
|
||||
return `${author}-${name}`.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,3 +1,3 @@
|
||||
{
|
||||
"myProperty": "wow"
|
||||
}
|
||||
"myProperty": "wow"
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
{
|
||||
"myProperty": "wow inside db"
|
||||
}
|
||||
"myProperty": "wow inside db"
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
{
|
||||
"myProperty": "wow inside db inside moredb"
|
||||
}
|
||||
"myProperty": "wow inside db inside moredb"
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint"
|
||||
]
|
||||
}
|
||||
}
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"refringe.spt-id-highlighter"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,20 @@
|
||||
{
|
||||
"name": "AsyncWithDependency1",
|
||||
"version": "1.0.0",
|
||||
"main": "src/mod.js",
|
||||
"license": "MIT",
|
||||
"author": "Chomp",
|
||||
"akiVersion": "~3.9",
|
||||
"loadBefore": [],
|
||||
"loadAfter": [],
|
||||
"incompatibilities": [],
|
||||
"contributors": [],
|
||||
"modDependencies": {
|
||||
"17AsyncImporterWithDependency2": "~1"
|
||||
},
|
||||
"loadBefore": [],
|
||||
"loadAfter": [],
|
||||
"incompatibilities": [],
|
||||
"isBundleMod": false,
|
||||
"main": "src/mod.js",
|
||||
"scripts": {
|
||||
"setup": "npm i",
|
||||
"build": "node ./build.mjs",
|
||||
"buildinfo": "node ./build.mjs --verbose"
|
||||
},
|
||||
"modDependencies": {
|
||||
"17AsyncImporterWithDependency2": "~1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "20.11",
|
||||
"@typescript-eslint/eslint-plugin": "7.2",
|
||||
@ -25,9 +23,11 @@
|
||||
"eslint": "8.57",
|
||||
"fs-extra": "11.2",
|
||||
"ignore": "^5.2",
|
||||
"os": "^0.1",
|
||||
"tsyringe": "4.8.0",
|
||||
"typescript": "5.4",
|
||||
"winston": "3.12"
|
||||
}
|
||||
},
|
||||
"author": "Chomp",
|
||||
"contributors": [],
|
||||
"license": "MIT"
|
||||
}
|
||||
|
@ -1,30 +1,31 @@
|
||||
import { DependencyContainer } from "tsyringe";
|
||||
|
||||
import { PreAkiModLoader } from "@spt-aki/loaders/PreAkiModLoader";
|
||||
import { IPreAkiLoadModAsync } from "@spt-aki/models/external/IPreAkiLoadModAsync";
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { ImporterUtil } from "@spt-aki/utils/ImporterUtil";
|
||||
import { DependencyContainer } from "tsyringe";
|
||||
import { ConfigsModelBase } from "./model/ConfigsModel";
|
||||
|
||||
class Mod implements IPreAkiLoadModAsync {
|
||||
public async preAkiLoadAsync(container: DependencyContainer): Promise<void> {
|
||||
// get logger
|
||||
const logger = container.resolve<ILogger>("WinstonLogger");
|
||||
public async preAkiLoadAsync(container: DependencyContainer): Promise<void> {
|
||||
// get logger
|
||||
const logger = container.resolve<ILogger>("WinstonLogger");
|
||||
|
||||
const importerUtil = container.resolve<ImporterUtil>("ImporterUtil");
|
||||
const modImporter = container.resolve<PreAkiModLoader>("PreAkiModLoader");
|
||||
const path = modImporter.getModPath("16ImporterUtil");
|
||||
const importerUtil = container.resolve<ImporterUtil>("ImporterUtil");
|
||||
const modImporter = container.resolve<PreAkiModLoader>("PreAkiModLoader");
|
||||
const path = modImporter.getModPath("16ImporterUtil");
|
||||
|
||||
const configPath = `${path}config/`;
|
||||
return importerUtil
|
||||
.loadAsync<ConfigsModelBase>(configPath)
|
||||
.then((configs) => {
|
||||
logger.info(
|
||||
`17ImporterWithDependency1 Configurations found: ${JSON.stringify(
|
||||
configs,
|
||||
)}`,
|
||||
);
|
||||
});
|
||||
}
|
||||
const configPath = `${path}config/`;
|
||||
return importerUtil
|
||||
.loadAsync<ConfigsModelBase>(configPath)
|
||||
.then((configs) => {
|
||||
logger.info(
|
||||
`17ImporterWithDependency1 Configurations found: ${JSON.stringify(
|
||||
configs,
|
||||
)}`,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { mod: new Mod() };
|
||||
export const mod = new Mod();
|
||||
|
@ -1,17 +1,17 @@
|
||||
export class ConfigsModelBase {
|
||||
db: ConfigsModelDb;
|
||||
config: ConfigModel;
|
||||
db: ConfigsModelDb;
|
||||
config: ConfigModel;
|
||||
}
|
||||
|
||||
export class ConfigsModelDb {
|
||||
moredb: ConfigsModelMoreDb;
|
||||
config: ConfigModel;
|
||||
moredb: ConfigsModelMoreDb;
|
||||
config: ConfigModel;
|
||||
}
|
||||
|
||||
export class ConfigsModelMoreDb {
|
||||
config: ConfigModel;
|
||||
config: ConfigModel;
|
||||
}
|
||||
|
||||
export class ConfigModel {
|
||||
myProperty: string;
|
||||
myProperty: string;
|
||||
}
|
||||
|
@ -11,8 +11,8 @@
|
||||
"resolveJsonModule": true,
|
||||
"outDir": "tmp",
|
||||
"paths": {
|
||||
"@spt-aki/*": [ "./types/*" ],
|
||||
"@spt-aki/*": ["./types/*"],
|
||||
},
|
||||
},
|
||||
"exclude": [ "node_modules", "dist", "tmp" ],
|
||||
}
|
||||
"exclude": ["node_modules", "dist", "tmp"],
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
# Exclude these folders from linting
|
||||
node_modules
|
||||
dist/
|
||||
types/
|
||||
**/node_modules
|
||||
/tmp
|
||||
/dist
|
||||
/types
|
||||
|
||||
# Exclude these filetypes from linting
|
||||
*.json
|
||||
*.txt
|
||||
*.exe
|
||||
*.exe
|
||||
|
@ -95,4 +95,4 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ Some resources to get you started:
|
||||
|
||||
## **Coding Guidelines**
|
||||
|
||||
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"license"`, `"author"`, and `"akiVersion"`.
|
||||
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"akiVersion"`, `"loadBefore"`, `"loadAfter"`, `"incompatibilities"`, `"isBundleMod"`, `"author"`, and `"license"`.
|
||||
|
||||
New to Typescript? Find comprehensive documentation on the [official website](https://www.typescriptlang.org/docs/).
|
||||
|
||||
|
@ -29,11 +29,10 @@
|
||||
* @version v1.0.0
|
||||
*/
|
||||
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import fs from "fs-extra";
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { dirname } from "path";
|
||||
import ignore from "ignore";
|
||||
import archiver from "archiver";
|
||||
import winston from "winston";
|
||||
@ -165,7 +164,7 @@ async function main() {
|
||||
* @returns {string} The absolute path of the current working directory.
|
||||
*/
|
||||
function getCurrentDirectory() {
|
||||
return dirname(fileURLToPath(import.meta.url));
|
||||
return path.dirname(fileURLToPath(import.meta.url));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -225,10 +224,9 @@ function createProjectName(packageJson) {
|
||||
// Remove any non-alphanumeric characters from the author and name.
|
||||
const author = packageJson.author.replace(/\W/g, "");
|
||||
const name = packageJson.name.replace(/\W/g, "");
|
||||
const version = packageJson.version;
|
||||
|
||||
// Ensure the name is lowercase, as per the package.json specification.
|
||||
return `${author}-${name}-${version}`.toLowerCase();
|
||||
return `${author}-${name}`.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,3 +1,3 @@
|
||||
{
|
||||
"myProperty": "wow"
|
||||
}
|
||||
"myProperty": "wow"
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
{
|
||||
"myProperty": "wow inside db"
|
||||
}
|
||||
"myProperty": "wow inside db"
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
{
|
||||
"myProperty": "wow inside db inside moredb"
|
||||
}
|
||||
"myProperty": "wow inside db inside moredb"
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint"
|
||||
]
|
||||
}
|
||||
}
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"refringe.spt-id-highlighter"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,12 @@
|
||||
{
|
||||
"name": "AsyncWithDependency2",
|
||||
"version": "1.0.0",
|
||||
"main": "src/mod.js",
|
||||
"license": "MIT",
|
||||
"author": "Chomp",
|
||||
"akiVersion": "~3.9",
|
||||
"loadBefore": [],
|
||||
"loadAfter": [],
|
||||
"incompatibilities": [],
|
||||
"contributors": [],
|
||||
"loadBefore": [],
|
||||
"loadAfter": [],
|
||||
"incompatibilities": [],
|
||||
"isBundleMod": false,
|
||||
"main": "src/mod.js",
|
||||
"scripts": {
|
||||
"setup": "npm i",
|
||||
"build": "node ./build.mjs",
|
||||
@ -22,9 +20,11 @@
|
||||
"eslint": "8.57",
|
||||
"fs-extra": "11.2",
|
||||
"ignore": "^5.2",
|
||||
"os": "^0.1",
|
||||
"tsyringe": "4.8.0",
|
||||
"typescript": "5.4",
|
||||
"winston": "3.12"
|
||||
}
|
||||
},
|
||||
"author": "Chomp",
|
||||
"contributors": [],
|
||||
"license": "MIT"
|
||||
}
|
||||
|
@ -1,30 +1,31 @@
|
||||
import { DependencyContainer } from "tsyringe";
|
||||
|
||||
import { PreAkiModLoader } from "@spt-aki/loaders/PreAkiModLoader";
|
||||
import { IPreAkiLoadModAsync } from "@spt-aki/models/external/IPreAkiLoadModAsync";
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { ImporterUtil } from "@spt-aki/utils/ImporterUtil";
|
||||
import { DependencyContainer } from "tsyringe";
|
||||
import { ConfigsModelBase } from "./model/ConfigsModel";
|
||||
|
||||
class Mod implements IPreAkiLoadModAsync {
|
||||
public async preAkiLoadAsync(container: DependencyContainer): Promise<void> {
|
||||
// get logger
|
||||
const logger = container.resolve<ILogger>("WinstonLogger");
|
||||
public async preAkiLoadAsync(container: DependencyContainer): Promise<void> {
|
||||
// get logger
|
||||
const logger = container.resolve<ILogger>("WinstonLogger");
|
||||
|
||||
const importerUtil = container.resolve<ImporterUtil>("ImporterUtil");
|
||||
const modImporter = container.resolve<PreAkiModLoader>("PreAkiModLoader");
|
||||
const path = modImporter.getModPath("16ImporterUtil");
|
||||
const importerUtil = container.resolve<ImporterUtil>("ImporterUtil");
|
||||
const modImporter = container.resolve<PreAkiModLoader>("PreAkiModLoader");
|
||||
const path = modImporter.getModPath("16ImporterUtil");
|
||||
|
||||
const configPath = `${path}config/`;
|
||||
return importerUtil
|
||||
.loadAsync<ConfigsModelBase>(configPath)
|
||||
.then((configs) => {
|
||||
logger.info(
|
||||
`17ImporterWithDependency2 Configurations found: ${JSON.stringify(
|
||||
configs,
|
||||
)}`,
|
||||
);
|
||||
});
|
||||
}
|
||||
const configPath = `${path}config/`;
|
||||
return importerUtil
|
||||
.loadAsync<ConfigsModelBase>(configPath)
|
||||
.then((configs) => {
|
||||
logger.info(
|
||||
`17ImporterWithDependency2 Configurations found: ${JSON.stringify(
|
||||
configs,
|
||||
)}`,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { mod: new Mod() };
|
||||
export const mod = new Mod();
|
||||
|
@ -1,17 +1,17 @@
|
||||
export class ConfigsModelBase {
|
||||
db: ConfigsModelDb;
|
||||
config: ConfigModel;
|
||||
db: ConfigsModelDb;
|
||||
config: ConfigModel;
|
||||
}
|
||||
|
||||
export class ConfigsModelDb {
|
||||
moredb: ConfigsModelMoreDb;
|
||||
config: ConfigModel;
|
||||
moredb: ConfigsModelMoreDb;
|
||||
config: ConfigModel;
|
||||
}
|
||||
|
||||
export class ConfigsModelMoreDb {
|
||||
config: ConfigModel;
|
||||
config: ConfigModel;
|
||||
}
|
||||
|
||||
export class ConfigModel {
|
||||
myProperty: string;
|
||||
myProperty: string;
|
||||
}
|
||||
|
@ -11,8 +11,8 @@
|
||||
"resolveJsonModule": true,
|
||||
"outDir": "tmp",
|
||||
"paths": {
|
||||
"@spt-aki/*": [ "./types/*" ],
|
||||
"@spt-aki/*": ["./types/*"],
|
||||
},
|
||||
},
|
||||
"exclude": [ "node_modules", "dist", "tmp" ],
|
||||
}
|
||||
"exclude": ["node_modules", "dist", "tmp"],
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
# Exclude these folders from linting
|
||||
node_modules
|
||||
dist/
|
||||
types/
|
||||
**/node_modules
|
||||
/tmp
|
||||
/dist
|
||||
/types
|
||||
|
||||
# Exclude these filetypes from linting
|
||||
*.json
|
||||
*.txt
|
||||
*.exe
|
||||
*.exe
|
||||
|
@ -95,4 +95,4 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ Some resources to get you started:
|
||||
|
||||
## **Coding Guidelines**
|
||||
|
||||
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"license"`, `"author"`, and `"akiVersion"`.
|
||||
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"akiVersion"`, `"loadBefore"`, `"loadAfter"`, `"incompatibilities"`, `"isBundleMod"`, `"author"`, and `"license"`.
|
||||
|
||||
New to Typescript? Find comprehensive documentation on the [official website](https://www.typescriptlang.org/docs/).
|
||||
|
||||
|
@ -29,11 +29,10 @@
|
||||
* @version v1.0.0
|
||||
*/
|
||||
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import fs from "fs-extra";
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { dirname } from "path";
|
||||
import ignore from "ignore";
|
||||
import archiver from "archiver";
|
||||
import winston from "winston";
|
||||
@ -165,7 +164,7 @@ async function main() {
|
||||
* @returns {string} The absolute path of the current working directory.
|
||||
*/
|
||||
function getCurrentDirectory() {
|
||||
return dirname(fileURLToPath(import.meta.url));
|
||||
return path.dirname(fileURLToPath(import.meta.url));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -225,10 +224,9 @@ function createProjectName(packageJson) {
|
||||
// Remove any non-alphanumeric characters from the author and name.
|
||||
const author = packageJson.author.replace(/\W/g, "");
|
||||
const name = packageJson.name.replace(/\W/g, "");
|
||||
const version = packageJson.version;
|
||||
|
||||
// Ensure the name is lowercase, as per the package.json specification.
|
||||
return `${author}-${name}-${version}`.toLowerCase();
|
||||
return `${author}-${name}`.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,12 +1,13 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint"
|
||||
]
|
||||
}
|
||||
}
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"refringe.spt-id-highlighter"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,12 @@
|
||||
{
|
||||
"name": "CustomItemService",
|
||||
"version": "1.0.0",
|
||||
"main": "src/mod.js",
|
||||
"license": "MIT",
|
||||
"author": "Choccy",
|
||||
"akiVersion": "~3.9",
|
||||
"loadBefore": [],
|
||||
"loadAfter": [],
|
||||
"incompatibilities": [],
|
||||
"contributors": [],
|
||||
"loadBefore": [],
|
||||
"loadAfter": [],
|
||||
"incompatibilities": [],
|
||||
"isBundleMod": false,
|
||||
"main": "src/mod.js",
|
||||
"scripts": {
|
||||
"setup": "npm i",
|
||||
"build": "node ./build.mjs",
|
||||
@ -22,9 +20,11 @@
|
||||
"eslint": "8.57",
|
||||
"fs-extra": "11.2",
|
||||
"ignore": "^5.2",
|
||||
"os": "^0.1",
|
||||
"tsyringe": "4.8.0",
|
||||
"typescript": "5.4",
|
||||
"winston": "3.12"
|
||||
}
|
||||
},
|
||||
"author": "Choccy",
|
||||
"contributors": [],
|
||||
"license": "MIT"
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
|
||||
class Mod implements IPostDBLoadMod, IPostAkiLoadMod
|
||||
{
|
||||
public postDBLoad(container: DependencyContainer): void
|
||||
public postDBLoad(container: DependencyContainer): void
|
||||
{
|
||||
// Resolve the CustomItemService container
|
||||
const CustomItem = container.resolve<CustomItemService>("CustomItemService");
|
||||
@ -19,13 +19,13 @@ class Mod implements IPostDBLoadMod, IPostAkiLoadMod
|
||||
overrideProperties: {
|
||||
Chambers: [
|
||||
{
|
||||
"_name": "patron_in_weapon_000",
|
||||
"_id": "61f7c9e189e6fb1a5e3ea791",
|
||||
"_parent": "CustomMP18",
|
||||
"_props": {
|
||||
"filters": [
|
||||
_name: "patron_in_weapon_000",
|
||||
_id: "61f7c9e189e6fb1a5e3ea791",
|
||||
_parent: "CustomMP18",
|
||||
_props: {
|
||||
filters: [
|
||||
{
|
||||
"Filter": [
|
||||
Filter: [
|
||||
"560d5e524bdc2d25448b4571",
|
||||
"5d6e6772a4b936088465b17c",
|
||||
"5d6e67fba4b9361bc73bc779",
|
||||
@ -41,16 +41,16 @@ class Mod implements IPostDBLoadMod, IPostAkiLoadMod
|
||||
"5d6e68b3a4b9361bca7e50b5",
|
||||
"5d6e6891a4b9361bd473feea",
|
||||
"5d6e689ca4b9361bc8618956",
|
||||
"5d6e68d1a4b93622fe60e845"
|
||||
]
|
||||
}
|
||||
]
|
||||
"5d6e68d1a4b93622fe60e845",
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
"_required": false,
|
||||
"_mergeSlotWithChildren": false,
|
||||
"_proto": "55d4af244bdc2d962f8b4571"
|
||||
}
|
||||
]
|
||||
_required: false,
|
||||
_mergeSlotWithChildren: false,
|
||||
_proto: "55d4af244bdc2d962f8b4571",
|
||||
},
|
||||
],
|
||||
}, //Overried properties basically tell the server on what data inside _props to be modified from the cloned item, in this example i am modifying the ammo used to be 12G
|
||||
parentId: "5447b6094bdc2dc3278b4567", //ParentId refers to the Node item the gun will be under, you can check it in https://db.sp-tarkov.com/search
|
||||
newId: "CustomMP18", //The new id of our cloned item
|
||||
@ -59,22 +59,24 @@ class Mod implements IPostDBLoadMod, IPostAkiLoadMod
|
||||
handbookParentId: "5b5f78e986f77447ed5636b1", //Handbook Parent Id refers to the category the gun will be under
|
||||
//you see those side box tab thing that only select gun under specific icon? Handbook parent can be found in Aki_Data\Server\database\templates.
|
||||
locales: {
|
||||
"en": {
|
||||
en: {
|
||||
name: "MP-18 12g",
|
||||
shortName: "Custom MP18",
|
||||
description: "A custom MP18 chambered in 12G"
|
||||
}
|
||||
}
|
||||
}
|
||||
description: "A custom MP18 chambered in 12G",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
CustomItem.createItemFromClone(ExampleCloneItem); //Basically calls the function and tell the server to add our Cloned new item into the server
|
||||
}
|
||||
|
||||
//Check if our item is in the server or not
|
||||
public postAkiLoad(container: DependencyContainer): void {
|
||||
const db = container.resolve<DatabaseServer>("DatabaseServer");
|
||||
const item = db.getTables().templates.items;
|
||||
|
||||
console.log(item["CustomMP18"]._props)
|
||||
console.log(item["CustomMP18"]._props);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { mod: new Mod() }
|
||||
export const mod = new Mod();
|
||||
|
@ -11,8 +11,8 @@
|
||||
"resolveJsonModule": true,
|
||||
"outDir": "tmp",
|
||||
"paths": {
|
||||
"@spt-aki/*": [ "./types/*" ],
|
||||
"@spt-aki/*": ["./types/*"],
|
||||
},
|
||||
},
|
||||
"exclude": [ "node_modules", "dist", "tmp" ],
|
||||
}
|
||||
"exclude": ["node_modules", "dist", "tmp"],
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user