Skip to content

Commit 15e959e

Browse files
committed
Custom Item Support
Custom items can be added into the extention database by adding a `.sptids` file into your project root and adding the custom items into the file.
1 parent 4774e2b commit 15e959e

File tree

4 files changed

+148
-15
lines changed

4 files changed

+148
-15
lines changed

README.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ This extension aids in the development of the [Single Player Tarkov](https://git
44

55
## Features
66

7-
- **Hover Information**: Hover over an item ID to see the full item name or short name, depending on your settings.
7+
- **Hover Information**: Hover over a SPT ID to see additional information about the object.
88
- **Multilingual Support**: Choose from a variety of languages for item names and descriptions.
9+
- **Custom ID Support**: Add a `.sptids` file to your project to provide information on custom IDs. [Example here.](https://github.com/refringe/spt-id-highlighter/wiki/Custom-ID-Support)
910

1011
![Hover Feature Example](https://github.com/refringe/spt-id-highlighter/blob/main/images/example.gif?raw=true)
1112

@@ -18,14 +19,21 @@ This extension requires Visual Studio Code version 1.40.0 or later.
1819
This extension contributes the following settings:
1920

2021
- `spt-id-highlighter.language`: specify the language for item names and descriptions.
21-
- `spt-id-highlighter.nameType`: choose between displaying the full item name or the short name on hover.
2222

2323
## Known Issues
2424

2525
No known issues at this time.
2626

2727
## Release Notes
2828

29+
### v1.2.0
30+
31+
Updates
32+
33+
- Updated IDs for SPT v3.10
34+
- Greatly expanded the data that is available on hover
35+
- Added support for custom IDs via a `.sptids` file. [Example here.](https://github.com/refringe/spt-id-highlighter/wiki/Custom-ID-Support)
36+
2937
### v1.1.0
3038

3139
Updates
@@ -60,4 +68,4 @@ Initial release of SPT Dev Extension.
6068

6169
## License
6270

63-
This extension is licensed under the [NCSA License](LICENSE). The locale assets are provided by the [SPT-AKI project](https://dev.sp-tarkov.com/SPT-AKI/Server) and are licensed under the [NCSA License](assets/database/locales/LICENSE).
71+
This extension is licensed under the [NCSA License](LICENSE). The locale assets are provided by the [SPT project](https://github.com/sp-tarkov/server) and are licensed under the [NCSA License](assets/database/locales/LICENSE).

images/example.gif

-921 KB
Loading

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@
3434
"contributes": {
3535
"configuration": {
3636
"type": "object",
37-
"title": "SPT Dev Configuration",
37+
"title": "SPT ID Highlighter Configuration",
3838
"properties": {
39-
"spt-dev.language": {
39+
"spt-id-highlighter.language": {
4040
"type": "string",
4141
"default": "en",
4242
"description": "Language for item names and descriptions.",

src/extension.ts

Lines changed: 135 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,123 @@
1+
import * as fs from "node:fs";
2+
import * as path from "node:path";
13
import * as vscode from "vscode";
24
import { ItemDetailType, ItemDetails, Items } from "./types/Items";
35

46
export function activate(context: vscode.ExtensionContext) {
5-
console.log("The SPT Dev extension is now active.");
7+
console.log("The SPT ID Highlighter extension is now active.");
8+
9+
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
10+
const validateItemDetails = (details: any): details is ItemDetails => {
11+
const validItemKeys: Array<keyof ItemDetails> = [
12+
"Name",
13+
"ShortName",
14+
"Type",
15+
"DetailLink",
16+
"Parent",
17+
"ParentID",
18+
"ParentDetailLink",
19+
"FleaBlacklisted",
20+
"QuestItem",
21+
"Weight",
22+
"Caliber",
23+
"Damage",
24+
"ArmorDamage",
25+
"PenetrationPower",
26+
"Currency",
27+
"UnlockedByDefault",
28+
"Description",
29+
"BodyPart",
30+
"Sides",
31+
"IntegratedArmorVest",
32+
"AvailableAsDefault",
33+
"PrefabPath",
34+
"Id",
35+
"AirdropChance",
36+
"EscapeTimeLimit",
37+
"Insurance",
38+
"BossSpawns",
39+
"Trader",
40+
"TraderId",
41+
"TraderLink",
42+
"QuestType",
43+
];
44+
return Object.keys(details).every((key) => validItemKeys.includes(key as keyof ItemDetails));
45+
};
46+
47+
const getProjectRoot = (): string => {
48+
const folders = vscode.workspace.workspaceFolders;
49+
return folders && folders.length > 0 ? folders[0].uri.fsPath : "";
50+
};
51+
52+
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
53+
const loadCustomIds = (projectRoot: string): Record<string, any> => {
54+
const sptidsPath = path.join(projectRoot, ".sptids");
55+
if (!fs.existsSync(sptidsPath)) {
56+
return {};
57+
}
58+
59+
try {
60+
const rawData = fs.readFileSync(sptidsPath, "utf-8");
61+
return JSON.parse(rawData);
62+
} catch (error) {
63+
console.error(`SPT ID Highlighter: Failed to load .sptids file: ${error}`);
64+
vscode.window.showErrorMessage("SPT ID Highlighter: The .sptids file is invalid or could not be read.");
65+
return {};
66+
}
67+
};
68+
69+
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
70+
const mergeCustomItems = (baseData: Items, customData: Record<string, any>, lang: string): Items => {
71+
const mergedData = { ...baseData };
72+
73+
for (const [id, localizedData] of Object.entries(customData)) {
74+
if (localizedData[lang]) {
75+
const customDetails = localizedData[lang];
76+
if (validateItemDetails(customDetails)) {
77+
mergedData[id] = {
78+
...mergedData[id],
79+
...customDetails,
80+
};
81+
} else {
82+
console.warn(`SPT ID Highlighter: Invalid item properties for ID ${id} in .sptids.`);
83+
vscode.window.showWarningMessage(
84+
`SPT ID Highlighter: Invalid item properties for ID ${id} in .sptids.`,
85+
);
86+
}
87+
}
88+
}
89+
90+
return mergedData;
91+
};
692

793
const loadItemsData = (lang: string): Items => {
894
try {
9-
return require(`./database/${lang}.json`);
95+
const baseData = require(`./database/${lang}.json`);
96+
const projectRoot = getProjectRoot();
97+
const customData = loadCustomIds(projectRoot);
98+
return mergeCustomItems(baseData, customData, lang);
1099
} catch (error) {
11-
console.error(`Failed to load language file: ${lang}.json`, error);
12-
vscode.window.showErrorMessage(`Failed to load language data for ${lang}. Falling back to English.`);
13-
return require("./database/en.json"); // Fallback to English
100+
console.error(`SPT ID Highlighter: Failed to load language file: ${lang}.json`, error);
101+
vscode.window.showErrorMessage(
102+
`SPT ID Highlighter: Failed to load language data for ${lang}. Falling back to English.`,
103+
);
104+
return require("./database/en.json");
14105
}
15106
};
16107

17108
const loadTranslations = (lang: string): Record<string, string> => {
18109
try {
19110
return require(`./translations/${lang}.json`);
20111
} catch (error) {
21-
console.error(`Failed to load translation file: ${lang}.json`, error);
22-
vscode.window.showErrorMessage(`Failed to load translations for ${lang}. Falling back to English.`);
112+
console.error(`SPT ID Highlighter: Failed to load translation file: ${lang}.json`, error);
113+
vscode.window.showErrorMessage(
114+
`SPT ID Highlighter: Failed to load translations for ${lang}. Falling back to English.`,
115+
);
23116
return require("./translations/en.json"); // Fallback to English
24117
}
25118
};
26119

27-
let configuration = vscode.workspace.getConfiguration("spt-dev");
120+
let configuration = vscode.workspace.getConfiguration("spt-id-highlighter");
28121
let language = configuration.get("language", "en");
29122
let itemsData: Items = loadItemsData(language);
30123
let translations: Record<string, string> = loadTranslations(language);
@@ -63,10 +156,42 @@ export function activate(context: vscode.ExtensionContext) {
63156
updateDecorations();
64157
}
65158

159+
const projectRoot = getProjectRoot();
160+
if (fs.existsSync(projectRoot)) {
161+
const watcher = fs.watch(projectRoot, (eventType, filename) => {
162+
if (filename === ".sptids") {
163+
const sptidsPath = path.join(projectRoot, ".sptids");
164+
if (eventType === "rename") {
165+
// File created or deleted
166+
if (fs.existsSync(sptidsPath)) {
167+
console.log("SPT ID Highlighter: Detected .sptids creation. Reloading...");
168+
itemsData = loadItemsData(language); // Reload items data
169+
updateDecorations(); // Update decorations
170+
vscode.window.showInformationMessage("SPT ID Highlighter: Successfully loaded custom items.");
171+
} else {
172+
console.log("SPT ID Highlighter: Detected .sptids file deletion.");
173+
itemsData = loadItemsData(language); // Reload without custom items
174+
updateDecorations(); // Update decorations
175+
vscode.window.showWarningMessage("SPT ID Highlighter: Successfully unloaded custom items.");
176+
}
177+
} else if (eventType === "change") {
178+
// File updated
179+
console.log("SPT ID Highlighter: Detected .sptids file change. Reloading...");
180+
itemsData = loadItemsData(language); // Reload items data
181+
updateDecorations(); // Update decorations
182+
vscode.window.showInformationMessage("SPT ID Highlighter: Successfully reloaded custom items.");
183+
}
184+
}
185+
});
186+
context.subscriptions.push({
187+
dispose: () => watcher.close(),
188+
});
189+
}
190+
66191
context.subscriptions.push(
67192
vscode.workspace.onDidChangeConfiguration((e) => {
68-
if (e.affectsConfiguration("spt-dev.language")) {
69-
configuration = vscode.workspace.getConfiguration("spt-dev");
193+
if (e.affectsConfiguration("spt-id-highlighter.language")) {
194+
configuration = vscode.workspace.getConfiguration("spt-id-highlighter");
70195
language = configuration.get("language", "en");
71196
itemsData = loadItemsData(language);
72197
translations = loadTranslations(language);

0 commit comments

Comments
 (0)