Replace Location table with packed 64-bit int (#679)

* Replace Location table with packed 64 bit int

* Remove double Include and fix Slot documentation

* Fix compilation errors from merge

* Fix namespaces and add expected values to unit tests
This commit is contained in:
Josh 2023-02-21 14:53:38 -06:00 committed by GitHub
commit 35ea2682b9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 996 additions and 930 deletions

View file

@ -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;

View file

@ -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);

View file

@ -36,7 +36,6 @@ public class CollectionController : ControllerBase
if (targetPlaylist == null) return this.BadRequest();
IQueryable<Slot> 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());

View file

@ -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<HeartedLevel> 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

View file

@ -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();

View file

@ -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);

View file

@ -75,7 +75,7 @@ public class SlotsController : ControllerBase
List<string?> 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);
}
}

View file

@ -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<string?> 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();
}

View file

@ -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))

View file

@ -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))

View file

@ -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

View file

@ -1,6 +1,6 @@
using System.Xml.Serialization;
namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Types;
namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Types.Users;
/// <summary>
/// Sent by the game client to inform the server

View file

@ -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
{

View file

@ -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")]

View file

@ -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;
/// <summary>
/// Used by the games to update details about a user's profile
/// LBP1 only uses Location and IconHash