265 lines
9.0 KiB
C#
265 lines
9.0 KiB
C#
using SPTarkov.DI.Annotations;
|
|
using SPTarkov.Server.Core.Helpers;
|
|
using SPTarkov.Server.Core.Models.Common;
|
|
using SPTarkov.Server.Core.Models.Eft.Builds;
|
|
using SPTarkov.Server.Core.Models.Eft.PresetBuild;
|
|
using SPTarkov.Server.Core.Models.Eft.Profile;
|
|
using SPTarkov.Server.Core.Models.Enums;
|
|
using SPTarkov.Server.Core.Models.Utils;
|
|
using SPTarkov.Server.Core.Servers;
|
|
using SPTarkov.Server.Core.Services;
|
|
using SPTarkov.Server.Core.Utils.Cloners;
|
|
|
|
namespace SPTarkov.Server.Core.Controllers;
|
|
|
|
[Injectable]
|
|
public class BuildController(
|
|
ISptLogger<BuildController> logger,
|
|
DatabaseService databaseService,
|
|
ProfileHelper profileHelper,
|
|
ServerLocalisationService serverLocalisationService,
|
|
ItemHelper itemHelper,
|
|
SaveServer saveServer,
|
|
ICloner cloner
|
|
)
|
|
{
|
|
/// <summary>
|
|
/// Handle client/handbook/builds/my/list
|
|
/// </summary>
|
|
/// <param name="sessionID">Session/player id</param>
|
|
/// <returns></returns>
|
|
public UserBuilds? GetUserBuilds(MongoId sessionID)
|
|
{
|
|
const string secureContainerSlotId = "SecuredContainer";
|
|
|
|
var profile = profileHelper.GetFullProfile(sessionID);
|
|
profile.UserBuildData ??= new UserBuilds
|
|
{
|
|
EquipmentBuilds = [],
|
|
WeaponBuilds = [],
|
|
MagazineBuilds = [],
|
|
};
|
|
|
|
// Ensure the secure container in the default presets match what the player has equipped
|
|
var defaultEquipmentPresetsClone = cloner
|
|
.Clone(databaseService.GetTemplates().DefaultEquipmentPresets)
|
|
.ToList();
|
|
|
|
// Get players secure container
|
|
var playerSecureContainer =
|
|
profile.CharacterData?.PmcData?.Inventory?.Items?.FirstOrDefault(x =>
|
|
x.SlotId == secureContainerSlotId
|
|
);
|
|
|
|
var firstDefaultItemsSecureContainer = defaultEquipmentPresetsClone
|
|
.FirstOrDefault()
|
|
?.Items?.FirstOrDefault(x => x.SlotId == secureContainerSlotId);
|
|
|
|
if (
|
|
playerSecureContainer is not null
|
|
&& playerSecureContainer.Template != firstDefaultItemsSecureContainer?.Template
|
|
)
|
|
// Default equipment presets' secure container tpl doesn't match players secure container tpl
|
|
{
|
|
foreach (var defaultPreset in defaultEquipmentPresetsClone)
|
|
{
|
|
// Find presets secure container
|
|
var secureContainer = defaultPreset.Items?.FirstOrDefault(item =>
|
|
item.SlotId == secureContainerSlotId
|
|
);
|
|
if (secureContainer is not null)
|
|
{
|
|
secureContainer.Template = playerSecureContainer.Template;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Clone player build data from profile and append the above defaults onto end
|
|
var userBuildsClone = cloner.Clone(profile?.UserBuildData);
|
|
|
|
userBuildsClone.EquipmentBuilds ??= [];
|
|
userBuildsClone.EquipmentBuilds?.AddRange(defaultEquipmentPresetsClone);
|
|
|
|
return userBuildsClone;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handle client/builds/weapon/save
|
|
/// </summary>
|
|
/// <param name="sessionId">Session/Player id</param>
|
|
/// <param name="request"></param>
|
|
public void SaveWeaponBuild(MongoId sessionId, PresetBuildActionRequestData request)
|
|
{
|
|
var pmcData = profileHelper.GetPmcProfile(sessionId);
|
|
|
|
// Replace duplicate Id's. The first item is the base item.
|
|
// The root ID and the base item ID need to match.
|
|
request.Items = itemHelper.ReplaceIDs(request.Items, pmcData);
|
|
request.Root = request.Items.FirstOrDefault().Id;
|
|
|
|
// Create new object ready to save into profile userbuilds.weaponBuilds
|
|
var newBuild = new WeaponBuild
|
|
{
|
|
Id = request.Id,
|
|
Name = request.Name,
|
|
Root = request.Root,
|
|
Items = request.Items.ToList(),
|
|
};
|
|
|
|
var profile = profileHelper.GetFullProfile(sessionId);
|
|
|
|
var savedWeaponBuilds = profile.UserBuildData.WeaponBuilds;
|
|
var existingBuild = savedWeaponBuilds.FirstOrDefault(x => x.Id == request.Id);
|
|
if (existingBuild is not null)
|
|
{
|
|
// exists, replace
|
|
profile.UserBuildData.WeaponBuilds.Remove(existingBuild);
|
|
profile.UserBuildData.WeaponBuilds.Add(existingBuild);
|
|
}
|
|
else
|
|
{
|
|
// Add fresh
|
|
profile.UserBuildData.WeaponBuilds.Add(newBuild);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handle client/builds/equipment/save event
|
|
/// </summary>
|
|
/// <param name="sessionID">Session/player id</param>
|
|
/// <param name="request"></param>
|
|
public void SaveEquipmentBuild(MongoId sessionID, PresetBuildActionRequestData request)
|
|
{
|
|
var profile = profileHelper.GetFullProfile(sessionID);
|
|
var pmcData = profile.CharacterData.PmcData;
|
|
|
|
var existingSavedEquipmentBuilds = saveServer
|
|
.GetProfile(sessionID)
|
|
.UserBuildData.EquipmentBuilds;
|
|
|
|
// Replace duplicate ID's. The first item is the base item.
|
|
// Root ID and the base item ID need to match.
|
|
request.Items = itemHelper.ReplaceIDs(request.Items, pmcData);
|
|
|
|
var newBuild = new EquipmentBuild
|
|
{
|
|
Id = request.Id,
|
|
Name = request.Name,
|
|
BuildType = EquipmentBuildType.Custom,
|
|
Root = request.Items.First().Id,
|
|
Items = request.Items.ToList(),
|
|
};
|
|
|
|
var existingBuild = existingSavedEquipmentBuilds?.FirstOrDefault(build =>
|
|
build.Name == request.Name || build.Id == request.Id
|
|
);
|
|
if (existingBuild is not null)
|
|
{
|
|
// Already exists, replace
|
|
profile.UserBuildData.EquipmentBuilds.Remove(existingBuild);
|
|
profile.UserBuildData.EquipmentBuilds.Add(newBuild);
|
|
}
|
|
else
|
|
{
|
|
// Fresh, add new
|
|
profile.UserBuildData.EquipmentBuilds.Add(newBuild);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handle client/builds/delete
|
|
/// </summary>
|
|
/// <param name="sessionId">Session/Player id</param>
|
|
/// <param name="request"></param>
|
|
public void RemoveBuild(MongoId sessionId, RemoveBuildRequestData request)
|
|
{
|
|
RemovePlayerBuild(request.Id, sessionId);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handle client/builds/magazine/save
|
|
/// </summary>
|
|
/// <param name="sessionId">Session/Player id</param>
|
|
/// <param name="request"></param>
|
|
public void CreateMagazineTemplate(MongoId sessionId, SetMagazineRequest request)
|
|
{
|
|
var result = new MagazineBuild
|
|
{
|
|
Id = request.Id,
|
|
Name = request.Name,
|
|
Caliber = request.Caliber,
|
|
TopCount = request.TopCount,
|
|
BottomCount = request.BottomCount,
|
|
Items = request.Items,
|
|
};
|
|
|
|
var profile = profileHelper.GetFullProfile(sessionId);
|
|
|
|
profile.UserBuildData.MagazineBuilds ??= [];
|
|
|
|
// Check if template with desired name already exists and remove it
|
|
var magazineBuildToRemove = profile.UserBuildData.MagazineBuilds.FirstOrDefault(item =>
|
|
item.Name == request.Name
|
|
);
|
|
if (magazineBuildToRemove is not null)
|
|
{
|
|
profile.UserBuildData.MagazineBuilds.Remove(magazineBuildToRemove);
|
|
}
|
|
|
|
// Add new template to profile
|
|
profile.UserBuildData.MagazineBuilds.Add(result);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handle client/builds/delete
|
|
/// Remove build from players profile
|
|
/// </summary>
|
|
/// <param name="idToRemove"></param>
|
|
/// <param name="sessionID">Session/Player id</param>
|
|
protected void RemovePlayerBuild(MongoId idToRemove, MongoId sessionID)
|
|
{
|
|
var profile = saveServer.GetProfile(sessionID);
|
|
var weaponBuilds = profile.UserBuildData.WeaponBuilds;
|
|
var equipmentBuilds = profile.UserBuildData.EquipmentBuilds;
|
|
var magazineBuilds = profile.UserBuildData.MagazineBuilds;
|
|
|
|
// Check for id in weapon array first
|
|
var matchingWeaponBuild = weaponBuilds.FirstOrDefault(weaponBuild =>
|
|
weaponBuild.Id == idToRemove
|
|
);
|
|
if (matchingWeaponBuild is not null)
|
|
{
|
|
weaponBuilds.Remove(matchingWeaponBuild);
|
|
|
|
return;
|
|
}
|
|
|
|
// Id not found in weapons, try equipment
|
|
var matchingEquipmentBuild = equipmentBuilds.FirstOrDefault(equipmentBuild =>
|
|
equipmentBuild.Id == idToRemove
|
|
);
|
|
if (matchingEquipmentBuild is not null)
|
|
{
|
|
equipmentBuilds.Remove(matchingEquipmentBuild);
|
|
|
|
return;
|
|
}
|
|
|
|
// Id not found in weapons/equipment, try mags
|
|
var matchingMagazineBuild = magazineBuilds.FirstOrDefault(magBuild =>
|
|
magBuild.Id == idToRemove
|
|
);
|
|
if (matchingMagazineBuild is not null)
|
|
{
|
|
magazineBuilds.Remove(matchingMagazineBuild);
|
|
|
|
return;
|
|
}
|
|
|
|
// Not found in weapons,equipment or magazines, not good
|
|
logger.Error(
|
|
serverLocalisationService.GetText("build-unable_to_delete_preset", idToRemove)
|
|
);
|
|
}
|
|
}
|