mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-05-16 14:42:28 +00:00
Re-do formatting
This commit is contained in:
parent
95a1fd35a5
commit
173addfd03
74 changed files with 1286 additions and 905 deletions
|
@ -1,5 +1,6 @@
|
|||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Development Database" type="docker-deploy" factoryName="docker-compose.yml" server-name="Docker">
|
||||
<configuration default="false" name="Development Database" type="docker-deploy" factoryName="docker-compose.yml"
|
||||
server-name="Docker">
|
||||
<deployment type="docker-compose.yml">
|
||||
<settings>
|
||||
<option name="envFilePath" value=""/>
|
||||
|
|
|
@ -2,12 +2,19 @@ using LBPUnion.ProjectLighthouse.Types.Settings;
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Xunit;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Tests {
|
||||
public sealed class DatabaseFact : FactAttribute {
|
||||
public DatabaseFact() {
|
||||
namespace LBPUnion.ProjectLighthouse.Tests
|
||||
{
|
||||
public sealed class DatabaseFact : FactAttribute
|
||||
{
|
||||
public DatabaseFact()
|
||||
{
|
||||
ServerSettings.DbConnectionString = "server=127.0.0.1;uid=root;pwd=lighthouse;database=lighthouse";
|
||||
if(!ServerSettings.DbConnected) this.Skip = "Database not available";
|
||||
else {
|
||||
if (!ServerSettings.DbConnected)
|
||||
{
|
||||
this.Skip = "Database not available";
|
||||
}
|
||||
else
|
||||
{
|
||||
using Database database = new();
|
||||
database.Database.Migrate();
|
||||
}
|
||||
|
|
|
@ -8,20 +8,23 @@ using LBPUnion.ProjectLighthouse.Types;
|
|||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Tests {
|
||||
namespace LBPUnion.ProjectLighthouse.Tests
|
||||
{
|
||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||
public class LighthouseTest {
|
||||
public readonly TestServer Server;
|
||||
public class LighthouseTest
|
||||
{
|
||||
public readonly HttpClient Client;
|
||||
public readonly TestServer Server;
|
||||
|
||||
public LighthouseTest() {
|
||||
this.Server = new TestServer(new WebHostBuilder()
|
||||
.UseStartup<Startup>());
|
||||
public LighthouseTest()
|
||||
{
|
||||
this.Server = new TestServer(new WebHostBuilder().UseStartup<Startup>());
|
||||
|
||||
this.Client = this.Server.CreateClient();
|
||||
}
|
||||
|
||||
public async Task<HttpResponseMessage> AuthenticateResponse(int number = 0) {
|
||||
public async Task<HttpResponseMessage> AuthenticateResponse(int number = 0)
|
||||
{
|
||||
const string username = "unitTestUser";
|
||||
|
||||
string stringContent = $"{LoginData.UsernamePrefix}{username}{number}{(char)0x00}";
|
||||
|
@ -30,7 +33,8 @@ namespace LBPUnion.ProjectLighthouse.Tests {
|
|||
return response;
|
||||
}
|
||||
|
||||
public async Task<LoginResult> Authenticate(int number = 0) {
|
||||
public async Task<LoginResult> Authenticate(int number = 0)
|
||||
{
|
||||
HttpResponseMessage response = await this.AuthenticateResponse(number);
|
||||
|
||||
string responseContent = LbpSerializer.StringElement("loginResult", await response.Content.ReadAsStringAsync());
|
||||
|
@ -41,30 +45,31 @@ namespace LBPUnion.ProjectLighthouse.Tests {
|
|||
|
||||
public Task<HttpResponseMessage> AuthenticatedRequest(string endpoint, string mmAuth) => this.AuthenticatedRequest(endpoint, mmAuth, HttpMethod.Get);
|
||||
|
||||
public Task<HttpResponseMessage> AuthenticatedRequest(string endpoint, string mmAuth, HttpMethod method) {
|
||||
using var requestMessage = new HttpRequestMessage(method, endpoint);
|
||||
public Task<HttpResponseMessage> AuthenticatedRequest(string endpoint, string mmAuth, HttpMethod method)
|
||||
{
|
||||
using HttpRequestMessage? requestMessage = new(method, endpoint);
|
||||
requestMessage.Headers.Add("Cookie", mmAuth);
|
||||
|
||||
return this.Client.SendAsync(requestMessage);
|
||||
}
|
||||
|
||||
public async Task<HttpResponseMessage> UploadFileRequest(string endpoint, string filePath) {
|
||||
return await this.Client.PostAsync(endpoint, new StringContent(await File.ReadAllTextAsync(filePath)));
|
||||
}
|
||||
public async Task<HttpResponseMessage> UploadFileRequest(string endpoint, string filePath)
|
||||
=> await this.Client.PostAsync(endpoint, new StringContent(await File.ReadAllTextAsync(filePath)));
|
||||
|
||||
public async Task<HttpResponseMessage> UploadDataRequest(string endpoint, byte[] data) {
|
||||
return await this.Client.PostAsync(endpoint, new ByteArrayContent(data));
|
||||
}
|
||||
public async Task<HttpResponseMessage> UploadDataRequest(string endpoint, byte[] data)
|
||||
=> await this.Client.PostAsync(endpoint, new ByteArrayContent(data));
|
||||
|
||||
public async Task<HttpResponseMessage> AuthenticatedUploadFileRequest(string endpoint, string filePath, string mmAuth) {
|
||||
using var requestMessage = new HttpRequestMessage(HttpMethod.Post, endpoint);
|
||||
public async Task<HttpResponseMessage> AuthenticatedUploadFileRequest(string endpoint, string filePath, string mmAuth)
|
||||
{
|
||||
using HttpRequestMessage? requestMessage = new(HttpMethod.Post, endpoint);
|
||||
requestMessage.Headers.Add("Cookie", mmAuth);
|
||||
requestMessage.Content = new StringContent(await File.ReadAllTextAsync(filePath));
|
||||
return await this.Client.SendAsync(requestMessage);
|
||||
}
|
||||
|
||||
public async Task<HttpResponseMessage> AuthenticatedUploadDataRequest(string endpoint, byte[] data, string mmAuth) {
|
||||
using var requestMessage = new HttpRequestMessage(HttpMethod.Post, endpoint);
|
||||
public async Task<HttpResponseMessage> AuthenticatedUploadDataRequest(string endpoint, byte[] data, string mmAuth)
|
||||
{
|
||||
using HttpRequestMessage? requestMessage = new(HttpMethod.Post, endpoint);
|
||||
requestMessage.Headers.Add("Cookie", mmAuth);
|
||||
requestMessage.Content = new ByteArrayContent(data);
|
||||
return await this.Client.SendAsync(requestMessage);
|
||||
|
|
|
@ -5,10 +5,13 @@ using LBPUnion.ProjectLighthouse.Types;
|
|||
using LBPUnion.ProjectLighthouse.Types.Settings;
|
||||
using Xunit;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Tests {
|
||||
public class AuthenticationTests : LighthouseTest {
|
||||
namespace LBPUnion.ProjectLighthouse.Tests
|
||||
{
|
||||
public class AuthenticationTests : LighthouseTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task ShouldReturnErrorOnNoPostData() {
|
||||
public async Task ShouldReturnErrorOnNoPostData()
|
||||
{
|
||||
HttpResponseMessage response = await this.Client.PostAsync("/LITTLEBIGPLANETPS3_XML/login", null!);
|
||||
Assert.False(response.IsSuccessStatusCode);
|
||||
#if NET6_0_OR_GREATER
|
||||
|
@ -19,7 +22,8 @@ namespace LBPUnion.ProjectLighthouse.Tests {
|
|||
}
|
||||
|
||||
[DatabaseFact]
|
||||
public async Task ShouldReturnWithValidData() {
|
||||
public async Task ShouldReturnWithValidData()
|
||||
{
|
||||
HttpResponseMessage response = await this.AuthenticateResponse();
|
||||
Assert.True(response.IsSuccessStatusCode);
|
||||
string responseContent = await response.Content.ReadAsStringAsync();
|
||||
|
@ -28,7 +32,8 @@ namespace LBPUnion.ProjectLighthouse.Tests {
|
|||
}
|
||||
|
||||
[DatabaseFact]
|
||||
public async Task CanSerializeBack() {
|
||||
public async Task CanSerializeBack()
|
||||
{
|
||||
LoginResult loginResult = await this.Authenticate();
|
||||
|
||||
Assert.NotNull(loginResult);
|
||||
|
@ -40,7 +45,8 @@ namespace LBPUnion.ProjectLighthouse.Tests {
|
|||
}
|
||||
|
||||
[DatabaseFact]
|
||||
public async Task CanUseToken() {
|
||||
public async Task CanUseToken()
|
||||
{
|
||||
LoginResult loginResult = await this.Authenticate();
|
||||
|
||||
HttpResponseMessage response = await this.AuthenticatedRequest("/LITTLEBIGPLANETPS3_XML/eula", loginResult.AuthTicket);
|
||||
|
@ -51,7 +57,8 @@ namespace LBPUnion.ProjectLighthouse.Tests {
|
|||
}
|
||||
|
||||
[DatabaseFact]
|
||||
public async Task ShouldReturnForbiddenWhenNotAuthenticated() {
|
||||
public async Task ShouldReturnForbiddenWhenNotAuthenticated()
|
||||
{
|
||||
HttpResponseMessage response = await this.Client.GetAsync("/LITTLEBIGPLANETPS3_XML/eula");
|
||||
Assert.False(response.IsSuccessStatusCode);
|
||||
Assert.True(response.StatusCode == HttpStatusCode.Forbidden);
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Tests {
|
||||
public class DatabaseTests : LighthouseTest {
|
||||
namespace LBPUnion.ProjectLighthouse.Tests
|
||||
{
|
||||
public class DatabaseTests : LighthouseTest
|
||||
{
|
||||
[DatabaseFact]
|
||||
public async Task CanCreateUserTwice() {
|
||||
public async Task CanCreateUserTwice()
|
||||
{
|
||||
await using Database database = new();
|
||||
int rand = new Random().Next();
|
||||
|
||||
|
|
|
@ -4,47 +4,56 @@ using System.Text;
|
|||
using LBPUnion.ProjectLighthouse.Types.Files;
|
||||
using Xunit;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Tests {
|
||||
public class FileTypeTests {
|
||||
namespace LBPUnion.ProjectLighthouse.Tests
|
||||
{
|
||||
public class FileTypeTests
|
||||
{
|
||||
[Fact]
|
||||
public void ShouldRecognizeLevel() {
|
||||
public void ShouldRecognizeLevel()
|
||||
{
|
||||
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestLevel.lvl"));
|
||||
Assert.True(file.FileType == LbpFileType.Level);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldRecognizeScript() {
|
||||
public void ShouldRecognizeScript()
|
||||
{
|
||||
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestScript.ff"));
|
||||
Assert.True(file.FileType == LbpFileType.Script);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldRecognizeTexture() {
|
||||
public void ShouldRecognizeTexture()
|
||||
{
|
||||
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestTexture.tex"));
|
||||
Assert.True(file.FileType == LbpFileType.Texture);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldRecognizeFileArchive() {
|
||||
public void ShouldRecognizeFileArchive()
|
||||
{
|
||||
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestFarc.farc"));
|
||||
Assert.True(file.FileType == LbpFileType.FileArchive);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldNotRecognizeFileArchiveAsScript() {
|
||||
public void ShouldNotRecognizeFileArchiveAsScript()
|
||||
{
|
||||
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestFarc.farc"));
|
||||
Assert.False(file.FileType == LbpFileType.Script);
|
||||
Assert.True(file.FileType == LbpFileType.FileArchive);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldRecognizeNothingAsUnknown() {
|
||||
public void ShouldRecognizeNothingAsUnknown()
|
||||
{
|
||||
LbpFile file = new(Array.Empty<byte>());
|
||||
Assert.True(file.FileType == LbpFileType.Unknown);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldRecognizeGarbageAsUnknown() {
|
||||
public void ShouldRecognizeGarbageAsUnknown()
|
||||
{
|
||||
LbpFile file = new(Encoding.ASCII.GetBytes("free pc only $900"));
|
||||
Assert.True(file.FileType == LbpFileType.Unknown);
|
||||
}
|
||||
|
|
|
@ -6,12 +6,15 @@ using System.Threading.Tasks;
|
|||
using LBPUnion.ProjectLighthouse.Types;
|
||||
using Xunit;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Tests {
|
||||
public class MatchTests : LighthouseTest {
|
||||
namespace LBPUnion.ProjectLighthouse.Tests
|
||||
{
|
||||
public class MatchTests : LighthouseTest
|
||||
{
|
||||
private static readonly SemaphoreSlim semaphore = new(1, 1);
|
||||
|
||||
[DatabaseFact]
|
||||
public async Task ShouldRejectEmptyData() {
|
||||
public async Task ShouldRejectEmptyData()
|
||||
{
|
||||
LoginResult loginResult = await this.Authenticate();
|
||||
await semaphore.WaitAsync();
|
||||
|
||||
|
@ -22,16 +25,13 @@ namespace LBPUnion.ProjectLighthouse.Tests {
|
|||
}
|
||||
|
||||
[DatabaseFact]
|
||||
public async Task ShouldReturnOk() {
|
||||
public async Task ShouldReturnOk()
|
||||
{
|
||||
LoginResult loginResult = await this.Authenticate();
|
||||
await semaphore.WaitAsync();
|
||||
|
||||
HttpResponseMessage result = await this.AuthenticatedUploadDataRequest(
|
||||
"LITTLEBIGPLANETPS3_XML/match",
|
||||
Encoding.ASCII.GetBytes("[UpdateMyPlayerData,[\"Player\":\"1984\"]]"),
|
||||
loginResult.AuthTicket
|
||||
);
|
||||
|
||||
HttpResponseMessage result = await this.AuthenticatedUploadDataRequest
|
||||
("LITTLEBIGPLANETPS3_XML/match", Encoding.ASCII.GetBytes("[UpdateMyPlayerData,[\"Player\":\"1984\"]]"), loginResult.AuthTicket);
|
||||
|
||||
semaphore.Release();
|
||||
Assert.True(result.IsSuccessStatusCode);
|
||||
|
@ -39,18 +39,16 @@ namespace LBPUnion.ProjectLighthouse.Tests {
|
|||
public async Task<int> GetPlayerCount() => Convert.ToInt32(await this.Client.GetStringAsync("LITTLEBIGPLANETPS3_XML/totalPlayerCount"));
|
||||
|
||||
[DatabaseFact]
|
||||
public async Task ShouldIncrementPlayerCount() {
|
||||
public async Task ShouldIncrementPlayerCount()
|
||||
{
|
||||
LoginResult loginResult = await this.Authenticate(new Random().Next());
|
||||
|
||||
await semaphore.WaitAsync();
|
||||
|
||||
int oldPlayerCount = await this.GetPlayerCount();
|
||||
|
||||
HttpResponseMessage result = await this.AuthenticatedUploadDataRequest(
|
||||
"LITTLEBIGPLANETPS3_XML/match",
|
||||
Encoding.ASCII.GetBytes("[UpdateMyPlayerData,[\"Player\":\"1984\"]]"),
|
||||
loginResult.AuthTicket
|
||||
);
|
||||
HttpResponseMessage result = await this.AuthenticatedUploadDataRequest
|
||||
("LITTLEBIGPLANETPS3_XML/match", Encoding.ASCII.GetBytes("[UpdateMyPlayerData,[\"Player\":\"1984\"]]"), loginResult.AuthTicket);
|
||||
|
||||
Assert.True(result.IsSuccessStatusCode);
|
||||
|
||||
|
|
|
@ -2,30 +2,42 @@ using System.Collections.Generic;
|
|||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
using Xunit;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Tests {
|
||||
public class SerializerTests : LighthouseTest {
|
||||
namespace LBPUnion.ProjectLighthouse.Tests
|
||||
{
|
||||
public class SerializerTests : LighthouseTest
|
||||
{
|
||||
[Fact]
|
||||
public void BlankElementWorks() {
|
||||
public void BlankElementWorks()
|
||||
{
|
||||
Assert.Equal("<test></test>", LbpSerializer.BlankElement("test"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StringElementWorks() {
|
||||
public void StringElementWorks()
|
||||
{
|
||||
Assert.Equal("<test>asd</test>", LbpSerializer.StringElement("test", "asd"));
|
||||
Assert.Equal("<test>asd</test>", LbpSerializer.StringElement(new KeyValuePair<string, object>("test", "asd")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TaggedStringElementWorks() {
|
||||
public void TaggedStringElementWorks()
|
||||
{
|
||||
Assert.Equal("<test foo=\"bar\">asd</test>", LbpSerializer.TaggedStringElement("test", "asd", "foo", "bar"));
|
||||
Assert.Equal("<test foo=\"bar\">asd</test>", LbpSerializer.TaggedStringElement(new KeyValuePair<string, object>("test", "asd"),
|
||||
new KeyValuePair<string, object>("foo", "bar")));
|
||||
Assert.Equal
|
||||
(
|
||||
"<test foo=\"bar\">asd</test>",
|
||||
LbpSerializer.TaggedStringElement(new KeyValuePair<string, object>("test", "asd"), new KeyValuePair<string, object>("foo", "bar"))
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ElementsWorks() {
|
||||
Assert.Equal("<test>asd</test><foo>bar</foo>", LbpSerializer.Elements(new KeyValuePair<string, object>("test", "asd"),
|
||||
new KeyValuePair<string, object>("foo", "bar")));
|
||||
public void ElementsWorks()
|
||||
{
|
||||
Assert.Equal
|
||||
(
|
||||
"<test>asd</test><foo>bar</foo>",
|
||||
LbpSerializer.Elements(new KeyValuePair<string, object>("test", "asd"), new KeyValuePair<string, object>("foo", "bar"))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,10 +4,13 @@ using LBPUnion.ProjectLighthouse.Types.Levels;
|
|||
using LBPUnion.ProjectLighthouse.Types.Profiles;
|
||||
using Xunit;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Tests {
|
||||
public class SlotTests : LighthouseTest {
|
||||
namespace LBPUnion.ProjectLighthouse.Tests
|
||||
{
|
||||
public class SlotTests : LighthouseTest
|
||||
{
|
||||
[DatabaseFact]
|
||||
public async Task ShouldOnlyShowUsersLevels() {
|
||||
public async Task ShouldOnlyShowUsersLevels()
|
||||
{
|
||||
await using Database database = new();
|
||||
|
||||
User userA = await database.CreateUser("unitTestUser0");
|
||||
|
@ -17,7 +20,8 @@ namespace LBPUnion.ProjectLighthouse.Tests {
|
|||
database.Locations.Add(l);
|
||||
await database.SaveChangesAsync();
|
||||
|
||||
Slot slotA = new() {
|
||||
Slot slotA = new()
|
||||
{
|
||||
Creator = userA,
|
||||
Name = "slotA",
|
||||
Location = l,
|
||||
|
@ -25,7 +29,8 @@ namespace LBPUnion.ProjectLighthouse.Tests {
|
|||
ResourceCollection = "",
|
||||
};
|
||||
|
||||
Slot slotB = new() {
|
||||
Slot slotB = new()
|
||||
{
|
||||
Creator = userB,
|
||||
Name = "slotB",
|
||||
Location = l,
|
||||
|
|
|
@ -4,39 +4,47 @@ using System.Net.Http;
|
|||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Tests {
|
||||
public class UploadTests : LighthouseTest {
|
||||
public UploadTests() {
|
||||
namespace LBPUnion.ProjectLighthouse.Tests
|
||||
{
|
||||
public class UploadTests : LighthouseTest
|
||||
{
|
||||
public UploadTests()
|
||||
{
|
||||
string assetsDirectory = Path.Combine(Environment.CurrentDirectory, "r");
|
||||
if (Directory.Exists(assetsDirectory)) Directory.Delete(assetsDirectory, true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ShouldNotAcceptScript() {
|
||||
public async Task ShouldNotAcceptScript()
|
||||
{
|
||||
HttpResponseMessage response = await this.UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/scriptTest", "ExampleFiles/TestScript.ff");
|
||||
Assert.False(response.IsSuccessStatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ShouldNotAcceptFarc() {
|
||||
public async Task ShouldNotAcceptFarc()
|
||||
{
|
||||
HttpResponseMessage response = await this.UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/farcTest", "ExampleFiles/TestFarc.farc");
|
||||
Assert.False(response.IsSuccessStatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ShouldNotAcceptGarbage() {
|
||||
public async Task ShouldNotAcceptGarbage()
|
||||
{
|
||||
HttpResponseMessage response = await this.UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/garbageTest", "ExampleFiles/TestGarbage.bin");
|
||||
Assert.False(response.IsSuccessStatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ShouldAcceptTexture() {
|
||||
public async Task ShouldAcceptTexture()
|
||||
{
|
||||
HttpResponseMessage response = await this.UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/textureTest", "ExampleFiles/TestTexture.tex");
|
||||
Assert.True(response.IsSuccessStatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ShouldAcceptLevel() {
|
||||
public async Task ShouldAcceptLevel()
|
||||
{
|
||||
HttpResponseMessage response = await this.UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/levelTest", "ExampleFiles/TestLevel.lvl");
|
||||
Assert.True(response.IsSuccessStatusCode);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,80 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeConstructorOrDestructorBody/@EntryIndexedValue">HINT</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeLocalFunctionBody/@EntryIndexedValue">HINT</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeMethodOrOperatorBody/@EntryIndexedValue">SUGGESTION</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeObjectCreationWhenTypeNotEvident/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeTrailingCommaInMultilineLists/@EntryIndexedValue">SUGGESTION</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeTrailingCommaInSinglelineLists/@EntryIndexedValue">SUGGESTION</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FBuiltInTypes/@EntryIndexedValue">WARNING</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FSimpleTypes/@EntryIndexedValue">ERROR</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/LOCAL_FUNCTION_BODY/@EntryValue">ExpressionBody</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/METHOD_OR_OPERATOR_BODY/@EntryValue">ExpressionBody</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/ThisQualifier/INSTANCE_MEMBERS_QUALIFY_MEMBERS/@EntryValue">Field, Property, Event, Method</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/TRAILING_COMMA_IN_MULTILINE_LISTS/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/TRAILING_COMMA_IN_SINGLELINE_LISTS/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue">NEXT_LINE</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/CASE_BLOCK_BRACES/@EntryValue">NEXT_LINE</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/EMPTY_BLOCK_STYLE/@EntryValue">TOGETHER</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_INSIDE_NAMESPACE/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_PREPROCESSOR_IF/@EntryValue">USUAL_INDENT</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_PREPROCESSOR_OTHER/@EntryValue">USUAL_INDENT</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INITIALIZER_BRACES/@EntryValue">NEXT_LINE</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INVOCABLE_DECLARATION_BRACES/@EntryValue">NEXT_LINE</s:String>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_CODE/@EntryValue">1</s:Int64>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue">1</s:Int64>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_DECLARATION_PARENS_ARRANGEMENT/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_EMBEDDED_ARRANGEMENT/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_EXPR_MEMBER_ARRANGEMENT/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_INITIALIZER_ARRANGEMENT/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_PROPERTY_PATTERNS_ARRANGEMENT/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_SWITCH_EXPRESSION_ARRANGEMENT/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_USER_LINEBREAKS/@EntryValue">False</s:Boolean>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_FORMAL_PARAMETERS_ON_LINE/@EntryValue">5</s:Int64>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_INITIALIZER_ELEMENTS_ON_LINE/@EntryValue">1</s:Int64>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/NESTED_TERNARY_STYLE/@EntryValue">EXPANDED</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/OTHER_BRACES/@EntryValue">NEXT_LINE</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSOR_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ANONYMOUSMETHOD_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_CASE_STATEMENT_ON_SAME_LINE/@EntryValue">IF_OWNER_IS_SINGLE_LINE</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_INITIALIZER_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_PROPERTY_PATTERN_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_WHILE_ON_NEW_LINE/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AROUND_ARROW_OP/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_FOREACH_PARENTHESES/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_IF_PARENTHESES/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_SWITCH_PARENTHESES/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_USING_PARENTHESES/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_WHILE_PARENTHESES/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/TYPE_DECLARATION_BRACES/@EntryValue">NEXT_LINE</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_DECLARATION_LPAR/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_INVOCATION_LPAR/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARGUMENTS_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARRAY_INITIALIZER_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_FIRST_TYPE_PARAMETER_CONSTRAINT/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_LINQ_EXPRESSION/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_CHAINED_BINARY_EXPRESSIONS/@EntryValue">CHOP_IF_LONG</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_CHAINED_METHOD_CALLS/@EntryValue">CHOP_IF_LONG</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_EXTENDS_LIST_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_OBJECT_AND_COLLECTION_INITIALIZER_STYLE/@EntryValue">CHOP_ALWAYS</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_PARAMETERS_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_PROPERTY_PATTERN/@EntryValue">CHOP_ALWAYS</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForBuiltInTypes/@EntryValue">UseExplicitType</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForOtherTypes/@EntryValue">UseExplicitType</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForSimpleTypes/@EntryValue">UseExplicitType</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MM/@EntryIndexedValue">MM</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Method/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="" Style="aaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Affero/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Braaains/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=brun/@EntryIndexedValue">True</s:Boolean>
|
||||
|
|
|
@ -2,32 +2,34 @@ using System.Diagnostics.CodeAnalysis;
|
|||
using LBPUnion.ProjectLighthouse.Types.Settings;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("LITTLEBIGPLANETPS3_XML/")]
|
||||
[Produces("text/plain")]
|
||||
public class ClientConfigurationController : ControllerBase {
|
||||
public class ClientConfigurationController : ControllerBase
|
||||
{
|
||||
[HttpGet("network_settings.nws")]
|
||||
[SuppressMessage("ReSharper", "StringLiteralTypo")]
|
||||
public IActionResult NetworkSettings() {
|
||||
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 true\nAllowModeratedPoppetItems true\nShowLevelBoos true\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 120.0\nTIMEOUT_WAIT_FOR_FIND_BEST_ROOM 30.0\nTIMEOUT_DIVE_IN_TOTAL 1000000.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\nCDNHostName localhost\nTelemetryServer localhost\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");
|
||||
}
|
||||
public IActionResult NetworkSettings()
|
||||
=> 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 true\nAllowModeratedPoppetItems true\nShowLevelBoos true\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 120.0\nTIMEOUT_WAIT_FOR_FIND_BEST_ROOM 30.0\nTIMEOUT_DIVE_IN_TOTAL 1000000.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\nCDNHostName localhost\nTelemetryServer localhost\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"
|
||||
);
|
||||
|
||||
[HttpGet("t_conf")]
|
||||
[Produces("text/json")]
|
||||
public IActionResult Conf() {
|
||||
return this.Ok("[{\"StatusCode\":200}]");
|
||||
}
|
||||
public IActionResult Conf() => this.Ok("[{\"StatusCode\":200}]");
|
||||
|
||||
[HttpGet("farc_hashes")]
|
||||
public IActionResult FarcHashes() {
|
||||
return this.Ok();
|
||||
}
|
||||
public IActionResult FarcHashes() => this.Ok();
|
||||
|
||||
[HttpGet("privacySettings")]
|
||||
[Produces("text/xml")]
|
||||
public IActionResult PrivacySettings() {
|
||||
PrivacySettings ps = new() {
|
||||
public IActionResult PrivacySettings()
|
||||
{
|
||||
PrivacySettings ps = new()
|
||||
{
|
||||
LevelVisibility = "all",
|
||||
ProfileVisibility = "all",
|
||||
};
|
||||
|
|
|
@ -10,20 +10,24 @@ using LBPUnion.ProjectLighthouse.Types.Profiles;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("LITTLEBIGPLANETPS3_XML/")]
|
||||
[Produces("text/xml")]
|
||||
public class CommentController : ControllerBase {
|
||||
public class CommentController : ControllerBase
|
||||
{
|
||||
private readonly Database database;
|
||||
public CommentController(Database database) {
|
||||
public CommentController(Database database)
|
||||
{
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
[HttpGet("userComments/{username}")]
|
||||
public async Task<IActionResult> GetComments(string username) {
|
||||
List<Comment> comments = await this.database.Comments
|
||||
.Include(c => c.Target)
|
||||
public async Task<IActionResult> GetComments(string username)
|
||||
{
|
||||
List<Comment> comments = await this.database.Comments.Include
|
||||
(c => c.Target)
|
||||
.Include(c => c.Poster)
|
||||
.Where(c => c.Target.Username == username)
|
||||
.OrderByDescending(c => c.Timestamp)
|
||||
|
@ -34,7 +38,8 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
}
|
||||
|
||||
[HttpPost("postUserComment/{username}")]
|
||||
public async Task<IActionResult> PostComment(string username) {
|
||||
public async Task<IActionResult> PostComment(string username)
|
||||
{
|
||||
this.Request.Body.Position = 0;
|
||||
string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync();
|
||||
|
||||
|
@ -60,15 +65,14 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
}
|
||||
|
||||
[HttpPost("deleteUserComment/{username}")]
|
||||
public async Task<IActionResult> DeleteComment([FromQuery] int commentId, string username) {
|
||||
public async Task<IActionResult> DeleteComment([FromQuery] int commentId, string username)
|
||||
{
|
||||
User user = await this.database.UserFromRequest(this.Request);
|
||||
if (user == null) return this.StatusCode(403, "");
|
||||
|
||||
Comment comment = await this.database.Comments
|
||||
.FirstOrDefaultAsync(c => c.CommentId == commentId);
|
||||
Comment comment = await this.database.Comments.FirstOrDefaultAsync(c => c.CommentId == commentId);
|
||||
|
||||
if(comment.TargetUserId != user.UserId && comment.PosterUserId != user.UserId)
|
||||
return this.StatusCode(403, "");
|
||||
if (comment.TargetUserId != user.UserId && comment.PosterUserId != user.UserId) return this.StatusCode(403, "");
|
||||
|
||||
this.database.Comments.Remove(comment);
|
||||
await this.database.SaveChangesAsync();
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("LITTLEBIGPLANETPS3_XML/enterLevel")]
|
||||
// [Produces("text/plain")]
|
||||
public class EnterLevelController : ControllerBase {
|
||||
public class EnterLevelController : ControllerBase
|
||||
{
|
||||
[HttpGet("enterLevel/{id}")]
|
||||
public IActionResult EnterLevel(string id) {
|
||||
return this.Ok();
|
||||
}
|
||||
public IActionResult EnterLevel(string id) => this.Ok();
|
||||
}
|
||||
}
|
|
@ -2,17 +2,21 @@ using System;
|
|||
using LBPUnion.ProjectLighthouse.Types.Levels;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("LITTLEBIGPLANETPS3_XML/tags")]
|
||||
[Produces("text/plain")]
|
||||
public class LevelTagsController : ControllerBase {
|
||||
public class LevelTagsController : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
public IActionResult Get() {
|
||||
public IActionResult Get()
|
||||
{
|
||||
string[] tags = Enum.GetNames(typeof(LevelTags));
|
||||
|
||||
int i = 0;
|
||||
foreach(string tag in tags) {
|
||||
foreach (string tag in tags)
|
||||
{
|
||||
tags[i] = $"TAG_{tag.Replace("_", "-")}";
|
||||
i++;
|
||||
}
|
||||
|
|
|
@ -8,23 +8,28 @@ using LBPUnion.ProjectLighthouse.Types.Levels;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("LITTLEBIGPLANETPS3_XML/")]
|
||||
[Produces("text/xml")]
|
||||
public class ListController : ControllerBase {
|
||||
public class ListController : ControllerBase
|
||||
{
|
||||
private readonly Database database;
|
||||
public ListController(Database database) {
|
||||
public ListController(Database database)
|
||||
{
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
#region Levels
|
||||
|
||||
#region Level Queue (lolcatftw)
|
||||
|
||||
[HttpGet("slots/lolcatftw/{username}")]
|
||||
public IActionResult GetLevelQueue(string username) {
|
||||
IEnumerable<QueuedLevel> queuedLevels = new Database().QueuedLevels
|
||||
.Include(q => q.User)
|
||||
public IActionResult GetLevelQueue(string username)
|
||||
{
|
||||
IEnumerable<QueuedLevel> queuedLevels = new Database().QueuedLevels.Include
|
||||
(q => q.User)
|
||||
.Include(q => q.Slot)
|
||||
.Include(q => q.Slot.Location)
|
||||
.Where(q => q.User.Username == username)
|
||||
|
@ -36,17 +41,22 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
}
|
||||
|
||||
[HttpPost("lolcatftw/add/user/{id:int}")]
|
||||
public async Task<IActionResult> AddQueuedLevel(int id) {
|
||||
public async Task<IActionResult> AddQueuedLevel(int id)
|
||||
{
|
||||
User? user = await this.database.UserFromRequest(this.Request);
|
||||
if (user == null) return this.StatusCode(403, "");
|
||||
|
||||
QueuedLevel queuedLevel = await this.database.QueuedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == id);
|
||||
if (queuedLevel != null) return this.Ok();
|
||||
|
||||
this.database.QueuedLevels.Add(new QueuedLevel {
|
||||
this.database.QueuedLevels.Add
|
||||
(
|
||||
new QueuedLevel
|
||||
{
|
||||
SlotId = id,
|
||||
UserId = user.UserId,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
await this.database.SaveChangesAsync();
|
||||
|
||||
|
@ -54,7 +64,8 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
}
|
||||
|
||||
[HttpPost("lolcatftw/remove/user/{id:int}")]
|
||||
public async Task<IActionResult> RemoveQueuedLevel(int id) {
|
||||
public async Task<IActionResult> RemoveQueuedLevel(int id)
|
||||
{
|
||||
User? user = await this.database.UserFromRequest(this.Request);
|
||||
if (user == null) return this.StatusCode(403, "");
|
||||
|
||||
|
@ -71,9 +82,10 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
#region Hearted Levels
|
||||
|
||||
[HttpGet("favouriteSlots/{username}")]
|
||||
public IActionResult GetFavouriteSlots(string username) {
|
||||
IEnumerable<HeartedLevel> heartedLevels = new Database().HeartedLevels
|
||||
.Include(q => q.User)
|
||||
public IActionResult GetFavouriteSlots(string username)
|
||||
{
|
||||
IEnumerable<HeartedLevel> heartedLevels = new Database().HeartedLevels.Include
|
||||
(q => q.User)
|
||||
.Include(q => q.Slot)
|
||||
.Include(q => q.Slot.Location)
|
||||
.Include(q => q.Slot.Creator)
|
||||
|
@ -86,17 +98,22 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
}
|
||||
|
||||
[HttpPost("favourite/slot/user/{id:int}")]
|
||||
public async Task<IActionResult> AddFavouriteSlot(int id) {
|
||||
public async Task<IActionResult> AddFavouriteSlot(int id)
|
||||
{
|
||||
User? user = await this.database.UserFromRequest(this.Request);
|
||||
if (user == null) return this.StatusCode(403, "");
|
||||
|
||||
HeartedLevel heartedLevel = await this.database.HeartedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == id);
|
||||
if (heartedLevel != null) return this.Ok();
|
||||
|
||||
this.database.HeartedLevels.Add(new HeartedLevel {
|
||||
this.database.HeartedLevels.Add
|
||||
(
|
||||
new HeartedLevel
|
||||
{
|
||||
SlotId = id,
|
||||
UserId = user.UserId,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
await this.database.SaveChangesAsync();
|
||||
|
||||
|
@ -104,7 +121,8 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
}
|
||||
|
||||
[HttpPost("unfavourite/slot/user/{id:int}")]
|
||||
public async Task<IActionResult> RemoveFavouriteSlot(int id) {
|
||||
public async Task<IActionResult> RemoveFavouriteSlot(int id)
|
||||
{
|
||||
User? user = await this.database.UserFromRequest(this.Request);
|
||||
if (user == null) return this.StatusCode(403, "");
|
||||
|
||||
|
@ -117,16 +135,16 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion Levels
|
||||
|
||||
#region Users
|
||||
|
||||
|
||||
|
||||
[HttpGet("favouriteUsers/{username}")]
|
||||
public IActionResult GetFavouriteUsers(string username) {
|
||||
IEnumerable<HeartedProfile> heartedProfiles = new Database().HeartedProfiles
|
||||
.Include(q => q.User)
|
||||
public IActionResult GetFavouriteUsers(string username)
|
||||
{
|
||||
IEnumerable<HeartedProfile> heartedProfiles = new Database().HeartedProfiles.Include
|
||||
(q => q.User)
|
||||
.Include(q => q.HeartedUser)
|
||||
.Include(q => q.HeartedUser.Location)
|
||||
.Where(q => q.User.Username == username)
|
||||
|
@ -138,22 +156,26 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
}
|
||||
|
||||
[HttpPost("favourite/user/{username}")]
|
||||
public async Task<IActionResult> AddFavouriteUser(string username) {
|
||||
public async Task<IActionResult> AddFavouriteUser(string username)
|
||||
{
|
||||
User? user = await this.database.UserFromRequest(this.Request);
|
||||
if (user == null) return this.StatusCode(403, "");
|
||||
|
||||
User? heartedUser = await this.database.Users
|
||||
.FirstOrDefaultAsync(u => u.Username == username);
|
||||
User? heartedUser = await this.database.Users.FirstOrDefaultAsync(u => u.Username == username);
|
||||
if (heartedUser == null) return this.NotFound();
|
||||
|
||||
HeartedProfile heartedProfile = await this.database.HeartedProfiles
|
||||
.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.HeartedUserId == heartedUser.UserId);
|
||||
HeartedProfile heartedProfile = await this.database.HeartedProfiles.FirstOrDefaultAsync
|
||||
(q => q.UserId == user.UserId && q.HeartedUserId == heartedUser.UserId);
|
||||
if (heartedProfile != null) return this.Ok();
|
||||
|
||||
this.database.HeartedProfiles.Add(new HeartedProfile {
|
||||
this.database.HeartedProfiles.Add
|
||||
(
|
||||
new HeartedProfile
|
||||
{
|
||||
HeartedUserId = heartedUser.UserId,
|
||||
UserId = user.UserId,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
await this.database.SaveChangesAsync();
|
||||
|
||||
|
@ -161,16 +183,16 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
}
|
||||
|
||||
[HttpPost("unfavourite/user/{username}")]
|
||||
public async Task<IActionResult> RemoveFavouriteUser(string username) {
|
||||
public async Task<IActionResult> RemoveFavouriteUser(string username)
|
||||
{
|
||||
User? user = await this.database.UserFromRequest(this.Request);
|
||||
if (user == null) return this.StatusCode(403, "");
|
||||
|
||||
User? heartedUser = await this.database.Users
|
||||
.FirstOrDefaultAsync(u => u.Username == username);
|
||||
User? heartedUser = await this.database.Users.FirstOrDefaultAsync(u => u.Username == username);
|
||||
if (heartedUser == null) return this.NotFound();
|
||||
|
||||
HeartedProfile heartedProfile = await this.database.HeartedProfiles
|
||||
.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.HeartedUserId == heartedUser.UserId);
|
||||
HeartedProfile heartedProfile = await this.database.HeartedProfiles.FirstOrDefaultAsync
|
||||
(q => q.UserId == user.UserId && q.HeartedUserId == heartedUser.UserId);
|
||||
if (heartedProfile != null) this.database.HeartedProfiles.Remove(heartedProfile);
|
||||
|
||||
await this.database.SaveChangesAsync();
|
||||
|
@ -179,5 +201,6 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
|
@ -5,26 +5,32 @@ using LBPUnion.ProjectLighthouse.Types;
|
|||
using LBPUnion.ProjectLighthouse.Types.Settings;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("LITTLEBIGPLANETPS3_XML/login")]
|
||||
[Produces("text/xml")]
|
||||
public class LoginController : ControllerBase {
|
||||
public class LoginController : ControllerBase
|
||||
{
|
||||
private readonly Database database;
|
||||
|
||||
public LoginController(Database database) {
|
||||
public LoginController(Database database)
|
||||
{
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Login() {
|
||||
public async Task<IActionResult> Login()
|
||||
{
|
||||
string body = await new StreamReader(this.Request.Body).ReadToEndAsync();
|
||||
|
||||
LoginData? loginData;
|
||||
try {
|
||||
try
|
||||
{
|
||||
loginData = LoginData.CreateFromString(body);
|
||||
}
|
||||
catch {
|
||||
catch
|
||||
{
|
||||
loginData = null;
|
||||
}
|
||||
|
||||
|
@ -34,10 +40,14 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
|
||||
if (token == null) return this.StatusCode(403, "");
|
||||
|
||||
return this.Ok(new LoginResult {
|
||||
return this.Ok
|
||||
(
|
||||
new LoginResult
|
||||
{
|
||||
AuthTicket = "MM_AUTH=" + token.UserToken,
|
||||
LbpEnvVer = ServerSettings.ServerName,
|
||||
}.Serialize());
|
||||
}.Serialize()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,39 +11,49 @@ using LBPUnion.ProjectLighthouse.Types.Profiles;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("LITTLEBIGPLANETPS3_XML/")]
|
||||
[Produces("text/xml")]
|
||||
public class MatchController : ControllerBase {
|
||||
public class MatchController : ControllerBase
|
||||
{
|
||||
private readonly Database database;
|
||||
public MatchController(Database database) {
|
||||
public MatchController(Database database)
|
||||
{
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
[HttpPost("match")]
|
||||
[Produces("text/json")]
|
||||
public async Task<IActionResult> Match() {
|
||||
public async Task<IActionResult> Match()
|
||||
{
|
||||
|
||||
User? user = await this.database.UserFromRequest(this.Request);
|
||||
|
||||
if (user == null) return this.StatusCode(403, "");
|
||||
|
||||
#region Parse match data
|
||||
|
||||
// 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.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 (string.IsNullOrEmpty(bodyString) || bodyString[0] != '[') return this.BadRequest();
|
||||
|
||||
IMatchData? matchData;
|
||||
try {
|
||||
try
|
||||
{
|
||||
matchData = MatchHelper.Deserialize(bodyString);
|
||||
}
|
||||
catch(Exception e) {
|
||||
catch(Exception e)
|
||||
{
|
||||
Logger.Log("Exception while parsing MatchData: " + e);
|
||||
Logger.Log("Data: " + bodyString);
|
||||
|
||||
|
@ -55,13 +65,15 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
#endregion
|
||||
|
||||
#region Update LastMatch
|
||||
LastMatch? lastMatch = await this.database.LastMatches
|
||||
.Where(l => l.UserId == user.UserId).FirstOrDefaultAsync();
|
||||
|
||||
LastMatch? lastMatch = await this.database.LastMatches.Where(l => l.UserId == user.UserId).FirstOrDefaultAsync();
|
||||
|
||||
// below makes it not look like trash
|
||||
// ReSharper disable once ConvertIfStatementToNullCoalescingExpression
|
||||
if(lastMatch == null) {
|
||||
lastMatch = new LastMatch {
|
||||
if (lastMatch == null)
|
||||
{
|
||||
lastMatch = new LastMatch
|
||||
{
|
||||
UserId = user.UserId,
|
||||
};
|
||||
this.database.LastMatches.Add(lastMatch);
|
||||
|
@ -70,6 +82,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
lastMatch.Timestamp = TimestampHelper.Timestamp;
|
||||
|
||||
await this.database.SaveChangesAsync();
|
||||
|
||||
#endregion
|
||||
|
||||
return this.Ok("[{\"StatusCode\":200}]");
|
||||
|
|
|
@ -6,42 +6,47 @@ using LBPUnion.ProjectLighthouse.Logging;
|
|||
using LBPUnion.ProjectLighthouse.Types;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("LITTLEBIGPLANETPS3_XML/")]
|
||||
[Produces("text/plain")]
|
||||
public class MessageController : ControllerBase {
|
||||
public class MessageController : ControllerBase
|
||||
{
|
||||
private readonly Database database;
|
||||
public MessageController(Database database) {
|
||||
public MessageController(Database database)
|
||||
{
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
[HttpGet("eula")]
|
||||
public async Task<IActionResult> Eula() {
|
||||
public async Task<IActionResult> Eula()
|
||||
{
|
||||
User user = await this.database.UserFromRequest(this.Request);
|
||||
return user == null
|
||||
? this.StatusCode(403, "")
|
||||
: this.Ok($"You are now logged in as user {user.Username} (id {user.UserId}).\n" +
|
||||
: this.Ok
|
||||
(
|
||||
$"You are now logged in as user {user.Username} (id {user.UserId}).\n" +
|
||||
// ReSharper disable once UnreachableCode
|
||||
(EulaHelper.ShowPrivateInstanceNotice ? "\n" + EulaHelper.PrivateInstanceNotice : "") + "\n" +
|
||||
$"{EulaHelper.License}\n");
|
||||
(EulaHelper.ShowPrivateInstanceNotice ? "\n" + EulaHelper.PrivateInstanceNotice : "") +
|
||||
"\n" +
|
||||
$"{EulaHelper.License}\n"
|
||||
);
|
||||
}
|
||||
|
||||
[HttpGet("announce")]
|
||||
public IActionResult Announce() {
|
||||
return this.Ok("");
|
||||
}
|
||||
public IActionResult Announce() => this.Ok("");
|
||||
|
||||
[HttpGet("notification")]
|
||||
public IActionResult Notification() {
|
||||
return this.Ok();
|
||||
}
|
||||
public IActionResult Notification() => this.Ok();
|
||||
/// <summary>
|
||||
/// Filters chat messages sent by a user.
|
||||
/// The reponse sent is the text that will appear in-game.
|
||||
/// </summary>
|
||||
[HttpPost("filter")]
|
||||
public async Task<IActionResult> Filter() {
|
||||
public async Task<IActionResult> Filter()
|
||||
{
|
||||
User user = await this.database.UserFromRequest(this.Request);
|
||||
if (user == null) return this.StatusCode(403, "");
|
||||
|
||||
|
|
|
@ -2,17 +2,25 @@ using LBPUnion.ProjectLighthouse.Serialization;
|
|||
using LBPUnion.ProjectLighthouse.Types.News;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("LITTLEBIGPLANETPS3_XML/news")]
|
||||
[Produces("text/xml")]
|
||||
public class NewsController : ControllerBase {
|
||||
public class NewsController : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
public IActionResult Get() {
|
||||
string newsEntry = LbpSerializer.StringElement("item", new NewsEntry {
|
||||
public IActionResult Get()
|
||||
{
|
||||
string newsEntry = LbpSerializer.StringElement
|
||||
(
|
||||
"item",
|
||||
new NewsEntry
|
||||
{
|
||||
Category = "no_category",
|
||||
Summary = "test summary",
|
||||
Image = new NewsImage {
|
||||
Image = new NewsImage
|
||||
{
|
||||
Hash = "4947269c5f7061b27225611ee58a9a91a8031bbe",
|
||||
Alignment = "right",
|
||||
},
|
||||
|
@ -20,7 +28,8 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
Title = "Test Title",
|
||||
Text = "Test Text",
|
||||
Date = 1348755214000,
|
||||
}.Serialize());
|
||||
}.Serialize()
|
||||
);
|
||||
|
||||
return this.Ok(LbpSerializer.StringElement("news", newsEntry));
|
||||
}
|
||||
|
|
|
@ -10,14 +10,17 @@ using LBPUnion.ProjectLighthouse.Types.Profiles;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("LITTLEBIGPLANETPS3_XML/")]
|
||||
[Produces("text/xml")]
|
||||
public class PublishController : ControllerBase {
|
||||
public class PublishController : ControllerBase
|
||||
{
|
||||
private readonly Database database;
|
||||
|
||||
public PublishController(Database database) {
|
||||
public PublishController(Database database)
|
||||
{
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
|
@ -25,7 +28,8 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
/// Endpoint the game uses to check what resources need to be uploaded and if the level can be uploaded
|
||||
/// </summary>
|
||||
[HttpPost("startPublish")]
|
||||
public async Task<IActionResult> StartPublish() {
|
||||
public async Task<IActionResult> StartPublish()
|
||||
{
|
||||
User user = await this.database.UserFromRequest(this.Request);
|
||||
if (user == null) return this.StatusCode(403, "");
|
||||
|
||||
|
@ -33,16 +37,16 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
if (slot == null) return this.BadRequest(); // if the level cant be parsed then it obviously cant be uploaded
|
||||
|
||||
// Republish logic
|
||||
if(slot.SlotId != 0) {
|
||||
if (slot.SlotId != 0)
|
||||
{
|
||||
Slot oldSlot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == slot.SlotId);
|
||||
if (oldSlot == null) return this.NotFound();
|
||||
if (oldSlot.CreatorId != user.UserId) return this.BadRequest();
|
||||
}
|
||||
|
||||
string resources = slot.Resources
|
||||
.Where(hash => !FileHelper.ResourceExists(hash))
|
||||
.Aggregate("", (current, hash) =>
|
||||
current + LbpSerializer.StringElement("resource", hash));
|
||||
string resources = slot.Resources.Where
|
||||
(hash => !FileHelper.ResourceExists(hash))
|
||||
.Aggregate("", (current, hash) => current + LbpSerializer.StringElement("resource", hash));
|
||||
|
||||
return this.Ok(LbpSerializer.TaggedStringElement("slot", resources, "type", "user"));
|
||||
}
|
||||
|
@ -51,17 +55,17 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
/// Endpoint actually used to publish a level
|
||||
/// </summary>
|
||||
[HttpPost("publish")]
|
||||
public async Task<IActionResult> Publish() {
|
||||
public async Task<IActionResult> Publish()
|
||||
{
|
||||
User user = await this.database.UserFromRequest(this.Request);
|
||||
if (user == null) return this.StatusCode(403, "");
|
||||
|
||||
Slot slot = await this.GetSlotFromBody();
|
||||
|
||||
// Republish logic
|
||||
if(slot.SlotId != 0) {
|
||||
Slot oldSlot = await this.database.Slots
|
||||
.Include(s => s.Location)
|
||||
.FirstOrDefaultAsync(s => s.SlotId == slot.SlotId);
|
||||
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.CreatorId != user.UserId) return this.BadRequest();
|
||||
|
||||
|
@ -80,7 +84,8 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
}
|
||||
|
||||
//TODO: parse location in body
|
||||
Location l = new() {
|
||||
Location l = new()
|
||||
{
|
||||
X = slot.Location.X,
|
||||
Y = slot.Location.Y,
|
||||
};
|
||||
|
@ -98,10 +103,9 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
}
|
||||
|
||||
[HttpPost("unpublish/{id:int}")]
|
||||
public async Task<IActionResult> Unpublish(int id) {
|
||||
Slot slot = await this.database.Slots
|
||||
.Include(s => s.Location)
|
||||
.FirstOrDefaultAsync(s => s.SlotId == id);
|
||||
public async Task<IActionResult> Unpublish(int id)
|
||||
{
|
||||
Slot slot = await this.database.Slots.Include(s => s.Location).FirstOrDefaultAsync(s => s.SlotId == id);
|
||||
|
||||
this.database.Locations.Remove(slot.Location);
|
||||
this.database.Slots.Remove(slot);
|
||||
|
@ -111,7 +115,8 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
return this.Ok();
|
||||
}
|
||||
|
||||
public async Task<Slot> GetSlotFromBody() {
|
||||
public async Task<Slot> GetSlotFromBody()
|
||||
{
|
||||
this.Request.Body.Position = 0;
|
||||
string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync();
|
||||
|
||||
|
|
|
@ -10,19 +10,20 @@ using LBPUnion.ProjectLighthouse.Types.Files;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using IOFile = System.IO.File;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("LITTLEBIGPLANETPS3_XML/")]
|
||||
[Produces("text/xml")]
|
||||
public class ResourcesController : ControllerBase {
|
||||
public class ResourcesController : ControllerBase
|
||||
{
|
||||
[HttpPost("showModerated")]
|
||||
public IActionResult ShowModerated() {
|
||||
return this.Ok(LbpSerializer.BlankElement("resources"));
|
||||
}
|
||||
public IActionResult ShowModerated() => this.Ok(LbpSerializer.BlankElement("resources"));
|
||||
|
||||
[HttpPost("filterResources")]
|
||||
[HttpPost("showNotUploaded")]
|
||||
public async Task<IActionResult> FilterResources() {
|
||||
public async Task<IActionResult> FilterResources()
|
||||
{
|
||||
string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync();
|
||||
|
||||
XmlSerializer serializer = new(typeof(ResourceList));
|
||||
|
@ -30,28 +31,28 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
|
||||
if (resourceList == null) return this.BadRequest();
|
||||
|
||||
string resources = resourceList.Resources
|
||||
.Where(s => !FileHelper.ResourceExists(s))
|
||||
.Aggregate("", (current, hash) =>
|
||||
current + LbpSerializer.StringElement("resource", hash));
|
||||
string resources = resourceList.Resources.Where
|
||||
(s => !FileHelper.ResourceExists(s))
|
||||
.Aggregate("", (current, hash) => current + LbpSerializer.StringElement("resource", hash));
|
||||
|
||||
return this.Ok(LbpSerializer.StringElement("resources", resources));
|
||||
}
|
||||
|
||||
[HttpGet("r/{hash}")]
|
||||
public IActionResult GetResource(string hash) {
|
||||
public IActionResult GetResource(string hash)
|
||||
{
|
||||
string path = FileHelper.GetResourcePath(hash);
|
||||
|
||||
if(FileHelper.ResourceExists(hash)) {
|
||||
return this.File(IOFile.OpenRead(path), "application/octet-stream");
|
||||
}
|
||||
if (FileHelper.ResourceExists(hash)) return this.File(IOFile.OpenRead(path), "application/octet-stream");
|
||||
|
||||
return this.NotFound();
|
||||
}
|
||||
|
||||
// TODO: check if this is a valid hash
|
||||
[HttpPost("upload/{hash}")]
|
||||
[AllowSynchronousIo]
|
||||
public async Task<IActionResult> UploadResource(string hash) {
|
||||
public async Task<IActionResult> UploadResource(string hash)
|
||||
{
|
||||
|
||||
string assetsDirectory = FileHelper.ResourcePath;
|
||||
string path = FileHelper.GetResourcePath(hash);
|
||||
|
@ -60,7 +61,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
if (FileHelper.ResourceExists(hash)) this.Ok(); // no reason to fail if it's already uploaded
|
||||
|
||||
Logger.Log($"Processing resource upload (hash: {hash})");
|
||||
LbpFile file = new(await BinaryHelper.ReadFromPipeReader(Request.BodyReader));
|
||||
LbpFile file = new(await BinaryHelper.ReadFromPipeReader(this.Request.BodyReader));
|
||||
|
||||
if (!FileHelper.IsFileSafe(file)) return this.UnprocessableEntity();
|
||||
|
||||
|
|
|
@ -6,19 +6,24 @@ using LBPUnion.ProjectLighthouse.Types.Levels;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("LITTLEBIGPLANETPS3_XML/")]
|
||||
[Produces("text/xml")]
|
||||
public class SearchController : ControllerBase {
|
||||
public class SearchController : ControllerBase
|
||||
{
|
||||
private readonly Database database;
|
||||
public SearchController(Database database) {
|
||||
public SearchController(Database database)
|
||||
{
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
[HttpGet("slots/search")]
|
||||
public async Task<IActionResult> SearchSlots([FromQuery] string query) {
|
||||
public async Task<IActionResult> SearchSlots([FromQuery] string query)
|
||||
{
|
||||
if (query == null) return this.BadRequest();
|
||||
|
||||
query = query.ToLower();
|
||||
|
||||
string[] keywords = query.Split(" ");
|
||||
|
@ -29,14 +34,14 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
.Where(s => s.SlotId >= 0); // dumb query to conv into IQueryable
|
||||
|
||||
// ReSharper disable once LoopCanBeConvertedToQuery
|
||||
foreach(string keyword in keywords) {
|
||||
dbQuery = dbQuery.Where(s =>
|
||||
s.Name.ToLower().Contains(keyword) ||
|
||||
foreach (string keyword in keywords)
|
||||
dbQuery = dbQuery.Where
|
||||
(
|
||||
s => s.Name.ToLower().Contains(keyword) ||
|
||||
s.Description.ToLower().Contains(keyword) ||
|
||||
s.Creator.Username.ToLower().Contains(keyword) ||
|
||||
s.SlotId.ToString().Equals(keyword)
|
||||
);
|
||||
}
|
||||
|
||||
List<Slot> slots = await dbQuery.ToListAsync();
|
||||
string response = slots.Aggregate("", (current, slot) => current + slot.Serialize());
|
||||
|
|
|
@ -6,34 +6,36 @@ using LBPUnion.ProjectLighthouse.Types.Levels;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("LITTLEBIGPLANETPS3_XML/")]
|
||||
[Produces("text/xml")]
|
||||
public class SlotsController : ControllerBase {
|
||||
public class SlotsController : ControllerBase
|
||||
{
|
||||
private readonly Database database;
|
||||
public SlotsController(Database database) {
|
||||
public SlotsController(Database database)
|
||||
{
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
[HttpGet("slots/by")]
|
||||
public IActionResult SlotsBy([FromQuery] string u) {
|
||||
string response = Enumerable.Aggregate(
|
||||
this.database.Slots
|
||||
.Include(s => s.Creator)
|
||||
.Include(s => s.Location)
|
||||
.Where(s => s.Creator.Username == u)
|
||||
, string.Empty, (current, slot) => current + slot.Serialize());
|
||||
public IActionResult SlotsBy([FromQuery] string u)
|
||||
{
|
||||
string response = Enumerable.Aggregate
|
||||
(
|
||||
this.database.Slots.Include(s => s.Creator).Include(s => s.Location).Where(s => s.Creator.Username == u),
|
||||
string.Empty,
|
||||
(current, slot) => current + slot.Serialize()
|
||||
);
|
||||
|
||||
return this.Ok(LbpSerializer.TaggedStringElement("slots", response, "total", 1));
|
||||
}
|
||||
|
||||
[HttpGet("s/user/{id:int}")]
|
||||
public async Task<IActionResult> SUser(int id) {
|
||||
Slot slot = await this.database.Slots
|
||||
.Include(s => s.Creator)
|
||||
.Include(s => s.Location)
|
||||
.FirstOrDefaultAsync(s => s.SlotId == id);
|
||||
public async Task<IActionResult> SUser(int id)
|
||||
{
|
||||
Slot slot = await this.database.Slots.Include(s => s.Creator).Include(s => s.Location).FirstOrDefaultAsync(s => s.SlotId == id);
|
||||
|
||||
if (slot == null) return this.NotFound();
|
||||
|
||||
|
@ -41,9 +43,10 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
}
|
||||
|
||||
[HttpGet("slots")]
|
||||
public IActionResult NewestSlots([FromQuery] int pageStart, [FromQuery] int pageSize) {
|
||||
IQueryable<Slot> slots = this.database.Slots
|
||||
.Include(s => s.Creator)
|
||||
public IActionResult NewestSlots([FromQuery] int pageStart, [FromQuery] int pageSize)
|
||||
{
|
||||
IQueryable<Slot> slots = this.database.Slots.Include
|
||||
(s => s.Creator)
|
||||
.Include(s => s.Location)
|
||||
.OrderByDescending(s => s.FirstUploaded)
|
||||
.Skip(pageStart - 1)
|
||||
|
|
|
@ -5,35 +5,39 @@ using LBPUnion.ProjectLighthouse.Serialization;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("LITTLEBIGPLANETPS3_XML/")]
|
||||
[Produces("text/plain")]
|
||||
public class StatisticsController : ControllerBase {
|
||||
public class StatisticsController : ControllerBase
|
||||
{
|
||||
private readonly Database database;
|
||||
public StatisticsController(Database database) {
|
||||
public StatisticsController(Database database)
|
||||
{
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
[HttpGet("playersInPodCount")]
|
||||
[HttpGet("totalPlayerCount")]
|
||||
public async Task<IActionResult> TotalPlayerCount() {
|
||||
int recentMatches = await this.database.LastMatches
|
||||
.Where(l => TimestampHelper.Timestamp - l.Timestamp < 60)
|
||||
.CountAsync();
|
||||
public async Task<IActionResult> TotalPlayerCount()
|
||||
{
|
||||
int recentMatches = await this.database.LastMatches.Where(l => TimestampHelper.Timestamp - l.Timestamp < 60).CountAsync();
|
||||
|
||||
return this.Ok(recentMatches.ToString());
|
||||
}
|
||||
|
||||
[HttpGet("planetStats")]
|
||||
public async Task<IActionResult> PlanetStats() {
|
||||
public async Task<IActionResult> PlanetStats()
|
||||
{
|
||||
int totalSlotCount = await this.database.Slots.CountAsync();
|
||||
const int mmPicksCount = 0;
|
||||
|
||||
return this.Ok(LbpSerializer.StringElement("planetStats",
|
||||
LbpSerializer.StringElement("totalSlotCount", totalSlotCount) +
|
||||
LbpSerializer.StringElement("mmPicksCount", mmPicksCount)
|
||||
));
|
||||
return this.Ok
|
||||
(
|
||||
LbpSerializer.StringElement
|
||||
("planetStats", LbpSerializer.StringElement("totalSlotCount", totalSlotCount) + LbpSerializer.StringElement("mmPicksCount", mmPicksCount))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,44 +8,41 @@ using LBPUnion.ProjectLighthouse.Types.Profiles;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("LITTLEBIGPLANETPS3_XML/")]
|
||||
[Produces("text/xml")]
|
||||
public class UserController : ControllerBase {
|
||||
public class UserController : ControllerBase
|
||||
{
|
||||
private readonly Database database;
|
||||
public UserController(Database database) {
|
||||
public UserController(Database database)
|
||||
{
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
[HttpGet("user/{username}")]
|
||||
public async Task<IActionResult> GetUser(string username) {
|
||||
User user = await this.database.Users
|
||||
.Include(u => u.Location)
|
||||
.FirstOrDefaultAsync(u => u.Username == username);
|
||||
public async Task<IActionResult> GetUser(string username)
|
||||
{
|
||||
User user = await this.database.Users.Include(u => u.Location).FirstOrDefaultAsync(u => u.Username == username);
|
||||
|
||||
if (user == null) return this.NotFound();
|
||||
|
||||
return this.Ok(user.Serialize());
|
||||
}
|
||||
|
||||
[HttpGet("users")]
|
||||
public async Task<IActionResult> GetUserAlt([FromQuery] string u) {
|
||||
return await GetUser(u);
|
||||
}
|
||||
|
||||
// [HttpPost("user/{username}")]
|
||||
// public async Task<IActionResult> CreateUser(string username) {
|
||||
// await new Database().CreateUser(username);
|
||||
// return await GetUser(username);
|
||||
// }
|
||||
public async Task<IActionResult> GetUserAlt([FromQuery] string u) => await this.GetUser(u);
|
||||
|
||||
[HttpPost("updateUser")]
|
||||
public async Task<IActionResult> UpdateUser() {
|
||||
public async Task<IActionResult> UpdateUser()
|
||||
{
|
||||
User user = await this.database.UserFromRequest(this.Request);
|
||||
|
||||
if (user == null) return this.StatusCode(403, "");
|
||||
|
||||
XmlReaderSettings settings = new() {
|
||||
XmlReaderSettings settings = new()
|
||||
{
|
||||
Async = true, // this is apparently not default
|
||||
};
|
||||
|
||||
|
@ -67,35 +64,40 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
// </updateUser>
|
||||
//
|
||||
// if you find a way to make it not stupid feel free to replace this
|
||||
using(XmlReader reader = XmlReader.Create(this.Request.Body, settings)) {
|
||||
using (XmlReader reader = XmlReader.Create(this.Request.Body, settings))
|
||||
{
|
||||
List<string> path = new(); // you can think of this as a file path in the XML, like <updateUser> -> <location> -> <x>
|
||||
while(await reader.ReadAsync()) {
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch(reader.NodeType) {
|
||||
while (await reader.ReadAsync()) // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (reader.NodeType)
|
||||
{
|
||||
case XmlNodeType.Element:
|
||||
path.Add(reader.Name);
|
||||
break;
|
||||
case XmlNodeType.Text:
|
||||
switch(path[1]) {
|
||||
case "biography": {
|
||||
switch (path[1])
|
||||
{
|
||||
case "biography":
|
||||
{
|
||||
user.Biography = await reader.GetValueAsync();
|
||||
break;
|
||||
}
|
||||
case "location": {
|
||||
case "location":
|
||||
{
|
||||
locationChanged = true; // if we're here then we're probably about to change the location.
|
||||
// ReSharper disable once ConvertIfStatementToSwitchStatement
|
||||
if(path[2] == "x") {
|
||||
user.Location.X = Convert.ToInt32(await reader.GetValueAsync()); // GetValue only returns a string, i guess we just hope its a number lol
|
||||
} else if(path[2] == "y") {
|
||||
user.Location.Y = Convert.ToInt32(await reader.GetValueAsync());
|
||||
}
|
||||
if (path[2] == "x")
|
||||
user.Location.X = Convert.ToInt32
|
||||
(await reader.GetValueAsync()); // GetValue only returns a string, i guess we just hope its a number lol
|
||||
else if (path[2] == "y") user.Location.Y = Convert.ToInt32(await reader.GetValueAsync());
|
||||
break;
|
||||
}
|
||||
case "icon": {
|
||||
case "icon":
|
||||
{
|
||||
user.IconHash = await reader.GetValueAsync();
|
||||
break;
|
||||
}
|
||||
case "planets": {
|
||||
case "planets":
|
||||
{
|
||||
user.PlanetHash = await reader.GetValueAsync();
|
||||
break;
|
||||
}
|
||||
|
@ -106,10 +108,10 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the way location on a user card works is stupid and will not save with the way below as-is, so we do the following:
|
||||
if(locationChanged) { // only modify the database if we modify here
|
||||
if (locationChanged)
|
||||
{ // only modify the database if we modify here
|
||||
Location l = await this.database.Locations.Where(l => l.Id == user.LocationId).FirstOrDefaultAsync(); // find the location in the database again
|
||||
|
||||
// set the location in the database to the one we modified above
|
||||
|
|
|
@ -8,8 +8,10 @@ using LBPUnion.ProjectLighthouse.Types.Settings;
|
|||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse {
|
||||
public class Database : DbContext {
|
||||
namespace LBPUnion.ProjectLighthouse
|
||||
{
|
||||
public class Database : DbContext
|
||||
{
|
||||
public DbSet<User> Users { get; set; }
|
||||
public DbSet<Location> Locations { get; set; }
|
||||
public DbSet<Slot> Slots { get; set; }
|
||||
|
@ -21,21 +23,20 @@ namespace LBPUnion.ProjectLighthouse {
|
|||
|
||||
public DbSet<LastMatch> LastMatches { get; set; }
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseMySql(
|
||||
ServerSettings.DbConnectionString,
|
||||
MySqlServerVersion.LatestSupportedServerVersion
|
||||
);
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder options)
|
||||
=> options.UseMySql(ServerSettings.DbConnectionString, MySqlServerVersion.LatestSupportedServerVersion);
|
||||
|
||||
public async Task<User> CreateUser(string username) {
|
||||
public async Task<User> CreateUser(string username)
|
||||
{
|
||||
User user;
|
||||
if((user = await this.Users.Where(u => u.Username == username).FirstOrDefaultAsync()) != null)
|
||||
return user;
|
||||
if ((user = await this.Users.Where(u => u.Username == username).FirstOrDefaultAsync()) != null) return user;
|
||||
|
||||
Location l = new(); // store to get id after submitting
|
||||
this.Locations.Add(l); // add to table
|
||||
await this.SaveChangesAsync(); // saving to the database returns the id and sets it on this entity
|
||||
|
||||
user = new User {
|
||||
user = new User
|
||||
{
|
||||
Username = username,
|
||||
LocationId = l.Id,
|
||||
Biography = username + " hasn't introduced themselves yet.",
|
||||
|
@ -48,12 +49,13 @@ namespace LBPUnion.ProjectLighthouse {
|
|||
}
|
||||
|
||||
#nullable enable
|
||||
public async Task<Token?> AuthenticateUser(LoginData loginData) {
|
||||
public async Task<Token?> AuthenticateUser(LoginData loginData)
|
||||
{
|
||||
// TODO: don't use psn name to authenticate
|
||||
User user = await this.Users.FirstOrDefaultAsync(u => u.Username == loginData.Username)
|
||||
?? await this.CreateUser(loginData.Username);
|
||||
User user = await this.Users.FirstOrDefaultAsync(u => u.Username == loginData.Username) ?? await this.CreateUser(loginData.Username);
|
||||
|
||||
Token token = new() {
|
||||
Token token = new()
|
||||
{
|
||||
UserToken = HashHelper.GenerateAuthToken(),
|
||||
UserId = user.UserId,
|
||||
};
|
||||
|
@ -64,18 +66,17 @@ namespace LBPUnion.ProjectLighthouse {
|
|||
return token;
|
||||
}
|
||||
|
||||
public async Task<User?> UserFromAuthToken(string authToken) {
|
||||
public async Task<User?> UserFromAuthToken(string authToken)
|
||||
{
|
||||
Token? token = await this.Tokens.FirstOrDefaultAsync(t => t.UserToken == authToken);
|
||||
if (token == null) return null;
|
||||
return await this.Users
|
||||
.Include(u => u.Location)
|
||||
.FirstOrDefaultAsync(u => u.UserId == token.UserId);
|
||||
|
||||
return await this.Users.Include(u => u.Location).FirstOrDefaultAsync(u => u.UserId == token.UserId);
|
||||
}
|
||||
|
||||
public async Task<User?> UserFromRequest(HttpRequest request) {
|
||||
if(!request.Cookies.TryGetValue("MM_AUTH", out string? mmAuth) || mmAuth == null) {
|
||||
return null;
|
||||
}
|
||||
public async Task<User?> UserFromRequest(HttpRequest request)
|
||||
{
|
||||
if (!request.Cookies.TryGetValue("MM_AUTH", out string? mmAuth) || mmAuth == null) return null;
|
||||
|
||||
return await this.UserFromAuthToken(mmAuth);
|
||||
}
|
||||
|
|
|
@ -2,15 +2,18 @@ using System;
|
|||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Helpers {
|
||||
namespace LBPUnion.ProjectLighthouse.Helpers
|
||||
{
|
||||
// Yoinked from https://stackoverflow.com/a/68530667
|
||||
// Thanks to T-moty!
|
||||
/// <summary>
|
||||
/// Allows synchronous stream operations for this request.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||
public class AllowSynchronousIoAttribute : ActionFilterAttribute {
|
||||
public override void OnResultExecuting(ResultExecutingContext context) {
|
||||
public class AllowSynchronousIoAttribute : ActionFilterAttribute
|
||||
{
|
||||
public override void OnResultExecuting(ResultExecutingContext context)
|
||||
{
|
||||
IHttpBodyControlFeature syncIoFeature = context.HttpContext.Features.Get<IHttpBodyControlFeature>();
|
||||
if (syncIoFeature != null) syncIoFeature.AllowSynchronousIO = true;
|
||||
}
|
||||
|
|
|
@ -6,27 +6,30 @@ using System.IO.Pipelines;
|
|||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Helpers {
|
||||
public static class BinaryHelper {
|
||||
public static string ReadString(BinaryReader reader) {
|
||||
namespace LBPUnion.ProjectLighthouse.Helpers
|
||||
{
|
||||
public static class BinaryHelper
|
||||
{
|
||||
public static string ReadString(BinaryReader reader)
|
||||
{
|
||||
List<byte> readBytes = new();
|
||||
|
||||
byte readByte;
|
||||
do {
|
||||
readBytes.Add(readByte = reader.ReadByte());
|
||||
} while(readByte != 0x00);
|
||||
do readBytes.Add(readByte = reader.ReadByte());
|
||||
while (readByte != 0x00);
|
||||
|
||||
return Encoding.UTF8.GetString(readBytes.ToArray());
|
||||
}
|
||||
|
||||
public static void ReadUntilByte(BinaryReader reader, byte byteToReadTo) {
|
||||
public static void ReadUntilByte(BinaryReader reader, byte byteToReadTo)
|
||||
{
|
||||
byte readByte;
|
||||
do {
|
||||
readByte = reader.ReadByte();
|
||||
} while(readByte != byteToReadTo);
|
||||
do readByte = reader.ReadByte();
|
||||
while (readByte != byteToReadTo);
|
||||
}
|
||||
|
||||
public static byte[] ReadLastBytes(BinaryReader reader, int count, bool restoreOldPosition = true) {
|
||||
public static byte[] ReadLastBytes(BinaryReader reader, int count, bool restoreOldPosition = true)
|
||||
{
|
||||
long oldPosition = reader.BaseStream.Position;
|
||||
|
||||
if (reader.BaseStream.Length < count) return Array.Empty<byte>();
|
||||
|
@ -41,9 +44,11 @@ namespace LBPUnion.ProjectLighthouse.Helpers {
|
|||
// Written with reference from
|
||||
// https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/request-response?view=aspnetcore-5.0
|
||||
// Surprisingly doesn't take seconds. (67ms for a 100kb file)
|
||||
public static async Task<byte[]> ReadFromPipeReader(PipeReader reader) {
|
||||
public static async Task<byte[]> ReadFromPipeReader(PipeReader reader)
|
||||
{
|
||||
List<byte> data = new();
|
||||
while(true) {
|
||||
while (true)
|
||||
{
|
||||
ReadResult readResult = await reader.ReadAsync();
|
||||
ReadOnlySequence<byte> buffer = readResult.Buffer;
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
namespace LBPUnion.ProjectLighthouse.Helpers {
|
||||
public static class EulaHelper {
|
||||
namespace LBPUnion.ProjectLighthouse.Helpers
|
||||
{
|
||||
public static class EulaHelper
|
||||
{
|
||||
public const string License = @"
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
|
|
|
@ -3,17 +3,23 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Helpers.Extensions {
|
||||
namespace LBPUnion.ProjectLighthouse.Helpers.Extensions
|
||||
{
|
||||
// https://stackoverflow.com/a/8039737
|
||||
public static class ExceptionExtensions {
|
||||
public static string ToDetailedException(this Exception exception) {
|
||||
public static class ExceptionExtensions
|
||||
{
|
||||
public static string ToDetailedException(this Exception exception)
|
||||
{
|
||||
PropertyInfo[] properties = exception.GetType().GetProperties();
|
||||
|
||||
IEnumerable<string> fields = properties
|
||||
.Select(property => new {
|
||||
IEnumerable<string> fields = properties.Select
|
||||
(
|
||||
property => new
|
||||
{
|
||||
property.Name,
|
||||
Value = property.GetValue(exception, null),
|
||||
})
|
||||
}
|
||||
)
|
||||
.Select(x => $"{x.Name} = {(x.Value != null ? x.Value.ToString() : string.Empty)}");
|
||||
|
||||
return string.Join("\n", fields);
|
||||
|
|
|
@ -4,16 +4,20 @@ using System.Linq;
|
|||
using System.Text;
|
||||
using LBPUnion.ProjectLighthouse.Types.Files;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Helpers {
|
||||
public static class FileHelper {
|
||||
namespace LBPUnion.ProjectLighthouse.Helpers
|
||||
{
|
||||
public static class FileHelper
|
||||
{
|
||||
public static readonly string ResourcePath = Path.Combine(Environment.CurrentDirectory, "r");
|
||||
|
||||
public static string GetResourcePath(string hash) => Path.Combine(ResourcePath, hash);
|
||||
|
||||
public static bool IsFileSafe(LbpFile file) {
|
||||
public static bool IsFileSafe(LbpFile file)
|
||||
{
|
||||
if (file.FileType == LbpFileType.Unknown) file.FileType = DetermineFileType(file.Data);
|
||||
|
||||
return file.FileType switch {
|
||||
return file.FileType switch
|
||||
{
|
||||
LbpFileType.FileArchive => false,
|
||||
LbpFileType.Painting => true,
|
||||
LbpFileType.Unknown => false,
|
||||
|
@ -30,7 +34,8 @@ namespace LBPUnion.ProjectLighthouse.Helpers {
|
|||
};
|
||||
}
|
||||
|
||||
public static LbpFileType DetermineFileType(byte[] data) {
|
||||
public static LbpFileType DetermineFileType(byte[] data)
|
||||
{
|
||||
using MemoryStream ms = new(data);
|
||||
using BinaryReader reader = new(ms);
|
||||
|
||||
|
@ -39,7 +44,8 @@ namespace LBPUnion.ProjectLighthouse.Helpers {
|
|||
|
||||
byte[] header = reader.ReadBytes(3);
|
||||
|
||||
return Encoding.ASCII.GetString(header) switch {
|
||||
return Encoding.ASCII.GetString(header) switch
|
||||
{
|
||||
"PTG" => LbpFileType.Painting,
|
||||
"TEX" => LbpFileType.Texture,
|
||||
"FSH" => LbpFileType.Script,
|
||||
|
@ -52,7 +58,8 @@ namespace LBPUnion.ProjectLighthouse.Helpers {
|
|||
|
||||
public static bool ResourceExists(string hash) => File.Exists(GetResourcePath(hash));
|
||||
|
||||
public static void EnsureDirectoryCreated(string path) {
|
||||
public static void EnsureDirectoryCreated(string path)
|
||||
{
|
||||
if (!Directory.Exists(path)) Directory.CreateDirectory(path ?? throw new ArgumentNullException(nameof(path)));
|
||||
}
|
||||
|
||||
|
|
|
@ -4,32 +4,22 @@ using System.Diagnostics.CodeAnalysis;
|
|||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Helpers {
|
||||
namespace LBPUnion.ProjectLighthouse.Helpers
|
||||
{
|
||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||
public static class HashHelper {
|
||||
public static class HashHelper
|
||||
{
|
||||
// private static readonly SHA1 sha1 = SHA1.Create();
|
||||
private static readonly SHA256 sha256 = SHA256.Create();
|
||||
private static readonly Random random = new();
|
||||
|
||||
#region Hash Functions
|
||||
public static string Sha256Hash(string str) => Sha256Hash(Encoding.UTF8.GetBytes(str));
|
||||
|
||||
public static string Sha256Hash(byte[] bytes) {
|
||||
byte[] hash = sha256.ComputeHash(bytes);
|
||||
return Encoding.UTF8.GetString(hash, 0, hash.Length);
|
||||
}
|
||||
|
||||
public static string BCryptHash(string str) => BCrypt.Net.BCrypt.HashPassword(str);
|
||||
|
||||
public static string BCryptHash(byte[] bytes) => BCrypt.Net.BCrypt.HashPassword(Encoding.UTF8.GetString(bytes));
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Generates a specified amount of random bytes in an array.
|
||||
/// </summary>
|
||||
/// <param name="count">The amount of bytes to generate.</param>
|
||||
/// <returns>The bytes generated</returns>
|
||||
public static IEnumerable<byte> GenerateRandomBytes(int count) {
|
||||
public static IEnumerable<byte> GenerateRandomBytes(int count)
|
||||
{
|
||||
byte[] b = new byte[count];
|
||||
random.NextBytes(b);
|
||||
|
||||
|
@ -40,10 +30,28 @@ namespace LBPUnion.ProjectLighthouse.Helpers {
|
|||
/// Generates a random SHA256 & BCrypted token
|
||||
/// </summary>
|
||||
/// <returns>The token as a string.</returns>
|
||||
public static string GenerateAuthToken() {
|
||||
public static string GenerateAuthToken()
|
||||
{
|
||||
byte[] bytes = (byte[])GenerateRandomBytes(256);
|
||||
|
||||
return BCryptHash(Sha256Hash(bytes));
|
||||
}
|
||||
|
||||
#region Hash Functions
|
||||
|
||||
public static string Sha256Hash(string str) => Sha256Hash(Encoding.UTF8.GetBytes(str));
|
||||
|
||||
public static string Sha256Hash(byte[] bytes)
|
||||
{
|
||||
byte[] hash = sha256.ComputeHash(bytes);
|
||||
return Encoding.UTF8.GetString(hash, 0, hash.Length);
|
||||
}
|
||||
|
||||
public static string BCryptHash(string str) => BCrypt.Net.BCrypt.HashPassword(str);
|
||||
|
||||
public static string BCryptHash(byte[] bytes) => BCrypt.Net.BCrypt.HashPassword(Encoding.UTF8.GetString(bytes));
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
|
@ -3,13 +3,17 @@ using System.Linq;
|
|||
using System.Text.Json;
|
||||
using LBPUnion.ProjectLighthouse.Types.Match;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Helpers {
|
||||
public static class MatchHelper {
|
||||
public static IMatchData? Deserialize(string data) {
|
||||
namespace LBPUnion.ProjectLighthouse.Helpers
|
||||
{
|
||||
public static class MatchHelper
|
||||
{
|
||||
public static IMatchData? Deserialize(string data)
|
||||
{
|
||||
string matchType = "";
|
||||
|
||||
int i = 1;
|
||||
while(true) {
|
||||
while (true)
|
||||
{
|
||||
if (data[i] == ',') break;
|
||||
|
||||
matchType += data[i];
|
||||
|
@ -21,8 +25,10 @@ namespace LBPUnion.ProjectLighthouse.Helpers {
|
|||
return Deserialize(matchType, matchData);
|
||||
}
|
||||
|
||||
public static IMatchData? Deserialize(string matchType, string matchData) {
|
||||
return matchType switch {
|
||||
public static IMatchData? Deserialize(string matchType, string matchData)
|
||||
{
|
||||
return matchType switch
|
||||
{
|
||||
"UpdateMyPlayerData" => JsonSerializer.Deserialize<UpdateMyPlayerData>(matchData),
|
||||
"UpdatePlayersInRoom" => JsonSerializer.Deserialize<UpdatePlayersInRoom>(matchData),
|
||||
_ => null,
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
using System;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Helpers {
|
||||
public static class TimeHelper {
|
||||
namespace LBPUnion.ProjectLighthouse.Helpers
|
||||
{
|
||||
public static class TimeHelper
|
||||
{
|
||||
public static long UnixTimeMilliseconds() => DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
||||
public static long UnixTimeSeconds() => DateTimeOffset.Now.ToUnixTimeSeconds();
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
using System;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Helpers {
|
||||
public static class TimestampHelper {
|
||||
namespace LBPUnion.ProjectLighthouse.Helpers
|
||||
{
|
||||
public static class TimestampHelper
|
||||
{
|
||||
public static long Timestamp => (long)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
|
||||
}
|
||||
}
|
|
@ -3,15 +3,16 @@ using Kettu;
|
|||
using LBPUnion.ProjectLighthouse.Helpers.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Logging {
|
||||
public class AspNetToKettuLogger : ILogger {
|
||||
namespace LBPUnion.ProjectLighthouse.Logging
|
||||
{
|
||||
public class AspNetToKettuLogger : ILogger
|
||||
{
|
||||
|
||||
public IDisposable BeginScope<TState>(TState state) {
|
||||
return NullScope.Instance;
|
||||
}
|
||||
public IDisposable BeginScope<TState>(TState state) => NullScope.Instance;
|
||||
public bool IsEnabled(LogLevel logLevel) => true;
|
||||
|
||||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) {
|
||||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
|
||||
{
|
||||
LoggerLevel loggerLevel = new LoggerLevelAspNet(logLevel);
|
||||
|
||||
Logger.Log(state.ToString(), loggerLevel);
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Logging {
|
||||
namespace LBPUnion.ProjectLighthouse.Logging
|
||||
{
|
||||
[ProviderAlias("Kettu")]
|
||||
public class AspNetToKettuLoggerProvider : ILoggerProvider, IDisposable {
|
||||
public void Dispose() {
|
||||
public class AspNetToKettuLoggerProvider : ILoggerProvider, IDisposable
|
||||
{
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public ILogger CreateLogger(string categoryName) {
|
||||
return new AspNetToKettuLogger();
|
||||
}
|
||||
public ILogger CreateLogger(string categoryName) => new AspNetToKettuLogger();
|
||||
}
|
||||
}
|
|
@ -3,11 +3,14 @@ using System.IO;
|
|||
using Kettu;
|
||||
using LBPUnion.ProjectLighthouse.Helpers;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Logging {
|
||||
public class LighthouseFileLogger : LoggerBase {
|
||||
namespace LBPUnion.ProjectLighthouse.Logging
|
||||
{
|
||||
public class LighthouseFileLogger : LoggerBase
|
||||
{
|
||||
private static readonly string logsDirectory = Path.Combine(Environment.CurrentDirectory, "logs");
|
||||
|
||||
public override void Send(LoggerLine line) {
|
||||
public override void Send(LoggerLine line)
|
||||
{
|
||||
FileHelper.EnsureDirectoryCreated(logsDirectory);
|
||||
|
||||
string channel = string.IsNullOrEmpty(line.LoggerLevel.Channel) ? "" : $"[{line.LoggerLevel.Channel}] ";
|
||||
|
|
|
@ -1,32 +1,39 @@
|
|||
using Kettu;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Logging {
|
||||
public class LoggerLevelStartup : LoggerLevel {
|
||||
public override string Name => "Startup";
|
||||
namespace LBPUnion.ProjectLighthouse.Logging
|
||||
{
|
||||
public class LoggerLevelStartup : LoggerLevel
|
||||
{
|
||||
public static readonly LoggerLevelStartup Instance = new();
|
||||
public override string Name => "Startup";
|
||||
}
|
||||
|
||||
public class LoggerLevelDatabase : LoggerLevel {
|
||||
public override string Name => "Database";
|
||||
public class LoggerLevelDatabase : LoggerLevel
|
||||
{
|
||||
public static readonly LoggerLevelDatabase Instance = new();
|
||||
public override string Name => "Database";
|
||||
}
|
||||
|
||||
public class LoggerLevelHttp : LoggerLevel {
|
||||
public override string Name => "HTTP";
|
||||
public class LoggerLevelHttp : LoggerLevel
|
||||
{
|
||||
public static readonly LoggerLevelHttp Instance = new();
|
||||
public override string Name => "HTTP";
|
||||
}
|
||||
|
||||
public class LoggerLevelFilter : LoggerLevel {
|
||||
public override string Name => "Filter";
|
||||
public class LoggerLevelFilter : LoggerLevel
|
||||
{
|
||||
public static readonly LoggerLevelFilter Instance = new();
|
||||
public override string Name => "Filter";
|
||||
}
|
||||
|
||||
public class LoggerLevelAspNet : LoggerLevel {
|
||||
public override string Name => "AspNet";
|
||||
public class LoggerLevelAspNet : LoggerLevel
|
||||
{
|
||||
|
||||
public LoggerLevelAspNet(LogLevel level) {
|
||||
public LoggerLevelAspNet(LogLevel level)
|
||||
{
|
||||
this.Channel = level.ToString();
|
||||
}
|
||||
public override string Name => "AspNet";
|
||||
}
|
||||
}
|
|
@ -1,12 +1,16 @@
|
|||
using System;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Logging {
|
||||
public class NullScope : IDisposable{
|
||||
namespace LBPUnion.ProjectLighthouse.Logging
|
||||
{
|
||||
public class NullScope : IDisposable
|
||||
{
|
||||
|
||||
private NullScope()
|
||||
{}
|
||||
public static NullScope Instance { get; } = new();
|
||||
|
||||
private NullScope() {}
|
||||
|
||||
public void Dispose() {
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,9 +14,12 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
|
|||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse {
|
||||
public static class Program {
|
||||
public static void Main(string[] args) {
|
||||
namespace LBPUnion.ProjectLighthouse
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
// Log startup time
|
||||
Stopwatch stopwatch = new();
|
||||
stopwatch.Start();
|
||||
|
@ -39,7 +42,6 @@ namespace LBPUnion.ProjectLighthouse {
|
|||
Logger.Log("Migrating database...", LoggerLevelDatabase.Instance);
|
||||
MigrateDatabase(database);
|
||||
|
||||
|
||||
Logger.Log("Fixing broken timestamps...", LoggerLevelDatabase.Instance);
|
||||
FixTimestamps(database);
|
||||
|
||||
|
@ -49,7 +51,8 @@ namespace LBPUnion.ProjectLighthouse {
|
|||
CreateHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
public static void MigrateDatabase(Database database) {
|
||||
public static void MigrateDatabase(Database database)
|
||||
{
|
||||
Stopwatch stopwatch = new();
|
||||
stopwatch.Start();
|
||||
|
||||
|
@ -59,21 +62,16 @@ namespace LBPUnion.ProjectLighthouse {
|
|||
Logger.Log($"Migration took {stopwatch.ElapsedMilliseconds}ms.", LoggerLevelDatabase.Instance);
|
||||
}
|
||||
|
||||
public static void FixTimestamps(Database database) {
|
||||
public static void FixTimestamps(Database database)
|
||||
{
|
||||
Stopwatch stopwatch = new();
|
||||
stopwatch.Start();
|
||||
|
||||
foreach(Slot slot in database.Slots.Where(s => s.FirstUploaded == 0)) {
|
||||
slot.FirstUploaded = TimeHelper.UnixTimeMilliseconds();
|
||||
}
|
||||
foreach (Slot slot in database.Slots.Where(s => s.FirstUploaded == 0)) slot.FirstUploaded = TimeHelper.UnixTimeMilliseconds();
|
||||
|
||||
foreach(Slot slot in database.Slots.Where(s => s.LastUpdated == 0)) {
|
||||
slot.LastUpdated = TimeHelper.UnixTimeMilliseconds();
|
||||
}
|
||||
foreach (Slot slot in database.Slots.Where(s => s.LastUpdated == 0)) slot.LastUpdated = TimeHelper.UnixTimeMilliseconds();
|
||||
|
||||
foreach(Comment comment in database.Comments.Where(c => c.Timestamp == 0)) {
|
||||
comment.Timestamp = TimeHelper.UnixTimeMilliseconds();
|
||||
}
|
||||
foreach (Comment comment in database.Comments.Where(c => c.Timestamp == 0)) comment.Timestamp = TimeHelper.UnixTimeMilliseconds();
|
||||
|
||||
database.SaveChanges();
|
||||
|
||||
|
@ -81,14 +79,22 @@ namespace LBPUnion.ProjectLighthouse {
|
|||
Logger.Log($"Fixing timestamps took {stopwatch.ElapsedMilliseconds}ms.", LoggerLevelDatabase.Instance);
|
||||
}
|
||||
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webBuilder => {
|
||||
public static IHostBuilder CreateHostBuilder(string[] args)
|
||||
=> Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults
|
||||
(
|
||||
webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
})
|
||||
.ConfigureLogging(logging => {
|
||||
}
|
||||
)
|
||||
.ConfigureLogging
|
||||
(
|
||||
logging =>
|
||||
{
|
||||
logging.ClearProviders();
|
||||
logging.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, AspNetToKettuLoggerProvider>());
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
|
@ -2,26 +2,30 @@ using System.Collections.Generic;
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Serialization {
|
||||
namespace LBPUnion.ProjectLighthouse.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// LBP doesn't like the XML serializer by C# that much, and it cant be controlled that much (cant have two root elements),
|
||||
/// LBP doesn't like the XML serializer by C# that much, and it cant be controlled that much (cant have two root
|
||||
/// elements),
|
||||
/// so I wrote my own crappy one.
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||
public static class LbpSerializer {
|
||||
public static class LbpSerializer
|
||||
{
|
||||
public static string BlankElement(string key) => $"<{key}></{key}>";
|
||||
|
||||
public static string StringElement(KeyValuePair<string, object> pair) => $"<{pair.Key}>{pair.Value}</{pair.Key}>";
|
||||
|
||||
public static string StringElement(string key, object value) => $"<{key}>{value}</{key}>";
|
||||
|
||||
public static string TaggedStringElement(KeyValuePair<string, object> pair, KeyValuePair<string, object> tagPair) =>
|
||||
$"<{pair.Key} {tagPair.Key}=\"{tagPair.Value}\">{pair.Value}</{pair.Key}>";
|
||||
public static string TaggedStringElement
|
||||
(KeyValuePair<string, object> pair, KeyValuePair<string, object> tagPair)
|
||||
=> $"<{pair.Key} {tagPair.Key}=\"{tagPair.Value}\">{pair.Value}</{pair.Key}>";
|
||||
|
||||
public static string TaggedStringElement(string key, object value, string tagKey, object tagValue) =>
|
||||
$"<{key} {tagKey}=\"{tagValue}\">{value}</{key}>";
|
||||
public static string TaggedStringElement(string key, object value, string tagKey, object tagValue) => $"<{key} {tagKey}=\"{tagValue}\">{value}</{key}>";
|
||||
|
||||
public static string Elements(params KeyValuePair<string, object>[] pairs) =>
|
||||
pairs.Aggregate(string.Empty, (current, pair) => current + StringElement(pair));
|
||||
public static string Elements
|
||||
(params KeyValuePair<string, object>[] pairs)
|
||||
=> pairs.Aggregate(string.Empty, (current, pair) => current + StringElement(pair));
|
||||
}
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Serialization {
|
||||
public class XmlOutputFormatter : StringOutputFormatter {
|
||||
public XmlOutputFormatter() {
|
||||
namespace LBPUnion.ProjectLighthouse.Serialization
|
||||
{
|
||||
public class XmlOutputFormatter : StringOutputFormatter
|
||||
{
|
||||
public XmlOutputFormatter()
|
||||
{
|
||||
this.SupportedMediaTypes.Add("text/xml");
|
||||
this.SupportedMediaTypes.Add("application/xml");
|
||||
}
|
||||
|
|
|
@ -10,33 +10,38 @@ using Microsoft.Extensions.Configuration;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse {
|
||||
public class Startup {
|
||||
public Startup(IConfiguration configuration) {
|
||||
namespace LBPUnion.ProjectLighthouse
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
this.Configuration = configuration;
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services) {
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddControllers();
|
||||
services.AddMvc(options =>
|
||||
options.OutputFormatters.Add(new XmlOutputFormatter()));
|
||||
services.AddMvc(options => options.OutputFormatters.Add(new XmlOutputFormatter()));
|
||||
|
||||
services.AddDbContext<Database>();
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
|
||||
if(env.IsDevelopment()) {
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
if (env.IsDevelopment()) app.UseDeveloperExceptionPage();
|
||||
|
||||
// Logs every request and the response to it
|
||||
// Example: "200, 13ms: GET /LITTLEBIGPLANETPS3_XML/news"
|
||||
// Example: "404, 127ms: GET /asdasd?query=osucookiezi727ppbluezenithtopplayhdhr"
|
||||
app.Use(async (context, next) => {
|
||||
app.Use
|
||||
(
|
||||
async (context, next) =>
|
||||
{
|
||||
Stopwatch requestStopwatch = new();
|
||||
requestStopwatch.Start();
|
||||
|
||||
|
@ -45,22 +50,29 @@ namespace LBPUnion.ProjectLighthouse {
|
|||
|
||||
requestStopwatch.Stop();
|
||||
|
||||
Logger.Log(
|
||||
Logger.Log
|
||||
(
|
||||
$"{context.Response.StatusCode}, {requestStopwatch.ElapsedMilliseconds}ms: {context.Request.Method} {context.Request.Path}{context.Request.QueryString}",
|
||||
LoggerLevelHttp.Instance
|
||||
);
|
||||
|
||||
if(context.Request.Method == "POST") {
|
||||
if (context.Request.Method == "POST")
|
||||
{
|
||||
context.Request.Body.Position = 0;
|
||||
Logger.Log(await new StreamReader(context.Request.Body).ReadToEndAsync(), LoggerLevelHttp.Instance);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseEndpoints(endpoints => {
|
||||
app.UseEndpoints
|
||||
(
|
||||
endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,21 +1,24 @@
|
|||
using LBPUnion.ProjectLighthouse.Helpers;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Files {
|
||||
public class LbpFile {
|
||||
public LbpFile(byte[] data) {
|
||||
this.Data = data;
|
||||
this.FileType = FileHelper.DetermineFileType(this.Data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The type of file.
|
||||
/// </summary>
|
||||
public LbpFileType FileType;
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Files
|
||||
{
|
||||
public class LbpFile
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// A buffer of the file's data.
|
||||
/// </summary>
|
||||
public readonly byte[] Data;
|
||||
|
||||
/// <summary>
|
||||
/// The type of file.
|
||||
/// </summary>
|
||||
public LbpFileType FileType;
|
||||
|
||||
public LbpFile(byte[] data)
|
||||
{
|
||||
this.Data = data;
|
||||
this.FileType = FileHelper.DetermineFileType(this.Data);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
namespace LBPUnion.ProjectLighthouse.Types.Files {
|
||||
public enum LbpFileType {
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Files
|
||||
{
|
||||
public enum LbpFileType
|
||||
{
|
||||
Script, // .ff, FSH
|
||||
Texture, // TEX
|
||||
Level, // LVL
|
||||
|
|
|
@ -2,22 +2,27 @@ using System;
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types {
|
||||
public class HeartedProfile {
|
||||
namespace LBPUnion.ProjectLighthouse.Types
|
||||
{
|
||||
public class HeartedProfile
|
||||
{
|
||||
// ReSharper disable once UnusedMember.Global
|
||||
#if NET6_0_OR_GREATER
|
||||
[Obsolete($"Use {nameof(HeartedUserId)} instead, this is a key which you should never need to use.")]
|
||||
#else
|
||||
[Obsolete("Use HeartedUserId instead, this is a key which you should never need to use.")]
|
||||
#endif
|
||||
[Key] public int HeartedProfileId { get; set; }
|
||||
[Key]
|
||||
public int HeartedProfileId { get; set; }
|
||||
|
||||
public int UserId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(UserId))] public User User { get; set; }
|
||||
[ForeignKey(nameof(UserId))]
|
||||
public User User { get; set; }
|
||||
|
||||
public int HeartedUserId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(HeartedUserId))] public User HeartedUser { get; set; }
|
||||
[ForeignKey(nameof(HeartedUserId))]
|
||||
public User HeartedUser { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,17 +1,22 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Levels {
|
||||
public class HeartedLevel {
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Levels
|
||||
{
|
||||
public class HeartedLevel
|
||||
{
|
||||
// ReSharper disable once UnusedMember.Global
|
||||
[Key] public int HeartedLevelId { get; set; }
|
||||
[Key]
|
||||
public int HeartedLevelId { get; set; }
|
||||
|
||||
public int UserId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(UserId))] public User User { get; set; }
|
||||
[ForeignKey(nameof(UserId))]
|
||||
public User User { get; set; }
|
||||
|
||||
public int SlotId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(SlotId))] public Slot Slot { get; set; }
|
||||
[ForeignKey(nameof(SlotId))]
|
||||
public Slot Slot { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,12 +1,14 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Levels {
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Levels
|
||||
{
|
||||
/// <summary>
|
||||
/// A series of tags that can be applied to a level
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||
public enum LevelTags {
|
||||
public enum LevelTags
|
||||
{
|
||||
Brilliant,
|
||||
Beautiful,
|
||||
Funky,
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Levels {
|
||||
public class QueuedLevel {
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Levels
|
||||
{
|
||||
public class QueuedLevel
|
||||
{
|
||||
// ReSharper disable once UnusedMember.Global
|
||||
[Key] public int QueuedLevelId { get; set; }
|
||||
[Key]
|
||||
public int QueuedLevelId { get; set; }
|
||||
|
||||
public int UserId { get; set; }
|
||||
|
||||
|
|
|
@ -5,12 +5,15 @@ using System.Xml.Serialization;
|
|||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Types.Profiles;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Levels {
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Levels
|
||||
{
|
||||
/// <summary>
|
||||
/// A LittleBigPlanet level.
|
||||
/// </summary>
|
||||
[XmlRoot("slot"), XmlType("slot")]
|
||||
public class Slot {
|
||||
[XmlRoot("slot")]
|
||||
[XmlType("slot")]
|
||||
public class Slot
|
||||
{
|
||||
[XmlAttribute("type")]
|
||||
[NotMapped]
|
||||
public string Type { get; set; }
|
||||
|
@ -19,7 +22,6 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels {
|
|||
[XmlElement("id")]
|
||||
public int SlotId { get; set; }
|
||||
|
||||
|
||||
[XmlElement("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
|
@ -93,13 +95,13 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels {
|
|||
[XmlIgnore]
|
||||
public bool MMPick { get; set; }
|
||||
|
||||
public string SerializeResources() {
|
||||
return this.Resources
|
||||
.Aggregate("", (current, resource) =>
|
||||
current + LbpSerializer.StringElement("resource", resource));
|
||||
public string SerializeResources()
|
||||
{
|
||||
return this.Resources.Aggregate("", (current, resource) => current + LbpSerializer.StringElement("resource", resource));
|
||||
}
|
||||
|
||||
public string Serialize() {
|
||||
public string Serialize()
|
||||
{
|
||||
string slotData = LbpSerializer.StringElement("name", this.Name) +
|
||||
LbpSerializer.StringElement("id", this.SlotId) +
|
||||
LbpSerializer.StringElement("game", 1) +
|
||||
|
|
|
@ -4,20 +4,30 @@ using System.IO;
|
|||
using System.Text;
|
||||
using LBPUnion.ProjectLighthouse.Helpers;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types {
|
||||
namespace LBPUnion.ProjectLighthouse.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// The data sent from POST /LOGIN.
|
||||
/// </summary>
|
||||
public class LoginData {
|
||||
public string Username { get; set; } = null!;
|
||||
public class LoginData
|
||||
{
|
||||
|
||||
public static readonly string UsernamePrefix = Encoding.ASCII.GetString(new byte[] { 0x04, 0x00, 0x20 });
|
||||
public static readonly string UsernamePrefix = Encoding.ASCII.GetString
|
||||
(
|
||||
new byte[]
|
||||
{
|
||||
0x04, 0x00, 0x20,
|
||||
}
|
||||
);
|
||||
|
||||
public string Username { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Converts a X-I-5 Ticket into `LoginData`.
|
||||
/// https://www.psdevwiki.com/ps3/X-I-5-Ticket
|
||||
/// </summary>
|
||||
public static LoginData? CreateFromString(string str) {
|
||||
public static LoginData? CreateFromString(string str)
|
||||
{
|
||||
str = str.Replace("\b", ""); // Remove backspace characters
|
||||
|
||||
using MemoryStream ms = new(Encoding.ASCII.GetBytes(str));
|
||||
|
|
|
@ -2,23 +2,23 @@ using System.Collections.Generic;
|
|||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types {
|
||||
namespace LBPUnion.ProjectLighthouse.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// Response to POST /login
|
||||
/// </summary>
|
||||
[XmlRoot("loginResult"), XmlType("loginResult")]
|
||||
public class LoginResult {
|
||||
[XmlRoot("loginResult")]
|
||||
[XmlType("loginResult")]
|
||||
public class LoginResult
|
||||
{
|
||||
[XmlElement("authTicket")]
|
||||
public string AuthTicket { get; set; }
|
||||
|
||||
[XmlElement("lbpEnvVer")]
|
||||
public string LbpEnvVer { get; set; }
|
||||
|
||||
public string Serialize() {
|
||||
return LbpSerializer.Elements(
|
||||
new KeyValuePair<string, object>("authTicket", this.AuthTicket),
|
||||
new KeyValuePair<string, object>("lbpEnvVer", this.LbpEnvVer)
|
||||
);
|
||||
}
|
||||
public string Serialize()
|
||||
=> LbpSerializer.Elements
|
||||
(new KeyValuePair<string, object>("authTicket", this.AuthTicket), new KeyValuePair<string, object>("lbpEnvVer", this.LbpEnvVer));
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
namespace LBPUnion.ProjectLighthouse.Types.Match {
|
||||
public interface IMatchData {
|
||||
|
||||
}
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Match
|
||||
{
|
||||
public interface IMatchData
|
||||
{}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
namespace LBPUnion.ProjectLighthouse.Types.Match {
|
||||
public enum RoomState {
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Match
|
||||
{
|
||||
public enum RoomState
|
||||
{
|
||||
Idle = 0,
|
||||
LookingForPlayersForLevel = 1,
|
||||
Unknown = 2,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
namespace LBPUnion.ProjectLighthouse.Types.Match {
|
||||
public class UpdateMyPlayerData : IMatchData {
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Match
|
||||
{
|
||||
public class UpdateMyPlayerData : IMatchData
|
||||
{
|
||||
public string Player;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Match {
|
||||
public class UpdatePlayersInRoom : IMatchData {
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Match
|
||||
{
|
||||
public class UpdatePlayersInRoom : IMatchData
|
||||
{
|
||||
public List<string> Players;
|
||||
public List<string> Reservations;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.News {
|
||||
namespace LBPUnion.ProjectLighthouse.Types.News
|
||||
{
|
||||
/// <summary>
|
||||
/// Used on the info moon on LBP1. Broken for unknown reasons
|
||||
/// </summary>
|
||||
public class NewsEntry {
|
||||
public class NewsEntry
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Summary { get; set; }
|
||||
|
@ -13,8 +15,8 @@ namespace LBPUnion.ProjectLighthouse.Types.News {
|
|||
public string Category { get; set; }
|
||||
public long Date { get; set; }
|
||||
|
||||
public string Serialize() {
|
||||
return LbpSerializer.StringElement("id", this.Id) +
|
||||
public string Serialize()
|
||||
=> LbpSerializer.StringElement("id", this.Id) +
|
||||
LbpSerializer.StringElement("title", this.Title) +
|
||||
LbpSerializer.StringElement("summary", this.Summary) +
|
||||
LbpSerializer.StringElement("text", this.Text) +
|
||||
|
@ -23,4 +25,3 @@ namespace LBPUnion.ProjectLighthouse.Types.News {
|
|||
LbpSerializer.StringElement("category", this.Category);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +1,13 @@
|
|||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.News {
|
||||
public class NewsImage {
|
||||
namespace LBPUnion.ProjectLighthouse.Types.News
|
||||
{
|
||||
public class NewsImage
|
||||
{
|
||||
public string Hash { get; set; }
|
||||
public string Alignment { get; set; }
|
||||
|
||||
public string Serialize() {
|
||||
return LbpSerializer.StringElement("image",
|
||||
LbpSerializer.StringElement("hash", this.Hash) +
|
||||
LbpSerializer.StringElement("alignment", this.Alignment));
|
||||
}
|
||||
public string Serialize()
|
||||
=> LbpSerializer.StringElement("image", LbpSerializer.StringElement("hash", this.Hash) + LbpSerializer.StringElement("alignment", this.Alignment));
|
||||
}
|
||||
}
|
|
@ -1,22 +1,26 @@
|
|||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Profiles {
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Profiles
|
||||
{
|
||||
[Keyless]
|
||||
public class ClientsConnected {
|
||||
public class ClientsConnected
|
||||
{
|
||||
public bool Lbp1 { get; set; }
|
||||
public bool Lbp2 { get; set; }
|
||||
public bool LbpMe { get; set; }
|
||||
public bool Lbp3Ps3 { get; set; }
|
||||
public bool Lbp3Ps4 { get; set; }
|
||||
|
||||
public string Serialize() {
|
||||
return LbpSerializer.StringElement("clientsConnected",
|
||||
public string Serialize()
|
||||
=> LbpSerializer.StringElement
|
||||
(
|
||||
"clientsConnected",
|
||||
LbpSerializer.StringElement("lbp1", this.Lbp1) +
|
||||
LbpSerializer.StringElement("lbp2", this.Lbp2) +
|
||||
LbpSerializer.StringElement("lbpme", this.LbpMe) +
|
||||
LbpSerializer.StringElement("lbp3ps3", this.Lbp3Ps3) +
|
||||
LbpSerializer.StringElement("lbp3ps4", this.Lbp3Ps4));
|
||||
}
|
||||
LbpSerializer.StringElement("lbp3ps4", this.Lbp3Ps4)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -3,9 +3,12 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Profiles {
|
||||
[XmlRoot("comment"), XmlType("comment")]
|
||||
public class Comment {
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Profiles
|
||||
{
|
||||
[XmlRoot("comment")]
|
||||
[XmlType("comment")]
|
||||
public class Comment
|
||||
{
|
||||
[Key]
|
||||
[XmlAttribute("id")]
|
||||
public int CommentId { get; set; }
|
||||
|
@ -24,24 +27,22 @@ namespace LBPUnion.ProjectLighthouse.Types.Profiles {
|
|||
|
||||
[XmlElement("message")]
|
||||
public string Message { get; set; }
|
||||
|
||||
public int ThumbsUp { get; set; }
|
||||
public int ThumbsDown { get; set; }
|
||||
|
||||
private string serialize() {
|
||||
return LbpSerializer.StringElement("id", this.CommentId) +
|
||||
private string serialize()
|
||||
=> LbpSerializer.StringElement("id", this.CommentId) +
|
||||
LbpSerializer.StringElement("npHandle", this.Poster.Username) +
|
||||
LbpSerializer.StringElement("timestamp", this.Timestamp) +
|
||||
LbpSerializer.StringElement("message", this.Message) +
|
||||
LbpSerializer.StringElement("thumbsup", this.ThumbsUp) +
|
||||
LbpSerializer.StringElement("thumbsdown", this.ThumbsDown);
|
||||
}
|
||||
|
||||
public string Serialize(int yourThumb) {
|
||||
return LbpSerializer.StringElement("comment", this.serialize() + LbpSerializer.StringElement("yourthumb", yourThumb));
|
||||
}
|
||||
public string Serialize
|
||||
(int yourThumb)
|
||||
=> LbpSerializer.StringElement("comment", this.serialize() + LbpSerializer.StringElement("yourthumb", yourThumb));
|
||||
|
||||
public string Serialize() {
|
||||
return LbpSerializer.StringElement("comment", this.serialize());
|
||||
}
|
||||
public string Serialize() => LbpSerializer.StringElement("comment", this.serialize());
|
||||
}
|
||||
}
|
|
@ -1,8 +1,12 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Profiles {
|
||||
public class LastMatch {
|
||||
[Key] public int UserId { get; set; }
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Profiles
|
||||
{
|
||||
public class LastMatch
|
||||
{
|
||||
[Key]
|
||||
public int UserId { get; set; }
|
||||
|
||||
public long Timestamp { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,12 +1,15 @@
|
|||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Profiles {
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Profiles
|
||||
{
|
||||
/// <summary>
|
||||
/// The location of a slot on a planet.
|
||||
/// </summary>
|
||||
[XmlRoot("location"), XmlType("location")]
|
||||
public class Location {
|
||||
[XmlRoot("location")]
|
||||
[XmlType("location")]
|
||||
public class Location
|
||||
{
|
||||
[XmlIgnore]
|
||||
public int Id { get; set; }
|
||||
|
||||
|
@ -16,9 +19,6 @@ namespace LBPUnion.ProjectLighthouse.Types.Profiles {
|
|||
[XmlElement("y")]
|
||||
public int Y { get; set; }
|
||||
|
||||
public string Serialize() {
|
||||
return LbpSerializer.StringElement("x", this.X) +
|
||||
LbpSerializer.StringElement("y", this.Y);
|
||||
}
|
||||
public string Serialize() => LbpSerializer.StringElement("x", this.X) + LbpSerializer.StringElement("y", this.Y);
|
||||
}
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
using System.Xml.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types {
|
||||
[XmlRoot("resources"), XmlType("resources")]
|
||||
public class ResourceList {
|
||||
namespace LBPUnion.ProjectLighthouse.Types
|
||||
{
|
||||
[XmlRoot("resources")]
|
||||
[XmlType("resources")]
|
||||
public class ResourceList
|
||||
{
|
||||
[XmlElement("resource")]
|
||||
public string[] Resources;
|
||||
}
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Settings {
|
||||
public class PrivacySettings {
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Settings
|
||||
{
|
||||
public class PrivacySettings
|
||||
{
|
||||
public string LevelVisibility { get; set; }
|
||||
public string ProfileVisibility { get; set; }
|
||||
|
||||
public string Serialize() {
|
||||
return LbpSerializer.StringElement("privacySettings",
|
||||
LbpSerializer.StringElement("levelVisibility", this.LevelVisibility) +
|
||||
LbpSerializer.StringElement("profileVisibility", this.ProfileVisibility)
|
||||
public string Serialize()
|
||||
=> LbpSerializer.StringElement
|
||||
(
|
||||
"privacySettings",
|
||||
LbpSerializer.StringElement("levelVisibility", this.LevelVisibility) + LbpSerializer.StringElement("profileVisibility", this.ProfileVisibility)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,8 +3,10 @@ using System;
|
|||
using Kettu;
|
||||
using LBPUnion.ProjectLighthouse.Logging;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Settings {
|
||||
public static class ServerSettings {
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Settings
|
||||
{
|
||||
public static class ServerSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum amount of slots allowed on users' earth
|
||||
/// </summary>
|
||||
|
@ -15,11 +17,11 @@ namespace LBPUnion.ProjectLighthouse.Types.Settings {
|
|||
public const string ServerName = "ProjectLighthouse";
|
||||
|
||||
private static string? dbConnectionString;
|
||||
|
||||
public static string DbConnectionString {
|
||||
get {
|
||||
if(dbConnectionString == null) {
|
||||
return dbConnectionString = Environment.GetEnvironmentVariable("LIGHTHOUSE_DB_CONNECTION_STRING") ?? "";
|
||||
}
|
||||
if (dbConnectionString == null) return dbConnectionString = Environment.GetEnvironmentVariable("LIGHTHOUSE_DB_CONNECTION_STRING") ?? "";
|
||||
|
||||
return dbConnectionString;
|
||||
}
|
||||
set => dbConnectionString = value;
|
||||
|
@ -27,10 +29,12 @@ namespace LBPUnion.ProjectLighthouse.Types.Settings {
|
|||
|
||||
public static bool DbConnected {
|
||||
get {
|
||||
try {
|
||||
try
|
||||
{
|
||||
return new Database().Database.CanConnect();
|
||||
}
|
||||
catch(Exception e) {
|
||||
catch(Exception e)
|
||||
{
|
||||
Logger.Log(e.ToString(), LoggerLevelDatabase.Instance);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types {
|
||||
public class Token {
|
||||
namespace LBPUnion.ProjectLighthouse.Types
|
||||
{
|
||||
public class Token
|
||||
{
|
||||
// ReSharper disable once UnusedMember.Global
|
||||
[Key] public int TokenId { get; set; }
|
||||
[Key]
|
||||
public int TokenId { get; set; }
|
||||
|
||||
public int UserId { get; set; }
|
||||
public string UserToken { get; set; }
|
||||
}
|
||||
|
|
|
@ -4,8 +4,13 @@ using LBPUnion.ProjectLighthouse.Serialization;
|
|||
using LBPUnion.ProjectLighthouse.Types.Profiles;
|
||||
using LBPUnion.ProjectLighthouse.Types.Settings;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types {
|
||||
public class User {
|
||||
namespace LBPUnion.ProjectLighthouse.Types
|
||||
{
|
||||
public class User
|
||||
{
|
||||
|
||||
// [NotMapped]
|
||||
public readonly ClientsConnected ClientsConnected = new();
|
||||
public int UserId { get; set; }
|
||||
public string Username { get; set; }
|
||||
public string IconHash { get; set; }
|
||||
|
@ -19,6 +24,7 @@ namespace LBPUnion.ProjectLighthouse.Types {
|
|||
/// A user-customizable biography shown on the profile card
|
||||
/// </summary>
|
||||
public string Biography { get; set; }
|
||||
|
||||
public int ReviewCount { get; set; }
|
||||
public int CommentCount { get; set; }
|
||||
public int PhotosByMeCount { get; set; }
|
||||
|
@ -43,55 +49,8 @@ namespace LBPUnion.ProjectLighthouse.Types {
|
|||
|
||||
public string PlanetHash { get; set; } = "";
|
||||
|
||||
// [NotMapped]
|
||||
public readonly ClientsConnected ClientsConnected = new();
|
||||
|
||||
#region Slots
|
||||
|
||||
/// <summary>
|
||||
/// The number of used slots on the earth
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public int UsedSlots {
|
||||
get {
|
||||
using Database database = new();
|
||||
return database.Slots.Count(s => s.CreatorId == this.UserId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The number of slots remaining on the earth
|
||||
/// </summary>
|
||||
public int FreeSlots => ServerSettings.EntitledSlots - this.UsedSlots;
|
||||
|
||||
private static readonly string[] slotTypes = {
|
||||
// "lbp1",
|
||||
"lbp2",
|
||||
"lbp3",
|
||||
"crossControl",
|
||||
};
|
||||
|
||||
private string SerializeSlots() {
|
||||
string slots = string.Empty;
|
||||
|
||||
slots += LbpSerializer.StringElement("lbp1UsedSlots", this.UsedSlots);
|
||||
slots += LbpSerializer.StringElement("entitledSlots", ServerSettings.EntitledSlots);
|
||||
slots += LbpSerializer.StringElement("freeSlots", this.FreeSlots);
|
||||
|
||||
foreach(string slotType in slotTypes) {
|
||||
slots += LbpSerializer.StringElement(slotType + "UsedSlots", this.UsedSlots);
|
||||
slots += LbpSerializer.StringElement(slotType + "EntitledSlots", ServerSettings.EntitledSlots);
|
||||
// ReSharper disable once StringLiteralTypo
|
||||
slots += LbpSerializer.StringElement(slotType + slotType == "crossControl" ? "PurchsedSlots" : "PurchasedSlots", 0);
|
||||
slots += LbpSerializer.StringElement(slotType + "FreeSlots", this.FreeSlots);
|
||||
}
|
||||
return slots;
|
||||
|
||||
}
|
||||
|
||||
#endregion Slots
|
||||
|
||||
public string Serialize() {
|
||||
public string Serialize()
|
||||
{
|
||||
string user = LbpSerializer.TaggedStringElement("npHandle", this.Username, "icon", this.IconHash) +
|
||||
LbpSerializer.StringElement("game", this.Game) +
|
||||
this.SerializeSlots() +
|
||||
|
@ -120,5 +79,52 @@ namespace LBPUnion.ProjectLighthouse.Types {
|
|||
|
||||
return LbpSerializer.TaggedStringElement("user", user, "type", "user");
|
||||
}
|
||||
|
||||
#region Slots
|
||||
|
||||
/// <summary>
|
||||
/// The number of used slots on the earth
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public int UsedSlots {
|
||||
get {
|
||||
using Database database = new();
|
||||
return database.Slots.Count(s => s.CreatorId == this.UserId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The number of slots remaining on the earth
|
||||
/// </summary>
|
||||
public int FreeSlots => ServerSettings.EntitledSlots - this.UsedSlots;
|
||||
|
||||
private static readonly string[] slotTypes =
|
||||
{
|
||||
// "lbp1",
|
||||
"lbp2", "lbp3", "crossControl",
|
||||
};
|
||||
|
||||
private string SerializeSlots()
|
||||
{
|
||||
string slots = string.Empty;
|
||||
|
||||
slots += LbpSerializer.StringElement("lbp1UsedSlots", this.UsedSlots);
|
||||
slots += LbpSerializer.StringElement("entitledSlots", ServerSettings.EntitledSlots);
|
||||
slots += LbpSerializer.StringElement("freeSlots", this.FreeSlots);
|
||||
|
||||
foreach (string slotType in slotTypes)
|
||||
{
|
||||
slots += LbpSerializer.StringElement(slotType + "UsedSlots", this.UsedSlots);
|
||||
slots += LbpSerializer.StringElement(slotType + "EntitledSlots", ServerSettings.EntitledSlots);
|
||||
// ReSharper disable once StringLiteralTypo
|
||||
slots += LbpSerializer.StringElement(slotType + slotType == "crossControl" ? "PurchsedSlots" : "PurchasedSlots", 0);
|
||||
slots += LbpSerializer.StringElement(slotType + "FreeSlots", this.FreeSlots);
|
||||
}
|
||||
return slots;
|
||||
|
||||
}
|
||||
|
||||
#endregion Slots
|
||||
|
||||
}
|
||||
}
|
53
README.md
53
README.md
|
@ -1,60 +1,75 @@
|
|||
# Project Lighthouse
|
||||
|
||||
Project Lighthouse is an umbrella project for all work to investigate and develop private servers for LittleBigPlanet.
|
||||
This project is the main server component that LittleBigPlanet games connect to.
|
||||
|
||||
## WARNING!
|
||||
This is beta software, and thus is not ready for public use yet.
|
||||
We're not responsible if someone connects and hacks your entire machine and deletes all your files.
|
||||
|
||||
This is beta software, and thus is not ready for public use yet. We're not responsible if someone connects and hacks
|
||||
your entire machine and deletes all your files.
|
||||
|
||||
That said, feel free to develop privately!
|
||||
|
||||
## Building
|
||||
|
||||
This will be written when we're out of beta. Consider this your barrier to entry ;).
|
||||
|
||||
## Running
|
||||
Lighthouse requires a MySQL database at this time.
|
||||
For Linux users running docker, one can be set up using the `docker-compose.yml` file in the root of the project folder.
|
||||
|
||||
Next, make sure the `LIGHTHOUSE_DB_CONNECTION_STRING` environment variable is set correctly.
|
||||
By default, it is `server=127.0.0.1;uid=root;pwd=lighthouse;database=lighthouse`. If you are running the database via
|
||||
the above `docker-compose.yml` you shouldn't need to change this. For other development/especially production environments
|
||||
Lighthouse requires a MySQL database at this time. For Linux users running docker, one can be set up using
|
||||
the `docker-compose.yml` file in the root of the project folder.
|
||||
|
||||
Next, make sure the `LIGHTHOUSE_DB_CONNECTION_STRING` environment variable is set correctly. By default, it
|
||||
is `server=127.0.0.1;uid=root;pwd=lighthouse;database=lighthouse`. If you are running the database via the
|
||||
above `docker-compose.yml` you shouldn't need to change this. For other development/especially production environments
|
||||
you will need to change this.
|
||||
|
||||
Once you've gotten MySQL running you can run Lighthouse. It will take care of the rest.
|
||||
|
||||
## Connecting
|
||||
PS3 is difficult to set up, so I will be going over how to set up RPCS3 instead. A guide will be coming for PS3 closer to release.
|
||||
You can also follow this guide if you want to learn how to modify your EBOOT.
|
||||
|
||||
*Note: This requires a modified copy of RPCS3. You can find a working patch [here](https://gist.github.com/jvyden/0d9619f7dd3dbc49f7583486bdacad75).*
|
||||
PS3 is difficult to set up, so I will be going over how to set up RPCS3 instead. A guide will be coming for PS3 closer
|
||||
to release. You can also follow this guide if you want to learn how to modify your EBOOT.
|
||||
|
||||
Start by getting a copy of LittleBigPlanet 2 installed. It can be digital (NPUA80662) or disc (BCUS98245).
|
||||
I won't get into how because if you got this far you should already know what you're doing. For those that don't, the [RPCS3 Quickstart Guide](https://rpcs3.net/quickstart) should cover it.
|
||||
*Note: This requires a modified copy of RPCS3. You can find a working
|
||||
patch [here](https://gist.github.com/jvyden/0d9619f7dd3dbc49f7583486bdacad75).*
|
||||
|
||||
Next, download [UnionPatcher](https://github.com/LBPUnion/UnionPatcher/). Binaries can be found by reading the README.md file.
|
||||
Start by getting a copy of LittleBigPlanet 2 installed. It can be digital (NPUA80662) or disc (BCUS98245). I won't get
|
||||
into how because if you got this far you should already know what you're doing. For those that don't,
|
||||
the [RPCS3 Quickstart Guide](https://rpcs3.net/quickstart) should cover it.
|
||||
|
||||
You should have everything you need now, so open up RPCS3 and go to Utilities -> Decrypt PS3 Binaries. Point this to `rpcs3/dev_hdd0/game/(title id)/USRDIR/EBOOT.BIN`.
|
||||
Next, download [UnionPatcher](https://github.com/LBPUnion/UnionPatcher/). Binaries can be found by reading the README.md
|
||||
file.
|
||||
|
||||
This should give you a file named `EBOOT.elf` in the same folder. Next, fire up UnionPatcher (making sure to select the correct project to start, e.g. on Mac launch `UnionPatcher.Gui.MacOS`.)
|
||||
You should have everything you need now, so open up RPCS3 and go to Utilities -> Decrypt PS3 Binaries. Point this
|
||||
to `rpcs3/dev_hdd0/game/(title id)/USRDIR/EBOOT.BIN`.
|
||||
|
||||
Now that you have your decrypted eboot, open UnionPatcher and select the `EBOOT.elf` you got earlier in the top box, enter `http://localhost:10060/LITTLEBIGPLANETPS3_XML` in the second, and the output filename in the third.
|
||||
For this guide I'll use `EBOOTlocalhost.elf`.
|
||||
This should give you a file named `EBOOT.elf` in the same folder. Next, fire up UnionPatcher (making sure to select the
|
||||
correct project to start, e.g. on Mac launch `UnionPatcher.Gui.MacOS`.)
|
||||
|
||||
Now that you have your decrypted eboot, open UnionPatcher and select the `EBOOT.elf` you got earlier in the top box,
|
||||
enter `http://localhost:10060/LITTLEBIGPLANETPS3_XML` in the second, and the output filename in the third. For this
|
||||
guide I'll use `EBOOTlocalhost.elf`.
|
||||
|
||||
Now, copy the `EBOOTlocalhost.elf` file to where you got your `EBOOT.elf` file from, and you're now good to go.
|
||||
|
||||
To launch the game with the patched EBOOT, open up RPCS3, go to File, Boot SELF/ELF, and open up `EBOOTlocalhost.elf`.
|
||||
|
||||
Assuming you are running the patched version of RPCS3, you patched the file correctly, the database is migrated, and Lighthouse is running, the game should now connect.
|
||||
Assuming you are running the patched version of RPCS3, you patched the file correctly, the database is migrated, and
|
||||
Lighthouse is running, the game should now connect.
|
||||
|
||||
Finally, take a break. Chances are that took a while.
|
||||
|
||||
## Contributing Tips
|
||||
|
||||
### Database
|
||||
|
||||
Some modifications may require updates to the database schema. You can automatically create a migration file by:
|
||||
|
||||
1. Making sure the tools are installed. You can do this by running `dotnet tool restore`.
|
||||
2. Making sure `LIGHTHOUSE_DB_CONNECTION_STRING` is set correctly. See the `Running` section for more details.
|
||||
3. Making your changes to the database. I won't cover this since if you're making database changes you should know what you're doing.
|
||||
3. Making your changes to the database. I won't cover this since if you're making database changes you should know what
|
||||
you're doing.
|
||||
4. Running `dotnet ef migrations add <NameOfMigrationInPascalCase> --project ProjectLighthouse`.
|
||||
|
||||
## Compatibility across games and platforms
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue