diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/ClientConfigurationController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/ClientConfigurationController.cs index 7e9dd31d..ad1652c4 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/ClientConfigurationController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/ClientConfigurationController.cs @@ -29,7 +29,7 @@ public class ClientConfigurationController : ControllerBase HostString hostname = this.Request.Host; return this.Ok ( - "ProbabilityOfPacketDelay 0.0\nMinPacketDelayFrames 0\nMaxPacketDelayFrames 3\nProbabilityOfPacketDrop 0.0\nEnableFakeConditionsForLoopback true\nNumberOfFramesPredictionAllowedForNonLocalPlayer 1000\nEnablePrediction true\nMinPredictedFrames 0\nMaxPredictedFrames 10\nAllowGameRendCameraSplit true\nFramesBeforeAgressiveCatchup 30\nPredictionPadSides 200\nPredictionPadTop 200\nPredictionPadBottom 200\nShowErrorNumbers true\nAllowModeratedLevels false\nAllowModeratedPoppetItems false\nTIMEOUT_WAIT_FOR_JOIN_RESPONSE_FROM_PREV_PARTY_HOST 50.0\nTIMEOUT_WAIT_FOR_CHANGE_LEVEL_PARTY_HOST 30.0\nTIMEOUT_WAIT_FOR_CHANGE_LEVEL_PARTY_MEMBER 45.0\nTIMEOUT_WAIT_FOR_REQUEST_JOIN_FRIEND 15.0\nTIMEOUT_WAIT_FOR_CONNECTION_FROM_HOST 30.0\nTIMEOUT_WAIT_FOR_ROOM_ID_TO_JOIN 60.0\nTIMEOUT_WAIT_FOR_GET_NUM_PLAYERS_ONLINE 60.0\nTIMEOUT_WAIT_FOR_SIGNALLING_CONNECTIONS 120.0\nTIMEOUT_WAIT_FOR_PARTY_DATA 60.0\nTIME_TO_WAIT_FOR_LEAVE_MESSAGE_TO_COME_BACK 20.0\nTIME_TO_WAIT_FOR_FOLLOWING_REQUESTS_TO_ARRIVE 30.0\nTIMEOUT_WAIT_FOR_FINISHED_MIGRATING_HOST 30.0\nTIMEOUT_WAIT_FOR_PARTY_LEADER_FINISH_JOINING 45.0\nTIMEOUT_WAIT_FOR_QUICKPLAY_LEVEL 60.0\nTIMEOUT_WAIT_FOR_PLAYERS_TO_JOIN 30.0\nTIMEOUT_WAIT_FOR_DIVE_IN_PLAYERS 240.0\nTIMEOUT_WAIT_FOR_FIND_BEST_ROOM 60.0\nTIMEOUT_DIVE_IN_TOTAL 300.0\nTIMEOUT_WAIT_FOR_SOCKET_CONNECTION 120.0\nTIMEOUT_WAIT_FOR_REQUEST_RESOURCE_MESSAGE 120.0\nTIMEOUT_WAIT_FOR_LOCAL_CLIENT_TO_GET_RESOURCE_LIST 120.0\nTIMEOUT_WAIT_FOR_CLIENT_TO_LOAD_RESOURCES 120.0\nTIMEOUT_WAIT_FOR_LOCAL_CLIENT_TO_SAVE_GAME_STATE 30.0\nTIMEOUT_WAIT_FOR_ADD_PLAYERS_TO_TAKE 30.0\nTIMEOUT_WAIT_FOR_UPDATE_FROM_CLIENT 90.0\nTIMEOUT_WAIT_FOR_HOST_TO_GET_RESOURCE_LIST 60.0\nTIMEOUT_WAIT_FOR_HOST_TO_SAVE_GAME_STATE 60.0\nTIMEOUT_WAIT_FOR_HOST_TO_ADD_US 30.0\nTIMEOUT_WAIT_FOR_UPDATE 60.0\nTIMEOUT_WAIT_FOR_REQUEST_JOIN 50.0\nTIMEOUT_WAIT_FOR_AUTOJOIN_PRESENCE 60.0\nTIMEOUT_WAIT_FOR_AUTOJOIN_CONNECTION 120.0\nSECONDS_BETWEEN_PINS_AWARDED_UPLOADS 300.0\nEnableKeepAlive true\nAllowVoIPRecordingPlayback true\nOverheatingThresholdDisallowMidgameJoin 0.95\nMaxCatchupFrames 3\nMaxLagBeforeShowLoading 23\nMinLagBeforeHideLoading 30\nLagImprovementInflectionPoint -1.0\nFlickerThreshold 2.0\nClosedDemo2014Version 1\nClosedDemo2014Expired false\nEnablePlayedFilter true\nEnableCommunityDecorations true\nGameStateUpdateRate 10.0\nGameStateUpdateRateWithConsumers 1.0\nDisableDLCPublishCheck false\nEnableDiveIn true\nEnableHackChecks false\nAllowOnlineCreate true" + + "ProbabilityOfPacketDelay 0.0\nMinPacketDelayFrames 0\nMaxPacketDelayFrames 3\nProbabilityOfPacketDrop 0.0\nEnableFakeConditionsForLoopback true\nNumberOfFramesPredictionAllowedForNonLocalPlayer 1000\nEnablePrediction true\nMinPredictedFrames 0\nMaxPredictedFrames 10\nAllowGameRendCameraSplit true\nFramesBeforeAgressiveCatchup 30\nPredictionPadSides 200\nPredictionPadTop 200\nPredictionPadBottom 200\nShowErrorNumbers true\nAllowModeratedLevels false\nAllowModeratedPoppetItems false\nTIMEOUT_WAIT_FOR_JOIN_RESPONSE_FROM_PREV_PARTY_HOST 50.0\nTIMEOUT_WAIT_FOR_CHANGE_LEVEL_PARTY_HOST 30.0\nTIMEOUT_WAIT_FOR_CHANGE_LEVEL_PARTY_MEMBER 45.0\nTIMEOUT_WAIT_FOR_REQUEST_JOIN_FRIEND 15.0\nTIMEOUT_WAIT_FOR_CONNECTION_FROM_HOST 30.0\nTIMEOUT_WAIT_FOR_ROOM_ID_TO_JOIN 60.0\nTIMEOUT_WAIT_FOR_GET_NUM_PLAYERS_ONLINE 60.0\nTIMEOUT_WAIT_FOR_SIGNALLING_CONNECTIONS 120.0\nTIMEOUT_WAIT_FOR_PARTY_DATA 60.0\nTIME_TO_WAIT_FOR_LEAVE_MESSAGE_TO_COME_BACK 20.0\nTIME_TO_WAIT_FOR_FOLLOWING_REQUESTS_TO_ARRIVE 30.0\nTIMEOUT_WAIT_FOR_FINISHED_MIGRATING_HOST 30.0\nTIMEOUT_WAIT_FOR_PARTY_LEADER_FINISH_JOINING 45.0\nTIMEOUT_WAIT_FOR_QUICKPLAY_LEVEL 60.0\nTIMEOUT_WAIT_FOR_PLAYERS_TO_JOIN 30.0\nTIMEOUT_WAIT_FOR_DIVE_IN_PLAYERS 240.0\nTIMEOUT_WAIT_FOR_FIND_BEST_ROOM 60.0\nTIMEOUT_DIVE_IN_TOTAL 300.0\nTIMEOUT_WAIT_FOR_SOCKET_CONNECTION 120.0\nTIMEOUT_WAIT_FOR_REQUEST_RESOURCE_MESSAGE 120.0\nTIMEOUT_WAIT_FOR_LOCAL_CLIENT_TO_GET_RESOURCE_LIST 120.0\nTIMEOUT_WAIT_FOR_CLIENT_TO_LOAD_RESOURCES 120.0\nTIMEOUT_WAIT_FOR_LOCAL_CLIENT_TO_SAVE_GAME_STATE 30.0\nTIMEOUT_WAIT_FOR_ADD_PLAYERS_TO_TAKE 30.0\nTIMEOUT_WAIT_FOR_UPDATE_FROM_CLIENT 90.0\nTIMEOUT_WAIT_FOR_HOST_TO_GET_RESOURCE_LIST 60.0\nTIMEOUT_WAIT_FOR_HOST_TO_SAVE_GAME_STATE 60.0\nTIMEOUT_WAIT_FOR_HOST_TO_ADD_US 30.0\nTIMEOUT_WAIT_FOR_UPDATE 60.0\nTIMEOUT_WAIT_FOR_REQUEST_JOIN 50.0\nTIMEOUT_WAIT_FOR_AUTOJOIN_PRESENCE 60.0\nTIMEOUT_WAIT_FOR_AUTOJOIN_CONNECTION 120.0\nSECONDS_BETWEEN_PINS_AWARDED_UPLOADS 300.0\nEnableKeepAlive true\nAllowVoIPRecordingPlayback true\nOverheatingThresholdDisallowMidgameJoin 0.95\nMaxCatchupFrames 3\nMaxLagBeforeShowLoading 23\nMinLagBeforeHideLoading 30\nLagImprovementInflectionPoint -1.0\nFlickerThreshold 2.0\nClosedDemo2014Version 1\nClosedDemo2014Expired false\nEnablePlayedFilter true\nEnableCommunityDecorations true\nGameStateUpdateRate 10.0\nGameStateUpdateRateWithConsumers 1.0\nDisableDLCPublishCheck false\nEnableDiveIn true\nEnableHackChecks false\nAllowOnlineCreate true\n" + $"TelemetryServer {hostname}\n" + $"CDNHostName {hostname}\n" + $"ShowLevelBoos {ServerConfiguration.Instance.UserGeneratedContentLimits.BooingEnabled.ToString().ToLower()}\n" diff --git a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/PublishController.cs b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/PublishController.cs index 8c7a2eb7..5f5d423c 100644 --- a/ProjectLighthouse.Servers.GameServer/Controllers/Slots/PublishController.cs +++ b/ProjectLighthouse.Servers.GameServer/Controllers/Slots/PublishController.cs @@ -4,6 +4,7 @@ using LBPUnion.ProjectLighthouse.Configuration; using LBPUnion.ProjectLighthouse.Files; using LBPUnion.ProjectLighthouse.Helpers; using LBPUnion.ProjectLighthouse.Levels; +using LBPUnion.ProjectLighthouse.Logging; using LBPUnion.ProjectLighthouse.PlayerData; using LBPUnion.ProjectLighthouse.PlayerData.Profiles; using LBPUnion.ProjectLighthouse.Serialization; @@ -82,34 +83,67 @@ public class PublishController : ControllerBase GameToken gameToken = userAndToken.Value.Item2; Slot? slot = await this.getSlotFromBody(); - if (slot == null) return this.BadRequest(); + if (slot == null) + { + Logger.Warn("Rejecting level upload, slot is null", LogArea.Publish); + return this.BadRequest(); + } - if (slot.Location == null) return this.BadRequest(); + if (slot.Location == null) + { + Logger.Warn("Rejecting level upload, slot location is null", LogArea.Publish); + return this.BadRequest(); + } - if (slot.Description.Length > 500) return this.BadRequest(); + if (slot.Description.Length > 512) + { + Logger.Warn($"Rejecting level upload, description too long ({slot.Description.Length} characters)", LogArea.Publish); + return this.BadRequest(); + } - if (slot.Name.Length > 64) return this.BadRequest(); + if (slot.Name.Length > 64) + { + Logger.Warn($"Rejecting level upload, title too long ({slot.Name.Length} characters)", LogArea.Publish); + return this.BadRequest(); + } if (slot.Resources.Any(resource => !FileHelper.ResourceExists(resource))) { + Logger.Warn("Rejecting level upload, missing resource(s)", LogArea.Publish); return this.BadRequest(); } LbpFile? rootLevel = LbpFile.FromHash(slot.RootLevel); - if (rootLevel == null) return this.BadRequest(); + if (rootLevel == null) + { + Logger.Warn("Rejecting level upload, unable to find rootLevel", LogArea.Publish); + return this.BadRequest(); + } - if (rootLevel.FileType != LbpFileType.Level) return this.BadRequest(); + if (rootLevel.FileType != LbpFileType.Level) + { + Logger.Warn("Rejecting level upload, rootLevel is not a level", LogArea.Publish); + return this.BadRequest(); + } // Republish logic if (slot.SlotId != 0) { Slot? oldSlot = await this.database.Slots.Include(s => s.Location).FirstOrDefaultAsync(s => s.SlotId == slot.SlotId); - if (oldSlot == null) return this.NotFound(); + 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) return this.BadRequest(); + if (oldSlot.CreatorId != user.UserId) + { + Logger.Warn("Rejecting level republish, old level not owned by current user", LogArea.Publish); + return this.BadRequest(); + } oldSlot.Location.X = slot.Location.X; oldSlot.Location.Y = slot.Location.Y; @@ -166,7 +200,8 @@ public class PublishController : ControllerBase if (user.GetUsedSlotsForGame(gameToken.GameVersion) > ServerConfiguration.Instance.UserGeneratedContentLimits.EntitledSlots) { - return this.StatusCode(403, ""); + Logger.Warn("Rejecting level upload, too many published slots", LogArea.Publish); + return this.BadRequest(); } //TODO: parse location in body @@ -197,6 +232,8 @@ public class PublishController : ControllerBase "New level published!", $"**{user.Username}** just published a new level: [**{slot.Name}**]({ServerConfiguration.Instance.ExternalUrl}/slot/{slot.SlotId})\n{slot.Description}" ); + + Logger.Success($"Successfully published level {slot.Name} (id: {slot.SlotId}) by {user.Username} (id: {user.UserId})", LogArea.Publish); return this.Ok(slot.Serialize(gameToken.GameVersion)); } diff --git a/ProjectLighthouse.Servers.Website/Controllers/Debug/RoomVisualizerController.cs b/ProjectLighthouse.Servers.Website/Controllers/Debug/RoomVisualizerController.cs index 7039a9bf..b4772da5 100644 --- a/ProjectLighthouse.Servers.Website/Controllers/Debug/RoomVisualizerController.cs +++ b/ProjectLighthouse.Servers.Website/Controllers/Debug/RoomVisualizerController.cs @@ -46,4 +46,17 @@ public class RoomVisualizerController : ControllerBase return this.Redirect("/debug/roomVisualizer"); #endif } + + [HttpGet("createRoomsWithDuplicatePlayers")] + public async Task CreateRoomsWithDuplicatePlayers() + { + #if !DEBUG + return this.NotFound(); + #else + List users = await this.database.Users.OrderByDescending(_ => EF.Functions.Random()).Take(1).Select(u => u.UserId).ToListAsync(); + RoomHelper.CreateRoom(users, GameVersion.LittleBigPlanet2, Platform.PS3); + RoomHelper.CreateRoom(users, GameVersion.LittleBigPlanet2, Platform.PS3); + return this.Redirect("/debug/roomVisualizer"); + #endif + } } \ No newline at end of file diff --git a/ProjectLighthouse.Servers.Website/Controllers/ResourcesController.cs b/ProjectLighthouse.Servers.Website/Controllers/ResourcesController.cs index 61158233..3edafd84 100644 --- a/ProjectLighthouse.Servers.Website/Controllers/ResourcesController.cs +++ b/ProjectLighthouse.Servers.Website/Controllers/ResourcesController.cs @@ -1,5 +1,4 @@ using LBPUnion.ProjectLighthouse.Files; -using LBPUnion.ProjectLighthouse.Helpers; using Microsoft.AspNetCore.Mvc; using IOFile = System.IO.File; diff --git a/ProjectLighthouse.Servers.Website/Pages/Debug/RoomVisualizerPage.cshtml b/ProjectLighthouse.Servers.Website/Pages/Debug/RoomVisualizerPage.cshtml index 9845e193..f8b81b74 100644 --- a/ProjectLighthouse.Servers.Website/Pages/Debug/RoomVisualizerPage.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Debug/RoomVisualizerPage.cshtml @@ -44,6 +44,10 @@
Create Fake Room
+ +
Create Rooms With Duplicate Players
+
+
Nuke all rooms
diff --git a/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml b/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml index f518939f..fbebba49 100644 --- a/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml @@ -11,11 +11,16 @@ @@ -32,6 +37,7 @@
@Html.AntiForgeryToken() +
diff --git a/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml.cs b/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml.cs index 656a0bf7..662f1f5b 100644 --- a/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml.cs +++ b/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml.cs @@ -22,7 +22,7 @@ public class LoginForm : BaseLayout public string? Error { get; private set; } [UsedImplicitly] - public async Task OnPost(string username, string password) + public async Task OnPost(string username, string password, string redirect) { if (string.IsNullOrWhiteSpace(username)) { @@ -105,9 +105,19 @@ public class LoginForm : BaseLayout if (user.PasswordResetRequired) return this.Redirect("~/passwordResetRequired"); if (ServerConfiguration.Instance.Mail.MailEnabled && !user.EmailAddressVerified) return this.Redirect("~/login/sendVerificationEmail"); - return this.RedirectToPage(nameof(LandingPage)); + if (string.IsNullOrWhiteSpace(redirect)) + { + return this.RedirectToPage(nameof(LandingPage)); + } + return this.Redirect(redirect); } [UsedImplicitly] - public IActionResult OnGet() => this.Page(); + public IActionResult OnGet() + { + if (this.Database.UserFromWebRequest(this.Request) != null) + return this.RedirectToPage(nameof(LandingPage)); + + return this.Page(); + } } \ No newline at end of file diff --git a/ProjectLighthouse.Servers.Website/Pages/Partials/CaptchaPartial.cshtml b/ProjectLighthouse.Servers.Website/Pages/Partials/CaptchaPartial.cshtml index d54cebce..3a202ba9 100644 --- a/ProjectLighthouse.Servers.Website/Pages/Partials/CaptchaPartial.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Partials/CaptchaPartial.cshtml @@ -1,6 +1,17 @@ @using LBPUnion.ProjectLighthouse.Configuration @if (ServerConfiguration.Instance.Captcha.CaptchaEnabled) { -
- + @switch (ServerConfiguration.Instance.Captcha.Type) + { + case CaptchaType.HCaptcha: +
+ + break; + case CaptchaType.ReCaptcha: +
+ + break; + default: + throw new ArgumentOutOfRangeException(); + } } \ No newline at end of file diff --git a/ProjectLighthouse.Servers.Website/Pages/Partials/CommentsPartial.cshtml b/ProjectLighthouse.Servers.Website/Pages/Partials/CommentsPartial.cshtml index 7a0430cf..c1b9b962 100644 --- a/ProjectLighthouse.Servers.Website/Pages/Partials/CommentsPartial.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Partials/CommentsPartial.cshtml @@ -48,7 +48,14 @@ int rating = comment.ThumbsUp - comment.ThumbsDown;
-
+ @{ + string style = ""; + if (Model.User?.UserId == comment.PosterUserId) + { + style = "visibility: hidden"; + } + } +
diff --git a/ProjectLighthouse.Servers.Website/Pages/Partials/SlotCardPartial.cshtml b/ProjectLighthouse.Servers.Website/Pages/Partials/SlotCardPartial.cshtml index 8a1766fb..d43ddcd3 100644 --- a/ProjectLighthouse.Servers.Website/Pages/Partials/SlotCardPartial.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Partials/SlotCardPartial.cshtml @@ -37,7 +37,9 @@ }
- + +
@if (!mini) @@ -80,7 +82,7 @@ @if (Model.GameVersion == GameVersion.LittleBigPlanet1) { - @Model.RatingLBP1 + @(Math.Round(Model.RatingLBP1 * 10) / 10) }

diff --git a/ProjectLighthouse/Configuration/CaptchaType.cs b/ProjectLighthouse/Configuration/CaptchaType.cs new file mode 100644 index 00000000..564d99c9 --- /dev/null +++ b/ProjectLighthouse/Configuration/CaptchaType.cs @@ -0,0 +1,16 @@ +namespace LBPUnion.ProjectLighthouse.Configuration; + +///

+/// The service to be used for presenting captchas to the user. +/// +public enum CaptchaType +{ + /// + /// A privacy-first captcha. https://www.hcaptcha.com/ + /// + HCaptcha, + /// + /// A captcha service by Google. https://developers.google.com/recaptcha/ + /// + ReCaptcha, +} \ No newline at end of file diff --git a/ProjectLighthouse/Configuration/ConfigurationCategories/CaptchaConfiguration.cs b/ProjectLighthouse/Configuration/ConfigurationCategories/CaptchaConfiguration.cs index fad16ae6..fd4ea31d 100644 --- a/ProjectLighthouse/Configuration/ConfigurationCategories/CaptchaConfiguration.cs +++ b/ProjectLighthouse/Configuration/ConfigurationCategories/CaptchaConfiguration.cs @@ -2,11 +2,10 @@ namespace LBPUnion.ProjectLighthouse.Configuration.ConfigurationCategories; public class CaptchaConfiguration { - // TODO: support recaptcha, not just hcaptcha - // use an enum to define which captcha services can be used? - // LBPUnion.ProjectLighthouse.Types.Settings.CaptchaService public bool CaptchaEnabled { get; set; } + public CaptchaType Type { get; set; } = CaptchaType.HCaptcha; + public string SiteKey { get; set; } = ""; public string Secret { get; set; } = ""; diff --git a/ProjectLighthouse/Configuration/ServerConfiguration.cs b/ProjectLighthouse/Configuration/ServerConfiguration.cs index 3142339e..30c5ee41 100644 --- a/ProjectLighthouse/Configuration/ServerConfiguration.cs +++ b/ProjectLighthouse/Configuration/ServerConfiguration.cs @@ -23,7 +23,7 @@ public class ServerConfiguration // You can use an ObsoleteAttribute instead. Make sure you set it to error, though. // // Thanks for listening~ - public const int CurrentConfigVersion = 6; + public const int CurrentConfigVersion = 7; #region Meta diff --git a/ProjectLighthouse/Extensions/RequestExtensions.cs b/ProjectLighthouse/Extensions/RequestExtensions.cs index d375246c..c922945d 100644 --- a/ProjectLighthouse/Extensions/RequestExtensions.cs +++ b/ProjectLighthouse/Extensions/RequestExtensions.cs @@ -15,7 +15,21 @@ namespace LBPUnion.ProjectLighthouse.Extensions; public static class RequestExtensions { - + static RequestExtensions() + { + Uri captchaUri = ServerConfiguration.Instance.Captcha.Type switch + { + CaptchaType.HCaptcha => new Uri("https://hcaptcha.com"), + CaptchaType.ReCaptcha => new Uri("https://www.google.com/recaptcha/api/"), + _ => throw new ArgumentOutOfRangeException(), + }; + + client = new HttpClient + { + BaseAddress = captchaUri, + }; + } + #region Mobile Checking // yoinked and adapted from https://stackoverflow.com/a/68641796 @@ -32,10 +46,7 @@ public static class RequestExtensions #region Captcha - private static readonly HttpClient client = new() - { - BaseAddress = new Uri("https://hcaptcha.com"), - }; + private static readonly HttpClient client; [SuppressMessage("ReSharper", "ArrangeObjectCreationWhenTypeNotEvident")] private static async Task verifyCaptcha(string token) @@ -48,7 +59,7 @@ public static class RequestExtensions new("response", token), }; - HttpResponseMessage response = await client.PostAsync("/siteverify", new FormUrlEncodedContent(payload)); + HttpResponseMessage response = await client.PostAsync("siteverify", new FormUrlEncodedContent(payload)); response.EnsureSuccessStatusCode(); @@ -63,7 +74,14 @@ public static class RequestExtensions { if (ServerConfiguration.Instance.Captcha.CaptchaEnabled) { - bool gotCaptcha = request.Form.TryGetValue("h-captcha-response", out StringValues values); + string keyName = ServerConfiguration.Instance.Captcha.Type switch + { + CaptchaType.HCaptcha => "h-captcha-response", + CaptchaType.ReCaptcha => "g-recaptcha-response", + _ => throw new ArgumentOutOfRangeException(), + }; + + bool gotCaptcha = request.Form.TryGetValue(keyName, out StringValues values); if (!gotCaptcha) return false; if (!await verifyCaptcha(values[0])) return false; diff --git a/ProjectLighthouse/Helpers/MatchHelper.cs b/ProjectLighthouse/Helpers/MatchHelper.cs index aa7d5908..45519705 100644 --- a/ProjectLighthouse/Helpers/MatchHelper.cs +++ b/ProjectLighthouse/Helpers/MatchHelper.cs @@ -36,6 +36,8 @@ public static class MatchHelper return recentlyDivedIn.Contains(otherUserId); } + public static bool ClearUserRecentDiveIns(int userId) => UserRecentlyDivedIn.Remove(userId); + // This is the function used to show people how laughably awful LBP's protocol is. Beware. public static IMatchCommand? Deserialize(string data) { diff --git a/ProjectLighthouse/Logging/LogArea.cs b/ProjectLighthouse/Logging/LogArea.cs index f83c0d76..3a8a6ad6 100644 --- a/ProjectLighthouse/Logging/LogArea.cs +++ b/ProjectLighthouse/Logging/LogArea.cs @@ -21,4 +21,5 @@ public enum LogArea Redis, Command, Admin, + Publish, } \ No newline at end of file diff --git a/ProjectLighthouse/Match/Rooms/RoomHelper.cs b/ProjectLighthouse/Match/Rooms/RoomHelper.cs index b65c3b3e..8726c216 100644 --- a/ProjectLighthouse/Match/Rooms/RoomHelper.cs +++ b/ProjectLighthouse/Match/Rooms/RoomHelper.cs @@ -1,4 +1,5 @@ #nullable enable +using System; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; @@ -47,10 +48,10 @@ public class RoomHelper return null; } - IEnumerable rooms = Rooms; + Random random = new(); + IEnumerable rooms = Rooms.OrderBy(_ => random.Next()); rooms = rooms.OrderBy(r => r.IsLookingForPlayers); - rooms = rooms.Where(r => r.RoomVersion == roomVersion).ToList(); if (platform != null) rooms = rooms.Where(r => r.RoomPlatform == platform).ToList(); @@ -137,6 +138,12 @@ public class RoomHelper return response; } + if (user != null) + { + MatchHelper.ClearUserRecentDiveIns(user.UserId); + Logger.Info($"Cleared {user.Username} (id: {user.UserId})'s recent dive-ins", LogArea.Match); + } + return null; } @@ -220,12 +227,19 @@ public class RoomHelper roomsToUpdate.Add(room); } + // DO NOT REMOVE ROOMS BEFORE THIS POINT! + // this will cause the room to be added back to the database + foreach (Room room in roomsToUpdate) + { + rooms.Update(room); + } + // Delete old rooms based on host if (hostId != null) { try { - rooms.RemoveAll(r => r.HostId == hostId); + rooms.RemoveAll(r => r.PlayerIds.Contains((int)hostId)); } catch { @@ -233,19 +247,16 @@ public class RoomHelper } } - // Remove players in this new room from other rooms + // Remove rooms containing players in this new room if (newRoom != null) - foreach (Room room in rooms) - { - if (room == newRoom) continue; - - foreach (int newRoomPlayer in newRoom.PlayerIds) room.PlayerIds.RemoveAll(p => p == newRoomPlayer); - roomsToUpdate.Add(room); - } - - foreach (Room room in roomsToUpdate) { - rooms.Update(room); + foreach (Room room in rooms.Where(room => room != newRoom)) + { + foreach (int newRoomPlayer in newRoom.PlayerIds) + { + if (room.PlayerIds.Contains(newRoomPlayer)) rooms.Remove(room); + } + } } rooms.RemoveAll(r => r.PlayerIds.Count == 0); // Remove empty rooms diff --git a/ProjectLighthouse/ProjectLighthouse.csproj b/ProjectLighthouse/ProjectLighthouse.csproj index 93abf2f0..73572f6e 100644 --- a/ProjectLighthouse/ProjectLighthouse.csproj +++ b/ProjectLighthouse/ProjectLighthouse.csproj @@ -20,11 +20,11 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + diff --git a/ProjectLighthouse/StaticFiles/assets/slotCardBackground.png b/ProjectLighthouse/StaticFiles/assets/slotCardBackground.png new file mode 100644 index 00000000..9d0174cb Binary files /dev/null and b/ProjectLighthouse/StaticFiles/assets/slotCardBackground.png differ diff --git a/ProjectLighthouse/StaticFiles/assets/slotCardOverlay.png b/ProjectLighthouse/StaticFiles/assets/slotCardOverlay.png index f1a6adb0..a2f1f3e2 100644 Binary files a/ProjectLighthouse/StaticFiles/assets/slotCardOverlay.png and b/ProjectLighthouse/StaticFiles/assets/slotCardOverlay.png differ