Add example

This commit is contained in:
Chomp
2025-02-10 16:12:57 +00:00
parent cd26c6ca87
commit 3dee6318da
6 changed files with 319 additions and 11 deletions
@@ -0,0 +1,84 @@
using Core.Models.Common;
using Core.Models.Eft.Common.Tables;
using Core.Models.Spt.Config;
using Core.Models.Spt.Server;
using Core.Utils;
namespace _13AddTraderWithAssortJson
{
public class AddTraderHelper
{
/**
* Add record to trader config to set the refresh time of trader in seconds (default is 60 minutes)
* @param traderConfig trader config to add our trader to
* @param baseJson json file for trader (db/base.json)
* @param refreshTimeSecondsMin How many seconds between trader stock refresh min time
* @param refreshTimeSecondsMax How many seconds between trader stock refresh max time
*/
public void SetTraderUpdateTime(TraderConfig traderConfig, dynamic baseJson, int refreshTimeSecondsMin, int refreshTimeSecondsMax)
{
// Add refresh time in seconds to config
var traderRefreshRecord = new UpdateTime
{
TraderId = baseJson.id,
Seconds = new MinMax<int>(refreshTimeSecondsMin, refreshTimeSecondsMax)
};
traderConfig.UpdateTime.Add(traderRefreshRecord);
}
/**
* Add our new trader to the database
* @param traderDetailsToAdd trader details
* @param tables database
* @param jsonUtil json utility class
*/
public void AddTraderToDb(dynamic traderDetailsToAdd, DatabaseTables tables, JsonUtil jsonUtil, object assortJson)
{
// Create trader data ready to add to database
var traderDataToAdd = new Trader
{
Assort =
jsonUtil.Deserialize<TraderAssort>(
jsonUtil.Serialize(assortJson)), // Deserialise/serialise creates a copy of the json
Base =
jsonUtil.Deserialize<TraderBase>(
jsonUtil.Serialize(traderDetailsToAdd)), // Deserialise/serialise creates a copy of the json
QuestAssort = new Dictionary<string, Dictionary<string, string>> // questassort is empty as trader has no assorts unlocked by quests
{
{ "Started", new Dictionary<string, string>() },
{ "Success", new Dictionary<string, string>() },
{ "Fail", new Dictionary<string, string>() }
}
};
// Add trader to trader table, key is the traders id
tables.Traders.Add(traderDetailsToAdd._id, traderDataToAdd);
}
/**
* Add traders name/location/description to the locale table
* @param baseJson json file for trader (db/base.json)
* @param tables database tables
* @param fullName Complete name of trader
* @param firstName First name of trader
* @param nickName Nickname of trader
* @param location Location of trader (e.g. "Here in the cat shop")
* @param description Description of trader
*/
public void AddTraderToLocales(dynamic baseJson, DatabaseTables tables, string fullName, string firstName, string nickName, string location, string description)
{
// For each language, add locale for the new trader
var locales = tables.Locales.Global;
foreach (var (key, value) in locales) {
value.Value[$"{baseJson._id} FullName"] = fullName;
value.Value[$"{baseJson._id} FirstName"] = firstName;
value.Value[$"{baseJson._id} Nickname"] = nickName;
value.Value[$"{baseJson._id} Location"] = location;
value.Value[$"{baseJson._id} Description"] = description;
}
}
}
}
@@ -0,0 +1,86 @@
using Core.Models.Eft.Common.Tables;
using Core.Models.External;
using Core.Models.Spt.Config;
using Core.Models.Utils;
using Core.Routers;
using Core.Servers;
using Core.Services;
using Core.Utils;
namespace _13AddTraderWithAssortJson
{
public class AddTraderWithAssortJson : IPostDBLoadMod
{
private readonly ISptLogger<AddTraderWithAssortJson> _logger;
private readonly JsonUtil _jsonUtil;
private readonly FileUtil _fileUtil;
private readonly DatabaseService _databaseService;
private readonly ImageRouter _imageRouter;
private readonly ConfigServer _configServer;
private readonly TraderConfig _traderConfig;
private readonly RagfairConfig _ragfairConfig;
public AddTraderWithAssortJson(
ISptLogger<AddTraderWithAssortJson> logger,
JsonUtil jsonUtil,
FileUtil fileUtil,
DatabaseService databaseService,
ImageRouter imageRouter,
ConfigServer configServer)
{
_logger = logger;
_jsonUtil = jsonUtil;
_fileUtil = fileUtil;
_databaseService = databaseService;
_imageRouter = imageRouter;
_configServer = configServer;
_traderConfig = _configServer.GetConfig<TraderConfig>();
_ragfairConfig = _configServer.GetConfig<RagfairConfig>();
}
public void PostDBLoad()
{
var traderImagePath = "./db/cat.jpg";
var baseJson = _fileUtil.ReadFile("./db/base.json");
var traderBase = _jsonUtil.Deserialize<TraderBase>(baseJson);
var assortJson = _fileUtil.ReadFile("./db/assort.json");
var assort = _jsonUtil.Deserialize<TraderAssort>(assortJson);
// Create helper class and use it to register our traders image/icon + set its stock refresh time
var addTraderHelper = new AddTraderHelper();
_imageRouter.AddRoute(traderBase.Avatar.Replace(".jpg", ""), System.IO.Path.GetFullPath(traderImagePath));
addTraderHelper.SetTraderUpdateTime(_traderConfig, traderBase, 3600, 4000);
// Add trader to flea market
_ragfairConfig.Traders[traderBase.Id] = true;
// Add new trader to the trader dictionary in DatabaseServer - this is where the assort json is loaded
/*
* The assortJSON includes the following:
* Milk available for roubles at LL1
* Milk available for item barter at LL1
* Helmet w/ soft armour available for roubles at LL1
* Helmet w/ soft armour available for item barter at LL1
*
* It is *REQUIRED* to use MongoIDs for IDs in the assort
*/
addTraderHelper.AddTraderToDb(
baseJson,
_databaseService.GetTables(),
_jsonUtil,
assortJson);
addTraderHelper.AddTraderToLocales(
baseJson,
_databaseService.GetTables(),
traderBase.Name,
"Cat",
traderBase.Nickname,
traderBase.Location,
"This is the cat shop. Meow.");
}
}
}
@@ -1,7 +0,0 @@
namespace _13AddTraderWithAssortJson
{
public class Class1
{
}
}
@@ -0,0 +1,132 @@
{
"items": [
{
"_name": "milk",
"_id": "6751d7d0ac6207409b0823a0",
"_tpl": "575146b724597720a27126d5",
"parentId": "hideout",
"slotId": "hideout",
"upd": {
"UnlimitedCount": false,
"StackObjectsCount": 200,
"BuyRestrictionMax": 10,
"BuyRestrictionCurrent": 0
}
},
{
"_name": "milk barter",
"_id": "6751d7d0ac6207409b0823a1",
"_tpl": "575146b724597720a27126d5",
"parentId": "hideout",
"slotId": "hideout",
"upd": {
"UnlimitedCount": false,
"StackObjectsCount": 200,
"BuyRestrictionMax": 10,
"BuyRestrictionCurrent": 0
}
},
{
"_name": "helmet",
"_id": "6751d7d0ac6207409b0823a2",
"_tpl": "5b40e3f35acfc40016388218",
"parentId": "hideout",
"slotId": "hideout",
"upd": {
"UnlimitedCount": false,
"StackObjectsCount": 200,
"BuyRestrictionMax": 10,
"BuyRestrictionCurrent": 0
}
},
{
"_name": "HELMET_SOFT_ARMOUR_TOP",
"_id": "6751d7d0ac6207409b0823a3",
"_tpl": "657f95bff92cd718b701550c",
"parentId": "HELMET_ID",
"slotId": "Helmet_top"
},
{
"_name": "HELMET_SOFT_ARMOUR_BACK_ID",
"_id": "6751d7d0ac6207409b0823a4",
"_tpl": "657f9605f4c82973640b2358",
"parentId": "HELMET_ID",
"slotId": "Helmet_back"
},
{
"_name": "HELMET_ID_BARTER",
"_id": "6751d7d0ac6207409b0823a5",
"_tpl": "5b40e3f35acfc40016388218",
"parentId": "hideout",
"slotId": "hideout",
"upd": {
"UnlimitedCount": false,
"StackObjectsCount": 200,
"BuyRestrictionMax": 10,
"BuyRestrictionCurrent": 0
}
},
{
"_name": "HELMET_SOFT_ARMOUR_TOP_ID_BARTER",
"_id": "6751d7d0ac6207409b0823a5",
"_tpl": "657f95bff92cd718b701550c",
"parentId": "HELMET_ID_BARTER",
"slotId": "Helmet_top"
},
{
"_name": "HELMET_SOFT_ARMOUR_BACK_ID_BARTER",
"_id": "6751d7d0ac6207409b0823a6",
"_tpl": "657f9605f4c82973640b2358",
"parentId": "HELMET_ID_BARTER",
"slotId": "Helmet_back"
}
],
"barter_scheme": {
"6751d7d0ac6207409b0823a0": [
[
{
"count": 2000,
"_tpl": "5449016a4bdc2d6f028b456f"
}
]
],
"6751d7d0ac6207409b0823a1": [
[
{
"count": 3,
"_tpl": "59faff1d86f7746c51718c9c"
},
{
"count": 1,
"_tpl": "544fb45d4bdc2dee738b4568"
}
]
],
"6751d7d0ac6207409b0823a2": [
[
{
"count": 2000,
"_tpl": "5449016a4bdc2d6f028b456f"
}
]
],
"6751d7d0ac6207409b0823a5": [
[
{
"count": 3,
"_tpl": "59faff1d86f7746c51718c9c"
},
{
"count": 1,
"_tpl": "544fb45d4bdc2dee738b4568"
}
]
]
},
"loyal_level_items": {
"6751d7d0ac6207409b0823a0": 1,
"6751d7d0ac6207409b0823a1": 1,
"6751d7d0ac6207409b0823a2": 1,
"6751d7d0ac6207409b0823a5": 1
}
}
@@ -0,0 +1,13 @@
{
"Name": "1313AddTraderWithAssortJson",
"Version": "1.0.0",
"SptVersion": "~4.0",
"LoadBefore": [],
"LoadAfter": [],
"IncompatibileMods": [],
"Url": "https://github.com/sp-tarkov/server-csharp/tree/develop/ExampleMods/Mods",
"IsBundleMod": false,
"Author": "SPT",
"Contributors": [],
"Licence": "MIT"
}
+4 -4
View File
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.12.35527.113 d17.12
VisualStudioVersion = 17.12.35527.113
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "1Logging", "1Logging\1Logging.csproj", "{98270ED7-04C7-4F90-91B1-820C672CE123}"
EndProject
@@ -91,9 +91,6 @@ Global
{636D5797-E37F-425A-B8DB-E3FBE4573F71}.Debug|Any CPU.Build.0 = Debug|Any CPU
{636D5797-E37F-425A-B8DB-E3FBE4573F71}.Release|Any CPU.ActiveCfg = Release|Any CPU
{636D5797-E37F-425A-B8DB-E3FBE4573F71}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
{B4DDC0E8-99D1-405E-9E01-823523FE642B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B4DDC0E8-99D1-405E-9E01-823523FE642B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B4DDC0E8-99D1-405E-9E01-823523FE642B}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -103,4 +100,7 @@ Global
{15F2B434-439E-498E-9B85-B7BBC2F4AFA4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{15F2B434-439E-498E-9B85-B7BBC2F4AFA4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal