mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-08-09 21:38:43 +00:00
Merge branch 'LBPUnion:main' into main
This commit is contained in:
commit
bc5c0a1b27
20 changed files with 183 additions and 47 deletions
|
@ -29,7 +29,7 @@ public class ClientConfigurationController : ControllerBase
|
||||||
HostString hostname = this.Request.Host;
|
HostString hostname = this.Request.Host;
|
||||||
return this.Ok
|
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" +
|
$"TelemetryServer {hostname}\n" +
|
||||||
$"CDNHostName {hostname}\n" +
|
$"CDNHostName {hostname}\n" +
|
||||||
$"ShowLevelBoos {ServerConfiguration.Instance.UserGeneratedContentLimits.BooingEnabled.ToString().ToLower()}\n"
|
$"ShowLevelBoos {ServerConfiguration.Instance.UserGeneratedContentLimits.BooingEnabled.ToString().ToLower()}\n"
|
||||||
|
|
|
@ -4,6 +4,7 @@ using LBPUnion.ProjectLighthouse.Configuration;
|
||||||
using LBPUnion.ProjectLighthouse.Files;
|
using LBPUnion.ProjectLighthouse.Files;
|
||||||
using LBPUnion.ProjectLighthouse.Helpers;
|
using LBPUnion.ProjectLighthouse.Helpers;
|
||||||
using LBPUnion.ProjectLighthouse.Levels;
|
using LBPUnion.ProjectLighthouse.Levels;
|
||||||
|
using LBPUnion.ProjectLighthouse.Logging;
|
||||||
using LBPUnion.ProjectLighthouse.PlayerData;
|
using LBPUnion.ProjectLighthouse.PlayerData;
|
||||||
using LBPUnion.ProjectLighthouse.PlayerData.Profiles;
|
using LBPUnion.ProjectLighthouse.PlayerData.Profiles;
|
||||||
using LBPUnion.ProjectLighthouse.Serialization;
|
using LBPUnion.ProjectLighthouse.Serialization;
|
||||||
|
@ -82,34 +83,67 @@ public class PublishController : ControllerBase
|
||||||
GameToken gameToken = userAndToken.Value.Item2;
|
GameToken gameToken = userAndToken.Value.Item2;
|
||||||
Slot? slot = await this.getSlotFromBody();
|
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)))
|
if (slot.Resources.Any(resource => !FileHelper.ResourceExists(resource)))
|
||||||
{
|
{
|
||||||
|
Logger.Warn("Rejecting level upload, missing resource(s)", LogArea.Publish);
|
||||||
return this.BadRequest();
|
return this.BadRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
LbpFile? rootLevel = LbpFile.FromHash(slot.RootLevel);
|
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
|
// Republish logic
|
||||||
if (slot.SlotId != 0)
|
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.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.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.X = slot.Location.X;
|
||||||
oldSlot.Location.Y = slot.Location.Y;
|
oldSlot.Location.Y = slot.Location.Y;
|
||||||
|
@ -166,7 +200,8 @@ public class PublishController : ControllerBase
|
||||||
|
|
||||||
if (user.GetUsedSlotsForGame(gameToken.GameVersion) > ServerConfiguration.Instance.UserGeneratedContentLimits.EntitledSlots)
|
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
|
//TODO: parse location in body
|
||||||
|
@ -198,6 +233,8 @@ public class PublishController : ControllerBase
|
||||||
$"**{user.Username}** just published a new level: [**{slot.Name}**]({ServerConfiguration.Instance.ExternalUrl}/slot/{slot.SlotId})\n{slot.Description}"
|
$"**{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));
|
return this.Ok(slot.Serialize(gameToken.GameVersion));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,4 +46,17 @@ public class RoomVisualizerController : ControllerBase
|
||||||
return this.Redirect("/debug/roomVisualizer");
|
return this.Redirect("/debug/roomVisualizer");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("createRoomsWithDuplicatePlayers")]
|
||||||
|
public async Task<IActionResult> CreateRoomsWithDuplicatePlayers()
|
||||||
|
{
|
||||||
|
#if !DEBUG
|
||||||
|
return this.NotFound();
|
||||||
|
#else
|
||||||
|
List<int> 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
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
using LBPUnion.ProjectLighthouse.Files;
|
using LBPUnion.ProjectLighthouse.Files;
|
||||||
using LBPUnion.ProjectLighthouse.Helpers;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using IOFile = System.IO.File;
|
using IOFile = System.IO.File;
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,10 @@
|
||||||
<div class="ui blue button">Create Fake Room</div>
|
<div class="ui blue button">Create Fake Room</div>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
<a href="/debug/roomVisualizer/createRoomsWithDuplicatePlayers">
|
||||||
|
<div class="ui blue button">Create Rooms With Duplicate Players</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
<a href="/debug/roomVisualizer/deleteRooms">
|
<a href="/debug/roomVisualizer/deleteRooms">
|
||||||
<div class="ui red button">Nuke all rooms</div>
|
<div class="ui red button">Nuke all rooms</div>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -11,11 +11,16 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function onSubmit(form) {
|
function onSubmit(form) {
|
||||||
|
if (document.referrer !== null && document.referrer !== "") {
|
||||||
|
const url = new URL(document.referrer);
|
||||||
|
if (url.pathname !== "/logout" && url.pathname !== "/login")
|
||||||
|
document.getElementById("redirect").value = url.pathname;
|
||||||
|
}
|
||||||
|
|
||||||
const passwordInput = document.getElementById("password");
|
const passwordInput = document.getElementById("password");
|
||||||
const passwordSubmit = document.getElementById("password-submit");
|
const passwordSubmit = document.getElementById("password-submit");
|
||||||
|
|
||||||
passwordSubmit.value = sha256(passwordInput.value);
|
passwordSubmit.value = sha256(passwordInput.value);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -32,6 +37,7 @@
|
||||||
|
|
||||||
<form class="ui form" onsubmit="return onSubmit(this)" method="post">
|
<form class="ui form" onsubmit="return onSubmit(this)" method="post">
|
||||||
@Html.AntiForgeryToken()
|
@Html.AntiForgeryToken()
|
||||||
|
<input type="hidden" id="redirect" name="redirect">
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Username</label>
|
<label>Username</label>
|
||||||
|
|
|
@ -22,7 +22,7 @@ public class LoginForm : BaseLayout
|
||||||
public string? Error { get; private set; }
|
public string? Error { get; private set; }
|
||||||
|
|
||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
public async Task<IActionResult> OnPost(string username, string password)
|
public async Task<IActionResult> OnPost(string username, string password, string redirect)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(username))
|
if (string.IsNullOrWhiteSpace(username))
|
||||||
{
|
{
|
||||||
|
@ -105,9 +105,19 @@ public class LoginForm : BaseLayout
|
||||||
if (user.PasswordResetRequired) return this.Redirect("~/passwordResetRequired");
|
if (user.PasswordResetRequired) return this.Redirect("~/passwordResetRequired");
|
||||||
if (ServerConfiguration.Instance.Mail.MailEnabled && !user.EmailAddressVerified) return this.Redirect("~/login/sendVerificationEmail");
|
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]
|
[UsedImplicitly]
|
||||||
public IActionResult OnGet() => this.Page();
|
public IActionResult OnGet()
|
||||||
|
{
|
||||||
|
if (this.Database.UserFromWebRequest(this.Request) != null)
|
||||||
|
return this.RedirectToPage(nameof(LandingPage));
|
||||||
|
|
||||||
|
return this.Page();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,17 @@
|
||||||
@using LBPUnion.ProjectLighthouse.Configuration
|
@using LBPUnion.ProjectLighthouse.Configuration
|
||||||
@if (ServerConfiguration.Instance.Captcha.CaptchaEnabled)
|
@if (ServerConfiguration.Instance.Captcha.CaptchaEnabled)
|
||||||
{
|
{
|
||||||
<div class="h-captcha" data-sitekey="@ServerConfiguration.Instance.Captcha.SiteKey"></div>
|
@switch (ServerConfiguration.Instance.Captcha.Type)
|
||||||
<script src="https://js.hcaptcha.com/1/api.js" async defer></script>
|
{
|
||||||
|
case CaptchaType.HCaptcha:
|
||||||
|
<div class="h-captcha" data-sitekey="@ServerConfiguration.Instance.Captcha.SiteKey"></div>
|
||||||
|
<script src="https://js.hcaptcha.com/1/api.js" async defer></script>
|
||||||
|
break;
|
||||||
|
case CaptchaType.ReCaptcha:
|
||||||
|
<div class="g-recaptcha" data-sitekey="@ServerConfiguration.Instance.Captcha.SiteKey"></div>
|
||||||
|
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -48,7 +48,14 @@
|
||||||
int rating = comment.ThumbsUp - comment.ThumbsDown;
|
int rating = comment.ThumbsUp - comment.ThumbsDown;
|
||||||
|
|
||||||
<div style="display: flex" id="@comment.CommentId">
|
<div style="display: flex" id="@comment.CommentId">
|
||||||
<div class="voting">
|
@{
|
||||||
|
string style = "";
|
||||||
|
if (Model.User?.UserId == comment.PosterUserId)
|
||||||
|
{
|
||||||
|
style = "visibility: hidden";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
<div class="voting" style="@(style)">
|
||||||
<a href="@url/rateComment?commentId=@(comment.CommentId)&rating=@(comment.YourThumb == 1 ? 0 : 1)">
|
<a href="@url/rateComment?commentId=@(comment.CommentId)&rating=@(comment.YourThumb == 1 ? 0 : 1)">
|
||||||
<i class="fitted @(comment.YourThumb == 1 ? "green" : "grey") arrow up link icon" style="display: block"></i>
|
<i class="fitted @(comment.YourThumb == 1 ? "green" : "grey") arrow up link icon" style="display: block"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -37,7 +37,9 @@
|
||||||
}
|
}
|
||||||
<div>
|
<div>
|
||||||
<img src="~/assets/slotCardOverlay.png" style="min-width: @(size)px; width: @(size)px; height: @(size)px; pointer-events: none; position: absolute">
|
<img src="~/assets/slotCardOverlay.png" style="min-width: @(size)px; width: @(size)px; height: @(size)px; pointer-events: none; position: absolute">
|
||||||
<img class="cardIcon slotCardIcon" src="/gameAssets/@iconHash" style="min-width: @(size)px; width: @(size)px; height: @(size)px">
|
<img src="~/assets/slotCardBackground.png" style="min-width: @(size)px; width: @(size)px; height: @(size)px; position: absolute; z-index: -1;">
|
||||||
|
<img class="cardIcon slotCardIcon" src="/gameAssets/@iconHash" style="min-width: @(size)px; width: @(size)px; height: @(size)px;"
|
||||||
|
onerror="this.onerror='';this.src='/gameAssets/@ServerConfiguration.Instance.WebsiteConfiguration.MissingIconHash'">
|
||||||
</div>
|
</div>
|
||||||
<div class="cardStats">
|
<div class="cardStats">
|
||||||
@if (!mini)
|
@if (!mini)
|
||||||
|
@ -80,7 +82,7 @@
|
||||||
@if (Model.GameVersion == GameVersion.LittleBigPlanet1)
|
@if (Model.GameVersion == GameVersion.LittleBigPlanet1)
|
||||||
{
|
{
|
||||||
<i class="yellow star icon" title="LBP1 Stars"></i>
|
<i class="yellow star icon" title="LBP1 Stars"></i>
|
||||||
<span>@Model.RatingLBP1</span>
|
<span>@(Math.Round(Model.RatingLBP1 * 10) / 10)</span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<p>
|
<p>
|
||||||
|
|
16
ProjectLighthouse/Configuration/CaptchaType.cs
Normal file
16
ProjectLighthouse/Configuration/CaptchaType.cs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
namespace LBPUnion.ProjectLighthouse.Configuration;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The service to be used for presenting captchas to the user.
|
||||||
|
/// </summary>
|
||||||
|
public enum CaptchaType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A privacy-first captcha. https://www.hcaptcha.com/
|
||||||
|
/// </summary>
|
||||||
|
HCaptcha,
|
||||||
|
/// <summary>
|
||||||
|
/// A captcha service by Google. https://developers.google.com/recaptcha/
|
||||||
|
/// </summary>
|
||||||
|
ReCaptcha,
|
||||||
|
}
|
|
@ -2,11 +2,10 @@ namespace LBPUnion.ProjectLighthouse.Configuration.ConfigurationCategories;
|
||||||
|
|
||||||
public class CaptchaConfiguration
|
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 bool CaptchaEnabled { get; set; }
|
||||||
|
|
||||||
|
public CaptchaType Type { get; set; } = CaptchaType.HCaptcha;
|
||||||
|
|
||||||
public string SiteKey { get; set; } = "";
|
public string SiteKey { get; set; } = "";
|
||||||
|
|
||||||
public string Secret { get; set; } = "";
|
public string Secret { get; set; } = "";
|
||||||
|
|
|
@ -23,7 +23,7 @@ public class ServerConfiguration
|
||||||
// You can use an ObsoleteAttribute instead. Make sure you set it to error, though.
|
// You can use an ObsoleteAttribute instead. Make sure you set it to error, though.
|
||||||
//
|
//
|
||||||
// Thanks for listening~
|
// Thanks for listening~
|
||||||
public const int CurrentConfigVersion = 6;
|
public const int CurrentConfigVersion = 7;
|
||||||
|
|
||||||
#region Meta
|
#region Meta
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,20 @@ namespace LBPUnion.ProjectLighthouse.Extensions;
|
||||||
|
|
||||||
public static class RequestExtensions
|
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
|
#region Mobile Checking
|
||||||
|
|
||||||
|
@ -32,10 +46,7 @@ public static class RequestExtensions
|
||||||
|
|
||||||
#region Captcha
|
#region Captcha
|
||||||
|
|
||||||
private static readonly HttpClient client = new()
|
private static readonly HttpClient client;
|
||||||
{
|
|
||||||
BaseAddress = new Uri("https://hcaptcha.com"),
|
|
||||||
};
|
|
||||||
|
|
||||||
[SuppressMessage("ReSharper", "ArrangeObjectCreationWhenTypeNotEvident")]
|
[SuppressMessage("ReSharper", "ArrangeObjectCreationWhenTypeNotEvident")]
|
||||||
private static async Task<bool> verifyCaptcha(string token)
|
private static async Task<bool> verifyCaptcha(string token)
|
||||||
|
@ -48,7 +59,7 @@ public static class RequestExtensions
|
||||||
new("response", token),
|
new("response", token),
|
||||||
};
|
};
|
||||||
|
|
||||||
HttpResponseMessage response = await client.PostAsync("/siteverify", new FormUrlEncodedContent(payload));
|
HttpResponseMessage response = await client.PostAsync("siteverify", new FormUrlEncodedContent(payload));
|
||||||
|
|
||||||
response.EnsureSuccessStatusCode();
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
@ -63,7 +74,14 @@ public static class RequestExtensions
|
||||||
{
|
{
|
||||||
if (ServerConfiguration.Instance.Captcha.CaptchaEnabled)
|
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 (!gotCaptcha) return false;
|
||||||
|
|
||||||
if (!await verifyCaptcha(values[0])) return false;
|
if (!await verifyCaptcha(values[0])) return false;
|
||||||
|
|
|
@ -36,6 +36,8 @@ public static class MatchHelper
|
||||||
return recentlyDivedIn.Contains(otherUserId);
|
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.
|
// This is the function used to show people how laughably awful LBP's protocol is. Beware.
|
||||||
public static IMatchCommand? Deserialize(string data)
|
public static IMatchCommand? Deserialize(string data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,4 +21,5 @@ public enum LogArea
|
||||||
Redis,
|
Redis,
|
||||||
Command,
|
Command,
|
||||||
Admin,
|
Admin,
|
||||||
|
Publish,
|
||||||
}
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
#nullable enable
|
#nullable enable
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
@ -47,10 +48,10 @@ public class RoomHelper
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<Room> rooms = Rooms;
|
Random random = new();
|
||||||
|
IEnumerable<Room> rooms = Rooms.OrderBy(_ => random.Next());
|
||||||
|
|
||||||
rooms = rooms.OrderBy(r => r.IsLookingForPlayers);
|
rooms = rooms.OrderBy(r => r.IsLookingForPlayers);
|
||||||
|
|
||||||
rooms = rooms.Where(r => r.RoomVersion == roomVersion).ToList();
|
rooms = rooms.Where(r => r.RoomVersion == roomVersion).ToList();
|
||||||
if (platform != null) rooms = rooms.Where(r => r.RoomPlatform == platform).ToList();
|
if (platform != null) rooms = rooms.Where(r => r.RoomPlatform == platform).ToList();
|
||||||
|
|
||||||
|
@ -137,6 +138,12 @@ public class RoomHelper
|
||||||
return response;
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,12 +227,19 @@ public class RoomHelper
|
||||||
roomsToUpdate.Add(room);
|
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
|
// Delete old rooms based on host
|
||||||
if (hostId != null)
|
if (hostId != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
rooms.RemoveAll(r => r.HostId == hostId);
|
rooms.RemoveAll(r => r.PlayerIds.Contains((int)hostId));
|
||||||
}
|
}
|
||||||
catch
|
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)
|
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
|
rooms.RemoveAll(r => r.PlayerIds.Count == 0); // Remove empty rooms
|
||||||
|
|
|
@ -20,11 +20,11 @@
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="6.0.1" />
|
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="6.0.2" />
|
||||||
<PackageReference Include="Redis.OM" Version="0.2.1" />
|
<PackageReference Include="Redis.OM" Version="0.2.1" />
|
||||||
<PackageReference Include="SharpZipLib" Version="1.3.3" />
|
<PackageReference Include="SharpZipLib" Version="1.3.3" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||||
<PackageReference Include="YamlDotNet" Version="11.2.1" />
|
<PackageReference Include="YamlDotNet" Version="12.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
BIN
ProjectLighthouse/StaticFiles/assets/slotCardBackground.png
Normal file
BIN
ProjectLighthouse/StaticFiles/assets/slotCardBackground.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 46 KiB |
Binary file not shown.
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 26 KiB |
Loading…
Add table
Add a link
Reference in a new issue