Skip to content
This repository has been archived by the owner on Oct 22, 2023. It is now read-only.

Commit

Permalink
Added support for a local userprofile
Browse files Browse the repository at this point in the history
  • Loading branch information
LennardF1989 committed Jul 18, 2023
1 parent d50798c commit 8c6a678
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 22 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -7,6 +7,7 @@ obj
# Server
/Src/HM5.Server/Contracts
/Src/HM5.Server/Logs
/Src/HM5.Server/userprofile.json

# Other
/Res
2 changes: 1 addition & 1 deletion Src/HM5.Server/Interfaces/IContractsService.cs
Expand Up @@ -9,7 +9,7 @@ public interface IContractsService
void CreateContract(HitmanController.UploadContractRequest request);
void CreateContract(string compressedBase64Contract);
void RemoveContract(string contractId);
IEnumerable<Contract> GetContracts(HitmanController.SearchForContracts2Request request);
IEnumerable<Contract> GetContracts(HitmanController.SearchForContracts2Request request, Func<Contract, bool> additionalFilter = null);
string GetShareableContractLink(string contractId);
string GetLevelName(Contract contract);
string GetDifficultyName(Contract contract);
Expand Down
6 changes: 3 additions & 3 deletions Src/HM5.Server/Services/ContractsService.cs
Expand Up @@ -110,15 +110,16 @@ public void RemoveContract(string contractId)
}
}

public IEnumerable<Contract> GetContracts(HitmanController.SearchForContracts2Request request)
public IEnumerable<Contract> GetContracts(HitmanController.SearchForContracts2Request request, Func<Contract, bool> additionalFilter = null)
{
return _contractCache
.Values
.Where(x =>
(request.LevelIndex == -1 || x.LevelIndex == request.LevelIndex) &&
(request.CheckpointId == -1 || x.CheckpointIndex == request.CheckpointId) &&
(request.Difficulty == -1 || x.Difficulty == request.Difficulty) &&
(request.ContractId == string.Empty || x.DisplayId.Contains(request.ContractId))
(request.ContractName == string.Empty || x.DisplayId.Contains(request.ContractName) || x.Title.Contains(request.ContractName, StringComparison.InvariantCultureIgnoreCase)) &&
(additionalFilter == null || additionalFilter(x))
)
.OrderBy(x => x.DisplayId)
.Skip(request.StartIndex)
Expand Down Expand Up @@ -255,7 +256,6 @@ private Contract MapSimpleContractToContract(string contractId, SimpleContract s
CheckpointIndex = simpleContract.CheckpointIndex,
StartingOutfitToken = simpleContract.StartingOutfitToken,
StartingWeaponToken = simpleContract.StartingWeaponToken,
UserScore = simpleContract.Score,
HighestScoringFriendName = simpleContract.UserId,
HighestScoringFriendScore = simpleContract.Score
};
Expand Down
199 changes: 181 additions & 18 deletions Src/HM5.Server/Services/LocalHitmanServer.cs
@@ -1,11 +1,39 @@
using HM5.Server.Controllers.Hitman;
using System.Text.Json;
using HM5.Server.Controllers.Hitman;
using HM5.Server.Interfaces;
using HM5.Server.Models;

namespace HM5.Server.Services
{
public class LocalHitmanServer : IHitmanServer
{
class UserProfile
{
public class PlayedContract
{
public int Plays { get; set; }
public int Score { get; set; }
}

public string UserId { get; set; }
public string DisplayName { get; set; }
public int TotalEarnings { get; set; }
public int WalletAmount { get; set; }
public int ContractsCreated { get; set; }
public Dictionary<string, PlayedContract> PlayedContracts { get; set; }
public HashSet<string> ContractQueue { get; set; }
public HashSet<string> Friends { get; set; }

public UserProfile()
{
PlayedContracts = new Dictionary<string, PlayedContract>();
ContractQueue = new HashSet<string>();
Friends = new HashSet<string>();
}
}

private const string USERPROFILE_PATH = "userprofile.json";

private static readonly List<int> _mockedGetAverageScoresResponse = new()
{
0, //World Average
Expand All @@ -16,12 +44,16 @@ public class LocalHitmanServer : IHitmanServer

private static readonly List<ScoreEntry> _mockedGetScoresResponse = new();

private static readonly object _profileLock = new();

private readonly ISimpleLogger _logger;
private readonly IContractsService _contractsService;

private GetUserOverviewData _userOverviewData;
private UserProfile _userProfile;

public LocalHitmanServer(IContractsService contractsService)
public LocalHitmanServer(ISimpleLogger logger, IContractsService contractsService)
{
_logger = logger;
_contractsService = contractsService;
}

Expand All @@ -31,15 +63,18 @@ public void Initialize()

_contractsService.RebuildCache();

_userOverviewData = new GetUserOverviewData
{
WalletAmount = 0
};
_userProfile = LoadUserProfile();
}

public int ExecuteWalletTransaction(HitmanController.ExecuteWalletTransactionRequest request)
{
return 0;
SaveUserProfile(() =>
{
//NOTE: This would allow wallet amount to go negative if the game doesn't do the proper validations.
_userProfile.WalletAmount -= request.Amount;
});

return _userProfile.WalletAmount;
}

public List<int> GetAverageScores(HitmanController.BaseGetAverageScoresRequest request)
Expand All @@ -59,7 +94,16 @@ public List<Message> GetMessages(HitmanController.GetMessagesRequest request)

public Contract GetFeaturedContract(HitmanController.GetFeaturedContractRequest request)
{
return null;
var contract = _contractsService
.GetContracts(new HitmanController.SearchForContracts2Request
{
LevelIndex = request.LevelIndex,
StartIndex = 0,
Range = 1
}, contract => !_userProfile.PlayedContracts.ContainsKey(contract.Id))
.FirstOrDefault();

return contract;
}

public int GetNewMessageCount(HitmanController.GetNewMessageCountRequest request)
Expand All @@ -69,49 +113,168 @@ public int GetNewMessageCount(HitmanController.GetNewMessageCountRequest request

public GetUserOverviewData GetUserOverviewData(HitmanController.GetUserOverviewDataRequest request)
{
return _userOverviewData;
return new GetUserOverviewData
{
WalletAmount = _userProfile.TotalEarnings,
ContractPlays = _userProfile.PlayedContracts.Sum(x => x.Value.Plays),
ContractsCreated = _userProfile.ContractsCreated
};
}

public int GetUserWallet(HitmanController.GetUserWalletRequest request)
{
return _userOverviewData.WalletAmount;
return _userProfile.WalletAmount;
}

public void MarkContractAsPlayed(HitmanController.MarkContractAsPlayedRequest request)
{
//Do nothing
SaveUserProfile(() =>
{
if (!_userProfile.PlayedContracts.TryGetValue(request.ContractId, out var playedContract))
{
playedContract = new UserProfile.PlayedContract();
_userProfile.PlayedContracts[request.ContractId] = playedContract;
}
playedContract.Plays++;
});
}

public int PutScore(HitmanController.PutScoreRequest request)
{
return 0;
var difference = 0;

SaveUserProfile(() =>
{
if (!_userProfile.PlayedContracts.TryGetValue(request.LeaderboardId, out var playedContract))
{
playedContract = new UserProfile.PlayedContract();
_userProfile.PlayedContracts[request.LeaderboardId] = playedContract;
}
difference = request.Score - playedContract.Score;
if (difference > 0)
{
_userProfile.TotalEarnings += difference;
_userProfile.WalletAmount += difference;
}
_userProfile.PlayedContracts[request.LeaderboardId].Score = Math.Max(request.Score, playedContract.Score);
});

return difference;
}

public void QueueAddContract(HitmanController.QueueAddContractRequest request)
{
//Do nothing
SaveUserProfile(() =>
{
_userProfile.ContractQueue.Add(request.ContractId);
});
}

public void QueueRemoveContract(HitmanController.QueueRemoveContractRequest request)
{
//Do nothing
SaveUserProfile(() =>
{
_userProfile.ContractQueue.Remove(request.ContractId);
});
}

public List<Contract> SearchForContracts2(HitmanController.SearchForContracts2Request request)
{
var contracts = _contractsService.GetContracts(request);
var contracts = _contractsService
.GetContracts(request, contract =>
{
return request.View switch
{
0 => true,
10 => _userProfile.ContractQueue.Contains(contract.Id),
20 => _userProfile.PlayedContracts.ContainsKey(contract.Id),
50 => _userProfile.UserId == contract.UserId,
60 => true, //NOTE: For convenience in the UI, should actually be false.
70 => _userProfile.Friends.Contains(contract.UserId),
_ => false
};
})
.ToList();

return contracts.ToList();
contracts.ForEach(x =>
{
if (!_userProfile.PlayedContracts.TryGetValue(x.Id, out var playedContract))
{
return;
}
x.UserScore = playedContract.Score;
x.Plays = playedContract.Plays;
});

return contracts;
}

public void UpdateUserInfo(HitmanController.UpdateUserInfoRequest request)
{
//Do nothing
SaveUserProfile(() =>
{
_userProfile.UserId = request.UserId;
_userProfile.DisplayName = request.DisplayName;
request.Friends.ForEach(x => _userProfile.Friends.Add(x));
});
}

public void UploadContract(HitmanController.UploadContractRequest request)
{
_contractsService.CreateContract(request);

SaveUserProfile(() =>
{
_userProfile.ContractsCreated++;
});
}

private UserProfile LoadUserProfile()
{
lock (_profileLock)
{
try
{
if (File.Exists(USERPROFILE_PATH))
{
return JsonSerializer.Deserialize<UserProfile>(
File.ReadAllText(USERPROFILE_PATH)
);
}
}
catch
{
if (File.Exists(USERPROFILE_PATH))
{
File.Move(
USERPROFILE_PATH,
$"{USERPROFILE_PATH}-{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}"
);
}

_logger.WriteLine("Failed to load user profile! Backing up original and creating new one instead.");
}

return new UserProfile();
}
}

private void SaveUserProfile(Action scope)
{
lock (_profileLock)
{
scope();

File.WriteAllText(USERPROFILE_PATH, JsonSerializer.Serialize(_userProfile));
}
}
}
}

0 comments on commit 8c6a678

Please sign in to comment.