diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/CollectionController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/CollectionController.cs index 4a64e18b..b14ee83d 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/CollectionController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/CollectionController.cs @@ -170,7 +170,16 @@ public class CollectionController : ControllerBase } [HttpGet("searches/{endpointName}")] - public async Task GetCategorySlots(string endpointName, [FromQuery] int pageStart, [FromQuery] int pageSize) + public async Task GetCategorySlots(string endpointName, [FromQuery] int pageStart, [FromQuery] int pageSize, + [FromQuery] int players = 0, + [FromQuery] string? labelFilter0 = null, + [FromQuery] string? labelFilter1 = null, + [FromQuery] string? labelFilter2 = null, + [FromQuery] string? labelFilter3 = null, + [FromQuery] string? labelFilter4 = null, + [FromQuery] string? move = null, + [FromQuery] string? adventure = null + ) { GameTokenEntity token = this.GetToken(); @@ -182,24 +191,52 @@ public class CollectionController : ControllerBase Logger.Debug("Found category " + category, LogArea.Category); - List slots; + List slots; int totalSlots; if (category is CategoryWithUser categoryWithUser) { slots = (await categoryWithUser.GetSlots(this.database, user, pageStart, pageSize) - .ToListAsync()) - .ToSerializableList(s => SlotBase.CreateFromEntity(s, token)); + .ToListAsync()); totalSlots = categoryWithUser.GetTotalSlots(this.database, user); } else { slots = category.GetSlots(this.database, pageStart, pageSize) - .ToList() - .ToSerializableList(s => SlotBase.CreateFromEntity(s, token)); + .ToList(); totalSlots = category.GetTotalSlots(this.database); } - return this.Ok(new GenericSlotResponse("results", slots, totalSlots, pageStart + pageSize)); + slots = this.filterSlots(slots, players + 1, labelFilter0, labelFilter1, labelFilter2, labelFilter3, labelFilter4, move, adventure); + + return this.Ok(new GenericSlotResponse("results", slots.ToSerializableList(s => SlotBase.CreateFromEntity(s, token)), totalSlots, pageStart + pageSize)); + } + + private List filterSlots(List slots, int players, string? labelFilter0 = null, string? labelFilter1 = null, string? labelFilter2 = null, string? labelFilter3 = null, string? labelFilter4 = null, string? move = null, string? adventure = null) + { + slots.RemoveAll(s => s.MinimumPlayers != players); + + if (labelFilter0 != null) + slots.RemoveAll(s => !s.AuthorLabels.Split(',').ToList().Contains(labelFilter0)); + if (labelFilter1 != null) + slots.RemoveAll(s => !s.AuthorLabels.Split(',').ToList().Contains(labelFilter1)); + if (labelFilter2 != null) + slots.RemoveAll(s => !s.AuthorLabels.Split(',').ToList().Contains(labelFilter2)); + if (labelFilter3 != null) + slots.RemoveAll(s => !s.AuthorLabels.Split(',').ToList().Contains(labelFilter3)); + if (labelFilter4 != null) + slots.RemoveAll(s => !s.AuthorLabels.Split(',').ToList().Contains(labelFilter4)); + + if (move == "noneCan") + slots.RemoveAll(s => s.MoveRequired); + if (move == "allMust") + slots.RemoveAll(s => !s.MoveRequired); + + if (adventure == "noneCan") + slots.RemoveAll(s => s.IsAdventurePlanet); + if (adventure == "allMust") + slots.RemoveAll(s => !s.IsAdventurePlanet); + + return slots; } } \ No newline at end of file diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/SearchController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/SearchController.cs index 07c2296e..b5e8102e 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/SearchController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/SearchController.cs @@ -8,6 +8,7 @@ using LBPUnion.ProjectLighthouse.Types.Serialization; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers.Slots; @@ -24,15 +25,32 @@ public class SearchController : ControllerBase } [HttpGet("searchLBP3")] - public Task SearchSlotsLBP3([FromQuery] int pageSize, [FromQuery] int pageStart, [FromQuery] string textFilter) - => this.SearchSlots(textFilter, pageSize, pageStart, "results"); + public Task SearchSlotsLBP3([FromQuery] int pageSize, [FromQuery] int pageStart, [FromQuery] string textFilter, + [FromQuery] int? players = 0, + [FromQuery] string? labelFilter0 = null, + [FromQuery] string? labelFilter1 = null, + [FromQuery] string? labelFilter2 = null, + [FromQuery] string? labelFilter3 = null, + [FromQuery] string? labelFilter4 = null, + [FromQuery] string? move = null, + [FromQuery] string? adventure = null) + => this.SearchSlots(textFilter, pageSize, pageStart, "results", false, players+1, labelFilter0, labelFilter1, labelFilter2, labelFilter3, labelFilter4, move, adventure); [HttpGet("search")] public async Task SearchSlots( [FromQuery] string query, [FromQuery] int pageSize, [FromQuery] int pageStart, - string? keyName = "slots" + string? keyName = "slots", + bool crosscontrol = false, + [FromQuery] int? players = null, + [FromQuery] string? labelFilter0 = null, + [FromQuery] string? labelFilter1 = null, + [FromQuery] string? labelFilter2 = null, + [FromQuery] string? labelFilter3 = null, + [FromQuery] string? labelFilter4 = null, + [FromQuery] string? move = null, + [FromQuery] string? adventure = null ) { GameTokenEntity token = this.GetToken(); @@ -46,7 +64,7 @@ public class SearchController : ControllerBase string[] keywords = query.Split(" "); IQueryable dbQuery = this.database.Slots.ByGameVersion(token.GameVersion, false, true) - .Where(s => s.Type == SlotType.User) + .Where(s => s.Type == SlotType.User && s.CrossControllerRequired == crosscontrol) .OrderBy(s => !s.TeamPick) .ThenByDescending(s => s.FirstUploaded) .Where(s => s.SlotId >= 0); // dumb query to conv into IQueryable @@ -61,14 +79,48 @@ public class SearchController : ControllerBase s.SlotId.ToString().Equals(keyword) ); - List slots = (await dbQuery.Skip(Math.Max(0, pageStart - 1)) + List slots = (await dbQuery.Skip(Math.Max(0, pageStart - 1)) .Take(Math.Min(pageSize, 30)) - .ToListAsync()) - .ToSerializableList(s => SlotBase.CreateFromEntity(s, token)); + .ToListAsync()); - return this.Ok(new GenericSlotResponse(keyName, slots, await dbQuery.CountAsync(), 0)); + slots = filterSlots(slots, players, labelFilter0, labelFilter1, labelFilter2, labelFilter3, labelFilter4, move, adventure); + + return this.Ok(new GenericSlotResponse(keyName, slots.ToSerializableList(s => SlotBase.CreateFromEntity(s, token)), await dbQuery.CountAsync(), 0)); } - + // /LITTLEBIGPLANETPS3_XML?pageStart=1&pageSize=10&resultTypes[]=slot&resultTypes[]=playlist&resultTypes[]=user&adventure=dontCare&textFilter=qwer + private List filterSlots(List slots, int? players = null, string? labelFilter0 = null, string? labelFilter1 = null, string? labelFilter2 = null, string? labelFilter3 = null, string? labelFilter4 = null, string? move = null, string? adventure = null) + { + if (players != null) + slots.RemoveAll(s => s.MinimumPlayers != players); + + if (labelFilter0 != null) + slots.RemoveAll(s => !s.AuthorLabels.Split(',').ToList().Contains(labelFilter0)); + if (labelFilter1 != null) + slots.RemoveAll(s => !s.AuthorLabels.Split(',').ToList().Contains(labelFilter1)); + if (labelFilter2 != null) + slots.RemoveAll(s => !s.AuthorLabels.Split(',').ToList().Contains(labelFilter2)); + if (labelFilter3 != null) + slots.RemoveAll(s => !s.AuthorLabels.Split(',').ToList().Contains(labelFilter3)); + if (labelFilter4 != null) + slots.RemoveAll(s => !s.AuthorLabels.Split(',').ToList().Contains(labelFilter4)); + + if (move == "false") + slots.RemoveAll(s => s.MoveRequired); + if (move == "only") + slots.RemoveAll(s => !s.MoveRequired); + + if (move == "noneCan") + slots.RemoveAll(s => s.MoveRequired); + if (move == "allMust") + slots.RemoveAll(s => !s.MoveRequired); + + if (adventure == "noneCan") + slots.RemoveAll(s => s.IsAdventurePlanet); + if (adventure == "allMust") + slots.RemoveAll(s => !s.IsAdventurePlanet); + + return slots; + } } diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/SlotsController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/SlotsController.cs index 1b2415ba..998636e0 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/SlotsController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/SlotsController.cs @@ -29,7 +29,7 @@ public class SlotsController : ControllerBase } [HttpGet("slots/by")] - public async Task SlotsBy([FromQuery(Name = "u")] string username, [FromQuery] int pageStart, [FromQuery] int pageSize) + public async Task SlotsBy([FromQuery(Name = "u")] string username, [FromQuery] int pageStart, [FromQuery] int pageSize, [FromQuery] bool crosscontrol = false) { GameTokenEntity token = this.GetToken(); @@ -42,12 +42,13 @@ public class SlotsController : ControllerBase List slots = (await this.database.Slots.Where(s => s.CreatorId == targetUserId) .ByGameVersion(token.GameVersion, token.UserId == targetUserId) + .Where(match => match.CrossControllerRequired == crosscontrol) .Skip(Math.Max(0, pageStart - 1)) .Take(Math.Min(pageSize, usedSlots)) .ToListAsync()).ToSerializableList(s => SlotBase.CreateFromEntity(s, token)); int start = pageStart + Math.Min(pageSize, usedSlots); - int total = await this.database.Slots.CountAsync(s => s.CreatorId == targetUserId); + int total = await this.database.Slots.CountAsync(s => s.CreatorId == targetUserId && s.CrossControllerRequired == crosscontrol); return this.Ok(new GenericSlotResponse("slots", slots, total, start)); } @@ -137,19 +138,24 @@ public class SlotsController : ControllerBase ( [FromQuery] int pageStart, [FromQuery] int pageSize, + [FromQuery] int players = 1, [FromQuery] string? gameFilterType = null, - [FromQuery] int? players = null, - [FromQuery] bool? move = null, - [FromQuery] int? page = null + [FromQuery] string? labelFilter0 = null, + [FromQuery] string? labelFilter1 = null, + [FromQuery] string? labelFilter2 = null, + [FromQuery] string? move = null, + [FromQuery] int? page = null, + [FromQuery] bool crosscontrol = false ) { if (page != null) pageStart = (int)page * 30; // bit of a better placeholder until we can track average user interaction with /stream endpoint - return await this.ThumbsSlots(pageStart, Math.Min(pageSize, 30), gameFilterType, players, move, "thisMonth"); + return await this.ThumbsSlots(pageStart, Math.Min(pageSize, 30), players, gameFilterType, "thisMonth", + labelFilter0, labelFilter1, labelFilter2, move, crosscontrol); } [HttpGet("slots")] - public async Task NewestSlots([FromQuery] int pageStart, [FromQuery] int pageSize) + public async Task NewestSlots([FromQuery] int pageStart, [FromQuery] int pageSize, [FromQuery] bool crosscontrol = false) { GameTokenEntity token = this.GetToken(); @@ -158,6 +164,7 @@ public class SlotsController : ControllerBase GameVersion gameVersion = token.GameVersion; List slots = (await this.database.Slots.ByGameVersion(gameVersion, false, true) + .Where(s => s.CrossControllerRequired == crosscontrol) .OrderByDescending(s => s.FirstUploaded) .ThenByDescending(s => s.SlotId) .Skip(Math.Max(0, pageStart - 1)) @@ -257,26 +264,51 @@ public class SlotsController : ControllerBase } [HttpGet("slots/mmpicks")] - public async Task TeamPickedSlots([FromQuery] int pageStart, [FromQuery] int pageSize) + public async Task TeamPickedSlots + ( + [FromQuery] int pageStart, + [FromQuery] int pageSize, + [FromQuery] int players, + [FromQuery] string? gameFilterType = null, + [FromQuery] string? dateFilterType = null, + [FromQuery] string? labelFilter0 = null, + [FromQuery] string? labelFilter1 = null, + [FromQuery] string? labelFilter2 = null, + [FromQuery] string? move = null, + [FromQuery] bool crosscontrol = false + ) { GameTokenEntity token = this.GetToken(); if (pageSize <= 0) return this.BadRequest(); - List slots = (await this.database.Slots.Where(s => s.TeamPick) - .ByGameVersion(token.GameVersion, false, true) + List slots = this.filterSlots((await this.filterByRequest(gameFilterType, dateFilterType, token.GameVersion) + .Where(s => s.TeamPick && s.CrossControllerRequired == crosscontrol) .OrderByDescending(s => s.LastUpdated) .Skip(Math.Max(0, pageStart - 1)) .Take(Math.Min(pageSize, 30)) - .ToListAsync()).ToSerializableList(s => SlotBase.CreateFromEntity(s, token)); + .ToListAsync()), players, labelFilter0, labelFilter1, labelFilter2, move).ToSerializableList(s => SlotBase.CreateFromEntity(s, token)); int start = pageStart + Math.Min(pageSize, ServerConfiguration.Instance.UserGeneratedContentLimits.EntitledSlots); - int total = await StatisticsHelper.TeamPickCountForGame(this.database, token.GameVersion); + int total = await StatisticsHelper.TeamPickCountForGame(this.database, token.GameVersion, crosscontrol); return this.Ok(new GenericSlotResponse(slots, total, start)); } [HttpGet("slots/lbp2luckydip")] - public async Task LuckyDipSlots([FromQuery] int pageStart, [FromQuery] int pageSize, [FromQuery] int seed) + public async Task LuckyDipSlots + ( + [FromQuery] int pageStart, + [FromQuery] int pageSize, + [FromQuery] int seed, + [FromQuery] int players = 1, + [FromQuery] string? gameFilterType = null, + [FromQuery] string? dateFilterType = null, + [FromQuery] string? labelFilter0 = null, + [FromQuery] string? labelFilter1 = null, + [FromQuery] string? labelFilter2 = null, + [FromQuery] string? move = null, + [FromQuery] bool crosscontrol = false + ) { GameTokenEntity token = this.GetToken(); @@ -285,10 +317,11 @@ public class SlotsController : ControllerBase GameVersion gameVersion = token.GameVersion; const double biasFactor = .8f; - List slots = (await this.database.Slots.ByGameVersion(gameVersion, false, true) + List slots = this.filterSlots((await this.filterByRequest(gameFilterType, dateFilterType, token.GameVersion) + .Where(s => s.CrossControllerRequired == crosscontrol) .OrderByDescending(s => EF.Functions.Random() * (s.FirstUploaded * biasFactor)) .Take(Math.Min(pageSize, 30)) - .ToListAsync()).ToSerializableList(s => SlotBase.CreateFromEntity(s, token)); + .ToListAsync()), players, labelFilter0, labelFilter1, labelFilter2, move).ToSerializableList(s => SlotBase.CreateFromEntity(s, token)); int start = pageStart + Math.Min(pageSize, ServerConfiguration.Instance.UserGeneratedContentLimits.EntitledSlots); int total = await StatisticsHelper.SlotCountForGame(this.database, token.GameVersion); @@ -301,17 +334,22 @@ public class SlotsController : ControllerBase ( [FromQuery] int pageStart, [FromQuery] int pageSize, + [FromQuery] int players, [FromQuery] string? gameFilterType = null, - [FromQuery] int? players = null, - [FromQuery] bool? move = null, - [FromQuery] string? dateFilterType = null + [FromQuery] string? dateFilterType = null, + [FromQuery] string? labelFilter0 = null, + [FromQuery] string? labelFilter1 = null, + [FromQuery] string? labelFilter2 = null, + [FromQuery] string? move = null, + [FromQuery] bool crosscontrol = false ) { GameTokenEntity token = this.GetToken(); if (pageSize <= 0) return this.BadRequest(); - List slots = (await this.filterByRequest(gameFilterType, dateFilterType, token.GameVersion) + List slots = this.filterSlots((await this.filterByRequest(gameFilterType, dateFilterType, token.GameVersion) + .Where(s => s.CrossControllerRequired == crosscontrol) .Select(s => new SlotMetadata { Slot = s, @@ -322,7 +360,7 @@ public class SlotsController : ControllerBase .Select(s => s.Slot) .Skip(Math.Max(0, pageStart - 1)) .Take(Math.Min(pageSize, 30)) - .ToListAsync()).ToSerializableList(s => SlotBase.CreateFromEntity(s, token)); + .ToListAsync()), players, labelFilter0, labelFilter1, labelFilter2, move).ToSerializableList(s => SlotBase.CreateFromEntity(s, token)); int start = pageStart + Math.Min(pageSize, ServerConfiguration.Instance.UserGeneratedContentLimits.EntitledSlots); int total = await StatisticsHelper.SlotCountForGame(this.database, token.GameVersion); @@ -335,10 +373,14 @@ public class SlotsController : ControllerBase ( [FromQuery] int pageStart, [FromQuery] int pageSize, + [FromQuery] int players, [FromQuery] string? gameFilterType = null, - [FromQuery] int? players = null, - [FromQuery] bool? move = null, - [FromQuery] string? dateFilterType = null + [FromQuery] string? labelFilter0 = null, + [FromQuery] string? labelFilter1 = null, + [FromQuery] string? labelFilter2 = null, + [FromQuery] string? move = null, + [FromQuery] string? dateFilterType = null, + [FromQuery] bool crosscontrol = false ) { GameTokenEntity token = this.GetToken(); @@ -356,11 +398,12 @@ public class SlotsController : ControllerBase string colName = $"Plays{game}Unique"; - List slots = (await this.filterByRequest(gameFilterType, dateFilterType, token.GameVersion) + List slots = this.filterSlots((await this.filterByRequest(gameFilterType, dateFilterType, token.GameVersion) + .Where(s => s.CrossControllerRequired == crosscontrol) .OrderByDescending(s => EF.Property(s, colName)) .Skip(Math.Max(0, pageStart - 1)) .Take(Math.Min(pageSize, 30)) - .ToListAsync()).ToSerializableList(s => SlotBase.CreateFromEntity(s, token)); + .ToListAsync()), players, labelFilter0, labelFilter1, labelFilter2, move).ToSerializableList(s => SlotBase.CreateFromEntity(s, token)); int start = pageStart + Math.Min(pageSize, ServerConfiguration.Instance.UserGeneratedContentLimits.EntitledSlots); int total = await StatisticsHelper.SlotCountForGame(this.database, token.GameVersion); @@ -373,17 +416,22 @@ public class SlotsController : ControllerBase ( [FromQuery] int pageStart, [FromQuery] int pageSize, + [FromQuery] int players, [FromQuery] string? gameFilterType = null, - [FromQuery] int? players = null, - [FromQuery] bool? move = null, - [FromQuery] string? dateFilterType = null + [FromQuery] string? labelFilter0 = null, + [FromQuery] string? labelFilter1 = null, + [FromQuery] string? labelFilter2 = null, + [FromQuery] string? move = null, + [FromQuery] string? dateFilterType = null, + [FromQuery] bool crosscontrol = false ) { GameTokenEntity token = this.GetToken(); if (pageSize <= 0) return this.BadRequest(); - List slots = (await this.filterByRequest(gameFilterType, dateFilterType, token.GameVersion) + List slots = this.filterSlots((await this.filterByRequest(gameFilterType, dateFilterType, token.GameVersion) + .Where(s => s.CrossControllerRequired == crosscontrol) .Select(s => new SlotMetadata { Slot = s, @@ -393,7 +441,7 @@ public class SlotsController : ControllerBase .Select(s => s.Slot) .Skip(Math.Max(0, pageStart - 1)) .Take(Math.Min(pageSize, 30)) - .ToListAsync()).ToSerializableList(s => SlotBase.CreateFromEntity(s, token)); + .ToListAsync()), players, labelFilter0, labelFilter1, labelFilter2, move).ToSerializableList(s => SlotBase.CreateFromEntity(s, token)); int start = pageStart + Math.Min(pageSize, ServerConfiguration.Instance.UserGeneratedContentLimits.EntitledSlots); int total = await StatisticsHelper.SlotCountForGame(this.database, token.GameVersion); @@ -408,8 +456,12 @@ public class SlotsController : ControllerBase [FromQuery] int pageStart, [FromQuery] int pageSize, [FromQuery] string? gameFilterType = null, - [FromQuery] int? players = null, - [FromQuery] bool? move = null + [FromQuery] int players = 1, + [FromQuery] string? labelFilter0 = null, + [FromQuery] string? labelFilter1 = null, + [FromQuery] string? labelFilter2 = null, + [FromQuery] string? move = null, + [FromQuery] bool crosscontrol = false ) { GameTokenEntity token = this.GetToken(); @@ -438,24 +490,44 @@ public class SlotsController : ControllerBase .OrderByDescending(kvp => kvp.Value) .Select(kvp => kvp.Key); - List slots = new(); + List slots = new(); foreach (int slotId in orderedPlayersBySlotId) { SlotEntity? slot = await this.database.Slots.ByGameVersion(token.GameVersion, false, true) - .Where(s => s.SlotId == slotId) + .Where(s => s.SlotId == slotId && s.CrossControllerRequired == crosscontrol) .FirstOrDefaultAsync(); if (slot == null) continue; // shouldn't happen ever unless the room is borked - slots.Add(SlotBase.CreateFromEntity(slot, token)); + slots.Add(slot); } + slots = this.filterSlots(slots, players, labelFilter0, labelFilter1, labelFilter2, move); + int start = pageStart + Math.Min(pageSize, ServerConfiguration.Instance.UserGeneratedContentLimits.EntitledSlots); int total = playersBySlotId.Count; - return this.Ok(new GenericSlotResponse(slots, total, start)); + return this.Ok(new GenericSlotResponse(slots.ToSerializableList(s => SlotBase.CreateFromEntity(s, token)), total, start)); } + private List filterSlots(List slots, int players, string? labelFilter0 = null, string? labelFilter1 = null, string? labelFilter2 = null, string? move = null) + { + slots.RemoveAll(s => s.MinimumPlayers != players); + + if (labelFilter0 != null) + slots.RemoveAll(s => !s.AuthorLabels.Split(',').ToList().Contains(labelFilter0)); + if (labelFilter1 != null) + slots.RemoveAll(s => !s.AuthorLabels.Split(',').ToList().Contains(labelFilter1)); + if (labelFilter2 != null) + slots.RemoveAll(s => !s.AuthorLabels.Split(',').ToList().Contains(labelFilter2)); + + if (move == "false") + slots.RemoveAll(s => s.MoveRequired); + if (move == "only") + slots.RemoveAll(s => !s.MoveRequired); + + return slots; + } private static GameVersion getGameFilter(string? gameFilterType, GameVersion version) { diff --git a/ProjectLighthouse.Servers.GameServer/Types/Categories/CustomCategory.cs b/ProjectLighthouse.Servers.GameServer/Types/Categories/CustomCategory.cs index 6757e9ff..c281739a 100644 --- a/ProjectLighthouse.Servers.GameServer/Types/Categories/CustomCategory.cs +++ b/ProjectLighthouse.Servers.GameServer/Types/Categories/CustomCategory.cs @@ -35,9 +35,9 @@ public class CustomCategory : Category public sealed override string Description { get; set; } public sealed override string IconHash { get; set; } public sealed override string Endpoint { get; set; } - public override SlotEntity? GetPreviewSlot(DatabaseContext database) => database.Slots.FirstOrDefault(s => s.SlotId == this.SlotIds[0]); + public override SlotEntity? GetPreviewSlot(DatabaseContext database) => database.Slots.FirstOrDefault(s => s.SlotId == this.SlotIds[0] && !s.CrossControllerRequired); public override IQueryable GetSlots (DatabaseContext database, int pageStart, int pageSize) - => database.Slots.ByGameVersion(GameVersion.LittleBigPlanet3).Where(s => this.SlotIds.Contains(s.SlotId)); + => database.Slots.ByGameVersion(GameVersion.LittleBigPlanet3).Where(s => this.SlotIds.Contains(s.SlotId) && !s.CrossControllerRequired); public override int GetTotalSlots(DatabaseContext database) => this.SlotIds.Count; } \ No newline at end of file diff --git a/ProjectLighthouse.Servers.GameServer/Types/Categories/HeartedCategory.cs b/ProjectLighthouse.Servers.GameServer/Types/Categories/HeartedCategory.cs index 015226fa..97ba3a6d 100644 --- a/ProjectLighthouse.Servers.GameServer/Types/Categories/HeartedCategory.cs +++ b/ProjectLighthouse.Servers.GameServer/Types/Categories/HeartedCategory.cs @@ -17,7 +17,7 @@ public class HeartedCategory : CategoryWithUser public override string Endpoint { get; set; } = "hearted"; public override SlotEntity? GetPreviewSlot(DatabaseContext database, UserEntity user) // note: developer slots act up in LBP3 when listed here, so I omitted it => database.HeartedLevels.Where(h => h.UserId == user.UserId) - .Where(h => h.Slot.Type == SlotType.User && !h.Slot.Hidden && h.Slot.GameVersion <= GameVersion.LittleBigPlanet3) + .Where(h => h.Slot.Type == SlotType.User && !h.Slot.Hidden && h.Slot.GameVersion <= GameVersion.LittleBigPlanet3 && !h.Slot.CrossControllerRequired) .OrderByDescending(h => h.HeartedLevelId) .Include(h => h.Slot.Creator) .Select(h => h.Slot) @@ -26,7 +26,7 @@ public class HeartedCategory : CategoryWithUser public override IQueryable GetSlots(DatabaseContext database, UserEntity user, int pageStart, int pageSize) => database.HeartedLevels.Where(h => h.UserId == user.UserId) - .Where(h => h.Slot.Type == SlotType.User && !h.Slot.Hidden && h.Slot.GameVersion <= GameVersion.LittleBigPlanet3) + .Where(h => h.Slot.Type == SlotType.User && !h.Slot.Hidden && h.Slot.GameVersion <= GameVersion.LittleBigPlanet3 && !h.Slot.CrossControllerRequired) .OrderByDescending(h => h.HeartedLevelId) .Include(h => h.Slot.Creator) .Select(h => h.Slot) diff --git a/ProjectLighthouse.Servers.GameServer/Types/Categories/HighestRatedCategory.cs b/ProjectLighthouse.Servers.GameServer/Types/Categories/HighestRatedCategory.cs index 44e62b21..01929878 100644 --- a/ProjectLighthouse.Servers.GameServer/Types/Categories/HighestRatedCategory.cs +++ b/ProjectLighthouse.Servers.GameServer/Types/Categories/HighestRatedCategory.cs @@ -16,7 +16,7 @@ public class HighestRatedCategory : Category public override string IconHash { get; set; } = "g820603"; public override string Endpoint { get; set; } = "thumbs"; public override SlotEntity? GetPreviewSlot(DatabaseContext database) => - database.Slots.Where(s => s.Type == SlotType.User) + database.Slots.Where(s => s.Type == SlotType.User && !s.CrossControllerRequired) .Select(s => new SlotMetadata { Slot = s, @@ -28,6 +28,7 @@ public class HighestRatedCategory : Category public override IEnumerable GetSlots(DatabaseContext database, int pageStart, int pageSize) => database.Slots.ByGameVersion(GameVersion.LittleBigPlanet3, false, true) + .Where(s => !s.CrossControllerRequired) .Select(s => new SlotMetadata { Slot = s, diff --git a/ProjectLighthouse.Servers.GameServer/Types/Categories/LuckyDipCategory.cs b/ProjectLighthouse.Servers.GameServer/Types/Categories/LuckyDipCategory.cs index 32bd4576..72ad0b95 100644 --- a/ProjectLighthouse.Servers.GameServer/Types/Categories/LuckyDipCategory.cs +++ b/ProjectLighthouse.Servers.GameServer/Types/Categories/LuckyDipCategory.cs @@ -14,10 +14,11 @@ public class LuckyDipCategory : Category public override string Description { get; set; } = "A random selection of content"; public override string IconHash { get; set; } = "g820605"; public override string Endpoint { get; set; } = "lbp2luckydip"; - public override SlotEntity? GetPreviewSlot(DatabaseContext database) => database.Slots.Where(s => s.Type == SlotType.User).OrderByDescending(_ => EF.Functions.Random()).FirstOrDefault(); + public override SlotEntity? GetPreviewSlot(DatabaseContext database) => database.Slots.Where(s => s.Type == SlotType.User && !s.CrossControllerRequired).OrderByDescending(_ => EF.Functions.Random()).FirstOrDefault(); public override IQueryable GetSlots (DatabaseContext database, int pageStart, int pageSize) => database.Slots.ByGameVersion(GameVersion.LittleBigPlanet3, false, true) + .Where(s => !s.CrossControllerRequired) .OrderByDescending(_ => EF.Functions.Random()) .Skip(Math.Max(0, pageStart - 1)) .Take(Math.Min(pageSize, 20)); diff --git a/ProjectLighthouse.Servers.GameServer/Types/Categories/MostHeartedCategory.cs b/ProjectLighthouse.Servers.GameServer/Types/Categories/MostHeartedCategory.cs index eebe6994..ce14ed0c 100644 --- a/ProjectLighthouse.Servers.GameServer/Types/Categories/MostHeartedCategory.cs +++ b/ProjectLighthouse.Servers.GameServer/Types/Categories/MostHeartedCategory.cs @@ -16,7 +16,7 @@ public class MostHeartedCategory : Category public override string Endpoint { get; set; } = "mostHearted"; public override SlotEntity? GetPreviewSlot(DatabaseContext database) => - database.Slots.Where(s => s.Type == SlotType.User) + database.Slots.Where(s => s.Type == SlotType.User && !s.CrossControllerRequired) .Select(s => new SlotMetadata { Slot = s, @@ -28,6 +28,7 @@ public class MostHeartedCategory : Category public override IEnumerable GetSlots(DatabaseContext database, int pageStart, int pageSize) => database.Slots.ByGameVersion(GameVersion.LittleBigPlanet3, false, true) + .Where(s => !s.CrossControllerRequired) .Select(s => new SlotMetadata { Slot = s, diff --git a/ProjectLighthouse.Servers.GameServer/Types/Categories/MostPlayedCategory.cs b/ProjectLighthouse.Servers.GameServer/Types/Categories/MostPlayedCategory.cs index 86f68741..56e0d63a 100644 --- a/ProjectLighthouse.Servers.GameServer/Types/Categories/MostPlayedCategory.cs +++ b/ProjectLighthouse.Servers.GameServer/Types/Categories/MostPlayedCategory.cs @@ -14,13 +14,14 @@ public class MostPlayedCategory : Category public override string IconHash { get; set; } = "g820608"; public override string Endpoint { get; set; } = "mostUniquePlays"; public override SlotEntity? GetPreviewSlot(DatabaseContext database) => database.Slots - .Where(s => s.Type == SlotType.User) + .Where(s => s.Type == SlotType.User && !s.CrossControllerRequired) .OrderByDescending(s => s.PlaysLBP1Unique + s.PlaysLBP2Unique + s.PlaysLBP3Unique) .ThenByDescending(s => s.PlaysLBP1 + s.PlaysLBP2 + s.PlaysLBP3) .FirstOrDefault(); public override IQueryable GetSlots (DatabaseContext database, int pageStart, int pageSize) => database.Slots.ByGameVersion(GameVersion.LittleBigPlanet3, false, true) + .Where(s => !s.CrossControllerRequired) .OrderByDescending(s => s.PlaysLBP1Unique + s.PlaysLBP2Unique + s.PlaysLBP3Unique) .ThenByDescending(s => s.PlaysLBP1 + s.PlaysLBP2 + s.PlaysLBP3) .Skip(Math.Max(0, pageStart - 1)) diff --git a/ProjectLighthouse.Servers.GameServer/Types/Categories/NewestLevelsCategory.cs b/ProjectLighthouse.Servers.GameServer/Types/Categories/NewestLevelsCategory.cs index 985d4866..9656a4e9 100644 --- a/ProjectLighthouse.Servers.GameServer/Types/Categories/NewestLevelsCategory.cs +++ b/ProjectLighthouse.Servers.GameServer/Types/Categories/NewestLevelsCategory.cs @@ -13,10 +13,11 @@ public class NewestLevelsCategory : Category public override string Description { get; set; } = "The most recently published content"; public override string IconHash { get; set; } = "g820623"; public override string Endpoint { get; set; } = "newest"; - public override SlotEntity? GetPreviewSlot(DatabaseContext database) => database.Slots.Where(s => s.Type == SlotType.User).OrderByDescending(s => s.FirstUploaded).FirstOrDefault(); + public override SlotEntity? GetPreviewSlot(DatabaseContext database) => database.Slots.Where(s => s.Type == SlotType.User && !s.CrossControllerRequired).OrderByDescending(s => s.FirstUploaded).FirstOrDefault(); public override IQueryable GetSlots (DatabaseContext database, int pageStart, int pageSize) => database.Slots.ByGameVersion(GameVersion.LittleBigPlanet3, false, true) + .Where(s => !s.CrossControllerRequired) .OrderByDescending(s => s.FirstUploaded) .Skip(Math.Max(0, pageStart - 1)) .Take(Math.Min(pageSize, 20)); diff --git a/ProjectLighthouse.Servers.GameServer/Types/Categories/TeamPicksCategory.cs b/ProjectLighthouse.Servers.GameServer/Types/Categories/TeamPicksCategory.cs index a8fef3bc..3d5422f3 100644 --- a/ProjectLighthouse.Servers.GameServer/Types/Categories/TeamPicksCategory.cs +++ b/ProjectLighthouse.Servers.GameServer/Types/Categories/TeamPicksCategory.cs @@ -13,12 +13,12 @@ public class TeamPicksCategory : Category public override string Description { get; set; } = "Community Team Picks"; public override string IconHash { get; set; } = "g820626"; public override string Endpoint { get; set; } = "team_picks"; - public override SlotEntity? GetPreviewSlot(DatabaseContext database) => database.Slots.OrderByDescending(s => s.FirstUploaded).FirstOrDefault(s => s.TeamPick); + public override SlotEntity? GetPreviewSlot(DatabaseContext database) => database.Slots.OrderByDescending(s => s.FirstUploaded).FirstOrDefault(s => s.TeamPick && !s.CrossControllerRequired); public override IQueryable GetSlots (DatabaseContext database, int pageStart, int pageSize) => database.Slots.ByGameVersion(GameVersion.LittleBigPlanet3, false, true) .OrderByDescending(s => s.FirstUploaded) - .Where(s => s.TeamPick) + .Where(s => s.TeamPick && !s.CrossControllerRequired) .Skip(Math.Max(0, pageStart - 1)) .Take(Math.Min(pageSize, 20)); public override int GetTotalSlots(DatabaseContext database) => database.Slots.Count(s => s.TeamPick); diff --git a/ProjectLighthouse/Helpers/StatisticsHelper.cs b/ProjectLighthouse/Helpers/StatisticsHelper.cs index 750ae34f..88c6063e 100644 --- a/ProjectLighthouse/Helpers/StatisticsHelper.cs +++ b/ProjectLighthouse/Helpers/StatisticsHelper.cs @@ -27,7 +27,7 @@ public static class StatisticsHelper public static async Task TeamPickCount(DatabaseContext database) => await database.Slots.CountAsync(s => s.TeamPick); - public static async Task TeamPickCountForGame(DatabaseContext database, GameVersion gameVersion) => await database.Slots.ByGameVersion(gameVersion).CountAsync(s => s.TeamPick); + public static async Task TeamPickCountForGame(DatabaseContext database, GameVersion gameVersion, bool? crosscontrol = null) => await database.Slots.ByGameVersion(gameVersion).CountAsync(s => s.TeamPick && (crosscontrol == null || s.CrossControllerRequired == crosscontrol)); public static async Task PhotoCount(DatabaseContext database) => await database.Photos.CountAsync(); diff --git a/ProjectLighthouse/Types/Serialization/GameUser.cs b/ProjectLighthouse/Types/Serialization/GameUser.cs index 83e04ac2..ab062707 100644 --- a/ProjectLighthouse/Types/Serialization/GameUser.cs +++ b/ProjectLighthouse/Types/Serialization/GameUser.cs @@ -194,7 +194,7 @@ public class GameUser : ILbpSerializable, INeedsPreparationForSerialization if (this.TargetGame == GameVersion.LittleBigPlanetVita) { this.Lbp2EntitledSlots = entitledSlots; - this.Lbp2UsedSlots = await SlotCount(GameVersion.LittleBigPlanet2).CountAsync(); + this.Lbp2UsedSlots = await SlotCount(GameVersion.LittleBigPlanetVita).CountAsync(); } else { @@ -203,7 +203,7 @@ public class GameUser : ILbpSerializable, INeedsPreparationForSerialization this.CrossControlEntitledSlots = entitledSlots; this.Lbp3EntitledSlots = entitledSlots; this.Lbp1UsedSlots = await SlotCount(GameVersion.LittleBigPlanet1).CountAsync(); - this.Lbp2UsedSlots = await SlotCount(GameVersion.LittleBigPlanet2).CountAsync(); + this.Lbp2UsedSlots = await SlotCount(GameVersion.LittleBigPlanet2).CountAsync(s => !s.CrossControllerRequired); this.Lbp3UsedSlots = await SlotCount(GameVersion.LittleBigPlanet3).CountAsync(); this.Lbp1FreeSlots = this.Lbp1EntitledSlots - this.Lbp1UsedSlots; diff --git a/ProjectLighthouse/Types/Serialization/GameUserSlot.cs b/ProjectLighthouse/Types/Serialization/GameUserSlot.cs index 6588266e..5f45bc2d 100644 --- a/ProjectLighthouse/Types/Serialization/GameUserSlot.cs +++ b/ProjectLighthouse/Types/Serialization/GameUserSlot.cs @@ -119,7 +119,7 @@ public class GameUserSlot : SlotBase, INeedsPreparationForSerialization public bool IsMoveRequired { get; set; } public bool ShouldSerializeIsMoveRequired() => this.SerializationMode == SerializationMode.Full; - [XmlElement("crossControlRequired")] + [XmlElement("vitaCrossControlRequired")] public bool IsCrossControlRequired { get; set; } public bool ShouldSerializeIsCrossControlRequired() => this.SerializationMode == SerializationMode.Full;