Merge pull request #30 from CWXDEV/main

Few things
This commit is contained in:
clodanSPT
2025-01-10 23:19:44 +00:00
committed by GitHub
9 changed files with 539 additions and 181 deletions
+31 -8
View File
@@ -1,28 +1,51 @@
using Core.DI;
using Core.Annotations;
using Core.DI;
using Core.Models.Enums;
using Core.Models.Spt.Config;
using Core.Servers;
using Core.Services;
namespace Core.Callbacks;
[Injectable]
public class SaveCallbacks : OnLoad, OnUpdate
{
private CoreConfig _coreConfig;
protected SaveServer _saveServer;
protected CoreConfig _coreConfig;
protected BackupService _backupService;
public SaveCallbacks()
public SaveCallbacks(
SaveServer saveServer,
ConfigServer configServer,
BackupService backupService
)
{
_saveServer = saveServer;
_coreConfig = configServer.GetConfig<CoreConfig>(ConfigTypes.CORE);
_backupService = backupService;
}
public async Task OnLoad()
public Task OnLoad()
{
throw new NotImplementedException();
_backupService.InitAsync();
_saveServer.Load();
return Task.CompletedTask;
}
public async Task<bool> OnUpdate(long SecondsSinceLastRun)
{
throw new NotImplementedException();
if (SecondsSinceLastRun > _coreConfig.ProfileSaveIntervalInSeconds)
{
_saveServer.Save();
return true;
}
return false;
}
public string GetRoute()
{
throw new NotImplementedException();
return "spt-save";
}
}
}
+3 -3
View File
@@ -82,7 +82,7 @@ public class LauncherController
{
var result = new Dictionary<string, string>();
var dbProfiles = _databaseService.GetProfiles();
foreach (var templatesProperty in typeof(ProfileTemplates).GetProperties())
foreach (var templatesProperty in typeof(ProfileTemplates).GetProperties().Where(p => p.CanWrite == true))
{
var propertyValue = templatesProperty.GetValue(dbProfiles);
if (propertyValue == null) {
@@ -102,7 +102,7 @@ public class LauncherController
return _saveServer.GetProfiles().TryGetValue(sessionId, out var profile) ? profile.ProfileInfo : null;
}
public string Login(LoginRequestData info)
public string? Login(LoginRequestData info)
{
foreach (var sessionID in _saveServer.GetProfiles()) {
var account = _saveServer.GetProfile(sessionID.Key).ProfileInfo;
@@ -111,7 +111,7 @@ public class LauncherController
}
}
return "";
return null;
}
public string Register(RegisterData info)
+160 -113
View File
@@ -31,12 +31,14 @@ public class ProfileController
protected LocalisationService _localisationService;
protected SeasonalEventService _seasonalEventService;
// TODO: MailSendService mailSendService: MailSendService
protected PlayerScavGenerator _playerScavGenerator;
// TODO: EventOutputHolder eventOutputHolder: EventOutputHolder
protected TraderHelper _traderHelper;
protected DialogueHelper _dialogueHelper;
protected QuestHelper _questHelper;
// TODO: MailSendService mailSendService: MailSendService
protected PlayerScavGenerator _playerScavGenerator;
// TODO: EventOutputHolder eventOutputHolder: EventOutputHolder
protected TraderHelper _traderHelper;
protected DialogueHelper _dialogueHelper;
protected QuestHelper _questHelper;
protected ProfileHelper _profileHelper;
public ProfileController(
@@ -90,7 +92,8 @@ public class ProfileController
public MiniProfile GetMiniProfile(string sessionID)
{
var profile = _saveServer.GetProfile(sessionID);
if (profile?.CharacterData == null) {
if (profile?.CharacterData == null)
{
throw new Exception($"Unable to find character data for id: {sessionID}. Profile may be corrupt");
}
@@ -98,36 +101,39 @@ public class ProfileController
var maxlvl = _profileHelper.GetMaxLevel();
// Player hasn't completed profile creation process, send defaults
if (pmc?.Info?.Level == null) {
return new MiniProfile(){
if (pmc?.Info?.Level == null)
{
return new MiniProfile()
{
Username = profile.ProfileInfo?.UserName ?? "",
Nickname = "unknown",
Side= "unknown",
CurrentLevel= 0,
CurrentExperience= 0,
PreviousExperience= 0,
NextLevel= 0,
MaxLevel= maxlvl,
Edition= profile.ProfileInfo?.Edition ?? "",
ProfileId= profile.ProfileInfo?.ProfileId ?? "",
SptData= _profileHelper.GetDefaultSptDataObject(),
Side = "unknown",
CurrentLevel = 0,
CurrentExperience = 0,
PreviousExperience = 0,
NextLevel = 0,
MaxLevel = maxlvl,
Edition = profile.ProfileInfo?.Edition ?? "",
ProfileId = profile.ProfileInfo?.ProfileId ?? "",
SptData = _profileHelper.GetDefaultSptDataObject(),
};
}
var currlvl = pmc.Info.Level;
var nextlvl = _profileHelper.GetExperience((int)(currlvl + 1));
return new MiniProfile(){
Username= profile.ProfileInfo.UserName,
Nickname= pmc.Info.Nickname,
Side= pmc.Info.Side,
CurrentLevel= (int) (pmc.Info.Level),
CurrentExperience= (int) (pmc.Info.Experience ?? 0),
PreviousExperience= currlvl == 0 ? 0 : _profileHelper.GetExperience((int) currlvl),
NextLevel= nextlvl,
MaxLevel= maxlvl,
Edition= profile.ProfileInfo?.Edition ?? "",
ProfileId= profile.ProfileInfo?.ProfileId ?? "",
SptData= profile.SptData,
return new MiniProfile()
{
Username = profile.ProfileInfo.UserName,
Nickname = pmc.Info.Nickname,
Side = pmc.Info.Side,
CurrentLevel = (int)(pmc.Info.Level),
CurrentExperience = (int)(pmc.Info.Experience ?? 0),
PreviousExperience = currlvl == 0 ? 0 : _profileHelper.GetExperience((int)currlvl),
NextLevel = nextlvl,
MaxLevel = maxlvl,
Edition = profile.ProfileInfo?.Edition ?? "",
ProfileId = profile.ProfileInfo?.ProfileId ?? "",
SptData = profile.SptData,
};
}
@@ -175,7 +181,8 @@ public class ProfileController
UpdateInventoryEquipmentId(pmcData);
if (pmcData.UnlockedInfo == null) {
if (pmcData.UnlockedInfo == null)
{
pmcData.UnlockedInfo = new UnlockedInfo { UnlockedProductionRecipe = [] };
}
@@ -191,31 +198,34 @@ public class ProfileController
);
// Create profile
var profileDetails = new SptProfile {
ProfileInfo= account,
CharacterData= new Characters { PmcData = pmcData, ScavData = new()},
Suits= profileTemplate.Suits,
UserBuildData= profileTemplate.UserBuilds,
DialogueRecords= profileTemplate.Dialogues,
SptData= _profileHelper.GetDefaultSptDataObject(),
VitalityData= new(),
InraidData= new (),
InsuranceList= [],
TraderPurchases= new(),
PlayerAchievements= new(),
FriendProfileIds= [],
var profileDetails = new SptProfile
{
ProfileInfo = account,
CharacterData = new Characters { PmcData = pmcData, ScavData = new() },
Suits = profileTemplate.Suits,
UserBuildData = profileTemplate.UserBuilds,
DialogueRecords = profileTemplate.Dialogues,
SptData = _profileHelper.GetDefaultSptDataObject(),
VitalityData = new(),
InraidData = new(),
InsuranceList = [],
TraderPurchases = new(),
PlayerAchievements = new(),
FriendProfileIds = [],
};
_profileFixerService.CheckForAndFixPmcProfileIssues(profileDetails.CharacterData.PmcData);
_saveServer.AddProfile(profileDetails);
if (profileTemplate.Trader.SetQuestsAvailableForStart ?? false) {
if (profileTemplate.Trader.SetQuestsAvailableForStart ?? false)
{
_questHelper.AddAllQuestsToProfile(profileDetails.CharacterData.PmcData, [QuestStatusEnum.AvailableForStart]);
}
// Profile is flagged as wanting quests set to ready to hand in and collect rewards
if (profileTemplate.Trader.SetQuestsAvailableForFinish ?? false) {
if (profileTemplate.Trader.SetQuestsAvailableForFinish ?? false)
{
_questHelper.AddAllQuestsToProfile(profileDetails.CharacterData.PmcData, [
QuestStatusEnum.AvailableForStart,
QuestStatusEnum.Started,
@@ -253,13 +263,16 @@ public class ProfileController
var oldEquipmentId = pmcData.Inventory.Equipment;
pmcData.Inventory.Equipment = _hashUtil.Generate();
foreach (var item in pmcData.Inventory.Items) {
if (item.ParentId == oldEquipmentId) {
foreach (var item in pmcData.Inventory.Items)
{
if (item.ParentId == oldEquipmentId)
{
item.ParentId = pmcData.Inventory.Equipment;
continue;
}
if (item.Id == oldEquipmentId) {
if (item.Id == oldEquipmentId)
{
item.Id = pmcData.Inventory.Equipment;
}
}
@@ -272,30 +285,38 @@ public class ProfileController
*/
protected void AddMissingInternalContainersToProfile(PmcData pmcData)
{
if (!pmcData.Inventory.Items.Any((item) => item.Id == pmcData.Inventory.HideoutCustomizationStashId)) {
pmcData.Inventory.Items.Add(new (){
if (!pmcData.Inventory.Items.Any((item) => item.Id == pmcData.Inventory.HideoutCustomizationStashId))
{
pmcData.Inventory.Items.Add(new()
{
Id = pmcData.Inventory.HideoutCustomizationStashId,
Template = ItemTpl.HIDEOUTAREACONTAINER_CUSTOMIZATION,
Template = ItemTpl.HIDEOUTAREACONTAINER_CUSTOMIZATION,
});
}
if (!pmcData.Inventory.Items.Any((item) => item.Id == pmcData.Inventory.SortingTable)) {
pmcData.Inventory.Items.Add(new (){
Id = pmcData.Inventory.SortingTable,
if (!pmcData.Inventory.Items.Any((item) => item.Id == pmcData.Inventory.SortingTable))
{
pmcData.Inventory.Items.Add(new()
{
Id = pmcData.Inventory.SortingTable,
Template = ItemTpl.SORTINGTABLE_SORTING_TABLE,
});
}
if (!pmcData.Inventory.Items.Any((item) => item.Id == pmcData.Inventory.QuestStashItems)) {
pmcData.Inventory.Items.Add(new (){
Id = pmcData.Inventory.QuestStashItems,
if (!pmcData.Inventory.Items.Any((item) => item.Id == pmcData.Inventory.QuestStashItems))
{
pmcData.Inventory.Items.Add(new()
{
Id = pmcData.Inventory.QuestStashItems,
Template = ItemTpl.STASH_QUESTOFFLINE,
});
}
if (!pmcData.Inventory.Items.Any((item) => item.Id == pmcData.Inventory.QuestRaidItems)) {
pmcData.Inventory.Items.Add(new (){
Id = pmcData.Inventory.QuestRaidItems,
if (!pmcData.Inventory.Items.Any((item) => item.Id == pmcData.Inventory.QuestRaidItems))
{
pmcData.Inventory.Items.Add(new()
{
Id = pmcData.Inventory.QuestRaidItems,
Template = ItemTpl.STASH_QUESTRAID,
});
}
@@ -307,9 +328,12 @@ public class ProfileController
*/
protected void DeleteProfileBySessionId(string sessionID)
{
if (_saveServer.GetProfiles().ContainsKey(sessionID)) {
if (_saveServer.GetProfiles().ContainsKey(sessionID))
{
_saveServer.DeleteProfileById(sessionID);
} else {
}
else
{
_logger.Warning(
_localisationService.GetText("profile-unable_to_find_profile_by_id_cannot_delete", sessionID)
);
@@ -329,7 +353,8 @@ public class ProfileController
ItemEventRouterResponse response
)
{
foreach (var quest in profileDetails.CharacterData.PmcData.Quests) {
foreach (var quest in profileDetails.CharacterData.PmcData.Quests)
{
var questFromDb = _questHelper.GetQuestFromDb(quest.QId, profileDetails.CharacterData.PmcData);
// Get messageId of text to send to player as text message in game
@@ -365,7 +390,8 @@ public class ProfileController
*/
protected void ResetAllTradersInProfile(string sessionId)
{
foreach (var traderId in _databaseService.GetTraders().Keys) {
foreach (var traderId in _databaseService.GetTraders().Keys)
{
_traderHelper.ResetTrader(sessionId, traderId);
}
}
@@ -386,11 +412,13 @@ public class ProfileController
*/
public string ValidateNickname(ValidateNicknameRequestData info, string sessionID)
{
if (info.Nickname.Length < 3) {
if (info.Nickname.Length < 3)
{
return "tooshort";
}
if (_profileHelper.IsNicknameTaken(info, sessionID)) {
if (_profileHelper.IsNicknameTaken(info, sessionID))
{
return "taken";
}
@@ -403,9 +431,10 @@ public class ProfileController
*/
public string ChangeNickname(ProfileChangeNicknameRequestData info, string sessionID)
{
var output = ValidateNickname(new ValidateNicknameRequestData(){Nickname = info.Nickname}, sessionID);
var output = ValidateNickname(new ValidateNicknameRequestData() { Nickname = info.Nickname }, sessionID);
if (output == "OK") {
if (output == "OK")
{
var pmcData = _profileHelper.GetPmcProfile(sessionID);
pmcData.Info.Nickname = info.Nickname;
@@ -427,17 +456,20 @@ public class ProfileController
/**
* Handle client/game/profile/search
*/
public List<SearchFriendResponse> GetFriends(SearchFriendRequestData info, string sessionID) {
public List<SearchFriendResponse> GetFriends(SearchFriendRequestData info, string sessionID)
{
// TODO: We should probably rename this method in the next client update
var result = new List<SearchFriendResponse>();
// Find any profiles with a nickname containing the entered name
var allProfiles = _saveServer.GetProfiles().Values;
foreach (var profile in allProfiles) {
foreach (var profile in allProfiles)
{
var pmcProfile = profile?.CharacterData?.PmcData;
if (!pmcProfile?.Info?.LowerNickname?.Contains(info.Nickname.ToLower()) ?? false) {
if (!pmcProfile?.Info?.LowerNickname?.Contains(info.Nickname.ToLower()) ?? false)
{
continue;
}
@@ -453,11 +485,13 @@ public class ProfileController
public GetProfileStatusResponseData GetProfileStatus(string sessionId)
{
var account = _saveServer.GetProfile(sessionId).ProfileInfo;
var response = new GetProfileStatusResponseData() {
var response = new GetProfileStatusResponseData()
{
MaxPveCountExceeded = false,
Profiles = [
new (){ ProfileId = account.ScavengerId, ProfileToken = null, Status = "Free",Sid = "", Ip = "", Port = 0 },
new (){ProfileId = account.ProfileId, ProfileToken = null, Status = "Free",Sid = "", Ip = "", Port = 0 },
Profiles =
[
new() { ProfileId = account.ScavengerId, ProfileToken = null, Status = "Free", Sid = "", Ip = "", Port = 0 },
new() { ProfileId = account.ProfileId, ProfileToken = null, Status = "Free", Sid = "", Ip = "", Port = 0 },
]
};
@@ -471,48 +505,58 @@ public class ProfileController
{
// Find the profile by the account ID, fall back to the current player if we can't find the account
var profile = _profileHelper.GetFullProfileByAccountId(request.AccountId);
if (profile?.CharacterData?.PmcData == null || profile?.CharacterData?.ScavData == null) {
if (profile?.CharacterData?.PmcData == null || profile?.CharacterData?.ScavData == null)
{
profile = _profileHelper.GetFullProfile(sessionId);
}
var playerPmc = profile.CharacterData.PmcData;
var playerScav = profile.CharacterData.ScavData;
return new GetOtherProfileResponse(){
Id= playerPmc.Id,
Aid= playerPmc.Aid as int?,
Info= {
Nickname= playerPmc.Info.Nickname,
Side= playerPmc.Info.Side,
Experience= playerPmc.Info.Experience as int?,
MemberCategory= playerPmc.Info.MemberCategory as int?,
BannedState= playerPmc.Info.BannedState,
BannedUntil= playerPmc.Info.BannedUntil,
RegistrationDate= playerPmc.Info.RegistrationDate,
return new GetOtherProfileResponse()
{
Id = playerPmc.Id,
Aid = playerPmc.Aid as int?,
Info =
{
Nickname = playerPmc.Info.Nickname,
Side = playerPmc.Info.Side,
Experience = playerPmc.Info.Experience as int?,
MemberCategory = playerPmc.Info.MemberCategory as int?,
BannedState = playerPmc.Info.BannedState,
BannedUntil = playerPmc.Info.BannedUntil,
RegistrationDate = playerPmc.Info.RegistrationDate,
},
Customization= {
Head= playerPmc.Customization.Head,
Body= playerPmc.Customization.Body,
Feet= playerPmc.Customization.Feet,
Hands= playerPmc.Customization.Hands,
Dogtag= playerPmc.Customization.DogTag,
Customization =
{
Head = playerPmc.Customization.Head,
Body = playerPmc.Customization.Body,
Feet = playerPmc.Customization.Feet,
Hands = playerPmc.Customization.Hands,
Dogtag = playerPmc.Customization.DogTag,
},
Skills= playerPmc.Skills,
Equipment= {
Id= playerPmc.Inventory.Equipment,
Items= playerPmc.Inventory.Items,
Skills = playerPmc.Skills,
Equipment =
{
Id = playerPmc.Inventory.Equipment,
Items = playerPmc.Inventory.Items,
},
Achievements= playerPmc.Achievements,
FavoriteItems= _profileHelper.GetOtherProfileFavorites(playerPmc),
PmcStats= {
Eft= {
TotalInGameTime= playerPmc.Stats.Eft.TotalInGameTime as int?,
OverAllCounters= playerPmc.Stats.Eft.OverallCounters,
Achievements = playerPmc.Achievements,
FavoriteItems = _profileHelper.GetOtherProfileFavorites(playerPmc),
PmcStats =
{
Eft =
{
TotalInGameTime = playerPmc.Stats.Eft.TotalInGameTime as int?,
OverAllCounters = playerPmc.Stats.Eft.OverallCounters,
},
},
ScavStats= {
Eft= {
TotalInGameTime= playerScav.Stats.Eft.TotalInGameTime as int?,
OverAllCounters= playerScav.Stats.Eft.OverallCounters,
ScavStats =
{
Eft =
{
TotalInGameTime = playerScav.Stats.Eft.TotalInGameTime as int?,
OverAllCounters = playerScav.Stats.Eft.OverallCounters,
}
}
};
@@ -521,18 +565,21 @@ public class ProfileController
/**
* Handle client/profile/settings
*/
public bool SetChosenProfileIcon(string sessionId, GetProfileSettingsRequest request )
public bool SetChosenProfileIcon(string sessionId, GetProfileSettingsRequest request)
{
var profileToUpdate = _profileHelper.GetPmcProfile(sessionId);
if (profileToUpdate == null) {
if (profileToUpdate == null)
{
return false;
}
if (request.MemberCategory != null) {
if (request.MemberCategory != null)
{
profileToUpdate.Info.SelectedMemberCategory = request.MemberCategory as MemberCategory?;
}
if (request.SquadInviteRestriction != null) {
if (request.SquadInviteRestriction != null)
{
profileToUpdate.Info.SquadInviteRestriction = request.SquadInviteRestriction;
}
+2
View File
@@ -1,9 +1,11 @@
using System.Text.Json.Serialization;
using Core.Annotations;
using Core.Models.Eft.Common;
using Core.Models.Eft.Common.Tables;
namespace Core.Helpers;
[Injectable]
public class ItemHelper
{
/**
+331 -46
View File
@@ -3,12 +3,52 @@ using Core.Models.Eft.Common;
using Core.Models.Eft.Common.Tables;
using Core.Models.Eft.Profile;
using Core.Models.Enums;
using Core.Models.Spt.Config;
using Core.Servers;
using Core.Services;
using Core.Utils;
using Core.Utils.Cloners;
namespace Core.Helpers;
[Injectable]
public class ProfileHelper
{
protected Models.Utils.ILogger _logger;
protected ICloner _cloner;
protected SaveServer _saveServer;
protected DatabaseService _databaseService;
protected Watermark _watermark;
protected ItemHelper _itemHelper;
protected TimeUtil _timeUtil;
protected LocalisationService _localisationService;
protected InventoryConfig _inventoryConfig;
protected HashUtil _hashUtil;
public ProfileHelper(
ICloner cloner,
SaveServer saveServer,
DatabaseService databaseService,
Watermark watermark,
ItemHelper itemHelper,
TimeUtil timeUtil,
LocalisationService localisationService,
HashUtil hashUtil,
ConfigServer configServer
)
{
_cloner = cloner;
_saveServer = saveServer;
_databaseService = databaseService;
_watermark = watermark;
_itemHelper = itemHelper;
_timeUtil = timeUtil;
_localisationService = localisationService;
_hashUtil = hashUtil;
_inventoryConfig = configServer.GetConfig<InventoryConfig>(ConfigTypes.INVENTORY);
}
/// <summary>
/// Remove/reset a completed quest condtion from players profile quest data
/// </summary>
@@ -16,7 +56,14 @@ public class ProfileHelper
/// <param name="questConditionId">Quest with condition to remove</param>
public void RemoveQuestConditionFromProfile(PmcData pmcData, Dictionary<string, string> questConditionId)
{
throw new NotImplementedException();
foreach (var questId in questConditionId)
{
var conditionId = questId.Value;
var profileQuest = pmcData.Quests.FirstOrDefault(q => q.QId == conditionId);
if (profileQuest != null) // Remove condition
profileQuest.CompletedConditions.Remove(conditionId);
}
}
/// <summary>
@@ -25,7 +72,7 @@ public class ProfileHelper
/// <returns>Dictionary of profiles</returns>
public Dictionary<string, SptProfile> GetProfiles()
{
throw new NotImplementedException();
return _saveServer.GetProfiles();
}
/// <summary>
@@ -35,7 +82,21 @@ public class ProfileHelper
/// <returns>Array of PmcData objects</returns>
public List<PmcData> GetCompleteProfile(string sessionId)
{
throw new NotImplementedException();
var output = new List<PmcData>();
if (IsWiped(sessionId))
return output;
var FullProfileClone = _cloner.Clone(GetFullProfile(sessionId));
// Sanitize any data the client can not receive
SanitizeProfileForClient(FullProfileClone);
// PMC must be at array index 0, scav at 1
output.Add(FullProfileClone.CharacterData.PmcData);
output.Add(FullProfileClone.CharacterData.ScavData);
return output;
}
/// <summary>
@@ -44,7 +105,12 @@ public class ProfileHelper
/// <param name="clonedProfile">A clone of the full player profile</param>
protected void SanitizeProfileForClient(SptProfile clonedProfile)
{
throw new NotImplementedException();
// Remove `loyaltyLevel` from `TradersInfo`, as otherwise it causes the client to not
// properly calculate the player's `loyaltyLevel`
foreach (var trader in clonedProfile.CharacterData.PmcData.TradersInfo.Values)
{
trader.LoyaltyLevel = null;
}
}
/// <summary>
@@ -55,17 +121,22 @@ public class ProfileHelper
/// <returns>True if already in use</returns>
public bool IsNicknameTaken(ValidateNicknameRequestData nicknameRequest, string sessionID)
{
throw new NotImplementedException();
var allProfiles = _saveServer.GetProfiles().Values;
// Find a profile that doesn't have same session id but has same name
return allProfiles.Any(p =>
ProfileHasInfoProperty(p) && !StringsMatch(p.ProfileInfo.ProfileId, sessionID) && // SessionIds dont match
StringsMatch(p.CharacterData.PmcData.Info.LowerNickname.ToLower(), nicknameRequest.Nickname.ToLower())); // Nicknames do
}
protected bool ProfileHasInfoProperty(SptProfile profile)
{
throw new NotImplementedException();
return profile?.CharacterData?.PmcData?.Info != null;
}
protected bool StringsMatch(string stringA, string stringB)
{
throw new NotImplementedException();
return stringA == stringB;
}
/// <summary>
@@ -75,7 +146,11 @@ public class ProfileHelper
/// <param name="experienceToAdd">Experience to add to PMC character</param>
public void AddExperienceToPmc(string sessionID, int experienceToAdd)
{
throw new NotImplementedException();
var pmcData = GetPmcProfile(sessionID);
if (pmcData != null)
pmcData.Info.Experience += experienceToAdd;
else
_logger.Error($"Profile {sessionID} does not exist");
}
/// <summary>
@@ -85,7 +160,7 @@ public class ProfileHelper
/// <returns>PmcData</returns>
public PmcData? GetProfileByPmcId(string pmcId)
{
throw new NotImplementedException();
return _saveServer.GetProfiles().Values.First(p => p.CharacterData?.PmcData?.Id == pmcId).CharacterData.PmcData;
}
/// <summary>
@@ -93,9 +168,21 @@ public class ProfileHelper
/// </summary>
/// <param name="level">Level to get xp for</param>
/// <returns>Number of xp points for level</returns>
public int GetExperience(int level)
public int? GetExperience(int level)
{
throw new NotImplementedException();
var playerLevel = level;
var expTable = _databaseService.GetGlobals().Configuration.Exp.Level.ExperienceTable;
int? exp = null;
if (playerLevel >= expTable.Length) // make sure to not go out of bounds
playerLevel = expTable.Length - 1;
foreach (var expLevel in expTable)
{
exp += expLevel.Experience;
}
return exp;
}
/// <summary>
@@ -104,7 +191,7 @@ public class ProfileHelper
/// <returns>Max level</returns>
public int GetMaxLevel()
{
throw new NotImplementedException();
return _databaseService.GetGlobals().Configuration.Exp.Level.ExperienceTable.Length - 1;
}
/// <summary>
@@ -113,7 +200,16 @@ public class ProfileHelper
/// <returns>Spt</returns>
public Spt GetDefaultSptDataObject()
{
throw new NotImplementedException();
return new()
{
Version = _watermark.GetVersionTag(true),
Mods = new(),
ReceivedGifts = new(),
BlacklistedItemTemplates = new(),
FreeRepeatableRefreshUsedCount = new(),
Migrations = new(),
CultistRewards = new()
};
}
/// <summary>
@@ -123,7 +219,7 @@ public class ProfileHelper
/// <returns>SptProfile object</returns>
public SptProfile? GetFullProfile(string sessionID)
{
throw new NotImplementedException();
return _saveServer.ProfileExists(sessionID) ? _saveServer.GetProfile(sessionID) : null;
}
/// <summary>
@@ -133,7 +229,11 @@ public class ProfileHelper
/// <returns></returns>
public SptProfile? GetFullProfileByAccountId(string accountID)
{
throw new NotImplementedException();
var check = int.TryParse(accountID, out var aid);
if (!check)
_logger.Error($"Account {accountID} does not exist");
return _saveServer.GetProfiles().FirstOrDefault(p => p.Value?.ProfileInfo?.Aid == aid).Value;
}
/// <summary>
@@ -143,7 +243,11 @@ public class ProfileHelper
/// <returns></returns>
public SearchFriendResponse? GetChatRoomMemberFromSessionId(string sessionID)
{
throw new NotImplementedException();
var pmcProfile = GetFullProfile(sessionID)?.CharacterData?.PmcData;
if (pmcProfile == null)
return null;
return GetChatRoomMemberFromPmcProfile(pmcProfile);
}
/// <summary>
@@ -151,9 +255,21 @@ public class ProfileHelper
/// </summary>
/// <param name="pmcProfile">The PMC profile data to format into a ChatRoomMember structure</param>
/// <returns></returns>
public SearchFriendResponse GetChatRoomMemberFromPmcProfile(PmcData pmcProfile)
public SearchFriendResponse? GetChatRoomMemberFromPmcProfile(PmcData pmcProfile)
{
throw new NotImplementedException();
return new()
{
Id = pmcProfile.Id,
Aid = pmcProfile.Aid,
Info = new()
{
Nickname = pmcProfile.Info.Nickname,
Side = pmcProfile.Info.Side,
Level = pmcProfile.Info.Level,
MemberCategory = pmcProfile.Info.MemberCategory,
SelectedMemberCategory = pmcProfile.Info.SelectedMemberCategory
}
};
}
/// <summary>
@@ -163,7 +279,9 @@ public class ProfileHelper
/// <returns>PmcData object</returns>
public PmcData? GetPmcProfile(string sessionID)
{
throw new NotImplementedException();
var fullProfile = GetFullProfile(sessionID);
return fullProfile?.CharacterData?.PmcData;
}
/// <summary>
@@ -171,9 +289,10 @@ public class ProfileHelper
/// </summary>
/// <param name="userId">Id to validate</param>
/// <returns>True is a player</returns>
/// UNUSED?
public bool IsPlayer(string userId)
{
throw new NotImplementedException();
return _saveServer.ProfileExists(userId);
}
/// <summary>
@@ -181,9 +300,9 @@ public class ProfileHelper
/// </summary>
/// <param name="sessionID">Profiles id</param>
/// <returns>IPmcData object</returns>
public PmcData GetScavProfile(string sessionID)
public PmcData? GetScavProfile(string sessionID)
{
throw new NotImplementedException();
return _saveServer.GetProfile(sessionID)?.CharacterData?.ScavData;
}
/// <summary>
@@ -192,7 +311,26 @@ public class ProfileHelper
/// <returns>Default profile Stats object</returns>
public Stats GetDefaultCounters()
{
throw new NotImplementedException();
return new()
{
Eft = new()
{
CarriedQuestItems = new(),
DamageHistory = new() { LethalDamagePart = "Head", LethalDamage = null, BodyParts = new()},
DroppedItems = new(),
ExperienceBonusMult = 0,
FoundInRaidItems = new(),
LastPlayerState = null,
LastSessionDate = 0,
OverallCounters = new(),
SessionCounters = new(),
SessionExperienceMult = 0,
SurvivorClass = "Unknown",
TotalInGameTime = 0,
TotalSessionExperience = 0,
Victims = new()
}
};
}
/// <summary>
@@ -200,9 +338,10 @@ public class ProfileHelper
/// </summary>
/// <param name="sessionID">Profile id</param>
/// <returns>True if profile is to be wiped of data/progress</returns>
/// TODO: logic doesnt feel right to have IsWiped being nullable
protected bool IsWiped(string sessionID)
{
throw new NotImplementedException();
return _saveServer.GetProfile(sessionID)?.ProfileInfo?.IsWiped ?? false;
}
/// <summary>
@@ -212,7 +351,18 @@ public class ProfileHelper
/// <returns>profile without secure container</returns>
public PmcData RemoveSecureContainer(PmcData profile)
{
throw new NotImplementedException();
var items = profile.Inventory.Items;
var secureContainer = items.First(i => i.SlotId == "SecuredContainer");
if (secureContainer != null)
{
// Find and remove container + children
var childItemsInSecureContainer = _itemHelper.FindAndReturnChildrenByItems(items, secureContainer.Id);
// Remove child items + secure container
profile.Inventory.Items = items.Where(i => !childItemsInSecureContainer.Contains(i.Id)).ToList();
}
return profile;
}
/// <summary>
@@ -224,7 +374,24 @@ public class ProfileHelper
/// <param name="maxCount">Limit of how many of this gift a player can have</param>
public void FlagGiftReceivedInProfile(string playerId, string giftId, int maxCount)
{
throw new NotImplementedException();
var profileToUpdate = GetFullProfile(playerId);
profileToUpdate.SptData.ReceivedGifts ??= new();
var giftData = profileToUpdate.SptData.ReceivedGifts.FirstOrDefault(g => g.GiftId == giftId);
if (giftData != null)
{
// Increment counter
giftData.Current++;
return;
}
// Player has never received gift, make a new object
profileToUpdate.SptData.ReceivedGifts.Add(new()
{
GiftId = giftId,
TimestampLastAccepted = _timeUtil.GetTimeStamp(),
Current = 1
});
}
/// <summary>
@@ -236,28 +403,56 @@ public class ProfileHelper
/// <returns>True if player has recieved gift previously</returns>
public bool PlayerHasRecievedMaxNumberOfGift(string playerId, string giftId, int maxGiftCount)
{
throw new NotImplementedException();
var profile = GetFullProfile(playerId);
if (profile == null)
{
_logger.Debug($"Unable to gift {giftId}, Profile: {playerId} does not exist");
return false;
}
if (profile.SptData.ReceivedGifts == null)
return false;
var giftDataFromProfile = profile.SptData.ReceivedGifts.FirstOrDefault(g => g.GiftId == giftId);
if (giftDataFromProfile == null)
return false;
return giftDataFromProfile.Current >= maxGiftCount;
}
/// <summary>
/// Find Stat in profile counters and increment by one
/// Find Stat in profile counters and increment by one.
/// </summary>
/// <param name="counters">Counters to search for key</param>
/// <param name="keyToIncrement">Key</param>
/// Was Includes in Node so might not be exact?
public void IncrementStatCounter(CounterKeyValue[] counters, string keyToIncrement)
{
throw new NotImplementedException();
var stat = counters.FirstOrDefault(c => c.Key.Contains(keyToIncrement));
if (stat != null)
stat.Value++;
}
/// <summary>
/// Check if player has a skill at elite level
/// </summary>
/// <param name="skillType">Skill to check</param>
/// <param name="skill">Skill to check</param>
/// <param name="pmcProfile">Profile to find skill in</param>
/// <returns>True if player has skill at elite level</returns>
public bool HasEliteSkillLevel(SkillTypes skillType, PmcData pmcProfile)
public bool HasEliteSkillLevel(SkillTypes skill, PmcData pmcProfile)
{
throw new NotImplementedException();
var profileSkills = pmcProfile.Skills.Common;
if (profileSkills == null)
return false;
var profileSkill = profileSkills.Dictionary.FirstOrDefault(s => s.Value.Id == skill.ToString()).Value;
if (profileSkill == null)
{
_logger.Error(_localisationService.GetText("quest-no_skill_found", skill));
return false;
}
return profileSkill.Progress >= 5100; // 51
}
/// <summary>
@@ -267,9 +462,42 @@ public class ProfileHelper
/// <param name="skill">Skill to add points to</param>
/// <param name="pointsToAdd">Points to add</param>
/// <param name="useSkillProgressRateMultipler">Skills are multiplied by a value in globals, default is off to maintain compatibility with legacy code</param>
public void AddSkillPointsToPlayer(PmcData pmcProfile, SkillTypes skill, int pointsToAdd, bool useSkillProgressRateMultipler = false)
public void AddSkillPointsToPlayer(PmcData pmcProfile, SkillTypes skill, double? pointsToAdd, bool useSkillProgressRateMultipler = false)
{
throw new NotImplementedException();
var pointsToAddToSkill = pointsToAdd;
if (pointsToAddToSkill < 0D)
{
_logger.Warning(_localisationService.GetText("player-attempt_to_increment_skill_with_negative_value", skill));
return;
}
var profileSkills = pmcProfile?.Skills?.Common;
if (profileSkills == null)
{
_logger.Warning($"Unable to add {pointsToAddToSkill} points to {skill}, Profile has no skills");
return;
}
var profileSkill = profileSkills.Dictionary.FirstOrDefault(s => s.Value.Id == skill.ToString()).Value;
if (profileSkill == null)
{
_logger.Error(_localisationService.GetText("quest-no_skill_found", skill));
return;
}
if (useSkillProgressRateMultipler)
{
var skillProgressRate = _databaseService.GetGlobals().Configuration.SkillsSettings.SkillProgressRate;
pointsToAddToSkill *= skillProgressRate;
}
if (_inventoryConfig.SkillGainMultipliers[skill.ToString()] != null)
pointsToAddToSkill *= _inventoryConfig.SkillGainMultipliers[skill.ToString()];
profileSkill.Progress += pointsToAddToSkill;
profileSkill.Progress = Math.Min(profileSkill?.Progress ?? 0D, 5100); // Prevent skill from ever going above level 51 (5100)
profileSkill.LastAccess = _timeUtil.GetTimeStamp();
}
/// <summary>
@@ -278,9 +506,13 @@ public class ProfileHelper
/// <param name="pmcData">Player profile</param>
/// <param name="skill">Skill to look up and return value from</param>
/// <returns>Common skill object from desired profile</returns>
public Common GetSkillFromProfile(PmcData pmcData, SkillTypes skill)
public Common? GetSkillFromProfile(PmcData pmcData, SkillTypes skill)
{
throw new NotImplementedException();
var skillToReturn = pmcData?.Skills?.Common.List.FirstOrDefault(s => s.Id == skill.ToString());
if (skillToReturn == null)
_logger.Warning($"Profile {pmcData.SessionId} does not have a skill named: {skill.ToString()}");
return skillToReturn;
}
/// <summary>
@@ -290,7 +522,7 @@ public class ProfileHelper
/// <returns>True if account is developer</returns>
public bool IsDeveloperAccount(string sessionID)
{
throw new NotImplementedException();
return GetFullProfile(sessionID)?.ProfileInfo?.Edition?.ToLower().StartsWith("spt developer") == false;
}
/// <summary>
@@ -300,7 +532,24 @@ public class ProfileHelper
/// <param name="rowsToAdd">How many rows to give profile</param>
public void AddStashRowsBonusToProfile(string sessionId, int rowsToAdd)
{
throw new NotImplementedException();
var profile = GetPmcProfile(sessionId);
var existingBonus = profile?.Bonuses?.FirstOrDefault(b => b.Type == BonusType.StashRows);
if (existingBonus != null)
{
profile?.Bonuses?.Add(new()
{
Id = _hashUtil.Generate(),
Value = rowsToAdd,
Type = BonusType.StashRows,
IsPassive = true,
IsVisible = true,
IsProduction = false
});
}
else
{
existingBonus.Value += rowsToAdd;
}
}
/// <summary>
@@ -309,14 +558,20 @@ public class ProfileHelper
/// <param name="pmcProfile">Player profile</param>
/// <param name="desiredBonus">Bonus to sum up</param>
/// <returns>Summed bonus value or 0 if no bonus found</returns>
public int GetBonusValueFromProfile(PmcData pmcProfile, BonusType desiredBonus)
public double GetBonusValueFromProfile(PmcData pmcProfile, BonusType desiredBonus)
{
throw new NotImplementedException();
var bonuses = pmcProfile?.Bonuses?.Where(b => b.Type == desiredBonus);
if (bonuses.Count() == 0)
return 0;
// Sum all bonuses found above
return bonuses?.Sum(new Func<Bonus, double>(bonus => bonus?.Value ?? 0)) ?? 0;
}
public bool PlayerIsFleaBanned(PmcData pmcProfile)
{
throw new NotImplementedException();
var currentTimestamp = _timeUtil.GetTimeStamp();
return pmcProfile?.Info?.Bans?.Any(b => b.BanType == BanType.RAGFAIR && currentTimestamp < b.DateTime) ?? false;
}
/// <summary>
@@ -326,12 +581,14 @@ public class ProfileHelper
/// <param name="achievementId">Id of achievement to add</param>
public void AddAchievementToProfile(PmcData pmcProfile, string achievementId)
{
throw new NotImplementedException();
pmcProfile.Achievements[achievementId] = _timeUtil.GetTimeStamp();
}
protected readonly List<string> gameEditions = ["edge_of_darkness", "unheard_edition"];
public bool HasAccessToRepeatableFreeRefreshSystem(PmcData pmcProfile)
{
throw new NotImplementedException();
return gameEditions.Contains(pmcProfile.Info.GameVersion);
}
/// <summary>
@@ -341,7 +598,19 @@ public class ProfileHelper
/// <param name="newPocketTpl">New tpl to set profiles Pockets to</param>
public void ReplaceProfilePocketTpl(PmcData pmcProfile, string newPocketTpl)
{
throw new NotImplementedException();
// Find all pockets in profile, may be multiple as they could have equipment stand
// (1 pocket for each upgrade level of equipment stand)
var pockets = pmcProfile.Inventory.Items.Where(i => i.SlotId == "Pockets");
if (pockets.Count() == 0)
{
_logger.Error($"Unable to replace profile: {pmcProfile.Id} pocket tpl with: {newPocketTpl} as Pocket item could not be found.");
return;
}
foreach (var pocket in pockets)
{
pocket.Id = newPocketTpl;
}
}
/// <summary>
@@ -351,7 +620,7 @@ public class ProfileHelper
/// <returns>List of item objects</returns>
public List<Item> GetQuestItemsInProfile(PmcData profile)
{
throw new NotImplementedException();
return profile?.Inventory?.Items.Where(i => i.ParentId == profile.Inventory.QuestRaidItems).ToList();
}
/// <summary>
@@ -361,6 +630,22 @@ public class ProfileHelper
/// <returns>A list of Item objects representing the favorited data</returns>
public List<Item> GetOtherProfileFavorites(PmcData profile)
{
throw new NotImplementedException();
var fullFavorites = new List<Item>();
foreach (var itemId in profile.Inventory.FavoriteItems ?? new List<string>())
{
// When viewing another users profile, the client expects a full item with children, so get that
var itemAndChildren = _itemHelper.FindAndReturnChildrenAsItems(profile.Inventory.Items, itemId);
if (itemAndChildren != null && itemAndChildren.Count > 0)
{
// To get the client to actually see the items, we set the main item's parent to null, so it's treated as a root item
var clonedItems = _cloner.Clone(itemAndChildren);
clonedItems.First().ParentId = null;
fullFavorites.AddRange(clonedItems);
}
}
return fullFavorites;
}
}
+2 -2
View File
@@ -1255,7 +1255,7 @@ public class Level
public class ExpTable
{
[JsonPropertyName("exp")]
public double? Experience { get; set; }
public int? Experience { get; set; }
}
public class LootAttempt
@@ -4347,4 +4347,4 @@ public class QuestSettings
[JsonPropertyName("GlobalRewardRepModifierQuestPvE")]
public double? GlobalRewardRepModifierQuestPvE { get; set; }
}
}
+2 -2
View File
@@ -71,7 +71,7 @@ public class BotBase
/** Achievement id and timestamp */
[JsonPropertyName("Achievements")]
[JsonConverter(typeof(ArrayToObjectFactoryConverter))]
public Dictionary<string, int>? Achievements { get; set; }
public Dictionary<string, long>? Achievements { get; set; }
[JsonPropertyName("RepeatableQuests")]
public List<PmcDataRepeatableQuest>? RepeatableQuests { get; set; }
@@ -332,7 +332,7 @@ public class BaseSkill
public class Common : BaseSkill
{
public int? PointsEarnedDuringSession { get; set; }
public int? LastAccess { get; set; }
public long? LastAccess { get; set; }
}
public class Mastering : BaseSkill
@@ -24,7 +24,7 @@ public class GetOtherProfileResponse
public OtherProfileEquipment? Equipment { get; set; }
[JsonPropertyName("achievements")]
public Dictionary<string, int>? Achievements { get; set; }
public Dictionary<string, long>? Achievements { get; set; }
[JsonPropertyName("favoriteItems")]
public List<Item>? FavoriteItems { get; set; }
@@ -100,4 +100,4 @@ public class OtherProfileSubStats
[JsonPropertyName("overAllCounters")]
public OverallCounters? OverAllCounters { get; set; }
}
}
@@ -1,4 +1,5 @@
using System.Text.Json.Serialization;
using Core.Models.Enums;
namespace Core.Models.Eft.Profile;
@@ -8,7 +9,7 @@ public class SearchFriendResponse
public string? Id { get; set; }
[JsonPropertyName("aid")]
public int? Aid { get; set; }
public double? Aid { get; set; }
[JsonPropertyName("Info")]
public FriendInfo? Info { get; set; }
@@ -24,11 +25,11 @@ public class FriendInfo
public string? Side { get; set; }
[JsonPropertyName("Level")]
public int? Level { get; set; }
public double? Level { get; set; }
[JsonPropertyName("MemberCategory")]
public int? MemberCategory { get; set; }
public MemberCategory? MemberCategory { get; set; }
[JsonPropertyName("SelectedMemberCategory")]
public int? SelectedMemberCategory { get; set; }
}
public MemberCategory? SelectedMemberCategory { get; set; }
}