diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 3ba7983d..f6baf5a4 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "dotnet-ef": { - "version": "7.0.2", + "version": "7.0.3", "commands": [ "dotnet-ef" ] diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/ClientConfigurationController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/ClientConfigurationController.cs index 9db3c8e7..a305c623 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/ClientConfigurationController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/ClientConfigurationController.cs @@ -3,7 +3,7 @@ using System.Diagnostics.CodeAnalysis; using LBPUnion.ProjectLighthouse.Configuration; using LBPUnion.ProjectLighthouse.Database; using LBPUnion.ProjectLighthouse.Extensions; -using LBPUnion.ProjectLighthouse.Servers.GameServer.Types; +using LBPUnion.ProjectLighthouse.Servers.GameServer.Types.Users; using LBPUnion.ProjectLighthouse.Types.Entities.Profile; using LBPUnion.ProjectLighthouse.Types.Entities.Token; using LBPUnion.ProjectLighthouse.Types.Users; diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/FriendsController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/FriendsController.cs index 50d84c6d..7a71e916 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/FriendsController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/FriendsController.cs @@ -3,7 +3,7 @@ using LBPUnion.ProjectLighthouse.Database; using LBPUnion.ProjectLighthouse.Extensions; using LBPUnion.ProjectLighthouse.Helpers; using LBPUnion.ProjectLighthouse.Serialization; -using LBPUnion.ProjectLighthouse.Servers.GameServer.Types; +using LBPUnion.ProjectLighthouse.Servers.GameServer.Types.Users; using LBPUnion.ProjectLighthouse.StorableLists.Stores; using LBPUnion.ProjectLighthouse.Types.Entities.Profile; using LBPUnion.ProjectLighthouse.Types.Entities.Token; @@ -79,7 +79,7 @@ public class FriendsController : ControllerBase string friends = ""; foreach (int friendId in friendStore.FriendIds) { - User? friend = await this.database.Users.Include(u => u.Location).FirstOrDefaultAsync(u => u.UserId == friendId); + User? friend = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == friendId); if (friend == null) continue; friends += friend.Serialize(token.GameVersion); diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/CollectionController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/CollectionController.cs index ffd68a27..33c1fbdb 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/CollectionController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/CollectionController.cs @@ -36,7 +36,6 @@ public class CollectionController : ControllerBase if (targetPlaylist == null) return this.BadRequest(); IQueryable slots = this.database.Slots.Include(s => s.Creator) - .Include(s => s.Location) .Where(s => targetPlaylist.SlotIds.Contains(s.SlotId)); string response = Enumerable.Aggregate(slots, string.Empty, (current, slot) => current + slot.Serialize()); diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/ListController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/ListController.cs index 07374cf3..ec63ca5c 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/ListController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/ListController.cs @@ -267,7 +267,6 @@ public class ListController : ControllerBase (q => q.HeartedUser) .OrderBy(q => q.HeartedProfileId) .Where(q => q.UserId == targetUser.UserId) - .Include(q => q.HeartedUser.Location) .Select(q => q.HeartedUser) .Skip(Math.Max(0, pageStart - 1)) .Take(Math.Min(pageSize, 30)) @@ -369,7 +368,7 @@ public class ListController : ControllerBase whereQueuedLevels = this.database.QueuedLevels.Where(q => q.User.Username == username) .Where(q => q.Slot.Type == SlotType.User && !q.Slot.Hidden && q.Slot.GameVersion == gameVersion && q.Slot.FirstUploaded >= oldestTime); - return whereQueuedLevels.OrderByDescending(q => q.QueuedLevelId).Include(q => q.Slot.Creator).Include(q => q.Slot.Location).Select(q => q.Slot).ByGameVersion(gameVersion, false, false, true); + return whereQueuedLevels.OrderByDescending(q => q.QueuedLevelId).Include(q => q.Slot.Creator).Select(q => q.Slot).ByGameVersion(gameVersion, false, false, true); } else { IQueryable whereHeartedLevels; @@ -385,7 +384,7 @@ public class ListController : ControllerBase whereHeartedLevels = this.database.HeartedLevels.Where(h => h.User.Username == username) .Where(h => (h.Slot.Type == SlotType.User || h.Slot.Type == SlotType.Developer) && !h.Slot.Hidden && h.Slot.GameVersion == gameVersion && h.Slot.FirstUploaded >= oldestTime); - return whereHeartedLevels.OrderByDescending(h => h.HeartedLevelId).Include(h => h.Slot.Creator).Include(h => h.Slot.Location).Select(h => h.Slot).ByGameVersion(gameVersion, false, false, true); + return whereHeartedLevels.OrderByDescending(h => h.HeartedLevelId).Include(h => h.Slot.Creator).Select(h => h.Slot).ByGameVersion(gameVersion, false, false, true); } } #endregion Filtering diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/PublishController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/PublishController.cs index fae4a7f7..c81ead07 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/PublishController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/PublishController.cs @@ -10,7 +10,6 @@ using LBPUnion.ProjectLighthouse.Types.Entities.Level; using LBPUnion.ProjectLighthouse.Types.Entities.Profile; using LBPUnion.ProjectLighthouse.Types.Entities.Token; using LBPUnion.ProjectLighthouse.Types.Logging; -using LBPUnion.ProjectLighthouse.Types.Misc; using LBPUnion.ProjectLighthouse.Types.Resources; using LBPUnion.ProjectLighthouse.Types.Users; using Microsoft.AspNetCore.Authorization; @@ -58,6 +57,12 @@ public class PublishController : ControllerBase if (string.IsNullOrEmpty(slot.ResourceCollection)) slot.ResourceCollection = slot.RootLevel; + if (slot.Resources == null) + { + Logger.Warn("Rejecting level upload, resource list is null", LogArea.Publish); + return this.BadRequest(); + } + // Republish logic if (slot.SlotId != 0) { @@ -106,12 +111,6 @@ public class PublishController : ControllerBase return this.BadRequest(); } - if (slot.Location == null) - { - Logger.Warn("Rejecting level upload, slot location is null", LogArea.Publish); - return this.BadRequest(); - } - slot.Description = CensorHelper.FilterMessage(slot.Description); if (slot.Description.Length > 512) @@ -128,7 +127,7 @@ public class PublishController : ControllerBase return this.BadRequest(); } - if (slot.Resources.Any(resource => !FileHelper.ResourceExists(resource))) + if (slot.Resources != null && slot.Resources.Any(resource => !FileHelper.ResourceExists(resource))) { Logger.Warn("Rejecting level upload, missing resource(s)", LogArea.Publish); return this.BadRequest(); @@ -169,15 +168,13 @@ public class PublishController : ControllerBase // Republish logic if (slot.SlotId != 0) { - Slot? oldSlot = await this.database.Slots.Include(s => s.Location).FirstOrDefaultAsync(s => s.SlotId == slot.SlotId); + Slot? oldSlot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == slot.SlotId); if (oldSlot == null) { Logger.Warn("Rejecting level republish, wasn't able to find old slot", LogArea.Publish); return this.NotFound(); } - if (oldSlot.Location == null) throw new ArgumentNullException(); - if (oldSlot.CreatorId != user.UserId) { Logger.Warn("Rejecting level republish, old level not owned by current user", LogArea.Publish); @@ -200,11 +197,7 @@ public class PublishController : ControllerBase } } - oldSlot.Location.X = slot.Location.X; - oldSlot.Location.Y = slot.Location.Y; - slot.CreatorId = oldSlot.CreatorId; - slot.LocationId = oldSlot.LocationId; slot.SlotId = oldSlot.SlotId; #region Set plays @@ -248,15 +241,6 @@ public class PublishController : ControllerBase return this.BadRequest(); } - //TODO: parse location in body - Location l = new() - { - X = slot.Location.X, - Y = slot.Location.Y, - }; - this.database.Locations.Add(l); - await this.database.SaveChangesAsync(); - slot.LocationId = l.Id; slot.CreatorId = user.UserId; slot.FirstUploaded = TimeHelper.TimestampMillis; slot.LastUpdated = TimeHelper.TimestampMillis; @@ -289,14 +273,11 @@ public class PublishController : ControllerBase { GameToken token = this.GetToken(); - Slot? slot = await this.database.Slots.Include(s => s.Location).FirstOrDefaultAsync(s => s.SlotId == id); + Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id); if (slot == null) return this.NotFound(); - if (slot.Location == null) throw new ArgumentNullException(nameof(id)); - if (slot.CreatorId != token.UserId) return this.StatusCode(403, ""); - this.database.Locations.Remove(slot.Location); this.database.Slots.Remove(slot); await this.database.SaveChangesAsync(); diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/ReviewController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/ReviewController.cs index 84eae921..1a51a93e 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/ReviewController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/ReviewController.cs @@ -32,7 +32,7 @@ public class ReviewController : ControllerBase { GameToken token = this.GetToken(); - Slot? slot = await this.database.Slots.Include(s => s.Creator).Include(s => s.Location).FirstOrDefaultAsync(s => s.SlotId == slotId); + Slot? slot = await this.database.Slots.Include(s => s.Creator).FirstOrDefaultAsync(s => s.SlotId == slotId); if (slot == null) return this.StatusCode(403, ""); RatedLevel? ratedLevel = await this.database.RatedLevels.FirstOrDefaultAsync(r => r.SlotId == slotId && r.UserId == token.UserId); @@ -61,7 +61,7 @@ public class ReviewController : ControllerBase { GameToken token = this.GetToken(); - Slot? slot = await this.database.Slots.Include(s => s.Location).FirstOrDefaultAsync(s => s.SlotId == slotId); + Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == slotId); if (slot == null) return this.StatusCode(403, ""); RatedLevel? ratedLevel = await this.database.RatedLevels.FirstOrDefaultAsync(r => r.SlotId == slotId && r.UserId == token.UserId); diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/SlotsController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/SlotsController.cs index 13084cdc..f4b67c83 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/SlotsController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/SlotsController.cs @@ -75,7 +75,7 @@ public class SlotsController : ControllerBase List serializedSlots = new(); foreach (int slotId in s) { - Slot? slot = await this.database.Slots.Include(t => t.Creator).Include(t => t.Location).Where(t => t.SlotId == slotId && t.Type == SlotType.User).FirstOrDefaultAsync(); + Slot? slot = await this.database.Slots.Include(t => t.Creator).Where(t => t.SlotId == slotId && t.Type == SlotType.User).FirstOrDefaultAsync(); if (slot == null) { slot = await this.database.Slots.Where(t => t.InternalSlotId == slotId && t.Type == SlotType.Developer).FirstOrDefaultAsync(); @@ -511,6 +511,6 @@ public class SlotsController : ControllerBase // Get game versions exactly equal to gamefiltertype whereSlots = this.database.Slots.Where(s => s.Type == SlotType.User && !s.Hidden && s.GameVersion == gameVersion && s.FirstUploaded >= oldestTime); - return whereSlots.Include(s => s.Creator).Include(s => s.Location); + return whereSlots.Include(s => s.Creator); } } \ No newline at end of file diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/UserController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/UserController.cs index cba70856..4e483aff 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/UserController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/UserController.cs @@ -5,12 +5,11 @@ using LBPUnion.ProjectLighthouse.Extensions; using LBPUnion.ProjectLighthouse.Files; using LBPUnion.ProjectLighthouse.Helpers; using LBPUnion.ProjectLighthouse.Serialization; -using LBPUnion.ProjectLighthouse.Servers.GameServer.Types; +using LBPUnion.ProjectLighthouse.Servers.GameServer.Types.Users; using LBPUnion.ProjectLighthouse.Types.Entities.Level; using LBPUnion.ProjectLighthouse.Types.Entities.Profile; using LBPUnion.ProjectLighthouse.Types.Entities.Token; using LBPUnion.ProjectLighthouse.Types.Levels; -using LBPUnion.ProjectLighthouse.Types.Misc; using LBPUnion.ProjectLighthouse.Types.Users; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -33,7 +32,7 @@ public class UserController : ControllerBase private async Task getSerializedUser(string username, GameVersion gameVersion = GameVersion.LittleBigPlanet1) { - User? user = await this.database.Users.Include(u => u.Location).FirstOrDefaultAsync(u => u.Username == username); + User? user = await this.database.Users.FirstOrDefaultAsync(u => u.Username == username); return user?.Serialize(gameVersion); } @@ -96,6 +95,8 @@ public class UserController : ControllerBase user.Biography = update.Biography; } + if (update.Location != null) user.Location = update.Location; + // ReSharper disable once LoopCanBeConvertedToQuery foreach (string? resource in new[]{update.IconHash, update.YayHash, update.MehHash, update.BooHash, update.PlanetHash,}) { @@ -127,12 +128,7 @@ public class UserController : ControllerBase if (slot.CreatorId != token.UserId) continue; - Location? loc = await this.database.Locations.FirstOrDefaultAsync(l => l.Id == slot.LocationId); - - if (loc == null) throw new ArgumentNullException(); - - loc.X = updateSlot.Location.X; - loc.Y = updateSlot.Location.Y; + slot.Location = updateSlot.Location; } } @@ -168,16 +164,8 @@ public class UserController : ControllerBase } } - if (update.Location != null) - { - Location? loc = await this.database.Locations.FirstOrDefaultAsync(l => l.Id == user.LocationId); - if (loc == null) throw new Exception("User loc is null, this should never happen."); + await this.database.SaveChangesAsync(); - loc.X = update.Location.X; - loc.Y = update.Location.Y; - } - - if (this.database.ChangeTracker.HasChanges()) await this.database.SaveChangesAsync(); return this.Ok(); } diff --git a/ProjectLighthouse.Servers.GameServer/Types/Categories/HeartedCategory.cs b/ProjectLighthouse.Servers.GameServer/Types/Categories/HeartedCategory.cs index 446de506..47936078 100644 --- a/ProjectLighthouse.Servers.GameServer/Types/Categories/HeartedCategory.cs +++ b/ProjectLighthouse.Servers.GameServer/Types/Categories/HeartedCategory.cs @@ -20,7 +20,6 @@ public class HeartedCategory : CategoryWithUser .Where(h => h.Slot.Type == SlotType.User && !h.Slot.Hidden && h.Slot.GameVersion <= GameVersion.LittleBigPlanet3) .OrderByDescending(h => h.HeartedLevelId) .Include(h => h.Slot.Creator) - .Include(h => h.Slot.Location) .Select(h => h.Slot) .ByGameVersion(GameVersion.LittleBigPlanet3, false, false, true) .FirstOrDefault(); @@ -30,7 +29,6 @@ public class HeartedCategory : CategoryWithUser .Where(h => h.Slot.Type == SlotType.User && !h.Slot.Hidden && h.Slot.GameVersion <= GameVersion.LittleBigPlanet3) .OrderByDescending(h => h.HeartedLevelId) .Include(h => h.Slot.Creator) - .Include(h => h.Slot.Location) .Select(h => h.Slot) .ByGameVersion(GameVersion.LittleBigPlanet3, false, false, true) .Skip(Math.Max(0, pageStart)) diff --git a/ProjectLighthouse.Servers.GameServer/Types/Categories/QueueCategory.cs b/ProjectLighthouse.Servers.GameServer/Types/Categories/QueueCategory.cs index 4a813580..29ef6b26 100644 --- a/ProjectLighthouse.Servers.GameServer/Types/Categories/QueueCategory.cs +++ b/ProjectLighthouse.Servers.GameServer/Types/Categories/QueueCategory.cs @@ -20,7 +20,6 @@ public class QueueCategory : CategoryWithUser .Where(q => q.Slot.Type == SlotType.User && !q.Slot.Hidden && q.Slot.GameVersion <= GameVersion.LittleBigPlanet3) .OrderByDescending(q => q.QueuedLevelId) .Include(q => q.Slot.Creator) - .Include(q => q.Slot.Location) .Select(q => q.Slot) .ByGameVersion(GameVersion.LittleBigPlanet3, false, false, true) .FirstOrDefault(); @@ -30,7 +29,6 @@ public class QueueCategory : CategoryWithUser .Where(q => q.Slot.Type == SlotType.User && !q.Slot.Hidden && q.Slot.GameVersion <= GameVersion.LittleBigPlanet3) .OrderByDescending(q => q.QueuedLevelId) .Include(q => q.Slot.Creator) - .Include(q => q.Slot.Location) .Select(q => q.Slot) .ByGameVersion(GameVersion.LittleBigPlanet3, false, false, true) .Skip(Math.Max(0, pageStart - 1)) diff --git a/ProjectLighthouse.Servers.GameServer/Types/User/ClientsConnected.cs b/ProjectLighthouse.Servers.GameServer/Types/Users/ClientsConnected.cs similarity index 91% rename from ProjectLighthouse.Servers.GameServer/Types/User/ClientsConnected.cs rename to ProjectLighthouse.Servers.GameServer/Types/Users/ClientsConnected.cs index dc1d206e..a9880709 100644 --- a/ProjectLighthouse.Servers.GameServer/Types/User/ClientsConnected.cs +++ b/ProjectLighthouse.Servers.GameServer/Types/Users/ClientsConnected.cs @@ -1,7 +1,7 @@ using LBPUnion.ProjectLighthouse.Serialization; using Microsoft.EntityFrameworkCore; -namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Types; +namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Types.Users; [Keyless] public class ClientsConnected diff --git a/ProjectLighthouse.Servers.GameServer/Types/User/NPData.cs b/ProjectLighthouse.Servers.GameServer/Types/Users/NPData.cs similarity index 87% rename from ProjectLighthouse.Servers.GameServer/Types/User/NPData.cs rename to ProjectLighthouse.Servers.GameServer/Types/Users/NPData.cs index d7ccb175..f93fea69 100644 --- a/ProjectLighthouse.Servers.GameServer/Types/User/NPData.cs +++ b/ProjectLighthouse.Servers.GameServer/Types/Users/NPData.cs @@ -1,6 +1,6 @@ using System.Xml.Serialization; -namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Types; +namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Types.Users; /// /// Sent by the game client to inform the server diff --git a/ProjectLighthouse.Servers.GameServer/Types/User/Pins.cs b/ProjectLighthouse.Servers.GameServer/Types/Users/Pins.cs similarity index 81% rename from ProjectLighthouse.Servers.GameServer/Types/User/Pins.cs rename to ProjectLighthouse.Servers.GameServer/Types/Users/Pins.cs index e9658caf..acc52f65 100644 --- a/ProjectLighthouse.Servers.GameServer/Types/User/Pins.cs +++ b/ProjectLighthouse.Servers.GameServer/Types/Users/Pins.cs @@ -1,6 +1,6 @@ using System.Text.Json.Serialization; -namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Types; +namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Types.Users; public class Pins { diff --git a/ProjectLighthouse.Servers.GameServer/Types/User/PrivacySettings.cs b/ProjectLighthouse.Servers.GameServer/Types/Users/PrivacySettings.cs similarity index 90% rename from ProjectLighthouse.Servers.GameServer/Types/User/PrivacySettings.cs rename to ProjectLighthouse.Servers.GameServer/Types/Users/PrivacySettings.cs index 084efba3..00ce3201 100644 --- a/ProjectLighthouse.Servers.GameServer/Types/User/PrivacySettings.cs +++ b/ProjectLighthouse.Servers.GameServer/Types/Users/PrivacySettings.cs @@ -2,7 +2,7 @@ using System.Xml.Serialization; using LBPUnion.ProjectLighthouse.Serialization; -namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Types; +namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Types.Users; [XmlRoot("privacySettings")] [XmlType("privacySettings")] diff --git a/ProjectLighthouse.Servers.GameServer/Types/User/UserUpdate.cs b/ProjectLighthouse.Servers.GameServer/Types/Users/UserUpdate.cs similarity index 94% rename from ProjectLighthouse.Servers.GameServer/Types/User/UserUpdate.cs rename to ProjectLighthouse.Servers.GameServer/Types/Users/UserUpdate.cs index be9d959f..d5ada8ed 100644 --- a/ProjectLighthouse.Servers.GameServer/Types/User/UserUpdate.cs +++ b/ProjectLighthouse.Servers.GameServer/Types/Users/UserUpdate.cs @@ -3,7 +3,7 @@ using System.Xml.Serialization; using LBPUnion.ProjectLighthouse.Types.Levels; using LBPUnion.ProjectLighthouse.Types.Misc; -namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Types; +namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Types.Users; /// /// Used by the games to update details about a user's profile /// LBP1 only uses Location and IconHash diff --git a/ProjectLighthouse.Servers.Website/Controllers/SlotPageController.cs b/ProjectLighthouse.Servers.Website/Controllers/SlotPageController.cs index 329e33b3..0837f21c 100644 --- a/ProjectLighthouse.Servers.Website/Controllers/SlotPageController.cs +++ b/ProjectLighthouse.Servers.Website/Controllers/SlotPageController.cs @@ -33,14 +33,11 @@ public class SlotPageController : ControllerBase WebToken? token = this.database.WebTokenFromRequest(this.Request); if (token == null) return this.Redirect("~/login"); - Slot? targetSlot = await this.database.Slots.Include(s => s.Location).FirstOrDefaultAsync(s => s.SlotId == id); + Slot? targetSlot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id); if (targetSlot == null) return this.Redirect("~/slots/0"); - if (targetSlot.Location == null) throw new ArgumentNullException(nameof(id)); - if (targetSlot.CreatorId != token.UserId) return this.Redirect("~/slot/" + id); - this.database.Locations.Remove(targetSlot.Location); this.database.Slots.Remove(targetSlot); await this.database.SaveChangesAsync(); diff --git a/ProjectLighthouse.Tests.GameApiTests/Tests/SlotTests.cs b/ProjectLighthouse.Tests.GameApiTests/Tests/SlotTests.cs index 9a81286b..036b98e2 100644 --- a/ProjectLighthouse.Tests.GameApiTests/Tests/SlotTests.cs +++ b/ProjectLighthouse.Tests.GameApiTests/Tests/SlotTests.cs @@ -25,21 +25,11 @@ public class SlotTests : LighthouseServerTest User userA = await database.CreateUser($"unitTestUser{r.Next()}", CryptoHelper.GenerateAuthToken()); User userB = await database.CreateUser($"unitTestUser{r.Next()}", CryptoHelper.GenerateAuthToken()); - Location l = new() - { - X = 0, - Y = 0, - }; - database.Locations.Add(l); - await database.SaveChangesAsync(); - Slot slotA = new() { Creator = userA, CreatorId = userA.UserId, Name = "slotA", - Location = l, - LocationId = l.Id, ResourceCollection = "", }; @@ -48,8 +38,6 @@ public class SlotTests : LighthouseServerTest Creator = userB, CreatorId = userB.UserId, Name = "slotB", - Location = l, - LocationId = l.Id, ResourceCollection = "", }; diff --git a/ProjectLighthouse.Tests/Tests/LocationTests.cs b/ProjectLighthouse.Tests/Tests/LocationTests.cs new file mode 100644 index 00000000..0786c2f6 --- /dev/null +++ b/ProjectLighthouse.Tests/Tests/LocationTests.cs @@ -0,0 +1,81 @@ +using System.IO; +using System.Xml.Serialization; +using LBPUnion.ProjectLighthouse.Types.Entities.Level; +using LBPUnion.ProjectLighthouse.Types.Entities.Profile; +using LBPUnion.ProjectLighthouse.Types.Misc; +using Xunit; + +namespace LBPUnion.ProjectLighthouse.Tests; + +public class LocationTests +{ + [Fact] + public void ShouldSetAndReadUserLocation() + { + Location expected = new() + { + X = 1000, + Y = 5000, + }; + User user = new() + { + Location = new Location + { + X = expected.X, + Y = expected.Y, + }, + }; + Assert.True(user.Location.X == expected.X); + Assert.True(user.Location.Y == expected.Y); + Assert.True(user.LocationPacked == 4_294_967_301_000); + } + + [Fact] + public void ShouldSetAndReadSlotLocation() + { + Location expected = new() + { + X = 1000, + Y = 5000, + }; + Slot slot = new() + { + Location = new Location + { + X = expected.X, + Y = expected.Y, + }, + }; + Assert.True(slot.Location.X == expected.X); + Assert.True(slot.Location.Y == expected.Y); + Assert.True(slot.LocationPacked == 4_294_967_301_000); + } + + [Fact] + public void ShouldReadLocationAfterDeserialization() + { + XmlSerializer deserializer = new(typeof(Slot)); + const string slotData = "testtest40009000"; + + Slot? deserialized = (Slot?)deserializer.Deserialize(new StringReader(slotData)); + Assert.True(deserialized != null); + Assert.True(deserialized.Name == "test"); + Assert.True(deserialized.Location.X == 4000); + Assert.True(deserialized.Location.Y == 9000); + Assert.True(deserialized.LocationPacked == 17_179_869_193_000); + } + + [Fact] + public void ShouldDeserializeEmptyLocation() + { + XmlSerializer deserializer = new(typeof(Slot)); + const string slotData = "test"; + + Slot? deserialized = (Slot?)deserializer.Deserialize(new StringReader(slotData)); + Assert.True(deserialized != null); + Assert.True(deserialized.Name == "test"); + Assert.True(deserialized.Location.X == 0); + Assert.True(deserialized.Location.Y == 0); + Assert.True(deserialized.LocationPacked == 0); + } +} \ No newline at end of file diff --git a/ProjectLighthouse/Administration/Maintenance/MaintenanceJobs/CleanupUnusedLocationsMaintenanceJob.cs b/ProjectLighthouse/Administration/Maintenance/MaintenanceJobs/CleanupUnusedLocationsMaintenanceJob.cs deleted file mode 100644 index 1488adcf..00000000 --- a/ProjectLighthouse/Administration/Maintenance/MaintenanceJobs/CleanupUnusedLocationsMaintenanceJob.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using LBPUnion.ProjectLighthouse.Database; -using LBPUnion.ProjectLighthouse.Types.Maintenance; -using LBPUnion.ProjectLighthouse.Types.Misc; - -namespace LBPUnion.ProjectLighthouse.Administration.Maintenance.MaintenanceJobs; - -public class CleanupUnusedLocationsMaintenanceJob : IMaintenanceJob -{ - private readonly DatabaseContext database = new(); - public string Name() => "Cleanup Unused Locations"; - public string Description() => "Cleanup unused locations in the database."; - - public async Task Run() - { - List usedLocationIds = new(); - - usedLocationIds.AddRange(this.database.Slots.Select(slot => slot.LocationId)); - usedLocationIds.AddRange(this.database.Users.Select(user => user.LocationId)); - - IQueryable locationsToRemove = this.database.Locations.Where(l => !usedLocationIds.Contains(l.Id)); - - foreach (Location location in locationsToRemove) - { - Console.WriteLine("Removing location " + location.Id); - this.database.Locations.Remove(location); - } - - await this.database.SaveChangesAsync(); - } -} \ No newline at end of file diff --git a/ProjectLighthouse/Database/DatabaseContext.cs b/ProjectLighthouse/Database/DatabaseContext.cs index d8c3bf97..89f6f17a 100644 --- a/ProjectLighthouse/Database/DatabaseContext.cs +++ b/ProjectLighthouse/Database/DatabaseContext.cs @@ -28,7 +28,6 @@ public partial class DatabaseContext : DbContext #region Users public DbSet Comments { get; set; } public DbSet LastContacts { get; set; } - public DbSet Locations { get; set; } public DbSet Photos { get; set; } public DbSet PhotoSubjects { get; set; } public DbSet PlatformLinkAttempts { get; set; } diff --git a/ProjectLighthouse/Database/DatabaseSlotUtils.cs b/ProjectLighthouse/Database/DatabaseSlotUtils.cs index 0e151908..df7f25c1 100644 --- a/ProjectLighthouse/Database/DatabaseSlotUtils.cs +++ b/ProjectLighthouse/Database/DatabaseSlotUtils.cs @@ -10,8 +10,6 @@ public partial class DatabaseContext { public async Task RemoveSlot(Slot slot, bool saveChanges = true) { - if (slot.Location != null) this.Locations.Remove(slot.Location); - this.Slots.Remove(slot); if (saveChanges) await this.SaveChangesAsync(); @@ -22,7 +20,7 @@ public partial class DatabaseContext HeartedPlaylist? heartedList = await this.HeartedPlaylists.FirstOrDefaultAsync(p => p.UserId == userId && p.PlaylistId == heartedPlaylist.PlaylistId); if (heartedList != null) return; - this.HeartedPlaylists.Add(new HeartedPlaylist() + this.HeartedPlaylists.Add(new HeartedPlaylist { PlaylistId = heartedPlaylist.PlaylistId, UserId = userId, diff --git a/ProjectLighthouse/Database/DatabaseUserUtils.cs b/ProjectLighthouse/Database/DatabaseUserUtils.cs index 206b9379..d606ffd0 100644 --- a/ProjectLighthouse/Database/DatabaseUserUtils.cs +++ b/ProjectLighthouse/Database/DatabaseUserUtils.cs @@ -39,15 +39,10 @@ public partial class DatabaseContext User? user = await this.Users.Where(u => u.Username == username).FirstOrDefaultAsync(); if (user != null) return user; - Location l = new(); // store to get id after submitting - this.Locations.Add(l); // add to table - await this.SaveChangesAsync(); // saving to the database returns the id and sets it on this entity - user = new User { Username = username, Password = password, - LocationId = l.Id, Biography = "", EmailAddress = emailAddress, }; @@ -99,8 +94,6 @@ public partial class DatabaseContext if (user == null) return; if (user.Username.Length == 0) return; // don't delete the placeholder user - if (user.Location != null) this.Locations.Remove(user.Location); - LastContact? lastContact = await this.LastContacts.FirstOrDefaultAsync(l => l.UserId == user.UserId); if (lastContact != null) this.LastContacts.Remove(lastContact); diff --git a/ProjectLighthouse/Extensions/DatabaseExtensions.cs b/ProjectLighthouse/Extensions/DatabaseExtensions.cs index e95a04cf..d842b7a4 100644 --- a/ProjectLighthouse/Extensions/DatabaseExtensions.cs +++ b/ProjectLighthouse/Extensions/DatabaseExtensions.cs @@ -12,17 +12,17 @@ namespace LBPUnion.ProjectLighthouse.Extensions; public static class DatabaseExtensions { public static IQueryable ByGameVersion - (this DbSet set, GameVersion gameVersion, bool includeSublevels = false, bool includeCreatorAndLocation = false) - => set.AsQueryable().ByGameVersion(gameVersion, includeSublevels, includeCreatorAndLocation); + (this DbSet set, GameVersion gameVersion, bool includeSublevels = false, bool includeCreator = false) + => set.AsQueryable().ByGameVersion(gameVersion, includeSublevels, includeCreator); public static IQueryable ByGameVersion - (this IQueryable query, GameVersion gameVersion, bool includeSublevels = false, bool includeCreatorAndLocation = false, bool includeDeveloperLevels = false) + (this IQueryable query, GameVersion gameVersion, bool includeSublevels = false, bool includeCreator = false, bool includeDeveloperLevels = false) { - query = query.Where(s => (s.Type == SlotType.User) || (s.Type == SlotType.Developer && includeDeveloperLevels)); + query = query.Where(s => s.Type == SlotType.User || (s.Type == SlotType.Developer && includeDeveloperLevels)); - if (includeCreatorAndLocation) + if (includeCreator) { - query = query.Include(s => s.Creator).Include(s => s.Location); + query = query.Include(s => s.Creator); } if (gameVersion == GameVersion.LittleBigPlanetVita || gameVersion == GameVersion.LittleBigPlanetPSP || gameVersion == GameVersion.Unknown) @@ -41,7 +41,7 @@ public static class DatabaseExtensions public static IQueryable ByGameVersion(this IQueryable queryable, GameVersion gameVersion, bool includeSublevels = false) { - IQueryable query = queryable.Include(r => r.Slot).Include(r => r.Slot.Creator).Include(r => r.Slot.Location); + IQueryable query = queryable.Include(r => r.Slot).Include(r => r.Slot.Creator); if (gameVersion == GameVersion.LittleBigPlanetVita || gameVersion == GameVersion.LittleBigPlanetPSP || gameVersion == GameVersion.Unknown) { diff --git a/ProjectLighthouse/Helpers/SlotHelper.cs b/ProjectLighthouse/Helpers/SlotHelper.cs index 28e80b4f..87ec79d9 100644 --- a/ProjectLighthouse/Helpers/SlotHelper.cs +++ b/ProjectLighthouse/Helpers/SlotHelper.cs @@ -7,7 +7,6 @@ using LBPUnion.ProjectLighthouse.Database; using LBPUnion.ProjectLighthouse.Types.Entities.Level; using LBPUnion.ProjectLighthouse.Types.Entities.Profile; using LBPUnion.ProjectLighthouse.Types.Levels; -using LBPUnion.ProjectLighthouse.Types.Misc; using LBPUnion.ProjectLighthouse.Types.Users; using Microsoft.EntityFrameworkCore; @@ -44,28 +43,6 @@ public static class SlotHelper private static readonly SemaphoreSlim semaphore = new(1, 1); - private static async Task GetPlaceholderLocationId(DatabaseContext database) - { - Location? devLocation = await database.Locations.FirstOrDefaultAsync(l => l.Id == 1); - - if (devLocation != null) return devLocation.Id; - - await semaphore.WaitAsync(TimeSpan.FromSeconds(5)); - try - { - devLocation = new Location - { - Id = 1, - }; - database.Locations.Add(devLocation); - return devLocation.Id; - } - finally - { - semaphore.Release(); - } - } - public static async Task GetPlaceholderUserId(DatabaseContext database) { int devCreatorId = await database.Users.Where(u => u.Username.Length == 0) @@ -82,7 +59,6 @@ public static class SlotHelper PermissionLevel = PermissionLevel.Banned, Biography = "Placeholder author of story levels", BannedReason = "Banned to not show in users list", - LocationId = await GetPlaceholderLocationId(database), }; database.Users.Add(devCreator); await database.SaveChangesAsync(); @@ -119,7 +95,6 @@ public static class SlotHelper Description = $"Placeholder for {slotType} type level", CreatorId = devCreatorId, InternalSlotId = guid, - LocationId = await GetPlaceholderLocationId(database), Type = slotType, }; diff --git a/ProjectLighthouse/Migrations/20230215195324_ChangeLocationStorage.cs b/ProjectLighthouse/Migrations/20230215195324_ChangeLocationStorage.cs new file mode 100644 index 00000000..1faa5c44 --- /dev/null +++ b/ProjectLighthouse/Migrations/20230215195324_ChangeLocationStorage.cs @@ -0,0 +1,129 @@ +using LBPUnion.ProjectLighthouse; +using LBPUnion.ProjectLighthouse.Database; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ProjectLighthouse.Migrations +{ + [DbContext(typeof(DatabaseContext))] + [Migration("20230215195324_ChangeLocationStorage")] + public partial class ChangeLocationStorage : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn(name: "LocationPacked", + table: "Users", + type: "bigint unsigned", + nullable: false, + defaultValue: 0ul); + + migrationBuilder.AddColumn(name: "LocationPacked", + table: "Slots", + type: "bigint unsigned", + nullable: false, + defaultValue: 0ul); + + migrationBuilder.Sql("UPDATE Users as u inner join Locations as l on u.LocationId = l.Id " + + "SET u.LocationPacked = (l.X << 32 | l.Y)"); + migrationBuilder.Sql("UPDATE Slots as s inner join Locations as l on s.LocationId = l.Id " + + "SET s.LocationPacked = (l.X << 32 | l.Y)"); + + migrationBuilder.DropForeignKey( + name: "FK_Slots_Locations_LocationId", + table: "Slots"); + + migrationBuilder.DropForeignKey( + name: "FK_Users_Locations_LocationId", + table: "Users"); + + migrationBuilder.DropTable( + name: "Locations"); + + migrationBuilder.DropIndex( + name: "IX_Users_LocationId", + table: "Users"); + + migrationBuilder.DropIndex( + name: "IX_Slots_LocationId", + table: "Slots"); + + migrationBuilder.DropColumn( + name: "LocationId", + table: "Users"); + + migrationBuilder.DropColumn( + name: "LocationId", + table: "Slots"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "LocationPacked", + table: "Users"); + + migrationBuilder.DropColumn( + name: "LocationPacked", + table: "Slots"); + + migrationBuilder.AddColumn( + name: "LocationId", + table: "Users", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "LocationId", + table: "Slots", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.CreateTable( + name: "Locations", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + X = table.Column(type: "int", nullable: false), + Y = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Locations", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "IX_Users_LocationId", + table: "Users", + column: "LocationId"); + + migrationBuilder.CreateIndex( + name: "IX_Slots_LocationId", + table: "Slots", + column: "LocationId"); + + migrationBuilder.AddForeignKey( + name: "FK_Slots_Locations_LocationId", + table: "Slots", + column: "LocationId", + principalTable: "Locations", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_Users_Locations_LocationId", + table: "Users", + column: "LocationId", + principalTable: "Locations", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/ProjectLighthouse/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs b/ProjectLighthouse/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs index ff0f0c1d..eda06ee2 100644 --- a/ProjectLighthouse/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs +++ b/ProjectLighthouse/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs @@ -17,149 +17,10 @@ namespace ProjectLighthouse.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "7.0.2") + .HasAnnotation("ProductVersion", "7.0.3") .HasAnnotation("Relational:MaxIdentifierLength", 64); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.Administration.CompletedMigration", b => - { - b.Property("MigrationName") - .HasColumnType("varchar(255)"); - - b.Property("RanAt") - .HasColumnType("datetime(6)"); - - b.HasKey("MigrationName"); - - b.ToTable("CompletedMigrations"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.Administration.ModerationCase", b => - { - b.Property("CaseId") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("AffectedId") - .HasColumnType("int"); - - b.Property("CreatedAt") - .HasColumnType("datetime(6)"); - - b.Property("CreatorId") - .HasColumnType("int"); - - b.Property("CreatorUsername") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("DismissedAt") - .HasColumnType("datetime(6)"); - - b.Property("DismisserId") - .HasColumnType("int"); - - b.Property("DismisserUsername") - .HasColumnType("longtext"); - - b.Property("ExpiresAt") - .HasColumnType("datetime(6)"); - - b.Property("ModeratorNotes") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Processed") - .HasColumnType("tinyint(1)"); - - b.Property("Reason") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Type") - .HasColumnType("int"); - - b.HasKey("CaseId"); - - b.HasIndex("CreatorId"); - - b.HasIndex("DismisserId"); - - b.ToTable("Cases"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.Administration.Reports.GriefReport", b => - { - b.Property("ReportId") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Bounds") - .HasColumnType("longtext"); - - b.Property("GriefStateHash") - .HasColumnType("longtext"); - - b.Property("InitialStateHash") - .HasColumnType("longtext"); - - b.Property("JpegHash") - .HasColumnType("longtext"); - - b.Property("LevelId") - .HasColumnType("int"); - - b.Property("LevelOwner") - .HasColumnType("longtext"); - - b.Property("LevelType") - .HasColumnType("longtext"); - - b.Property("Players") - .HasColumnType("longtext"); - - b.Property("ReportingPlayerId") - .HasColumnType("int"); - - b.Property("Timestamp") - .HasColumnType("bigint"); - - b.Property("Type") - .HasColumnType("int"); - - b.HasKey("ReportId"); - - b.HasIndex("ReportingPlayerId"); - - b.ToTable("Reports"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.Categories.DatabaseCategory", b => - { - b.Property("CategoryId") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Description") - .HasColumnType("longtext"); - - b.Property("Endpoint") - .HasColumnType("longtext"); - - b.Property("IconHash") - .HasColumnType("longtext"); - - b.Property("Name") - .HasColumnType("longtext"); - - b.Property("SlotIdsCollection") - .HasColumnType("longtext"); - - b.HasKey("CategoryId"); - - b.ToTable("CustomCategories"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.HeartedLevel", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Interaction.HeartedLevel", b => { b.Property("HeartedLevelId") .ValueGeneratedOnAdd() @@ -180,7 +41,7 @@ namespace ProjectLighthouse.Migrations b.ToTable("HeartedLevels"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.HeartedPlaylist", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Interaction.HeartedPlaylist", b => { b.Property("HeartedPlaylistId") .ValueGeneratedOnAdd() @@ -201,35 +62,28 @@ namespace ProjectLighthouse.Migrations b.ToTable("HeartedPlaylists"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.Playlist", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Interaction.HeartedProfile", b => { - b.Property("PlaylistId") + b.Property("HeartedProfileId") .ValueGeneratedOnAdd() .HasColumnType("int"); - b.Property("CreatorId") + b.Property("HeartedUserId") .HasColumnType("int"); - b.Property("Description") - .IsRequired() - .HasColumnType("longtext"); + b.Property("UserId") + .HasColumnType("int"); - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); + b.HasKey("HeartedProfileId"); - b.Property("SlotCollection") - .IsRequired() - .HasColumnType("longtext"); + b.HasIndex("HeartedUserId"); - b.HasKey("PlaylistId"); + b.HasIndex("UserId"); - b.HasIndex("CreatorId"); - - b.ToTable("Playlists"); + b.ToTable("HeartedProfiles"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.QueuedLevel", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Interaction.QueuedLevel", b => { b.Property("QueuedLevelId") .ValueGeneratedOnAdd() @@ -250,7 +104,7 @@ namespace ProjectLighthouse.Migrations b.ToTable("QueuedLevels"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.RatedLevel", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Interaction.RatedLevel", b => { b.Property("RatedLevelId") .ValueGeneratedOnAdd() @@ -280,7 +134,210 @@ namespace ProjectLighthouse.Migrations b.ToTable("RatedLevels"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.Slot", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Interaction.RatedReview", b => + { + b.Property("RatedReviewId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ReviewId") + .HasColumnType("int"); + + b.Property("Thumb") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("RatedReviewId"); + + b.HasIndex("ReviewId"); + + b.HasIndex("UserId"); + + b.ToTable("RatedReviews"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Interaction.Reaction", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Rating") + .HasColumnType("int"); + + b.Property("TargetId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("RatingId"); + + b.ToTable("Reactions"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Interaction.VisitedLevel", b => + { + b.Property("VisitedLevelId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("PlaysLBP1") + .HasColumnType("int"); + + b.Property("PlaysLBP2") + .HasColumnType("int"); + + b.Property("PlaysLBP3") + .HasColumnType("int"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("VisitedLevelId"); + + b.HasIndex("SlotId"); + + b.HasIndex("UserId"); + + b.ToTable("VisitedLevels"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Level.DatabaseCategory", b => + { + b.Property("CategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("Endpoint") + .HasColumnType("longtext"); + + b.Property("IconHash") + .HasColumnType("longtext"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("SlotIdsCollection") + .HasColumnType("longtext"); + + b.HasKey("CategoryId"); + + b.ToTable("CustomCategories"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Level.Playlist", b => + { + b.Property("PlaylistId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatorId") + .HasColumnType("int"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SlotCollection") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("PlaylistId"); + + b.HasIndex("CreatorId"); + + b.ToTable("Playlists"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Level.Review", b => + { + b.Property("ReviewId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Deleted") + .HasColumnType("tinyint(1)"); + + b.Property("DeletedBy") + .HasColumnType("int"); + + b.Property("LabelCollection") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ReviewerId") + .HasColumnType("int"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("Text") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Thumb") + .HasColumnType("int"); + + b.Property("ThumbsDown") + .HasColumnType("int"); + + b.Property("ThumbsUp") + .HasColumnType("int"); + + b.Property("Timestamp") + .HasColumnType("bigint"); + + b.HasKey("ReviewId"); + + b.HasIndex("ReviewerId"); + + b.HasIndex("SlotId"); + + b.ToTable("Reviews"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Level.Score", b => + { + b.Property("ScoreId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ChildSlotId") + .HasColumnType("int"); + + b.Property("PlayerIdCollection") + .HasColumnType("longtext"); + + b.Property("Points") + .HasColumnType("int"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("ScoreId"); + + b.HasIndex("SlotId"); + + b.ToTable("Scores"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Level.Slot", b => { b.Property("SlotId") .ValueGeneratedOnAdd() @@ -343,8 +400,8 @@ namespace ProjectLighthouse.Migrations .IsRequired() .HasColumnType("longtext"); - b.Property("LocationId") - .HasColumnType("int"); + b.Property("LocationPacked") + .HasColumnType("bigint unsigned"); b.Property("MaximumPlayers") .HasColumnType("int"); @@ -410,69 +467,190 @@ namespace ProjectLighthouse.Migrations b.HasIndex("CreatorId"); - b.HasIndex("LocationId"); - b.ToTable("Slots"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.VisitedLevel", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Maintenance.CompletedMigration", b => { - b.Property("VisitedLevelId") + b.Property("MigrationName") + .HasColumnType("varchar(255)"); + + b.Property("RanAt") + .HasColumnType("datetime(6)"); + + b.HasKey("MigrationName"); + + b.ToTable("CompletedMigrations"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Moderation.GriefReport", b => + { + b.Property("ReportId") .ValueGeneratedOnAdd() .HasColumnType("int"); - b.Property("PlaysLBP1") + b.Property("Bounds") + .HasColumnType("longtext"); + + b.Property("GriefStateHash") + .HasColumnType("longtext"); + + b.Property("InitialStateHash") + .HasColumnType("longtext"); + + b.Property("JpegHash") + .HasColumnType("longtext"); + + b.Property("LevelId") .HasColumnType("int"); - b.Property("PlaysLBP2") + b.Property("LevelOwner") + .HasColumnType("longtext"); + + b.Property("LevelType") + .HasColumnType("longtext"); + + b.Property("Players") + .HasColumnType("longtext"); + + b.Property("ReportingPlayerId") .HasColumnType("int"); - b.Property("PlaysLBP3") + b.Property("Timestamp") + .HasColumnType("bigint"); + + b.Property("Type") .HasColumnType("int"); - b.Property("SlotId") + b.HasKey("ReportId"); + + b.HasIndex("ReportingPlayerId"); + + b.ToTable("Reports"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Moderation.ModerationCase", b => + { + b.Property("CaseId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AffectedId") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnType("int"); + + b.Property("CreatorUsername") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("DismissedAt") + .HasColumnType("datetime(6)"); + + b.Property("DismisserId") + .HasColumnType("int"); + + b.Property("DismisserUsername") + .HasColumnType("longtext"); + + b.Property("ExpiresAt") + .HasColumnType("datetime(6)"); + + b.Property("ModeratorNotes") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Processed") + .HasColumnType("tinyint(1)"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("CaseId"); + + b.HasIndex("CreatorId"); + + b.HasIndex("DismisserId"); + + b.ToTable("Cases"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Profile.BlockedProfile", b => + { + b.Property("BlockedProfileId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BlockedUserId") .HasColumnType("int"); b.Property("UserId") .HasColumnType("int"); - b.HasKey("VisitedLevelId"); + b.HasKey("BlockedProfileId"); - b.HasIndex("SlotId"); + b.HasIndex("BlockedUserId"); b.HasIndex("UserId"); - b.ToTable("VisitedLevels"); + b.ToTable("BlockedProfiles"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.APIKey", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Profile.Comment", b => { - b.Property("Id") + b.Property("CommentId") .ValueGeneratedOnAdd() .HasColumnType("int"); - b.Property("Created") - .HasColumnType("datetime(6)"); + b.Property("Deleted") + .HasColumnType("tinyint(1)"); - b.Property("Description") + b.Property("DeletedBy") .HasColumnType("longtext"); - b.Property("Key") + b.Property("DeletedType") .HasColumnType("longtext"); - b.HasKey("Id"); + b.Property("Message") + .HasColumnType("longtext"); - b.ToTable("APIKeys"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.GameToken", b => - { - b.Property("TokenId") - .ValueGeneratedOnAdd() + b.Property("PosterUserId") .HasColumnType("int"); - b.Property("ExpiresAt") - .HasColumnType("datetime(6)"); + b.Property("TargetId") + .HasColumnType("int"); + + b.Property("ThumbsDown") + .HasColumnType("int"); + + b.Property("ThumbsUp") + .HasColumnType("int"); + + b.Property("Timestamp") + .HasColumnType("bigint"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("CommentId"); + + b.HasIndex("PosterUserId"); + + b.ToTable("Comments"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Profile.LastContact", b => + { + b.Property("UserId") + .HasColumnType("int"); b.Property("GameVersion") .HasColumnType("int"); @@ -480,46 +658,15 @@ namespace ProjectLighthouse.Migrations b.Property("Platform") .HasColumnType("int"); - b.Property("TicketHash") - .HasColumnType("longtext"); + b.Property("Timestamp") + .HasColumnType("bigint"); - b.Property("UserId") - .HasColumnType("int"); + b.HasKey("UserId"); - b.Property("UserLocation") - .HasColumnType("longtext"); - - b.Property("UserToken") - .HasColumnType("longtext"); - - b.HasKey("TokenId"); - - b.HasIndex("UserId"); - - b.ToTable("GameTokens"); + b.ToTable("LastContacts"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.PasswordResetToken", b => - { - b.Property("TokenId") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("ResetToken") - .HasColumnType("longtext"); - - b.Property("UserId") - .HasColumnType("int"); - - b.HasKey("TokenId"); - - b.ToTable("PasswordResetTokens"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Photo", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Profile.Photo", b => { b.Property("PhotoId") .ValueGeneratedOnAdd() @@ -563,7 +710,7 @@ namespace ProjectLighthouse.Migrations b.ToTable("Photos"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.PhotoSubject", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Profile.PhotoSubject", b => { b.Property("PhotoSubjectId") .ValueGeneratedOnAdd() @@ -582,7 +729,7 @@ namespace ProjectLighthouse.Migrations b.ToTable("PhotoSubjects"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.PlatformLinkAttempt", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Profile.PlatformLinkAttempt", b => { b.Property("PlatformLinkAttemptId") .ValueGeneratedOnAdd() @@ -610,172 +757,7 @@ namespace ProjectLighthouse.Migrations b.ToTable("PlatformLinkAttempts"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Profiles.BlockedProfile", b => - { - b.Property("BlockedProfileId") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("BlockedUserId") - .HasColumnType("int"); - - b.Property("UserId") - .HasColumnType("int"); - - b.HasKey("BlockedProfileId"); - - b.HasIndex("BlockedUserId"); - - b.HasIndex("UserId"); - - b.ToTable("BlockedProfiles"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Profiles.Comment", b => - { - b.Property("CommentId") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Deleted") - .HasColumnType("tinyint(1)"); - - b.Property("DeletedBy") - .HasColumnType("longtext"); - - b.Property("DeletedType") - .HasColumnType("longtext"); - - b.Property("Message") - .HasColumnType("longtext"); - - b.Property("PosterUserId") - .HasColumnType("int"); - - b.Property("TargetId") - .HasColumnType("int"); - - b.Property("ThumbsDown") - .HasColumnType("int"); - - b.Property("ThumbsUp") - .HasColumnType("int"); - - b.Property("Timestamp") - .HasColumnType("bigint"); - - b.Property("Type") - .HasColumnType("int"); - - b.HasKey("CommentId"); - - b.HasIndex("PosterUserId"); - - b.ToTable("Comments"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Profiles.Email.EmailSetToken", b => - { - b.Property("EmailSetTokenId") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("EmailToken") - .HasColumnType("longtext"); - - b.Property("ExpiresAt") - .HasColumnType("datetime(6)"); - - b.Property("UserId") - .HasColumnType("int"); - - b.HasKey("EmailSetTokenId"); - - b.HasIndex("UserId"); - - b.ToTable("EmailSetTokens"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Profiles.Email.EmailVerificationToken", b => - { - b.Property("EmailVerificationTokenId") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("EmailToken") - .HasColumnType("longtext"); - - b.Property("ExpiresAt") - .HasColumnType("datetime(6)"); - - b.Property("UserId") - .HasColumnType("int"); - - b.HasKey("EmailVerificationTokenId"); - - b.HasIndex("UserId"); - - b.ToTable("EmailVerificationTokens"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Profiles.HeartedProfile", b => - { - b.Property("HeartedProfileId") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("HeartedUserId") - .HasColumnType("int"); - - b.Property("UserId") - .HasColumnType("int"); - - b.HasKey("HeartedProfileId"); - - b.HasIndex("HeartedUserId"); - - b.HasIndex("UserId"); - - b.ToTable("HeartedProfiles"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Profiles.LastContact", b => - { - b.Property("UserId") - .HasColumnType("int"); - - b.Property("GameVersion") - .HasColumnType("int"); - - b.Property("Platform") - .HasColumnType("int"); - - b.Property("Timestamp") - .HasColumnType("bigint"); - - b.HasKey("UserId"); - - b.ToTable("LastContacts"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Profiles.Location", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("X") - .HasColumnType("int"); - - b.Property("Y") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("Locations"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", b => { b.Property("UserId") .ValueGeneratedOnAdd() @@ -826,8 +808,8 @@ namespace ProjectLighthouse.Migrations b.Property("LinkedRpcnId") .HasColumnType("bigint unsigned"); - b.Property("LocationId") - .HasColumnType("int"); + b.Property("LocationPacked") + .HasColumnType("bigint unsigned"); b.Property("MehHash") .HasColumnType("longtext"); @@ -877,32 +859,128 @@ namespace ProjectLighthouse.Migrations b.HasKey("UserId"); - b.HasIndex("LocationId"); - b.ToTable("Users"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Reaction", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Token.ApiKey", b => { - b.Property("RatingId") + b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int"); - b.Property("Rating") + b.Property("Created") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("APIKeys"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Token.EmailSetToken", b => + { + b.Property("EmailSetTokenId") + .ValueGeneratedOnAdd() .HasColumnType("int"); - b.Property("TargetId") - .HasColumnType("int"); + b.Property("EmailToken") + .HasColumnType("longtext"); + + b.Property("ExpiresAt") + .HasColumnType("datetime(6)"); b.Property("UserId") .HasColumnType("int"); - b.HasKey("RatingId"); + b.HasKey("EmailSetTokenId"); - b.ToTable("Reactions"); + b.HasIndex("UserId"); + + b.ToTable("EmailSetTokens"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.RegistrationToken", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Token.EmailVerificationToken", b => + { + b.Property("EmailVerificationTokenId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EmailToken") + .HasColumnType("longtext"); + + b.Property("ExpiresAt") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("EmailVerificationTokenId"); + + b.HasIndex("UserId"); + + b.ToTable("EmailVerificationTokens"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Token.GameToken", b => + { + b.Property("TokenId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ExpiresAt") + .HasColumnType("datetime(6)"); + + b.Property("GameVersion") + .HasColumnType("int"); + + b.Property("Platform") + .HasColumnType("int"); + + b.Property("TicketHash") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("int"); + + b.Property("UserLocation") + .HasColumnType("longtext"); + + b.Property("UserToken") + .HasColumnType("longtext"); + + b.HasKey("TokenId"); + + b.HasIndex("UserId"); + + b.ToTable("GameTokens"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Token.PasswordResetToken", b => + { + b.Property("TokenId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Created") + .HasColumnType("datetime(6)"); + + b.Property("ResetToken") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("TokenId"); + + b.ToTable("PasswordResetTokens"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Token.RegistrationToken", b => { b.Property("TokenId") .ValueGeneratedOnAdd() @@ -922,106 +1000,7 @@ namespace ProjectLighthouse.Migrations b.ToTable("RegistrationTokens"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Reviews.RatedReview", b => - { - b.Property("RatedReviewId") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ReviewId") - .HasColumnType("int"); - - b.Property("Thumb") - .HasColumnType("int"); - - b.Property("UserId") - .HasColumnType("int"); - - b.HasKey("RatedReviewId"); - - b.HasIndex("ReviewId"); - - b.HasIndex("UserId"); - - b.ToTable("RatedReviews"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Reviews.Review", b => - { - b.Property("ReviewId") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Deleted") - .HasColumnType("tinyint(1)"); - - b.Property("DeletedBy") - .HasColumnType("int"); - - b.Property("LabelCollection") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ReviewerId") - .HasColumnType("int"); - - b.Property("SlotId") - .HasColumnType("int"); - - b.Property("Text") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Thumb") - .HasColumnType("int"); - - b.Property("ThumbsDown") - .HasColumnType("int"); - - b.Property("ThumbsUp") - .HasColumnType("int"); - - b.Property("Timestamp") - .HasColumnType("bigint"); - - b.HasKey("ReviewId"); - - b.HasIndex("ReviewerId"); - - b.HasIndex("SlotId"); - - b.ToTable("Reviews"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Score", b => - { - b.Property("ScoreId") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ChildSlotId") - .HasColumnType("int"); - - b.Property("PlayerIdCollection") - .HasColumnType("longtext"); - - b.Property("Points") - .HasColumnType("int"); - - b.Property("SlotId") - .HasColumnType("int"); - - b.Property("Type") - .HasColumnType("int"); - - b.HasKey("ScoreId"); - - b.HasIndex("SlotId"); - - b.ToTable("Scores"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.WebToken", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Token.WebToken", b => { b.Property("TokenId") .ValueGeneratedOnAdd() @@ -1044,43 +1023,15 @@ namespace ProjectLighthouse.Migrations b.ToTable("WebTokens"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.Administration.ModerationCase", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Interaction.HeartedLevel", b => { - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "Creator") - .WithMany() - .HasForeignKey("CreatorId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "Dismisser") - .WithMany() - .HasForeignKey("DismisserId"); - - b.Navigation("Creator"); - - b.Navigation("Dismisser"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.Administration.Reports.GriefReport", b => - { - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "ReportingPlayer") - .WithMany() - .HasForeignKey("ReportingPlayerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ReportingPlayer"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.HeartedLevel", b => - { - b.HasOne("LBPUnion.ProjectLighthouse.Levels.Slot", "Slot") + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Level.Slot", "Slot") .WithMany() .HasForeignKey("SlotId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "User") + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "User") .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -1091,15 +1042,15 @@ namespace ProjectLighthouse.Migrations b.Navigation("User"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.HeartedPlaylist", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Interaction.HeartedPlaylist", b => { - b.HasOne("LBPUnion.ProjectLighthouse.Levels.Playlist", "Playlist") + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Level.Playlist", "Playlist") .WithMany() .HasForeignKey("PlaylistId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "User") + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "User") .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -1110,204 +1061,15 @@ namespace ProjectLighthouse.Migrations b.Navigation("User"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.Playlist", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Interaction.HeartedProfile", b => { - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "Creator") - .WithMany() - .HasForeignKey("CreatorId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Creator"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.QueuedLevel", b => - { - b.HasOne("LBPUnion.ProjectLighthouse.Levels.Slot", "Slot") - .WithMany() - .HasForeignKey("SlotId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Slot"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.RatedLevel", b => - { - b.HasOne("LBPUnion.ProjectLighthouse.Levels.Slot", "Slot") - .WithMany() - .HasForeignKey("SlotId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Slot"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.Slot", b => - { - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "Creator") - .WithMany() - .HasForeignKey("CreatorId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.Location", "Location") - .WithMany() - .HasForeignKey("LocationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Creator"); - - b.Navigation("Location"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.Levels.VisitedLevel", b => - { - b.HasOne("LBPUnion.ProjectLighthouse.Levels.Slot", "Slot") - .WithMany() - .HasForeignKey("SlotId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Slot"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.GameToken", b => - { - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Photo", b => - { - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "Creator") - .WithMany() - .HasForeignKey("CreatorId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("LBPUnion.ProjectLighthouse.Levels.Slot", "Slot") - .WithMany() - .HasForeignKey("SlotId"); - - b.Navigation("Creator"); - - b.Navigation("Slot"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.PhotoSubject", b => - { - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.PlatformLinkAttempt", b => - { - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Profiles.BlockedProfile", b => - { - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "BlockedUser") - .WithMany() - .HasForeignKey("BlockedUserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("BlockedUser"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Profiles.Comment", b => - { - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "Poster") - .WithMany() - .HasForeignKey("PosterUserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Poster"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Profiles.Email.EmailSetToken", b => - { - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Profiles.Email.EmailVerificationToken", b => - { - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Profiles.HeartedProfile", b => - { - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "HeartedUser") + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "HeartedUser") .WithMany() .HasForeignKey("HeartedUserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "User") + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "User") .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -1318,37 +1080,53 @@ namespace ProjectLighthouse.Migrations b.Navigation("User"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Profiles.LastContact", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Interaction.QueuedLevel", b => { - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "User") + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Level.Slot", "Slot") + .WithMany() + .HasForeignKey("SlotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "User") .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + b.Navigation("Slot"); + b.Navigation("User"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Interaction.RatedLevel", b => { - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.Location", "Location") + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Level.Slot", "Slot") .WithMany() - .HasForeignKey("LocationId") + .HasForeignKey("SlotId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.Navigation("Location"); + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Slot"); + + b.Navigation("User"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Reviews.RatedReview", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Interaction.RatedReview", b => { - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Reviews.Review", "Review") + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Level.Review", "Review") .WithMany() .HasForeignKey("ReviewId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "User") + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "User") .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -1359,15 +1137,45 @@ namespace ProjectLighthouse.Migrations b.Navigation("User"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Reviews.Review", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Interaction.VisitedLevel", b => { - b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "Reviewer") + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Level.Slot", "Slot") + .WithMany() + .HasForeignKey("SlotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Slot"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Level.Playlist", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Level.Review", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "Reviewer") .WithMany() .HasForeignKey("ReviewerId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("LBPUnion.ProjectLighthouse.Levels.Slot", "Slot") + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Level.Slot", "Slot") .WithMany() .HasForeignKey("SlotId") .OnDelete(DeleteBehavior.Cascade) @@ -1378,9 +1186,9 @@ namespace ProjectLighthouse.Migrations b.Navigation("Slot"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Score", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Level.Score", b => { - b.HasOne("LBPUnion.ProjectLighthouse.Levels.Slot", "Slot") + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Level.Slot", "Slot") .WithMany() .HasForeignKey("SlotId") .OnDelete(DeleteBehavior.Cascade) @@ -1388,6 +1196,158 @@ namespace ProjectLighthouse.Migrations b.Navigation("Slot"); }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Level.Slot", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Moderation.GriefReport", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "ReportingPlayer") + .WithMany() + .HasForeignKey("ReportingPlayerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ReportingPlayer"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Moderation.ModerationCase", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "Dismisser") + .WithMany() + .HasForeignKey("DismisserId"); + + b.Navigation("Creator"); + + b.Navigation("Dismisser"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Profile.BlockedProfile", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "BlockedUser") + .WithMany() + .HasForeignKey("BlockedUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("BlockedUser"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Profile.Comment", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "Poster") + .WithMany() + .HasForeignKey("PosterUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Poster"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Profile.LastContact", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Profile.Photo", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Level.Slot", "Slot") + .WithMany() + .HasForeignKey("SlotId"); + + b.Navigation("Creator"); + + b.Navigation("Slot"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Profile.PhotoSubject", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Profile.PlatformLinkAttempt", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Token.EmailSetToken", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Token.EmailVerificationToken", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Token.GameToken", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); #pragma warning restore 612, 618 } } diff --git a/ProjectLighthouse/Types/Entities/Level/Slot.cs b/ProjectLighthouse/Types/Entities/Level/Slot.cs index ad34e702..6644b743 100644 --- a/ProjectLighthouse/Types/Entities/Level/Slot.cs +++ b/ProjectLighthouse/Types/Entities/Level/Slot.cs @@ -73,16 +73,33 @@ public class Slot public string ResourceCollection { get; set; } = ""; [NotMapped] - [XmlElement("resource")] [JsonIgnore] - public string[] Resources { - get => this.ResourceCollection.Split(","); - set => this.ResourceCollection = string.Join(',', value); + [XmlElement("resource")] + public string[]? Resources { + get => this.ResourceCollection.Split(",", StringSplitOptions.RemoveEmptyEntries); + set => this.ResourceCollection = string.Join(',', value ?? Array.Empty()); } - [XmlIgnore] + /// + /// The location of the level on the user's earth + /// Stored as a single 64 bit unsigned integer but split into + /// 2 unsigned 32 bit integers + /// [JsonIgnore] - public int LocationId { get; set; } + public ulong LocationPacked { get; set; } + + [NotMapped] + [XmlElement("location")] + public Location Location + { + get => + new() + { + X = (int)(this.LocationPacked >> 32), + Y = (int)this.LocationPacked, + }; + set => this.LocationPacked = (ulong)value.X << 32 | (uint)value.Y; + } [XmlIgnore] public int CreatorId { get; set; } @@ -91,14 +108,6 @@ public class Slot [JsonIgnore] public User? Creator { get; set; } - /// - /// The location of the level on the creator's earth - /// - [XmlElement("location")] - [ForeignKey(nameof(LocationId))] - [JsonIgnore] - public Location? Location { get; set; } - [XmlElement("initiallyLocked")] public bool InitiallyLocked { get; set; } @@ -297,7 +306,7 @@ public class Slot string slotData = LbpSerializer.StringElement("id", this.SlotId) + LbpSerializer.StringElement("npHandle", this.Creator?.Username) + - LbpSerializer.StringElement("location", this.Location?.Serialize()) + + LbpSerializer.StringElement("location", this.Location.Serialize()) + LbpSerializer.StringElement("game", (int)this.GameVersion) + LbpSerializer.StringElement("name", this.Name) + LbpSerializer.StringElement("description", this.Description) + @@ -356,7 +365,7 @@ public class Slot LbpSerializer.StringElement("lbp3CompletionCount", this.PlaysLBP3Complete) + LbpSerializer.StringElement("lbp3UniquePlayCount", this.PlaysLBP3Unique) + (gameVersion == GameVersion.LittleBigPlanetVita ? - LbpSerializer.StringElement("sizeOfResources", this.Resources.Sum(FileHelper.ResourceSize)) + LbpSerializer.StringElement("sizeOfResources", this.Resources!.Sum(FileHelper.ResourceSize)) : ""); diff --git a/ProjectLighthouse/Types/Entities/Profile/User.cs b/ProjectLighthouse/Types/Entities/Profile/User.cs index 078c75bc..26888f6a 100644 --- a/ProjectLighthouse/Types/Entities/Profile/User.cs +++ b/ProjectLighthouse/Types/Entities/Profile/User.cs @@ -98,15 +98,26 @@ public class User select id).Count(); } - [JsonIgnore] - public int LocationId { get; set; } - /// /// The location of the profile card on the user's earth + /// Stored as a single 64 bit unsigned integer but split into + /// 2 unsigned 32 bit integers /// - [ForeignKey("LocationId")] [JsonIgnore] - public Location Location { get; set; } + public ulong LocationPacked { get; set; } + + [NotMapped] + [XmlElement("location")] + public Location Location + { + get => + new() + { + X = (int)(this.LocationPacked >> 32), + Y = (int)this.LocationPacked, + }; + set => this.LocationPacked = (ulong)value.X << 32 | (uint)value.Y; + } [NotMapped] [JsonIgnore] diff --git a/ProjectLighthouse/Types/Misc/Location.cs b/ProjectLighthouse/Types/Misc/Location.cs index 91b276c6..57a17d7d 100644 --- a/ProjectLighthouse/Types/Misc/Location.cs +++ b/ProjectLighthouse/Types/Misc/Location.cs @@ -10,9 +10,6 @@ namespace LBPUnion.ProjectLighthouse.Types.Misc; [XmlType("location")] public class Location { - [XmlIgnore] - public int Id { get; set; } - [XmlElement("x")] public int X { get; set; }