mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-05-12 12:52:28 +00:00
Add score logging, friend scores, and fix case processing
This commit is contained in:
parent
fddef506c8
commit
22905d419c
6 changed files with 91 additions and 20 deletions
|
@ -4,9 +4,7 @@ using LBPUnion.ProjectLighthouse.Helpers;
|
||||||
using LBPUnion.ProjectLighthouse.PlayerData;
|
using LBPUnion.ProjectLighthouse.PlayerData;
|
||||||
using LBPUnion.ProjectLighthouse.PlayerData.Profiles;
|
using LBPUnion.ProjectLighthouse.PlayerData.Profiles;
|
||||||
using LBPUnion.ProjectLighthouse.Serialization;
|
using LBPUnion.ProjectLighthouse.Serialization;
|
||||||
using LBPUnion.ProjectLighthouse.StorableLists;
|
|
||||||
using LBPUnion.ProjectLighthouse.StorableLists.Stores;
|
using LBPUnion.ProjectLighthouse.StorableLists.Stores;
|
||||||
using LBPUnion.ProjectLighthouse.Types;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
@ -56,8 +54,7 @@ public class FriendsController : ControllerBase
|
||||||
blockedUsers.Add(blockedUser.UserId);
|
blockedUsers.Add(blockedUser.UserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
UserFriendData? friendStore = UserFriendStore.GetUserFriendData(token.UserId);
|
UserFriendData friendStore = UserFriendStore.GetUserFriendData(token.UserId) ?? UserFriendStore.CreateUserFriendData(token.UserId);
|
||||||
if (friendStore == null) friendStore = UserFriendStore.CreateUserFriendData(token.UserId);
|
|
||||||
|
|
||||||
friendStore.FriendIds = friends.Select(u => u.UserId).ToList();
|
friendStore.FriendIds = friends.Select(u => u.UserId).ToList();
|
||||||
friendStore.BlockedIds = blockedUsers;
|
friendStore.BlockedIds = blockedUsers;
|
||||||
|
|
|
@ -3,9 +3,13 @@ using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
using LBPUnion.ProjectLighthouse.Helpers;
|
using LBPUnion.ProjectLighthouse.Helpers;
|
||||||
using LBPUnion.ProjectLighthouse.Levels;
|
using LBPUnion.ProjectLighthouse.Levels;
|
||||||
|
using LBPUnion.ProjectLighthouse.Logging;
|
||||||
using LBPUnion.ProjectLighthouse.PlayerData;
|
using LBPUnion.ProjectLighthouse.PlayerData;
|
||||||
|
using LBPUnion.ProjectLighthouse.PlayerData.Profiles;
|
||||||
using LBPUnion.ProjectLighthouse.Serialization;
|
using LBPUnion.ProjectLighthouse.Serialization;
|
||||||
|
using LBPUnion.ProjectLighthouse.StorableLists.Stores;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers.Slots;
|
namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers.Slots;
|
||||||
|
|
||||||
|
@ -29,20 +33,45 @@ public class ScoreController : ControllerBase
|
||||||
|
|
||||||
string username = await this.database.UsernameFromGameToken(token);
|
string username = await this.database.UsernameFromGameToken(token);
|
||||||
|
|
||||||
if (SlotHelper.IsTypeInvalid(slotType)) return this.BadRequest();
|
if (SlotHelper.IsTypeInvalid(slotType))
|
||||||
|
{
|
||||||
|
Logger.Warn($"Rejecting score upload, slot type is invalid (slotType={slotType}, user={username})", LogArea.Score);
|
||||||
|
return this.BadRequest();
|
||||||
|
}
|
||||||
|
|
||||||
this.Request.Body.Position = 0;
|
this.Request.Body.Position = 0;
|
||||||
string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync();
|
string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync();
|
||||||
|
|
||||||
XmlSerializer serializer = new(typeof(Score));
|
XmlSerializer serializer = new(typeof(Score));
|
||||||
Score? score = (Score?)serializer.Deserialize(new StringReader(bodyString));
|
Score? score = (Score?)serializer.Deserialize(new StringReader(bodyString));
|
||||||
if (score == null) return this.BadRequest();
|
if (score == null)
|
||||||
|
{
|
||||||
|
Logger.Warn($"Rejecting score upload, score is null (slotType={slotType}, slotId={id}, user={username})", LogArea.Score);
|
||||||
|
return this.BadRequest();
|
||||||
|
}
|
||||||
|
|
||||||
if (score.PlayerIds.Length == 0) return this.BadRequest();
|
if (score.PlayerIds.Length == 0)
|
||||||
|
{
|
||||||
|
Logger.Warn($"Rejecting score upload, there are 0 playerIds (slotType={slotType}, slotId={id}, user={username})", LogArea.Score);
|
||||||
|
return this.BadRequest();
|
||||||
|
}
|
||||||
|
|
||||||
if (score.Points < 0) return this.BadRequest();
|
if (score.Points < 0)
|
||||||
|
{
|
||||||
|
Logger.Warn($"Rejecting score upload, points value is less than 0 (points={score.Points}, user={username})", LogArea.Score);
|
||||||
|
return this.BadRequest();
|
||||||
|
}
|
||||||
|
|
||||||
if (score.Type is > 4 or < 1) return this.BadRequest();
|
// Score types:
|
||||||
|
// 1-4: Co-op with the number representing the number of players
|
||||||
|
// 5: leaderboard filtered by day (never uploaded with this id)
|
||||||
|
// 6: leaderboard filtered by week (never uploaded either)
|
||||||
|
// 7: Versus levels & leaderboard filtered by all time
|
||||||
|
if (score.Type is > 4 or < 1 && score.Type != 7)
|
||||||
|
{
|
||||||
|
Logger.Warn($"Rejecting score upload, score type is out of bounds (type={score.Type}, user={username})", LogArea.Score);
|
||||||
|
return this.BadRequest();
|
||||||
|
}
|
||||||
|
|
||||||
SanitizationHelper.SanitizeStringsInClass(score);
|
SanitizationHelper.SanitizeStringsInClass(score);
|
||||||
|
|
||||||
|
@ -51,7 +80,11 @@ public class ScoreController : ControllerBase
|
||||||
score.SlotId = id;
|
score.SlotId = id;
|
||||||
|
|
||||||
Slot? slot = this.database.Slots.FirstOrDefault(s => s.SlotId == score.SlotId);
|
Slot? slot = this.database.Slots.FirstOrDefault(s => s.SlotId == score.SlotId);
|
||||||
if (slot == null) return this.BadRequest();
|
if (slot == null)
|
||||||
|
{
|
||||||
|
Logger.Warn($"Rejecting score upload, slot is null (slotId={score.SlotId}, slotType={slotType}, reqId={id}, user={username})", LogArea.Score);
|
||||||
|
return this.BadRequest();
|
||||||
|
}
|
||||||
|
|
||||||
switch (token.GameVersion)
|
switch (token.GameVersion)
|
||||||
{
|
{
|
||||||
|
@ -109,10 +142,35 @@ public class ScoreController : ControllerBase
|
||||||
return this.Ok(myRanking);
|
return this.Ok(myRanking);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("friendscores/user/{slotId:int}/{type:int}")]
|
[HttpGet("friendscores/{slotType}/{slotId:int}/{type:int}")]
|
||||||
public IActionResult FriendScores(int slotId, int type)
|
public async Task<IActionResult> FriendScores(string slotType, int slotId, int type, [FromQuery] int pageStart = -1, [FromQuery] int pageSize = 5)
|
||||||
//=> await TopScores(slotId, type);
|
{
|
||||||
=> this.Ok(LbpSerializer.BlankElement("scores"));
|
GameToken? token = await this.database.GameTokenFromRequest(this.Request);
|
||||||
|
if (token == null) return this.StatusCode(403, "");
|
||||||
|
|
||||||
|
if (pageSize <= 0) return this.BadRequest();
|
||||||
|
|
||||||
|
string username = await this.database.UsernameFromGameToken(token);
|
||||||
|
|
||||||
|
if (SlotHelper.IsTypeInvalid(slotType)) return this.BadRequest();
|
||||||
|
|
||||||
|
if (slotType == "developer") slotId = await SlotHelper.GetPlaceholderSlotId(this.database, slotId, SlotType.Developer);
|
||||||
|
|
||||||
|
UserFriendData? store = UserFriendStore.GetUserFriendData(token.UserId);
|
||||||
|
if (store == null) return this.Ok();
|
||||||
|
|
||||||
|
List<string> friendNames = new();
|
||||||
|
|
||||||
|
foreach (int friendId in store.FriendIds)
|
||||||
|
{
|
||||||
|
string? friendUsername = await this.database.Users.Where(u => u.UserId == friendId)
|
||||||
|
.Select(u => u.Username)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
if (friendUsername != null) friendNames.Add(friendUsername);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.Ok(this.getScores(slotId, type, username, pageStart, pageSize, "scores", friendNames.ToArray()));
|
||||||
|
}
|
||||||
|
|
||||||
[HttpGet("topscores/{slotType}/{slotId:int}/{type:int}")]
|
[HttpGet("topscores/{slotType}/{slotId:int}/{type:int}")]
|
||||||
[SuppressMessage("ReSharper", "PossibleMultipleEnumeration")]
|
[SuppressMessage("ReSharper", "PossibleMultipleEnumeration")]
|
||||||
|
@ -140,13 +198,15 @@ public class ScoreController : ControllerBase
|
||||||
string username,
|
string username,
|
||||||
int pageStart = -1,
|
int pageStart = -1,
|
||||||
int pageSize = 5,
|
int pageSize = 5,
|
||||||
string rootName = "scores"
|
string rootName = "scores",
|
||||||
|
string[]? playerIds = null
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|
||||||
// This is hella ugly but it technically assigns the proper rank to a score
|
// This is hella ugly but it technically assigns the proper rank to a score
|
||||||
// var needed for Anonymous type returned from SELECT
|
// var needed for Anonymous type returned from SELECT
|
||||||
var rankedScores = this.database.Scores
|
var rankedScores = this.database.Scores
|
||||||
|
.Where(s => playerIds == null || playerIds.Any(id => s.PlayerIdCollection.Split(",", StringSplitOptions.None).Contains(id)))
|
||||||
.Where(s => s.SlotId == slotId && s.Type == type)
|
.Where(s => s.SlotId == slotId && s.Type == type)
|
||||||
.OrderByDescending(s => s.Points)
|
.OrderByDescending(s => s.Points)
|
||||||
.ThenBy(s => s.ScoreId)
|
.ThenBy(s => s.ScoreId)
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using LBPUnion.ProjectLighthouse.Levels;
|
using LBPUnion.ProjectLighthouse.Levels;
|
||||||
|
using LBPUnion.ProjectLighthouse.Logging;
|
||||||
using LBPUnion.ProjectLighthouse.PlayerData.Profiles;
|
using LBPUnion.ProjectLighthouse.PlayerData.Profiles;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
@ -23,10 +24,23 @@ public class PerformCaseActionsTask : IRepeatingTask
|
||||||
if (@case.Type.AffectsUser())
|
if (@case.Type.AffectsUser())
|
||||||
{
|
{
|
||||||
user = await @case.GetUserAsync(database);
|
user = await @case.GetUserAsync(database);
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
Logger.Error($"Target user for case {@case.CaseId} is null (userId={@case.AffectedId}", LogArea.Maintenance);
|
||||||
|
@case.Processed = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(@case.Type.AffectsLevel())
|
else if(@case.Type.AffectsLevel())
|
||||||
{
|
{
|
||||||
slot = await @case.GetSlotAsync(database);
|
slot = await @case.GetSlotAsync(database);
|
||||||
|
if (slot == null)
|
||||||
|
{
|
||||||
|
Logger.Error($"Target slot for case {@case.CaseId} is null (slotId={@case.AffectedId}", LogArea.Maintenance);
|
||||||
|
// Just mark as processed, this needs to be handled better in the future
|
||||||
|
@case.Processed = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (@case.Expired || @case.Dismissed)
|
if (@case.Expired || @case.Dismissed)
|
||||||
|
@ -50,7 +64,6 @@ public class PerformCaseActionsTask : IRepeatingTask
|
||||||
{
|
{
|
||||||
slot!.Hidden = false;
|
slot!.Hidden = false;
|
||||||
slot.HiddenReason = "";
|
slot.HiddenReason = "";
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CaseType.LevelDisableComments:
|
case CaseType.LevelDisableComments:
|
||||||
|
|
|
@ -47,7 +47,7 @@ public static class RepeatingTaskHandler
|
||||||
await task.Run(database);
|
await task.Run(database);
|
||||||
task.LastRan = DateTime.Now;
|
task.LastRan = DateTime.Now;
|
||||||
|
|
||||||
Logger.Debug($"Ran task \"{task.Name}\"", LogArea.Maintenace);
|
Logger.Debug($"Ran task \"{task.Name}\"", LogArea.Maintenance);
|
||||||
}
|
}
|
||||||
|
|
||||||
taskQueue.Enqueue(task);
|
taskQueue.Enqueue(task);
|
||||||
|
@ -55,7 +55,7 @@ public static class RepeatingTaskHandler
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
Logger.Warn($"Error occured while processing repeating tasks: \n{e}", LogArea.Maintenace);
|
Logger.Warn($"Error occured while processing repeating tasks: \n{e}", LogArea.Maintenance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -451,7 +451,7 @@ public class Database : DbContext
|
||||||
|
|
||||||
public async Task RemoveExpiredTokens()
|
public async Task RemoveExpiredTokens()
|
||||||
{
|
{
|
||||||
foreach (GameToken token in this.GameTokens.Where(t => DateTime.Now > t.ExpiresAt).ToList())
|
foreach (GameToken token in await this.GameTokens.Where(t => DateTime.Now > t.ExpiresAt).ToListAsync())
|
||||||
{
|
{
|
||||||
User? user = await this.Users.FirstOrDefaultAsync(u => u.UserId == token.UserId);
|
User? user = await this.Users.FirstOrDefaultAsync(u => u.UserId == token.UserId);
|
||||||
if(user != null) user.LastLogout = TimeHelper.TimestampMillis;
|
if(user != null) user.LastLogout = TimeHelper.TimestampMillis;
|
||||||
|
|
|
@ -22,5 +22,6 @@ public enum LogArea
|
||||||
Command,
|
Command,
|
||||||
Admin,
|
Admin,
|
||||||
Publish,
|
Publish,
|
||||||
Maintenace,
|
Maintenance,
|
||||||
|
Score,
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue