diff --git a/ProjectLighthouse/Controllers/EnterLevelController.cs b/ProjectLighthouse/Controllers/EnterLevelController.cs index 4b6c5236..1c783cef 100644 --- a/ProjectLighthouse/Controllers/EnterLevelController.cs +++ b/ProjectLighthouse/Controllers/EnterLevelController.cs @@ -1,4 +1,8 @@ +#nullable enable +using System.Threading.Tasks; +using LBPUnion.ProjectLighthouse.Types.Levels; using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; namespace LBPUnion.ProjectLighthouse.Controllers { @@ -7,7 +11,25 @@ namespace LBPUnion.ProjectLighthouse.Controllers // [Produces("text/plain")] public class EnterLevelController : ControllerBase { - [HttpGet("enterLevel/{id}")] - public IActionResult EnterLevel(string id) => this.Ok(); + private readonly Database database; + + public EnterLevelController(Database database) + { + this.database = database; + } + + // Only used in LBP1 + [HttpGet("enterLevel/{id:int}")] + public async Task EnterLevel(int id) + { + Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id); + if (slot == null) return this.NotFound(); + + slot.Plays++; + + await this.database.SaveChangesAsync(); + + return this.Ok(); + } } } \ No newline at end of file diff --git a/ProjectLighthouse/Controllers/MatchController.cs b/ProjectLighthouse/Controllers/MatchController.cs index ddf4de8f..73ec3bbb 100644 --- a/ProjectLighthouse/Controllers/MatchController.cs +++ b/ProjectLighthouse/Controllers/MatchController.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Kettu; using LBPUnion.ProjectLighthouse.Helpers; using LBPUnion.ProjectLighthouse.Types; +using LBPUnion.ProjectLighthouse.Types.Levels; using LBPUnion.ProjectLighthouse.Types.Match; using LBPUnion.ProjectLighthouse.Types.Profiles; using Microsoft.AspNetCore.Mvc; @@ -39,11 +40,6 @@ namespace LBPUnion.ProjectLighthouse.Controllers // Example POST /match: [UpdateMyPlayerData,["Player":"FireGamer9872"]] string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync(); - if (bodyString.Contains("FindBestRoom")) - return this.Ok - ( - "[{\"StatusCode\":200},{\"Players\":[{\"PlayerId\":\"literally1984\",\"matching_res\":0},{\"PlayerId\":\"jvyden\",\"matching_res\":1}],\"Slots\":[[5,0]],\"RoomState\":\"E_ROOM_IN_POD\",\"HostMood\":\"E_MOOD_EVERYONE\",\"LevelCompletionEstimate\":0,\"PassedNoJoinPoint\":0,\"MoveConnected\":false,\"Location\":[\"127.0.0.1\"],\"BuildVersion\":289,\"Language\":1,\"FirstSeenTimestamp\":1427331263756,\"LastSeenTimestamp\":1635112546000,\"GameId\":1,\"NatType\":2,\"Friends\":[],\"Blocked\":[],\"RecentlyLeft\":[],\"FailedJoin\":[]}]" - ); if (bodyString.Length == 0 || bodyString[0] != '[') return this.BadRequest(); @@ -64,6 +60,28 @@ namespace LBPUnion.ProjectLighthouse.Controllers #endregion + #region Process match data + + if (matchData is CreateRoom createRoom) + { + if (createRoom.Slots.Count == 0) return this.BadRequest(); + if (createRoom.FirstSlot.Count != 2) return this.BadRequest(); + + int slotType = createRoom.FirstSlot[0]; + int slotId = createRoom.FirstSlot[1]; + + if (slotType == 1) + { + Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == slotId); + if (slot == null) return this.BadRequest(); + + slot.Plays++; + await this.database.SaveChangesAsync(); + } + } + + #endregion + #region Update LastMatch LastMatch? lastMatch = await this.database.LastMatches.Where(l => l.UserId == user.UserId).FirstOrDefaultAsync(); diff --git a/ProjectLighthouse/Helpers/MatchHelper.cs b/ProjectLighthouse/Helpers/MatchHelper.cs index e7e66895..766dfd91 100644 --- a/ProjectLighthouse/Helpers/MatchHelper.cs +++ b/ProjectLighthouse/Helpers/MatchHelper.cs @@ -31,6 +31,7 @@ namespace LBPUnion.ProjectLighthouse.Helpers { "UpdateMyPlayerData" => JsonSerializer.Deserialize(matchData), "UpdatePlayersInRoom" => JsonSerializer.Deserialize(matchData), + "CreateRoom" => JsonSerializer.Deserialize(matchData), _ => null, }; } diff --git a/ProjectLighthouse/Migrations/20211108015422_AddPlaysToSlot.Designer.cs b/ProjectLighthouse/Migrations/20211108015422_AddPlaysToSlot.Designer.cs new file mode 100644 index 00000000..40001bd0 --- /dev/null +++ b/ProjectLighthouse/Migrations/20211108015422_AddPlaysToSlot.Designer.cs @@ -0,0 +1,540 @@ +// +using LBPUnion.ProjectLighthouse; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace ProjectLighthouse.Migrations +{ + [DbContext(typeof(Database))] + [Migration("20211108015422_AddPlaysToSlot")] + partial class AddPlaysToSlot + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Relational:MaxIdentifierLength", 64) + .HasAnnotation("ProductVersion", "5.0.12"); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.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.Types.Levels.HeartedLevel", b => + { + b.Property("HeartedLevelId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("HeartedLevelId"); + + b.HasIndex("SlotId"); + + b.HasIndex("UserId"); + + b.ToTable("HeartedLevels"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b => + { + b.Property("QueuedLevelId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("QueuedLevelId"); + + b.HasIndex("SlotId"); + + b.HasIndex("UserId"); + + b.ToTable("QueuedLevels"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b => + { + b.Property("SlotId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AuthorLabels") + .HasColumnType("longtext"); + + b.Property("BackgroundHash") + .HasColumnType("longtext"); + + b.Property("CreatorId") + .HasColumnType("int"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("FirstUploaded") + .HasColumnType("bigint"); + + b.Property("GameVersion") + .HasColumnType("int"); + + b.Property("IconHash") + .HasColumnType("longtext"); + + b.Property("InitiallyLocked") + .HasColumnType("tinyint(1)"); + + b.Property("LastUpdated") + .HasColumnType("bigint"); + + b.Property("Lbp1Only") + .HasColumnType("tinyint(1)"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("MaximumPlayers") + .HasColumnType("int"); + + b.Property("MinimumPlayers") + .HasColumnType("int"); + + b.Property("MoveRequired") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("Plays") + .HasColumnType("int"); + + b.Property("ResourceCollection") + .HasColumnType("longtext"); + + b.Property("RootLevel") + .HasColumnType("longtext"); + + b.Property("Shareable") + .HasColumnType("int"); + + b.Property("SubLevel") + .HasColumnType("tinyint(1)"); + + b.Property("TeamPick") + .HasColumnType("tinyint(1)"); + + b.HasKey("SlotId"); + + b.HasIndex("CreatorId"); + + b.HasIndex("LocationId"); + + b.ToTable("Slots"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b => + { + b.Property("PhotoId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatorId") + .HasColumnType("int"); + + b.Property("LargeHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MediumHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PhotoSubjectCollection") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PlanHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SmallHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Timestamp") + .HasColumnType("bigint"); + + b.HasKey("PhotoId"); + + b.HasIndex("CreatorId"); + + b.ToTable("Photos"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b => + { + b.Property("PhotoSubjectId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Bounds") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("PhotoSubjectId"); + + b.HasIndex("UserId"); + + b.ToTable("PhotoSubjects"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b => + { + b.Property("CommentId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Message") + .HasColumnType("longtext"); + + b.Property("PosterUserId") + .HasColumnType("int"); + + b.Property("TargetUserId") + .HasColumnType("int"); + + b.Property("ThumbsDown") + .HasColumnType("int"); + + b.Property("ThumbsUp") + .HasColumnType("int"); + + b.Property("Timestamp") + .HasColumnType("bigint"); + + b.HasKey("CommentId"); + + b.HasIndex("PosterUserId"); + + b.HasIndex("TargetUserId"); + + b.ToTable("Comments"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.LastMatch", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Timestamp") + .HasColumnType("bigint"); + + b.HasKey("UserId"); + + b.ToTable("LastMatches"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.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.Types.Score", b => + { + b.Property("ScoreId") + .ValueGeneratedOnAdd() + .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.Token", b => + { + b.Property("TokenId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("GameVersion") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.Property("UserToken") + .HasColumnType("longtext"); + + b.HasKey("TokenId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Biography") + .HasColumnType("longtext"); + + b.Property("BooHash") + .HasColumnType("longtext"); + + b.Property("CommentCount") + .HasColumnType("int"); + + b.Property("FavouriteSlotCount") + .HasColumnType("int"); + + b.Property("FavouriteUserCount") + .HasColumnType("int"); + + b.Property("Game") + .HasColumnType("int"); + + b.Property("HeartCount") + .HasColumnType("int"); + + b.Property("IconHash") + .HasColumnType("longtext"); + + b.Property("Lists") + .HasColumnType("int"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("LolCatFtwCount") + .HasColumnType("int"); + + b.Property("Pins") + .HasColumnType("longtext"); + + b.Property("PlanetHash") + .HasColumnType("longtext"); + + b.Property("ReviewCount") + .HasColumnType("int"); + + b.Property("StaffChallengeBronzeCount") + .HasColumnType("int"); + + b.Property("StaffChallengeGoldCount") + .HasColumnType("int"); + + b.Property("StaffChallengeSilverCount") + .HasColumnType("int"); + + b.Property("Username") + .HasColumnType("longtext"); + + b.Property("YayHash") + .HasColumnType("longtext"); + + b.HasKey("UserId"); + + b.HasIndex("LocationId"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "HeartedUser") + .WithMany() + .HasForeignKey("HeartedUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("HeartedUser"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot") + .WithMany() + .HasForeignKey("SlotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Slot"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot") + .WithMany() + .HasForeignKey("SlotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Slot"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Location"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Poster") + .WithMany() + .HasForeignKey("PosterUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Target") + .WithMany() + .HasForeignKey("TargetUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Poster"); + + b.Navigation("Target"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot") + .WithMany() + .HasForeignKey("SlotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Slot"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Location"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProjectLighthouse/Migrations/20211108015422_AddPlaysToSlot.cs b/ProjectLighthouse/Migrations/20211108015422_AddPlaysToSlot.cs new file mode 100644 index 00000000..38ec2118 --- /dev/null +++ b/ProjectLighthouse/Migrations/20211108015422_AddPlaysToSlot.cs @@ -0,0 +1,24 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace ProjectLighthouse.Migrations +{ + public partial class AddPlaysToSlot : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Plays", + table: "Slots", + type: "int", + nullable: false, + defaultValue: 0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Plays", + table: "Slots"); + } + } +} diff --git a/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs b/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs index da35b605..40961787 100644 --- a/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs +++ b/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs @@ -14,7 +14,7 @@ namespace ProjectLighthouse.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("Relational:MaxIdentifierLength", 64) - .HasAnnotation("ProductVersion", "5.0.11"); + .HasAnnotation("ProductVersion", "5.0.12"); modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b => { @@ -130,6 +130,9 @@ namespace ProjectLighthouse.Migrations b.Property("Name") .HasColumnType("longtext"); + b.Property("Plays") + .HasColumnType("int"); + b.Property("ResourceCollection") .HasColumnType("longtext"); diff --git a/ProjectLighthouse/Types/Levels/Slot.cs b/ProjectLighthouse/Types/Levels/Slot.cs index c21fb698..1057fa48 100644 --- a/ProjectLighthouse/Types/Levels/Slot.cs +++ b/ProjectLighthouse/Types/Levels/Slot.cs @@ -98,6 +98,19 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels [XmlIgnore] public GameVersion GameVersion { get; set; } + [XmlIgnore] + [NotMapped] + public int Hearts { + get { + using Database database = new(); + + return database.HeartedLevels.Count(s => s.SlotId == this.SlotId); + } + } + + [XmlIgnore] + public int Plays { get; set; } + public string SerializeResources() { return this.Resources.Aggregate("", (current, resource) => current + LbpSerializer.StringElement("resource", resource)); @@ -124,7 +137,9 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels LbpSerializer.StringElement("moveRequired", this.MoveRequired) + LbpSerializer.StringElement("firstPublished", this.FirstUploaded) + LbpSerializer.StringElement("lastUpdated", this.LastUpdated) + - LbpSerializer.StringElement("mmpick", this.TeamPick); + LbpSerializer.StringElement("mmpick", this.TeamPick) + + LbpSerializer.StringElement("heartCount", this.Hearts) + + LbpSerializer.StringElement("playCount", this.Plays); return LbpSerializer.TaggedStringElement("slot", slotData, "type", "user"); } diff --git a/ProjectLighthouse/Types/Match/CreateRoom.cs b/ProjectLighthouse/Types/Match/CreateRoom.cs new file mode 100644 index 00000000..ff379e48 --- /dev/null +++ b/ProjectLighthouse/Types/Match/CreateRoom.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json.Serialization; + +namespace LBPUnion.ProjectLighthouse.Types.Match +{ + [SuppressMessage("ReSharper", "CollectionNeverUpdated.Global")] + public class CreateRoom : IMatchData + { + public List Players { get; set; } + public List Reservations { get; set; } + + // v slot type, 1 = 2974 + // "Slots":[[5,0]] + // ^ slot id + // no idea why this is an array, but we'll work with it i suppose + public List> Slots { get; set; } + + [JsonIgnore] + public List FirstSlot => this.Slots[0]; + } +} \ No newline at end of file