From 8fdd464e2e8d34838146664942d615acaad780db Mon Sep 17 00:00:00 2001 From: jvyden Date: Wed, 16 Feb 2022 19:02:07 -0500 Subject: [PATCH 01/26] [skip ci] Don't log nptickets in debug builds --- ProjectLighthouse/Controllers/GameApi/LoginController.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ProjectLighthouse/Controllers/GameApi/LoginController.cs b/ProjectLighthouse/Controllers/GameApi/LoginController.cs index 739e5322..8e95ed4e 100644 --- a/ProjectLighthouse/Controllers/GameApi/LoginController.cs +++ b/ProjectLighthouse/Controllers/GameApi/LoginController.cs @@ -34,10 +34,6 @@ public class LoginController : ControllerBase await this.Request.Body.CopyToAsync(ms); byte[] loginData = ms.ToArray(); - #if DEBUG - await IOFile.WriteAllBytesAsync($"npTicket-{TimestampHelper.TimestampMillis}.txt", loginData); - #endif - NPTicket? npTicket; try { From 2b521be45c22542faa04e256ffbbc98176d6a97b Mon Sep 17 00:00:00 2001 From: jvyden Date: Wed, 16 Feb 2022 20:24:57 -0500 Subject: [PATCH 02/26] Add user status api endpoint --- .../Controllers/Api/UserEndpoints.cs | 20 +++++++++ .../Controllers/GameApi/CommentController.cs | 23 +++++----- .../Types/ApiEndpointController.cs | 2 +- .../Types/Profiles/StatusType.cs | 7 ++++ .../Types/Profiles/UserStatus.cs | 42 +++++++++++++++++++ ProjectLighthouse/Types/User.cs | 11 +---- 6 files changed, 83 insertions(+), 22 deletions(-) create mode 100644 ProjectLighthouse/Types/Profiles/StatusType.cs create mode 100644 ProjectLighthouse/Types/Profiles/UserStatus.cs diff --git a/ProjectLighthouse/Controllers/Api/UserEndpoints.cs b/ProjectLighthouse/Controllers/Api/UserEndpoints.cs index 7fc505eb..63510326 100644 --- a/ProjectLighthouse/Controllers/Api/UserEndpoints.cs +++ b/ProjectLighthouse/Controllers/Api/UserEndpoints.cs @@ -1,10 +1,13 @@ #nullable enable using System.Threading.Tasks; using LBPUnion.ProjectLighthouse.Types; +using LBPUnion.ProjectLighthouse.Types.Profiles; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; +// ReSharper disable RouteTemplates.ActionRoutePrefixCanBeExtractedToControllerRoute + namespace LBPUnion.ProjectLighthouse.Controllers.Api; /// @@ -36,4 +39,21 @@ public class UserEndpoints : ApiEndpointController return this.Ok(user); } + + /// + /// Gets a user and their information from the database. + /// + /// The ID of the user + /// The user's status + /// The user's status, if successful. + /// The user could not be found. + [HttpGet("user/{id:int}/status")] + [ProducesResponseType(typeof(UserStatus), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task GetUserStatus(int id) + { + UserStatus userStatus = new(this.database, id); + + return this.Ok(userStatus); + } } \ No newline at end of file diff --git a/ProjectLighthouse/Controllers/GameApi/CommentController.cs b/ProjectLighthouse/Controllers/GameApi/CommentController.cs index cfca4f09..e2ca484c 100644 --- a/ProjectLighthouse/Controllers/GameApi/CommentController.cs +++ b/ProjectLighthouse/Controllers/GameApi/CommentController.cs @@ -5,7 +5,6 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using System.Xml.Serialization; -using LBPUnion.ProjectLighthouse.Helpers; using LBPUnion.ProjectLighthouse.Serialization; using LBPUnion.ProjectLighthouse.Types; using LBPUnion.ProjectLighthouse.Types.Levels; @@ -39,14 +38,13 @@ public class CommentController : ControllerBase return this.Ok(); } - [HttpGet("comments/user/{slotId:int}")] [HttpGet("userComments/{username}")] public async Task GetComments([FromQuery] int pageStart, [FromQuery] int pageSize, string? username, int? slotId) { User? user = await this.database.UserFromGameRequest(this.Request); if (user == null) return this.StatusCode(403, ""); - + int targetId = slotId.GetValueOrDefault(); CommentType type = CommentType.Level; if (!string.IsNullOrWhiteSpace(username)) @@ -55,24 +53,24 @@ public class CommentController : ControllerBase type = CommentType.Profile; } - List comments = await this.database.Comments - .Include(c => c.Poster) + List comments = await this.database.Comments.Include + (c => c.Poster) .Where(c => c.TargetId == targetId && c.Type == type) .OrderByDescending(c => c.Timestamp) .Skip(pageStart - 1) - .Take(Math.Min(pageSize, - 30)) + .Take(Math.Min(pageSize, 30)) .ToListAsync(); - string outputXml = comments.Aggregate(string.Empty, (current, comment) => current + - comment.Serialize(this.getReaction(user.UserId, comment.CommentId).Result)); + string outputXml = comments.Aggregate + (string.Empty, (current, comment) => current + comment.Serialize(this.getReaction(user.UserId, comment.CommentId).Result)); return this.Ok(LbpSerializer.StringElement("comments", outputXml)); } - public async Task getReaction(int userId, int commentId) + private async Task getReaction(int userId, int commentId) { Reaction? reaction = await this.database.Reactions.FirstOrDefaultAsync(r => r.UserId == userId && r.TargetId == commentId); if (reaction == null) return 0; + return reaction.Rating; } @@ -80,11 +78,11 @@ public class CommentController : ControllerBase [HttpPost("postComment/user/{slotId:int}")] public async Task PostComment(string? username, int? slotId) { - this.Request.Body.Position = 0; + this.Request.Body.Position = 0; string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync(); XmlSerializer serializer = new(typeof(Comment)); - Comment? comment = (Comment?) serializer.Deserialize(new StringReader(bodyString)); + Comment? comment = (Comment?)serializer.Deserialize(new StringReader(bodyString)); CommentType type = (slotId.GetValueOrDefault() == 0 ? CommentType.Profile : CommentType.Level); @@ -112,6 +110,7 @@ public class CommentController : ControllerBase Comment? comment = await this.database.Comments.FirstOrDefaultAsync(c => c.CommentId == commentId); if (comment == null) return this.NotFound(); + // if you are not the poster if (comment.PosterUserId != user.UserId) { diff --git a/ProjectLighthouse/Types/ApiEndpointController.cs b/ProjectLighthouse/Types/ApiEndpointController.cs index e026df83..7a717cab 100644 --- a/ProjectLighthouse/Types/ApiEndpointController.cs +++ b/ProjectLighthouse/Types/ApiEndpointController.cs @@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Mvc; namespace LBPUnion.ProjectLighthouse.Types; [ApiController] -[Route("/api/v1/")] +[Route("/api/v1")] [Produces("application/json")] public class ApiEndpointController : ControllerBase {} \ No newline at end of file diff --git a/ProjectLighthouse/Types/Profiles/StatusType.cs b/ProjectLighthouse/Types/Profiles/StatusType.cs new file mode 100644 index 00000000..ea7d99a6 --- /dev/null +++ b/ProjectLighthouse/Types/Profiles/StatusType.cs @@ -0,0 +1,7 @@ +namespace LBPUnion.ProjectLighthouse.Types.Profiles; + +public enum StatusType +{ + Offline = 0, + Online = 1, +} \ No newline at end of file diff --git a/ProjectLighthouse/Types/Profiles/UserStatus.cs b/ProjectLighthouse/Types/Profiles/UserStatus.cs new file mode 100644 index 00000000..67cde0f6 --- /dev/null +++ b/ProjectLighthouse/Types/Profiles/UserStatus.cs @@ -0,0 +1,42 @@ +#nullable enable +using System.Linq; +using LBPUnion.ProjectLighthouse.Helpers; + +namespace LBPUnion.ProjectLighthouse.Types.Profiles; + +public class UserStatus +{ + public StatusType StatusType { get; set; } + public GameVersion? CurrentVersion { get; set; } + + public UserStatus() + {} + + public UserStatus(Database database, int userId) + { + LastContact? lastContact = database.LastContacts.Where(l => l.UserId == userId).FirstOrDefault(l => TimestampHelper.Timestamp - l.Timestamp < 300); + + if (lastContact == null) + { + StatusType = StatusType.Offline; + CurrentVersion = null; + } + else + { + StatusType = StatusType.Online; + CurrentVersion = lastContact.GameVersion; + } + } + + public override string ToString() + { + CurrentVersion ??= GameVersion.Unknown; + + return this.StatusType switch + { + StatusType.Online => $"Currently online on {((GameVersion)this.CurrentVersion).ToPrettyString()}", + StatusType.Offline => "Offline", + _ => "Unknown", + }; + } +} \ No newline at end of file diff --git a/ProjectLighthouse/Types/User.cs b/ProjectLighthouse/Types/User.cs index 7b730d49..a370aaef 100644 --- a/ProjectLighthouse/Types/User.cs +++ b/ProjectLighthouse/Types/User.cs @@ -2,7 +2,6 @@ using System.ComponentModel.DataAnnotations.Schema; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text.Json.Serialization; -using LBPUnion.ProjectLighthouse.Helpers; using LBPUnion.ProjectLighthouse.Serialization; using LBPUnion.ProjectLighthouse.Types.Profiles; using LBPUnion.ProjectLighthouse.Types.Settings; @@ -153,16 +152,10 @@ public class User #nullable enable [NotMapped] [JsonIgnore] - public string Status { + public UserStatus Status { get { using Database database = new(); - LastContact? lastMatch = database.LastContacts.Where - (l => l.UserId == this.UserId) - .FirstOrDefault(l => TimestampHelper.Timestamp - l.Timestamp < 300); - - if (lastMatch == null) return "Offline"; - - return "Currently online on " + lastMatch.GameVersion.ToPrettyString(); + return new UserStatus(database, this.UserId); } } #nullable disable From aeeb819759a4372f4406f387691dcaef3f13c6ee Mon Sep 17 00:00:00 2001 From: jvyden Date: Thu, 17 Feb 2022 00:57:02 -0500 Subject: [PATCH 03/26] Increase information in UserStatus, add platform for lastcontacts and gametokens --- .../GameApi/Matching/MatchController.cs | 2 +- ProjectLighthouse/Database.cs | 3 +- .../Helpers/LastContactHelper.cs | 3 +- ProjectLighthouse/Helpers/RoomHelper.cs | 9 ++++ ...AddPlatformForLastContactsAndGameTokens.cs | 41 +++++++++++++++++++ .../Migrations/DatabaseModelSnapshot.cs | 6 +++ ProjectLighthouse/Startup/Startup.cs | 3 +- ProjectLighthouse/Types/GameToken.cs | 2 + ProjectLighthouse/Types/Match/Room.cs | 21 +++++++--- ProjectLighthouse/Types/Match/RoomSlot.cs | 4 +- .../Types/Profiles/LastContact.cs | 2 + .../Types/Profiles/UserStatus.cs | 10 ++++- 12 files changed, 93 insertions(+), 13 deletions(-) create mode 100644 ProjectLighthouse/Migrations/20220217045519_AddPlatformForLastContactsAndGameTokens.cs diff --git a/ProjectLighthouse/Controllers/GameApi/Matching/MatchController.cs b/ProjectLighthouse/Controllers/GameApi/Matching/MatchController.cs index 7ba10605..f173e1bc 100644 --- a/ProjectLighthouse/Controllers/GameApi/Matching/MatchController.cs +++ b/ProjectLighthouse/Controllers/GameApi/Matching/MatchController.cs @@ -74,7 +74,7 @@ public class MatchController : ControllerBase #endregion - await LastContactHelper.SetLastContact(user, gameToken.GameVersion); + await LastContactHelper.SetLastContact(user, gameToken.GameVersion, gameToken.Platform); #region Process match data diff --git a/ProjectLighthouse/Database.cs b/ProjectLighthouse/Database.cs index 6ae7f4e2..abb0977a 100644 --- a/ProjectLighthouse/Database.cs +++ b/ProjectLighthouse/Database.cs @@ -82,6 +82,7 @@ public class Database : DbContext UserId = user.UserId, UserLocation = userLocation, GameVersion = npTicket.GameVersion, + Platform = npTicket.Platform, }; this.GameTokens.Add(gameToken); @@ -151,7 +152,7 @@ public class Database : DbContext else { Slot? targetSlot = await this.Slots.FirstOrDefaultAsync(u => u.SlotId == targetId); - if(targetSlot == null) return false; + if (targetSlot == null) return false; } this.Comments.Add diff --git a/ProjectLighthouse/Helpers/LastContactHelper.cs b/ProjectLighthouse/Helpers/LastContactHelper.cs index cdc7a06d..8f76bf22 100644 --- a/ProjectLighthouse/Helpers/LastContactHelper.cs +++ b/ProjectLighthouse/Helpers/LastContactHelper.cs @@ -11,7 +11,7 @@ public static class LastContactHelper { private static readonly Database database = new(); - public static async Task SetLastContact(User user, GameVersion gameVersion) + public static async Task SetLastContact(User user, GameVersion gameVersion, Platform platform) { LastContact? lastContact = await database.LastContacts.Where(l => l.UserId == user.UserId).FirstOrDefaultAsync(); @@ -28,6 +28,7 @@ public static class LastContactHelper lastContact.Timestamp = TimestampHelper.Timestamp; lastContact.GameVersion = gameVersion; + lastContact.Platform = platform; await database.SaveChangesAsync(); } diff --git a/ProjectLighthouse/Helpers/RoomHelper.cs b/ProjectLighthouse/Helpers/RoomHelper.cs index 7cca021b..cc81af01 100644 --- a/ProjectLighthouse/Helpers/RoomHelper.cs +++ b/ProjectLighthouse/Helpers/RoomHelper.cs @@ -152,6 +152,15 @@ public class RoomHelper return createIfDoesNotExist ? CreateRoom(user, roomVersion) : null; } + public static Room? FindRoomByUserId(int userId) + { + lock(Rooms) + foreach (Room room in Rooms.Where(room => room.Players.Any(player => player.UserId == userId))) + return room; + + return null; + } + [SuppressMessage("ReSharper", "InvertIf")] public static void CleanupRooms(User? host = null, Room? newRoom = null) { diff --git a/ProjectLighthouse/Migrations/20220217045519_AddPlatformForLastContactsAndGameTokens.cs b/ProjectLighthouse/Migrations/20220217045519_AddPlatformForLastContactsAndGameTokens.cs new file mode 100644 index 00000000..78342cfe --- /dev/null +++ b/ProjectLighthouse/Migrations/20220217045519_AddPlatformForLastContactsAndGameTokens.cs @@ -0,0 +1,41 @@ +using LBPUnion.ProjectLighthouse; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ProjectLighthouse.Migrations +{ + [DbContext(typeof(Database))] + [Migration("20220217045519_AddPlatformForLastContactsAndGameTokens")] + public partial class AddPlatformForLastContactsAndGameTokens : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Platform", + table: "LastContacts", + type: "int", + nullable: false, + defaultValue: -1); + + migrationBuilder.AddColumn( + name: "Platform", + table: "GameTokens", + type: "int", + nullable: false, + defaultValue: -1); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Platform", + table: "LastContacts"); + + migrationBuilder.DropColumn( + name: "Platform", + table: "GameTokens"); + } + } +} diff --git a/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs b/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs index 21676d01..23e9069d 100644 --- a/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs +++ b/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs @@ -81,6 +81,9 @@ namespace ProjectLighthouse.Migrations b.Property("GameVersion") .HasColumnType("int"); + b.Property("Platform") + .HasColumnType("int"); + b.Property("Used") .HasColumnType("tinyint(1)"); @@ -458,6 +461,9 @@ namespace ProjectLighthouse.Migrations b.Property("GameVersion") .HasColumnType("int"); + b.Property("Platform") + .HasColumnType("int"); + b.Property("Timestamp") .HasColumnType("bigint"); diff --git a/ProjectLighthouse/Startup/Startup.cs b/ProjectLighthouse/Startup/Startup.cs index 5cc33fe0..97c6833f 100644 --- a/ProjectLighthouse/Startup/Startup.cs +++ b/ProjectLighthouse/Startup/Startup.cs @@ -250,7 +250,8 @@ public class Startup if (gameToken != null && gameToken.GameVersion == GameVersion.LittleBigPlanet1) // Ignore UserFromGameToken null because user must exist for a token to exist - await LastContactHelper.SetLastContact((await database.UserFromGameToken(gameToken))!, GameVersion.LittleBigPlanet1); + await LastContactHelper.SetLastContact + ((await database.UserFromGameToken(gameToken))!, GameVersion.LittleBigPlanet1, gameToken.Platform); } #nullable disable diff --git a/ProjectLighthouse/Types/GameToken.cs b/ProjectLighthouse/Types/GameToken.cs index d084c034..0e57d7fd 100644 --- a/ProjectLighthouse/Types/GameToken.cs +++ b/ProjectLighthouse/Types/GameToken.cs @@ -20,6 +20,8 @@ public class GameToken public GameVersion GameVersion { get; set; } + public Platform Platform { get; set; } + // Set by /authentication webpage public bool Approved { get; set; } diff --git a/ProjectLighthouse/Types/Match/Room.cs b/ProjectLighthouse/Types/Match/Room.cs index aa659041..1541cb10 100644 --- a/ProjectLighthouse/Types/Match/Room.cs +++ b/ProjectLighthouse/Types/Match/Room.cs @@ -1,23 +1,34 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Text.Json.Serialization; using LBPUnion.ProjectLighthouse.Types.Levels; namespace LBPUnion.ProjectLighthouse.Types.Match; public class Room { - public List Players; - public int RoomId; + [JsonIgnore] + public List Players { get; set; } - public GameVersion RoomVersion; - public RoomSlot Slot; - public RoomState State; + public int RoomId { get; set; } + [JsonIgnore] + public GameVersion RoomVersion { get; set; } + + public RoomSlot Slot { get; set; } + public RoomState State { get; set; } + + [JsonIgnore] public bool IsInPod => this.Slot.SlotType == SlotType.Pod; + + [JsonIgnore] public bool IsLookingForPlayers => this.State == RoomState.PlayingLevel || this.State == RoomState.DivingInWaiting; + [JsonIgnore] public User Host => this.Players[0]; + public int PlayerCount => this.Players.Count; + #nullable enable public override bool Equals(object? obj) { diff --git a/ProjectLighthouse/Types/Match/RoomSlot.cs b/ProjectLighthouse/Types/Match/RoomSlot.cs index 063715d4..b3d2c0e4 100644 --- a/ProjectLighthouse/Types/Match/RoomSlot.cs +++ b/ProjectLighthouse/Types/Match/RoomSlot.cs @@ -4,6 +4,6 @@ namespace LBPUnion.ProjectLighthouse.Types.Match; public class RoomSlot { - public int SlotId; - public SlotType SlotType; + public int SlotId { get; set; } + public SlotType SlotType { get; set; } } \ No newline at end of file diff --git a/ProjectLighthouse/Types/Profiles/LastContact.cs b/ProjectLighthouse/Types/Profiles/LastContact.cs index 7fb0593a..14073106 100644 --- a/ProjectLighthouse/Types/Profiles/LastContact.cs +++ b/ProjectLighthouse/Types/Profiles/LastContact.cs @@ -10,4 +10,6 @@ public class LastContact public long Timestamp { get; set; } public GameVersion GameVersion { get; set; } = GameVersion.Unknown; + + public Platform Platform { get; set; } = Platform.Unknown; } \ No newline at end of file diff --git a/ProjectLighthouse/Types/Profiles/UserStatus.cs b/ProjectLighthouse/Types/Profiles/UserStatus.cs index 67cde0f6..c9192a35 100644 --- a/ProjectLighthouse/Types/Profiles/UserStatus.cs +++ b/ProjectLighthouse/Types/Profiles/UserStatus.cs @@ -1,6 +1,7 @@ #nullable enable using System.Linq; using LBPUnion.ProjectLighthouse.Helpers; +using LBPUnion.ProjectLighthouse.Types.Match; namespace LBPUnion.ProjectLighthouse.Types.Profiles; @@ -8,6 +9,8 @@ public class UserStatus { public StatusType StatusType { get; set; } public GameVersion? CurrentVersion { get; set; } + public Platform? CurrentPlatform { get; set; } + public Room? CurrentRoom { get; set; } public UserStatus() {} @@ -25,16 +28,19 @@ public class UserStatus { StatusType = StatusType.Online; CurrentVersion = lastContact.GameVersion; + CurrentPlatform = lastContact.Platform; } + + CurrentRoom = RoomHelper.FindRoomByUserId(userId); } public override string ToString() { CurrentVersion ??= GameVersion.Unknown; - + CurrentPlatform ??= Platform.Unknown; return this.StatusType switch { - StatusType.Online => $"Currently online on {((GameVersion)this.CurrentVersion).ToPrettyString()}", + StatusType.Online => $"Currently online on {((GameVersion)this.CurrentVersion).ToPrettyString()} on {((Platform)this.CurrentPlatform)}", StatusType.Offline => "Offline", _ => "Unknown", }; From fcdbd46c987bf6d4390e58ade087cc63cf2742bb Mon Sep 17 00:00:00 2001 From: jvyden Date: Thu, 17 Feb 2022 12:36:53 -0500 Subject: [PATCH 04/26] Remove offline players from rooms --- ProjectLighthouse/Helpers/RoomHelper.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ProjectLighthouse/Helpers/RoomHelper.cs b/ProjectLighthouse/Helpers/RoomHelper.cs index cc81af01..cf22d8a4 100644 --- a/ProjectLighthouse/Helpers/RoomHelper.cs +++ b/ProjectLighthouse/Helpers/RoomHelper.cs @@ -7,6 +7,7 @@ using LBPUnion.ProjectLighthouse.Logging; using LBPUnion.ProjectLighthouse.Types; using LBPUnion.ProjectLighthouse.Types.Levels; using LBPUnion.ProjectLighthouse.Types.Match; +using LBPUnion.ProjectLighthouse.Types.Profiles; namespace LBPUnion.ProjectLighthouse.Helpers; @@ -166,6 +167,15 @@ public class RoomHelper { lock(Rooms) { + // Remove offline players from rooms + foreach (Room room in Rooms) + { + foreach (User player in room.Players.Where(player => player.Status.StatusType == StatusType.Offline)) + { + room.Players.Remove(player); + } + } + // Delete old rooms based on host if (host != null) try From 487ec5bc8fb3f3fc840fb454a271e0be8039a469 Mon Sep 17 00:00:00 2001 From: jvyden Date: Thu, 17 Feb 2022 16:12:21 -0500 Subject: [PATCH 05/26] Move PNG conversion to FileHelper --- ProjectLighthouse/Helpers/FileHelper.cs | 46 +++++++++++++++++++++++++ ProjectLighthouse/Program.cs | 40 +-------------------- 2 files changed, 47 insertions(+), 39 deletions(-) diff --git a/ProjectLighthouse/Helpers/FileHelper.cs b/ProjectLighthouse/Helpers/FileHelper.cs index 9d8c4f20..e3e39d17 100644 --- a/ProjectLighthouse/Helpers/FileHelper.cs +++ b/ProjectLighthouse/Helpers/FileHelper.cs @@ -1,7 +1,13 @@ +#nullable enable using System; +using System.Collections.Concurrent; using System.IO; using System.Linq; using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Kettu; +using LBPUnion.ProjectLighthouse.Logging; using LBPUnion.ProjectLighthouse.Types.Files; using LBPUnion.ProjectLighthouse.Types.Settings; @@ -101,4 +107,44 @@ public static class FileHelper } public static string[] ResourcesNotUploaded(params string[] hashes) => hashes.Where(hash => !ResourceExists(hash)).ToArray(); + + public static void ConvertAllTexturesToPng() + { + EnsureDirectoryCreated(Path.Combine(Environment.CurrentDirectory, "png")); + if (Directory.Exists("r")) + { + Logger.Log + ("Converting all textures to PNG. This may take a while if this is the first time running this operation...", LoggerLevelStartup.Instance); + + ConcurrentQueue fileQueue = new(); + + foreach (string filename in Directory.GetFiles("r")) fileQueue.Enqueue(filename); + + for(int i = 0; i < Environment.ProcessorCount; i++) + { + Task.Factory.StartNew + ( + () => + { + while (fileQueue.TryDequeue(out string? filename)) + { + LbpFile? file = LbpFile.FromHash(filename.Replace("r" + Path.DirectorySeparatorChar, "")); + if (file == null) continue; + + if (file.FileType == LbpFileType.Jpeg || file.FileType == LbpFileType.Png || file.FileType == LbpFileType.Texture) + { + ImageHelper.LbpFileToPNG(file); + } + } + } + ); + } + + while (!fileQueue.IsEmpty) + { + Thread.Sleep(100); + } + } + } + } \ No newline at end of file diff --git a/ProjectLighthouse/Program.cs b/ProjectLighthouse/Program.cs index eda0cb43..65a7077f 100644 --- a/ProjectLighthouse/Program.cs +++ b/ProjectLighthouse/Program.cs @@ -1,14 +1,10 @@ #nullable enable using System; -using System.Collections.Concurrent; using System.Diagnostics; -using System.IO; using System.Threading; -using System.Threading.Tasks; using Kettu; using LBPUnion.ProjectLighthouse.Helpers; using LBPUnion.ProjectLighthouse.Logging; -using LBPUnion.ProjectLighthouse.Types.Files; using LBPUnion.ProjectLighthouse.Types.Settings; using Microsoft.AspNetCore.Hosting; using Microsoft.EntityFrameworkCore; @@ -82,41 +78,7 @@ public static class Program return; } - FileHelper.EnsureDirectoryCreated(Path.Combine(Environment.CurrentDirectory, "png")); - if (Directory.Exists("r")) - { - Logger.Log - ("Converting all textures to PNG. This may take a while if this is the first time running this operation...", LoggerLevelStartup.Instance); - - ConcurrentQueue fileQueue = new(); - - foreach (string filename in Directory.GetFiles("r")) fileQueue.Enqueue(filename); - - for(int i = 0; i < Environment.ProcessorCount; i++) - { - Task.Factory.StartNew - ( - () => - { - while (fileQueue.TryDequeue(out string? filename)) - { - LbpFile? file = LbpFile.FromHash(filename.Replace("r" + Path.DirectorySeparatorChar, "")); - if (file == null) continue; - - if (file.FileType == LbpFileType.Jpeg || file.FileType == LbpFileType.Png || file.FileType == LbpFileType.Texture) - { - ImageHelper.LbpFileToPNG(file); - } - } - } - ); - } - - while (!fileQueue.IsEmpty) - { - Thread.Sleep(100); - } - } + FileHelper.ConvertAllTexturesToPng(); stopwatch.Stop(); Logger.Log($"Ready! Startup took {stopwatch.ElapsedMilliseconds}ms. Passing off control to ASP.NET...", LoggerLevelStartup.Instance); From 3f2993462818e2e5d75c752d079d8458cb7d7438 Mon Sep 17 00:00:00 2001 From: jvyden Date: Thu, 17 Feb 2022 16:16:55 -0500 Subject: [PATCH 06/26] Add automatic room cleanup --- ProjectLighthouse/Helpers/RoomHelper.cs | 26 +++++++++++++++++++++++++ ProjectLighthouse/Program.cs | 3 +++ 2 files changed, 29 insertions(+) diff --git a/ProjectLighthouse/Helpers/RoomHelper.cs b/ProjectLighthouse/Helpers/RoomHelper.cs index cf22d8a4..0ae4343c 100644 --- a/ProjectLighthouse/Helpers/RoomHelper.cs +++ b/ProjectLighthouse/Helpers/RoomHelper.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Threading.Tasks; using Kettu; using LBPUnion.ProjectLighthouse.Logging; using LBPUnion.ProjectLighthouse.Types; @@ -23,6 +24,22 @@ public class RoomHelper private static int roomIdIncrement; + public static void StartCleanupThread() + { + // ReSharper disable once FunctionNeverReturns + Task.Factory.StartNew + ( + async () => + { + while (true) + { + CleanupRooms(); + await Task.Delay(10000); + } + } + ); + } + internal static int RoomIdIncrement => roomIdIncrement++; public static FindBestRoomResponse? FindBestRoom(User? user, GameVersion roomVersion, string? location) @@ -167,6 +184,8 @@ public class RoomHelper { lock(Rooms) { + int roomCountBeforeCleanup = Rooms.Count; + // Remove offline players from rooms foreach (Room room in Rooms) { @@ -198,6 +217,13 @@ public class RoomHelper Rooms.RemoveAll(r => r.Players.Count == 0); // Remove empty rooms Rooms.RemoveAll(r => r.Players.Count > 4); // Remove obviously bogus rooms + + int roomCountAfterCleanup = Rooms.Count; + + if (roomCountBeforeCleanup != roomCountAfterCleanup) + { + Logger.Log($"Cleaned up {roomCountBeforeCleanup - roomCountAfterCleanup} rooms.", LoggerLevelMatch.Instance); + } } } } \ No newline at end of file diff --git a/ProjectLighthouse/Program.cs b/ProjectLighthouse/Program.cs index 65a7077f..0fcfaab5 100644 --- a/ProjectLighthouse/Program.cs +++ b/ProjectLighthouse/Program.cs @@ -80,6 +80,9 @@ public static class Program FileHelper.ConvertAllTexturesToPng(); + Logger.Log("Starting room cleanup thread...", LoggerLevelStartup.Instance); + RoomHelper.StartCleanupThread(); + stopwatch.Stop(); Logger.Log($"Ready! Startup took {stopwatch.ElapsedMilliseconds}ms. Passing off control to ASP.NET...", LoggerLevelStartup.Instance); From 41dde8eed2f64f61c6fa23c8367fa332ce3f8ec2 Mon Sep 17 00:00:00 2001 From: jvyden Date: Thu, 17 Feb 2022 16:23:09 -0500 Subject: [PATCH 07/26] Add platform matching to rooms --- .../Controllers/GameApi/LoginController.cs | 2 +- .../Controllers/GameApi/Matching/MatchController.cs | 6 +++--- .../Website/Debug/RoomVisualizerController.cs | 2 +- ProjectLighthouse/Helpers/RoomHelper.cs | 13 ++++++++----- .../Pages/Debug/RoomVisualizerPage.cshtml | 4 ++-- ProjectLighthouse/Types/Match/Room.cs | 3 +++ 6 files changed, 18 insertions(+), 12 deletions(-) diff --git a/ProjectLighthouse/Controllers/GameApi/LoginController.cs b/ProjectLighthouse/Controllers/GameApi/LoginController.cs index 8e95ed4e..20ec33ae 100644 --- a/ProjectLighthouse/Controllers/GameApi/LoginController.cs +++ b/ProjectLighthouse/Controllers/GameApi/LoginController.cs @@ -141,7 +141,7 @@ public class LoginController : ControllerBase await this.database.SaveChangesAsync(); // Create a new room on LBP2/3/Vita - if (token.GameVersion != GameVersion.LittleBigPlanet1) RoomHelper.CreateRoom(user, token.GameVersion); + if (token.GameVersion != GameVersion.LittleBigPlanet1) RoomHelper.CreateRoom(user, token.GameVersion, token.Platform); return this.Ok ( diff --git a/ProjectLighthouse/Controllers/GameApi/Matching/MatchController.cs b/ProjectLighthouse/Controllers/GameApi/Matching/MatchController.cs index f173e1bc..d250fb44 100644 --- a/ProjectLighthouse/Controllers/GameApi/Matching/MatchController.cs +++ b/ProjectLighthouse/Controllers/GameApi/Matching/MatchController.cs @@ -81,7 +81,7 @@ public class MatchController : ControllerBase if (matchData is UpdateMyPlayerData playerData) { MatchHelper.SetUserLocation(user.UserId, gameToken.UserLocation); - Room? room = RoomHelper.FindRoomByUser(user, gameToken.GameVersion, true); + Room? room = RoomHelper.FindRoomByUser(user, gameToken.GameVersion, gameToken.Platform, true); if (playerData.RoomState != null) if (room != null && Equals(room.Host, user)) @@ -90,7 +90,7 @@ public class MatchController : ControllerBase if (matchData is FindBestRoom && MatchHelper.UserLocations.Count > 1) { - FindBestRoomResponse? response = RoomHelper.FindBestRoom(user, gameToken.GameVersion, gameToken.UserLocation); + FindBestRoomResponse? response = RoomHelper.FindBestRoom(user, gameToken.GameVersion, gameToken.Platform, gameToken.UserLocation); if (response == null) return this.NotFound(); @@ -112,7 +112,7 @@ public class MatchController : ControllerBase } // Create a new one as requested - RoomHelper.CreateRoom(users, gameToken.GameVersion, createRoom.RoomSlot); + RoomHelper.CreateRoom(users, gameToken.GameVersion, gameToken.Platform, createRoom.RoomSlot); } if (matchData is UpdatePlayersInRoom updatePlayersInRoom) diff --git a/ProjectLighthouse/Controllers/Website/Debug/RoomVisualizerController.cs b/ProjectLighthouse/Controllers/Website/Debug/RoomVisualizerController.cs index 854f05c9..cc690c93 100644 --- a/ProjectLighthouse/Controllers/Website/Debug/RoomVisualizerController.cs +++ b/ProjectLighthouse/Controllers/Website/Debug/RoomVisualizerController.cs @@ -26,7 +26,7 @@ public class RoomVisualizerController : ControllerBase return this.NotFound(); #else List users = await this.database.Users.OrderByDescending(_ => EF.Functions.Random()).Take(2).ToListAsync(); - RoomHelper.CreateRoom(users, GameVersion.LittleBigPlanet2); + RoomHelper.CreateRoom(users, GameVersion.LittleBigPlanet2, Platform.PS3); foreach (User user in users) { diff --git a/ProjectLighthouse/Helpers/RoomHelper.cs b/ProjectLighthouse/Helpers/RoomHelper.cs index 0ae4343c..cbf3dc8a 100644 --- a/ProjectLighthouse/Helpers/RoomHelper.cs +++ b/ProjectLighthouse/Helpers/RoomHelper.cs @@ -42,7 +42,7 @@ public class RoomHelper internal static int RoomIdIncrement => roomIdIncrement++; - public static FindBestRoomResponse? FindBestRoom(User? user, GameVersion roomVersion, string? location) + public static FindBestRoomResponse? FindBestRoom(User? user, GameVersion roomVersion, Platform? platform, string? location) { if (roomVersion == GameVersion.LittleBigPlanet1 || roomVersion == GameVersion.LittleBigPlanetPSP) { @@ -60,6 +60,7 @@ public class RoomHelper } rooms = rooms.Where(r => r.RoomVersion == roomVersion).ToList(); + if (platform != null) rooms = rooms.Where(r => r.RoomPlatform == platform).ToList(); foreach (Room room in rooms) // Look for rooms looking for players before moving on to rooms that are idle. @@ -133,7 +134,7 @@ public class RoomHelper return null; } - public static Room CreateRoom(User user, GameVersion roomVersion, RoomSlot? slot = null) + public static Room CreateRoom(User user, GameVersion roomVersion, Platform roomPlatform, RoomSlot? slot = null) => CreateRoom ( new List @@ -141,9 +142,10 @@ public class RoomHelper user, }, roomVersion, + roomPlatform, slot ); - public static Room CreateRoom(List users, GameVersion roomVersion, RoomSlot? slot = null) + public static Room CreateRoom(List users, GameVersion roomVersion, Platform roomPlatform, RoomSlot? slot = null) { Room room = new() { @@ -152,6 +154,7 @@ public class RoomHelper State = RoomState.Idle, Slot = slot ?? PodSlot, RoomVersion = roomVersion, + RoomPlatform = roomPlatform, }; CleanupRooms(room.Host, room); @@ -161,13 +164,13 @@ public class RoomHelper return room; } - public static Room? FindRoomByUser(User user, GameVersion roomVersion, bool createIfDoesNotExist = false) + public static Room? FindRoomByUser(User user, GameVersion roomVersion, Platform roomPlatform, bool createIfDoesNotExist = false) { lock(Rooms) foreach (Room room in Rooms.Where(room => room.Players.Any(player => user == player))) return room; - return createIfDoesNotExist ? CreateRoom(user, roomVersion) : null; + return createIfDoesNotExist ? CreateRoom(user, roomVersion, roomPlatform) : null; } public static Room? FindRoomByUserId(int userId) diff --git a/ProjectLighthouse/Pages/Debug/RoomVisualizerPage.cshtml b/ProjectLighthouse/Pages/Debug/RoomVisualizerPage.cshtml index 0316b86c..265b4951 100644 --- a/ProjectLighthouse/Pages/Debug/RoomVisualizerPage.cshtml +++ b/ProjectLighthouse/Pages/Debug/RoomVisualizerPage.cshtml @@ -52,7 +52,7 @@ { if (version == GameVersion.LittleBigPlanet1 || version == GameVersion.LittleBigPlanetPSP || version == GameVersion.Unknown) continue; - FindBestRoomResponse? response = RoomHelper.FindBestRoom(null, version, null); + FindBestRoomResponse? response = RoomHelper.FindBestRoom(null, version, null, null); string text = response == null ? "No room found." : "Room " + response.RoomId;

Best room for @version.ToPrettyString(): @text

@@ -72,7 +72,7 @@ You are currently in this room.

} -

@room.Players.Count players, state is @room.State, version is @room.RoomVersion.ToPrettyString()

+

@room.Players.Count players, state is @room.State, version is @room.RoomVersion.ToPrettyString()on paltform @room.RoomPlatform

Slot type: @room.Slot.SlotType, slot id: @room.Slot.SlotId

@foreach (User player in room.Players) { diff --git a/ProjectLighthouse/Types/Match/Room.cs b/ProjectLighthouse/Types/Match/Room.cs index 1541cb10..63128150 100644 --- a/ProjectLighthouse/Types/Match/Room.cs +++ b/ProjectLighthouse/Types/Match/Room.cs @@ -15,6 +15,9 @@ public class Room [JsonIgnore] public GameVersion RoomVersion { get; set; } + [JsonIgnore] + public Platform RoomPlatform { get; set; } + public RoomSlot Slot { get; set; } public RoomState State { get; set; } From 7b5ce09fb471ee73497c39be25e841797f4400f9 Mon Sep 17 00:00:00 2001 From: jvyden Date: Fri, 18 Feb 2022 16:32:33 -0500 Subject: [PATCH 08/26] Fix collection modified error when cleaning up rooms --- ProjectLighthouse/Helpers/RoomHelper.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ProjectLighthouse/Helpers/RoomHelper.cs b/ProjectLighthouse/Helpers/RoomHelper.cs index cbf3dc8a..81db373a 100644 --- a/ProjectLighthouse/Helpers/RoomHelper.cs +++ b/ProjectLighthouse/Helpers/RoomHelper.cs @@ -192,10 +192,9 @@ public class RoomHelper // Remove offline players from rooms foreach (Room room in Rooms) { - foreach (User player in room.Players.Where(player => player.Status.StatusType == StatusType.Offline)) - { - room.Players.Remove(player); - } + // do not shorten, this prevents collection modified errors + List playersToRemove = room.Players.Where(player => player.Status.StatusType == StatusType.Offline).ToList(); + foreach (User user in playersToRemove) room.Players.Remove(user); } // Delete old rooms based on host From a3e8c291420089cf8bb20c781bd65fa61590da72 Mon Sep 17 00:00:00 2001 From: jvyden Date: Fri, 18 Feb 2022 17:42:53 -0500 Subject: [PATCH 09/26] Check used slots for version on upload, not for all versions --- .../Controllers/GameApi/Slots/PublishController.cs | 14 +++++++++++--- ProjectLighthouse/Types/User.cs | 7 +++++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/ProjectLighthouse/Controllers/GameApi/Slots/PublishController.cs b/ProjectLighthouse/Controllers/GameApi/Slots/PublishController.cs index b7128d8d..564a0607 100644 --- a/ProjectLighthouse/Controllers/GameApi/Slots/PublishController.cs +++ b/ProjectLighthouse/Controllers/GameApi/Slots/PublishController.cs @@ -33,10 +33,18 @@ public class PublishController : ControllerBase [HttpPost("startPublish")] public async Task StartPublish() { - User? user = await this.database.UserFromGameRequest(this.Request); - if (user == null) return this.StatusCode(403, ""); + (User, GameToken)? userAndToken = await this.database.UserAndGameTokenFromRequest(this.Request); - if (user.UsedSlots >= ServerSettings.Instance.EntitledSlots) return this.BadRequest(); + if (userAndToken == null) return this.StatusCode(403, ""); + + // ReSharper disable once PossibleInvalidOperationException + User user = userAndToken.Value.Item1; + GameToken gameToken = userAndToken.Value.Item2; + + if (user.GetUsedSlotsForGame(gameToken.GameVersion, database) > 50) + { + return this.StatusCode(403, ""); + } Slot? slot = await this.getSlotFromBody(); if (slot == null) return this.BadRequest(); // if the level cant be parsed then it obviously cant be uploaded diff --git a/ProjectLighthouse/Types/User.cs b/ProjectLighthouse/Types/User.cs index a370aaef..0678209d 100644 --- a/ProjectLighthouse/Types/User.cs +++ b/ProjectLighthouse/Types/User.cs @@ -223,11 +223,14 @@ public class User } } - public int GetUsedSlotsForGame(GameVersion version) + #nullable enable + public int GetUsedSlotsForGame(GameVersion version, Database? database = null) { - using Database database = new(); + database ??= new Database(); + return database.Slots.Count(s => s.CreatorId == this.UserId && s.GameVersion == version); } + #nullable disable /// /// The number of slots remaining on the earth From 3cda95447b509f0575cb12f1cde936a6705cd8ad Mon Sep 17 00:00:00 2001 From: jvyden Date: Fri, 18 Feb 2022 17:51:40 -0500 Subject: [PATCH 10/26] Show sublevels for creators of sublevels --- .../Controllers/GameApi/Slots/SlotsController.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/ProjectLighthouse/Controllers/GameApi/Slots/SlotsController.cs b/ProjectLighthouse/Controllers/GameApi/Slots/SlotsController.cs index 04d94441..950be32c 100644 --- a/ProjectLighthouse/Controllers/GameApi/Slots/SlotsController.cs +++ b/ProjectLighthouse/Controllers/GameApi/Slots/SlotsController.cs @@ -24,16 +24,22 @@ public class SlotsController : ControllerBase this.database = database; } - private IQueryable getSlots(GameVersion gameVersion) + private IQueryable getSlots(GameVersion gameVersion, bool includeSublevels = false) { IQueryable query = this.database.Slots.Include(s => s.Creator).Include(s => s.Location); if (gameVersion == GameVersion.LittleBigPlanetVita || gameVersion == GameVersion.LittleBigPlanetPSP || gameVersion == GameVersion.Unknown) { - return query.Where(s => s.GameVersion == gameVersion && !s.SubLevel); + query = query.Where(s => s.GameVersion == gameVersion); + } + else + { + query = query.Where(s => s.GameVersion <= gameVersion); } - return query.Where(s => s.GameVersion <= gameVersion && !s.SubLevel); + if (!includeSublevels) query = query.Where(s => !s.SubLevel); + + return query; } [HttpGet("slots/by")] @@ -49,8 +55,7 @@ public class SlotsController : ControllerBase string response = Enumerable.Aggregate ( - this.getSlots - (gameVersion) + this.getSlots(gameVersion, token.UserId == user.UserId) .Where(s => s.Creator!.Username == user.Username) .Skip(pageStart - 1) .Take(Math.Min(pageSize, ServerSettings.Instance.EntitledSlots)), From be9e3edef546a0a74326361389f2ac8bec93e0ab Mon Sep 17 00:00:00 2001 From: Josh Date: Mon, 21 Feb 2022 11:03:25 -0600 Subject: [PATCH 11/26] Fix review button not showing up (#180) --- .../GameApi/Slots/ReviewController.cs | 38 ++----------------- ProjectLighthouse/Types/Levels/Slot.cs | 9 ++--- 2 files changed, 7 insertions(+), 40 deletions(-) diff --git a/ProjectLighthouse/Controllers/GameApi/Slots/ReviewController.cs b/ProjectLighthouse/Controllers/GameApi/Slots/ReviewController.cs index e7ad7d7f..71bbc3f4 100644 --- a/ProjectLighthouse/Controllers/GameApi/Slots/ReviewController.cs +++ b/ProjectLighthouse/Controllers/GameApi/Slots/ReviewController.cs @@ -17,7 +17,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers.GameApi.Slots; [ApiController] [Route("LITTLEBIGPLANETPS3_XML/")] -[Produces("text/plain")] +[Produces("text/xml")] public class ReviewController : ControllerBase { private readonly Database database; @@ -141,51 +141,19 @@ public class ReviewController : ControllerBase GameVersion gameVersion = gameToken.GameVersion; - Random rand = new(); - - Review? yourReview = await this.database.Reviews.FirstOrDefaultAsync - (r => r.ReviewerId == user.UserId && r.SlotId == slotId && r.Slot.GameVersion <= gameVersion); - - VisitedLevel? visitedLevel = await this.database.VisitedLevels.FirstOrDefaultAsync - (v => v.UserId == user.UserId && v.SlotId == slotId && v.Slot.GameVersion <= gameVersion); - Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == slotId); if (slot == null) return this.BadRequest(); - bool canNowReviewLevel = slot.CreatorId != user.UserId && visitedLevel != null && yourReview == null; - if (canNowReviewLevel) - { - RatedLevel? ratedLevel = await this.database.RatedLevels.FirstOrDefaultAsync - (r => r.UserId == user.UserId && r.SlotId == slotId && r.Slot.GameVersion <= gameVersion); - - yourReview = new Review(); - yourReview.ReviewerId = user.UserId; - yourReview.Reviewer = user; - yourReview.Thumb = ratedLevel?.Rating ?? 0; - yourReview.Slot = slot; - yourReview.SlotId = slotId; - yourReview.Deleted = false; - yourReview.DeletedBy = DeletedBy.None; - yourReview.Text = "You haven't reviewed this level yet. Edit this to write one!"; - yourReview.LabelCollection = ""; - yourReview.Timestamp = TimeHelper.UnixTimeMilliseconds(); - } - IQueryable reviews = this.database.Reviews.Where(r => r.SlotId == slotId && r.Slot.GameVersion <= gameVersion) .Include(r => r.Reviewer) .Include(r => r.Slot) .OrderByDescending(r => r.ThumbsUp) - .ThenByDescending(_ => EF.Functions.Random()) + .ThenByDescending(r => r.Timestamp) .Skip(pageStart - 1) .Take(pageSize); - IEnumerable prependedReviews; - if (canNowReviewLevel) // this can only be true if you have not posted a review but have visited the level - // prepend the fake review to the top of the list to be easily edited - prependedReviews = reviews.ToList().Prepend(yourReview); - else prependedReviews = reviews.ToList(); - string inner = prependedReviews.Aggregate + string inner = reviews.ToList().Aggregate ( string.Empty, (current, review) => diff --git a/ProjectLighthouse/Types/Levels/Slot.cs b/ProjectLighthouse/Types/Levels/Slot.cs index 23a9d495..f2a35c21 100644 --- a/ProjectLighthouse/Types/Levels/Slot.cs +++ b/ProjectLighthouse/Types/Levels/Slot.cs @@ -299,9 +299,8 @@ public class Slot LbpSerializer.StringElement("leveltype", this.LevelType) + LbpSerializer.StringElement("yourRating", yourRatingStats?.RatingLBP1) + LbpSerializer.StringElement("yourDPadRating", yourRatingStats?.Rating) + - LbpSerializer.StringElement("yourLBP1PlayCount", yourVisitedStats?.PlaysLBP1) + - LbpSerializer.StringElement("yourLBP2PlayCount", yourVisitedStats?.PlaysLBP2) + - LbpSerializer.StringElement("yourLBP3PlayCount", yourVisitedStats?.PlaysLBP3) + + LbpSerializer.StringElement("yourlbpPlayCount", yourVisitedStats?.PlaysLBP1) + + LbpSerializer.StringElement("yourlbp3PlayCount", yourVisitedStats?.PlaysLBP3) + yourReview?.Serialize("yourReview") + LbpSerializer.StringElement("reviewsEnabled", ServerSettings.Instance.LevelReviewsEnabled) + LbpSerializer.StringElement("commentsEnabled", ServerSettings.Instance.LevelCommentsEnabled) + @@ -309,14 +308,14 @@ public class Slot if (gameVersion == GameVersion.LittleBigPlanetVita) { - slotData += LbpSerializer.StringElement("yourLBP2PlayCount", yourVisitedStats?.PlaysLBPVita) + + slotData += LbpSerializer.StringElement("yourlbp2PlayCount", yourVisitedStats?.PlaysLBPVita) + LbpSerializer.StringElement("lbp2PlayCount", this.PlaysLBPVita) + LbpSerializer.StringElement("lbp2CompletionCount", this.PlaysLBPVitaComplete) + LbpSerializer.StringElement("lbp2UniquePlayCount", this.PlaysLBPVitaUnique); } else { - slotData += LbpSerializer.StringElement("yourLBP2PlayCount", yourVisitedStats?.PlaysLBPVita) + + slotData += LbpSerializer.StringElement("yourlbp2PlayCount", yourVisitedStats?.PlaysLBP2) + LbpSerializer.StringElement("lbp2PlayCount", this.PlaysLBP2) + LbpSerializer.StringElement("lbp2CompletionCount", this.PlaysLBP2Complete) + LbpSerializer.StringElement("lbp2UniquePlayCount", this.PlaysLBP2Unique); // not actually used ingame, as per above comment From 40ce3edba7347ebfe2772e007c1f994c6d1cfc40 Mon Sep 17 00:00:00 2001 From: jvyden Date: Mon, 21 Feb 2022 19:18:57 -0500 Subject: [PATCH 12/26] Use Database.RemoveSlot when removing slot on website --- .../Controllers/Website/Admin/AdminSlotController.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ProjectLighthouse/Controllers/Website/Admin/AdminSlotController.cs b/ProjectLighthouse/Controllers/Website/Admin/AdminSlotController.cs index 3f84078f..ad99952e 100644 --- a/ProjectLighthouse/Controllers/Website/Admin/AdminSlotController.cs +++ b/ProjectLighthouse/Controllers/Website/Admin/AdminSlotController.cs @@ -62,10 +62,7 @@ public class AdminSlotController : ControllerBase if (slot.Location == null) throw new ArgumentNullException(); - this.database.Locations.Remove(slot.Location); - this.database.Slots.Remove(slot); - - await this.database.SaveChangesAsync(); + await this.database.RemoveSlot(slot); return this.Ok(); } From 3e3d6b74aa622c42452388b7a0b780ac466ee6cf Mon Sep 17 00:00:00 2001 From: jvyden Date: Mon, 21 Feb 2022 19:22:26 -0500 Subject: [PATCH 13/26] Check if there are no free slots *after* handling republished levels Closes #179 --- .../GameApi/Slots/PublishController.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/ProjectLighthouse/Controllers/GameApi/Slots/PublishController.cs b/ProjectLighthouse/Controllers/GameApi/Slots/PublishController.cs index 564a0607..bcfdd34a 100644 --- a/ProjectLighthouse/Controllers/GameApi/Slots/PublishController.cs +++ b/ProjectLighthouse/Controllers/GameApi/Slots/PublishController.cs @@ -41,11 +41,6 @@ public class PublishController : ControllerBase User user = userAndToken.Value.Item1; GameToken gameToken = userAndToken.Value.Item2; - if (user.GetUsedSlotsForGame(gameToken.GameVersion, database) > 50) - { - return this.StatusCode(403, ""); - } - Slot? slot = await this.getSlotFromBody(); if (slot == null) return this.BadRequest(); // if the level cant be parsed then it obviously cant be uploaded @@ -60,6 +55,10 @@ public class PublishController : ControllerBase if (oldSlot == null) return this.NotFound(); if (oldSlot.CreatorId != user.UserId) return this.BadRequest(); } + else if (user.GetUsedSlotsForGame(gameToken.GameVersion, database) > ServerSettings.Instance.EntitledSlots) + { + return this.StatusCode(403, ""); + } slot.ResourceCollection += "," + slot.IconHash; // tells LBP to upload icon after we process resources here @@ -84,9 +83,6 @@ public class PublishController : ControllerBase // ReSharper disable once PossibleInvalidOperationException User user = userAndToken.Value.Item1; GameToken gameToken = userAndToken.Value.Item2; - - if (user.UsedSlots >= ServerSettings.Instance.EntitledSlots) return this.BadRequest(); - Slot? slot = await this.getSlotFromBody(); if (slot?.Location == null) return this.BadRequest(); @@ -141,6 +137,11 @@ public class PublishController : ControllerBase return this.Ok(oldSlot.Serialize(gameToken.GameVersion)); } + if (user.GetUsedSlotsForGame(gameToken.GameVersion, database) > ServerSettings.Instance.EntitledSlots) + { + return this.StatusCode(403, ""); + } + //TODO: parse location in body Location l = new() { From 81622441be21c064ad178d0db014a6a9bf64994b Mon Sep 17 00:00:00 2001 From: jvyden Date: Mon, 21 Feb 2022 19:36:23 -0500 Subject: [PATCH 14/26] Move comment input bar to the top of the segment Closes #170 --- .../Pages/Partials/CommentsPartial.cshtml | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/ProjectLighthouse/Pages/Partials/CommentsPartial.cshtml b/ProjectLighthouse/Pages/Partials/CommentsPartial.cshtml index 7d038558..a4a50ec2 100644 --- a/ProjectLighthouse/Pages/Partials/CommentsPartial.cshtml +++ b/ProjectLighthouse/Pages/Partials/CommentsPartial.cshtml @@ -1,7 +1,6 @@ @using System.IO @using System.Web @using LBPUnion.ProjectLighthouse.Types.Profiles -