mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-06-02 22:22:28 +00:00
Resolve conflicts
This commit is contained in:
commit
4308ee1a71
85 changed files with 3200 additions and 936 deletions
17
.github/workflows/ci.yml
vendored
17
.github/workflows/ci.yml
vendored
|
@ -1,4 +1,4 @@
|
||||||
on: [push]
|
on: [ push ]
|
||||||
name: Continuous Integration
|
name: Continuous Integration
|
||||||
|
|
||||||
# Inspired by osu! lazer's CI
|
# Inspired by osu! lazer's CI
|
||||||
|
@ -22,11 +22,6 @@ jobs:
|
||||||
DB_USER: root
|
DB_USER: root
|
||||||
DB_PASSWORD: lighthouse
|
DB_PASSWORD: lighthouse
|
||||||
steps:
|
steps:
|
||||||
- name: Cancel previous runs of this workflow
|
|
||||||
uses: styfle/cancel-workflow-action@0.6.0
|
|
||||||
with:
|
|
||||||
access_token: ${{ github.token }}
|
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
@ -36,11 +31,11 @@ jobs:
|
||||||
with:
|
with:
|
||||||
mysql-version: '8.0'
|
mysql-version: '8.0'
|
||||||
root-password: ${{ env.DB_PASSWORD }}
|
root-password: ${{ env.DB_PASSWORD }}
|
||||||
|
|
||||||
- name: Create Lighthouse Database
|
- name: Create Lighthouse Database
|
||||||
if: ${{ matrix.os.database }}
|
if: ${{ matrix.os.database }}
|
||||||
run: mysql -u${{ env.DB_USER }} -p${{ env.DB_PASSWORD }} -h 127.0.0.1 -e "CREATE DATABASE ${{ env.DB_DATABASE }};";
|
run: mysql -u${{ env.DB_USER }} -p${{ env.DB_PASSWORD }} -h 127.0.0.1 -e "CREATE DATABASE ${{ env.DB_DATABASE }};";
|
||||||
|
|
||||||
- name: Install .NET 5.0
|
- name: Install .NET 5.0
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
|
@ -52,10 +47,10 @@ jobs:
|
||||||
with:
|
with:
|
||||||
dotnet-version: "6.0.x"
|
dotnet-version: "6.0.x"
|
||||||
include-prerelease: true
|
include-prerelease: true
|
||||||
|
|
||||||
- name: Compile
|
- name: Compile
|
||||||
run: dotnet build -c Debug
|
run: dotnet build -c Debug
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
run: dotnet test --logger "trx;LogFileName=${{github.workspace}}/TestResults-${{matrix.os.prettyName}}.trx"
|
run: dotnet test --logger "trx;LogFileName=${{github.workspace}}/TestResults-${{matrix.os.prettyName}}.trx"
|
||||||
|
@ -84,7 +79,7 @@ jobs:
|
||||||
create-status-check: false
|
create-status-check: false
|
||||||
create-pr-comment: false
|
create-pr-comment: false
|
||||||
update-comment-if-one-exists: false
|
update-comment-if-one-exists: false
|
||||||
|
|
||||||
- name: Check Test Results
|
- name: Check Test Results
|
||||||
if: steps.process-trx.outputs.test-outcome == 'Failed'
|
if: steps.process-trx.outputs.test-outcome == 'Failed'
|
||||||
run: |
|
run: |
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
<component name="ProjectRunConfigurationManager">
|
<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"
|
||||||
<deployment type="docker-compose.yml">
|
server-name="Docker">
|
||||||
<settings>
|
<deployment type="docker-compose.yml">
|
||||||
<option name="envFilePath" value="" />
|
<settings>
|
||||||
<option name="sourceFilePath" value="docker-compose.yml" />
|
<option name="envFilePath" value=""/>
|
||||||
</settings>
|
<option name="sourceFilePath" value="docker-compose.yml"/>
|
||||||
</deployment>
|
</settings>
|
||||||
<method v="2" />
|
</deployment>
|
||||||
</configuration>
|
<method v="2"/>
|
||||||
|
</configuration>
|
||||||
</component>
|
</component>
|
|
@ -2,12 +2,19 @@ using LBPUnion.ProjectLighthouse.Types.Settings;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Tests {
|
namespace LBPUnion.ProjectLighthouse.Tests
|
||||||
public sealed class DatabaseFact : FactAttribute {
|
{
|
||||||
public DatabaseFact() {
|
public sealed class DatabaseFact : FactAttribute
|
||||||
|
{
|
||||||
|
public DatabaseFact()
|
||||||
|
{
|
||||||
ServerSettings.DbConnectionString = "server=127.0.0.1;uid=root;pwd=lighthouse;database=lighthouse";
|
ServerSettings.DbConnectionString = "server=127.0.0.1;uid=root;pwd=lighthouse;database=lighthouse";
|
||||||
if(!ServerSettings.DbConnected) this.Skip = "Database not available";
|
if (!ServerSettings.DbConnected)
|
||||||
else {
|
{
|
||||||
|
this.Skip = "Database not available";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
using Database database = new();
|
using Database database = new();
|
||||||
database.Database.Migrate();
|
database.Database.Migrate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,31 +8,33 @@ using LBPUnion.ProjectLighthouse.Types;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.TestHost;
|
using Microsoft.AspNetCore.TestHost;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Tests {
|
namespace LBPUnion.ProjectLighthouse.Tests
|
||||||
|
{
|
||||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||||
public class LighthouseTest {
|
public class LighthouseTest
|
||||||
public readonly TestServer Server;
|
{
|
||||||
public readonly HttpClient Client;
|
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();
|
this.Client = this.Server.CreateClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<HttpResponseMessage> AuthenticateResponse(int number = 0) {
|
public async Task<HttpResponseMessage> AuthenticateResponse(int number = 0)
|
||||||
const char nullChar = (char)0x00;
|
{
|
||||||
const char sepChar = (char)0x20;
|
|
||||||
const string username = "unitTestUser";
|
const string username = "unitTestUser";
|
||||||
|
|
||||||
string stringContent = $"{nullChar}{sepChar}{username}{number}{nullChar}";
|
string stringContent = $"{LoginData.UsernamePrefix}{username}{number}{(char)0x00}";
|
||||||
|
|
||||||
HttpResponseMessage response = await this.Client.PostAsync("/LITTLEBIGPLANETPS3_XML/login", new StringContent(stringContent));
|
HttpResponseMessage response = await this.Client.PostAsync("/LITTLEBIGPLANETPS3_XML/login", new StringContent(stringContent));
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<LoginResult> Authenticate(int number = 0) {
|
public async Task<LoginResult> Authenticate(int number = 0)
|
||||||
|
{
|
||||||
HttpResponseMessage response = await this.AuthenticateResponse(number);
|
HttpResponseMessage response = await this.AuthenticateResponse(number);
|
||||||
|
|
||||||
string responseContent = LbpSerializer.StringElement("loginResult", await response.Content.ReadAsStringAsync());
|
string responseContent = LbpSerializer.StringElement("loginResult", await response.Content.ReadAsStringAsync());
|
||||||
|
@ -43,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) => this.AuthenticatedRequest(endpoint, mmAuth, HttpMethod.Get);
|
||||||
|
|
||||||
public Task<HttpResponseMessage> AuthenticatedRequest(string endpoint, string mmAuth, HttpMethod method) {
|
public Task<HttpResponseMessage> AuthenticatedRequest(string endpoint, string mmAuth, HttpMethod method)
|
||||||
using var requestMessage = new HttpRequestMessage(method, endpoint);
|
{
|
||||||
|
using HttpRequestMessage? requestMessage = new(method, endpoint);
|
||||||
requestMessage.Headers.Add("Cookie", mmAuth);
|
requestMessage.Headers.Add("Cookie", mmAuth);
|
||||||
|
|
||||||
return this.Client.SendAsync(requestMessage);
|
return this.Client.SendAsync(requestMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<HttpResponseMessage> UploadFileRequest(string endpoint, string filePath) {
|
public async Task<HttpResponseMessage> UploadFileRequest(string endpoint, string filePath)
|
||||||
return await this.Client.PostAsync(endpoint, new StringContent(await File.ReadAllTextAsync(filePath)));
|
=> await this.Client.PostAsync(endpoint, new StringContent(await File.ReadAllTextAsync(filePath)));
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<HttpResponseMessage> UploadDataRequest(string endpoint, byte[] data) {
|
public async Task<HttpResponseMessage> UploadDataRequest(string endpoint, byte[] data)
|
||||||
return await this.Client.PostAsync(endpoint, new ByteArrayContent(data));
|
=> await this.Client.PostAsync(endpoint, new ByteArrayContent(data));
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<HttpResponseMessage> AuthenticatedUploadFileRequest(string endpoint, string filePath, string mmAuth) {
|
public async Task<HttpResponseMessage> AuthenticatedUploadFileRequest(string endpoint, string filePath, string mmAuth)
|
||||||
using var requestMessage = new HttpRequestMessage(HttpMethod.Post, endpoint);
|
{
|
||||||
|
using HttpRequestMessage? requestMessage = new(HttpMethod.Post, endpoint);
|
||||||
requestMessage.Headers.Add("Cookie", mmAuth);
|
requestMessage.Headers.Add("Cookie", mmAuth);
|
||||||
requestMessage.Content = new StringContent(await File.ReadAllTextAsync(filePath));
|
requestMessage.Content = new StringContent(await File.ReadAllTextAsync(filePath));
|
||||||
return await this.Client.SendAsync(requestMessage);
|
return await this.Client.SendAsync(requestMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<HttpResponseMessage> AuthenticatedUploadDataRequest(string endpoint, byte[] data, string mmAuth) {
|
public async Task<HttpResponseMessage> AuthenticatedUploadDataRequest(string endpoint, byte[] data, string mmAuth)
|
||||||
using var requestMessage = new HttpRequestMessage(HttpMethod.Post, endpoint);
|
{
|
||||||
|
using HttpRequestMessage? requestMessage = new(HttpMethod.Post, endpoint);
|
||||||
requestMessage.Headers.Add("Cookie", mmAuth);
|
requestMessage.Headers.Add("Cookie", mmAuth);
|
||||||
requestMessage.Content = new ByteArrayContent(data);
|
requestMessage.Content = new ByteArrayContent(data);
|
||||||
return await this.Client.SendAsync(requestMessage);
|
return await this.Client.SendAsync(requestMessage);
|
||||||
|
|
|
@ -13,9 +13,9 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.11" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.11"/>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0"/>
|
||||||
<PackageReference Include="xunit" Version="2.4.1" />
|
<PackageReference Include="xunit" Version="2.4.1"/>
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\ProjectLighthouse\ProjectLighthouse.csproj" />
|
<ProjectReference Include="..\ProjectLighthouse\ProjectLighthouse.csproj"/>
|
||||||
<Content Include="ExampleFiles\**">
|
<Content Include="ExampleFiles\**">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
|
|
@ -5,10 +5,13 @@ using LBPUnion.ProjectLighthouse.Types;
|
||||||
using LBPUnion.ProjectLighthouse.Types.Settings;
|
using LBPUnion.ProjectLighthouse.Types.Settings;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Tests {
|
namespace LBPUnion.ProjectLighthouse.Tests
|
||||||
public class AuthenticationTests : LighthouseTest {
|
{
|
||||||
|
public class AuthenticationTests : LighthouseTest
|
||||||
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ShouldReturnErrorOnNoPostData() {
|
public async Task ShouldReturnErrorOnNoPostData()
|
||||||
|
{
|
||||||
HttpResponseMessage response = await this.Client.PostAsync("/LITTLEBIGPLANETPS3_XML/login", null!);
|
HttpResponseMessage response = await this.Client.PostAsync("/LITTLEBIGPLANETPS3_XML/login", null!);
|
||||||
Assert.False(response.IsSuccessStatusCode);
|
Assert.False(response.IsSuccessStatusCode);
|
||||||
#if NET6_0_OR_GREATER
|
#if NET6_0_OR_GREATER
|
||||||
|
@ -19,7 +22,8 @@ namespace LBPUnion.ProjectLighthouse.Tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
[DatabaseFact]
|
[DatabaseFact]
|
||||||
public async Task ShouldReturnWithValidData() {
|
public async Task ShouldReturnWithValidData()
|
||||||
|
{
|
||||||
HttpResponseMessage response = await this.AuthenticateResponse();
|
HttpResponseMessage response = await this.AuthenticateResponse();
|
||||||
Assert.True(response.IsSuccessStatusCode);
|
Assert.True(response.IsSuccessStatusCode);
|
||||||
string responseContent = await response.Content.ReadAsStringAsync();
|
string responseContent = await response.Content.ReadAsStringAsync();
|
||||||
|
@ -28,9 +32,10 @@ namespace LBPUnion.ProjectLighthouse.Tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
[DatabaseFact]
|
[DatabaseFact]
|
||||||
public async Task CanSerializeBack() {
|
public async Task CanSerializeBack()
|
||||||
|
{
|
||||||
LoginResult loginResult = await this.Authenticate();
|
LoginResult loginResult = await this.Authenticate();
|
||||||
|
|
||||||
Assert.NotNull(loginResult);
|
Assert.NotNull(loginResult);
|
||||||
Assert.NotNull(loginResult.AuthTicket);
|
Assert.NotNull(loginResult.AuthTicket);
|
||||||
Assert.NotNull(loginResult.LbpEnvVer);
|
Assert.NotNull(loginResult.LbpEnvVer);
|
||||||
|
@ -40,18 +45,20 @@ namespace LBPUnion.ProjectLighthouse.Tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
[DatabaseFact]
|
[DatabaseFact]
|
||||||
public async Task CanUseToken() {
|
public async Task CanUseToken()
|
||||||
|
{
|
||||||
LoginResult loginResult = await this.Authenticate();
|
LoginResult loginResult = await this.Authenticate();
|
||||||
|
|
||||||
HttpResponseMessage response = await this.AuthenticatedRequest("/LITTLEBIGPLANETPS3_XML/eula", loginResult.AuthTicket);
|
HttpResponseMessage response = await this.AuthenticatedRequest("/LITTLEBIGPLANETPS3_XML/eula", loginResult.AuthTicket);
|
||||||
string responseContent = await response.Content.ReadAsStringAsync();
|
string responseContent = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
Assert.True(response.IsSuccessStatusCode);
|
Assert.True(response.IsSuccessStatusCode);
|
||||||
Assert.Contains("You are logged in", responseContent);
|
Assert.Contains("You are now logged in", responseContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DatabaseFact]
|
[DatabaseFact]
|
||||||
public async Task ShouldReturnForbiddenWhenNotAuthenticated() {
|
public async Task ShouldReturnForbiddenWhenNotAuthenticated()
|
||||||
|
{
|
||||||
HttpResponseMessage response = await this.Client.GetAsync("/LITTLEBIGPLANETPS3_XML/eula");
|
HttpResponseMessage response = await this.Client.GetAsync("/LITTLEBIGPLANETPS3_XML/eula");
|
||||||
Assert.False(response.IsSuccessStatusCode);
|
Assert.False(response.IsSuccessStatusCode);
|
||||||
Assert.True(response.StatusCode == HttpStatusCode.Forbidden);
|
Assert.True(response.StatusCode == HttpStatusCode.Forbidden);
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Tests {
|
namespace LBPUnion.ProjectLighthouse.Tests
|
||||||
public class DatabaseTests : LighthouseTest {
|
{
|
||||||
|
public class DatabaseTests : LighthouseTest
|
||||||
|
{
|
||||||
[DatabaseFact]
|
[DatabaseFact]
|
||||||
public async Task CanCreateUserTwice() {
|
public async Task CanCreateUserTwice()
|
||||||
|
{
|
||||||
await using Database database = new();
|
await using Database database = new();
|
||||||
int rand = new Random().Next();
|
int rand = new Random().Next();
|
||||||
|
|
||||||
|
|
|
@ -4,47 +4,56 @@ using System.Text;
|
||||||
using LBPUnion.ProjectLighthouse.Types.Files;
|
using LBPUnion.ProjectLighthouse.Types.Files;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Tests {
|
namespace LBPUnion.ProjectLighthouse.Tests
|
||||||
public class FileTypeTests {
|
{
|
||||||
|
public class FileTypeTests
|
||||||
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ShouldRecognizeLevel() {
|
public void ShouldRecognizeLevel()
|
||||||
|
{
|
||||||
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestLevel.lvl"));
|
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestLevel.lvl"));
|
||||||
Assert.True(file.FileType == LbpFileType.Level);
|
Assert.True(file.FileType == LbpFileType.Level);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ShouldRecognizeScript() {
|
public void ShouldRecognizeScript()
|
||||||
|
{
|
||||||
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestScript.ff"));
|
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestScript.ff"));
|
||||||
Assert.True(file.FileType == LbpFileType.Script);
|
Assert.True(file.FileType == LbpFileType.Script);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ShouldRecognizeTexture() {
|
public void ShouldRecognizeTexture()
|
||||||
|
{
|
||||||
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestTexture.tex"));
|
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestTexture.tex"));
|
||||||
Assert.True(file.FileType == LbpFileType.Texture);
|
Assert.True(file.FileType == LbpFileType.Texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ShouldRecognizeFileArchive() {
|
public void ShouldRecognizeFileArchive()
|
||||||
|
{
|
||||||
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestFarc.farc"));
|
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestFarc.farc"));
|
||||||
Assert.True(file.FileType == LbpFileType.FileArchive);
|
Assert.True(file.FileType == LbpFileType.FileArchive);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ShouldNotRecognizeFileArchiveAsScript() {
|
public void ShouldNotRecognizeFileArchiveAsScript()
|
||||||
|
{
|
||||||
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestFarc.farc"));
|
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestFarc.farc"));
|
||||||
Assert.False(file.FileType == LbpFileType.Script);
|
Assert.False(file.FileType == LbpFileType.Script);
|
||||||
Assert.True(file.FileType == LbpFileType.FileArchive);
|
Assert.True(file.FileType == LbpFileType.FileArchive);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ShouldRecognizeNothingAsUnknown() {
|
public void ShouldRecognizeNothingAsUnknown()
|
||||||
|
{
|
||||||
LbpFile file = new(Array.Empty<byte>());
|
LbpFile file = new(Array.Empty<byte>());
|
||||||
Assert.True(file.FileType == LbpFileType.Unknown);
|
Assert.True(file.FileType == LbpFileType.Unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ShouldRecognizeGarbageAsUnknown() {
|
public void ShouldRecognizeGarbageAsUnknown()
|
||||||
|
{
|
||||||
LbpFile file = new(Encoding.ASCII.GetBytes("free pc only $900"));
|
LbpFile file = new(Encoding.ASCII.GetBytes("free pc only $900"));
|
||||||
Assert.True(file.FileType == LbpFileType.Unknown);
|
Assert.True(file.FileType == LbpFileType.Unknown);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,39 +1,59 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using LBPUnion.ProjectLighthouse.Types;
|
using LBPUnion.ProjectLighthouse.Types;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Tests {
|
namespace LBPUnion.ProjectLighthouse.Tests
|
||||||
public class MatchTests : LighthouseTest {
|
{
|
||||||
|
public class MatchTests : LighthouseTest
|
||||||
|
{
|
||||||
private static readonly SemaphoreSlim semaphore = new(1, 1);
|
private static readonly SemaphoreSlim semaphore = new(1, 1);
|
||||||
|
|
||||||
[DatabaseFact]
|
[DatabaseFact]
|
||||||
public async Task ShouldReturnOk() {
|
public async Task ShouldRejectEmptyData()
|
||||||
|
{
|
||||||
LoginResult loginResult = await this.Authenticate();
|
LoginResult loginResult = await this.Authenticate();
|
||||||
await semaphore.WaitAsync();
|
await semaphore.WaitAsync();
|
||||||
|
|
||||||
HttpResponseMessage result = await this.AuthenticatedUploadDataRequest("LITTLEBIGPLANETPS3_XML/match", Array.Empty<byte>(), loginResult.AuthTicket);
|
HttpResponseMessage result = await this.AuthenticatedUploadDataRequest("LITTLEBIGPLANETPS3_XML/match", Array.Empty<byte>(), loginResult.AuthTicket);
|
||||||
Assert.True(result.IsSuccessStatusCode);
|
|
||||||
|
|
||||||
semaphore.Release();
|
semaphore.Release();
|
||||||
|
Assert.False(result.IsSuccessStatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[DatabaseFact]
|
||||||
|
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);
|
||||||
|
|
||||||
|
semaphore.Release();
|
||||||
|
Assert.True(result.IsSuccessStatusCode);
|
||||||
}
|
}
|
||||||
public async Task<int> GetPlayerCount() => Convert.ToInt32(await this.Client.GetStringAsync("LITTLEBIGPLANETPS3_XML/totalPlayerCount"));
|
public async Task<int> GetPlayerCount() => Convert.ToInt32(await this.Client.GetStringAsync("LITTLEBIGPLANETPS3_XML/totalPlayerCount"));
|
||||||
|
|
||||||
[DatabaseFact]
|
[DatabaseFact]
|
||||||
public async Task ShouldIncrementPlayerCount() {
|
public async Task ShouldIncrementPlayerCount()
|
||||||
|
{
|
||||||
LoginResult loginResult = await this.Authenticate(new Random().Next());
|
LoginResult loginResult = await this.Authenticate(new Random().Next());
|
||||||
|
|
||||||
await semaphore.WaitAsync();
|
await semaphore.WaitAsync();
|
||||||
|
|
||||||
int oldPlayerCount = await this.GetPlayerCount();
|
int oldPlayerCount = await this.GetPlayerCount();
|
||||||
|
|
||||||
HttpResponseMessage result = await this.AuthenticatedUploadDataRequest("LITTLEBIGPLANETPS3_XML/match", Array.Empty<byte>(), loginResult.AuthTicket);
|
HttpResponseMessage result = await this.AuthenticatedUploadDataRequest
|
||||||
|
("LITTLEBIGPLANETPS3_XML/match", Encoding.ASCII.GetBytes("[UpdateMyPlayerData,[\"Player\":\"1984\"]]"), loginResult.AuthTicket);
|
||||||
|
|
||||||
Assert.True(result.IsSuccessStatusCode);
|
Assert.True(result.IsSuccessStatusCode);
|
||||||
|
|
||||||
int playerCount = await this.GetPlayerCount();
|
int playerCount = await this.GetPlayerCount();
|
||||||
|
|
||||||
semaphore.Release();
|
semaphore.Release();
|
||||||
Assert.Equal(oldPlayerCount + 1, playerCount);
|
Assert.Equal(oldPlayerCount + 1, playerCount);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,30 +2,42 @@ using System.Collections.Generic;
|
||||||
using LBPUnion.ProjectLighthouse.Serialization;
|
using LBPUnion.ProjectLighthouse.Serialization;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Tests {
|
namespace LBPUnion.ProjectLighthouse.Tests
|
||||||
public class SerializerTests : LighthouseTest {
|
{
|
||||||
|
public class SerializerTests : LighthouseTest
|
||||||
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public void BlankElementWorks() {
|
public void BlankElementWorks()
|
||||||
|
{
|
||||||
Assert.Equal("<test></test>", LbpSerializer.BlankElement("test"));
|
Assert.Equal("<test></test>", LbpSerializer.BlankElement("test"));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void StringElementWorks() {
|
public void StringElementWorks()
|
||||||
|
{
|
||||||
Assert.Equal("<test>asd</test>", LbpSerializer.StringElement("test", "asd"));
|
Assert.Equal("<test>asd</test>", LbpSerializer.StringElement("test", "asd"));
|
||||||
Assert.Equal("<test>asd</test>", LbpSerializer.StringElement(new KeyValuePair<string, object>("test", "asd")));
|
Assert.Equal("<test>asd</test>", LbpSerializer.StringElement(new KeyValuePair<string, object>("test", "asd")));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[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("test", "asd", "foo", "bar"));
|
||||||
Assert.Equal("<test foo=\"bar\">asd</test>", LbpSerializer.TaggedStringElement(new KeyValuePair<string, object>("test", "asd"),
|
Assert.Equal
|
||||||
new KeyValuePair<string, object>("foo", "bar")));
|
(
|
||||||
|
"<test foo=\"bar\">asd</test>",
|
||||||
|
LbpSerializer.TaggedStringElement(new KeyValuePair<string, object>("test", "asd"), new KeyValuePair<string, object>("foo", "bar"))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ElementsWorks() {
|
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")));
|
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 LBPUnion.ProjectLighthouse.Types.Profiles;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Tests {
|
namespace LBPUnion.ProjectLighthouse.Tests
|
||||||
public class SlotTests : LighthouseTest {
|
{
|
||||||
|
public class SlotTests : LighthouseTest
|
||||||
|
{
|
||||||
[DatabaseFact]
|
[DatabaseFact]
|
||||||
public async Task ShouldOnlyShowUsersLevels() {
|
public async Task ShouldOnlyShowUsersLevels()
|
||||||
|
{
|
||||||
await using Database database = new();
|
await using Database database = new();
|
||||||
|
|
||||||
User userA = await database.CreateUser("unitTestUser0");
|
User userA = await database.CreateUser("unitTestUser0");
|
||||||
|
@ -17,7 +20,8 @@ namespace LBPUnion.ProjectLighthouse.Tests {
|
||||||
database.Locations.Add(l);
|
database.Locations.Add(l);
|
||||||
await database.SaveChangesAsync();
|
await database.SaveChangesAsync();
|
||||||
|
|
||||||
Slot slotA = new() {
|
Slot slotA = new()
|
||||||
|
{
|
||||||
Creator = userA,
|
Creator = userA,
|
||||||
Name = "slotA",
|
Name = "slotA",
|
||||||
Location = l,
|
Location = l,
|
||||||
|
@ -25,7 +29,8 @@ namespace LBPUnion.ProjectLighthouse.Tests {
|
||||||
ResourceCollection = "",
|
ResourceCollection = "",
|
||||||
};
|
};
|
||||||
|
|
||||||
Slot slotB = new() {
|
Slot slotB = new()
|
||||||
|
{
|
||||||
Creator = userB,
|
Creator = userB,
|
||||||
Name = "slotB",
|
Name = "slotB",
|
||||||
Location = l,
|
Location = l,
|
||||||
|
@ -47,7 +52,7 @@ namespace LBPUnion.ProjectLighthouse.Tests {
|
||||||
Assert.NotEqual(respA, respB);
|
Assert.NotEqual(respA, respB);
|
||||||
Assert.DoesNotContain(respA, "slotB");
|
Assert.DoesNotContain(respA, "slotB");
|
||||||
Assert.DoesNotContain(respB, "slotA");
|
Assert.DoesNotContain(respB, "slotA");
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
|
|
||||||
database.Slots.Remove(slotA);
|
database.Slots.Remove(slotA);
|
||||||
|
|
|
@ -4,39 +4,47 @@ using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Tests {
|
namespace LBPUnion.ProjectLighthouse.Tests
|
||||||
public class UploadTests : LighthouseTest {
|
{
|
||||||
public UploadTests() {
|
public class UploadTests : LighthouseTest
|
||||||
|
{
|
||||||
|
public UploadTests()
|
||||||
|
{
|
||||||
string assetsDirectory = Path.Combine(Environment.CurrentDirectory, "r");
|
string assetsDirectory = Path.Combine(Environment.CurrentDirectory, "r");
|
||||||
if(Directory.Exists(assetsDirectory)) Directory.Delete(assetsDirectory, true);
|
if (Directory.Exists(assetsDirectory)) Directory.Delete(assetsDirectory, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ShouldNotAcceptScript() {
|
public async Task ShouldNotAcceptScript()
|
||||||
|
{
|
||||||
HttpResponseMessage response = await this.UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/scriptTest", "ExampleFiles/TestScript.ff");
|
HttpResponseMessage response = await this.UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/scriptTest", "ExampleFiles/TestScript.ff");
|
||||||
Assert.False(response.IsSuccessStatusCode);
|
Assert.False(response.IsSuccessStatusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ShouldNotAcceptFarc() {
|
public async Task ShouldNotAcceptFarc()
|
||||||
|
{
|
||||||
HttpResponseMessage response = await this.UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/farcTest", "ExampleFiles/TestFarc.farc");
|
HttpResponseMessage response = await this.UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/farcTest", "ExampleFiles/TestFarc.farc");
|
||||||
Assert.False(response.IsSuccessStatusCode);
|
Assert.False(response.IsSuccessStatusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ShouldNotAcceptGarbage() {
|
public async Task ShouldNotAcceptGarbage()
|
||||||
|
{
|
||||||
HttpResponseMessage response = await this.UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/garbageTest", "ExampleFiles/TestGarbage.bin");
|
HttpResponseMessage response = await this.UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/garbageTest", "ExampleFiles/TestGarbage.bin");
|
||||||
Assert.False(response.IsSuccessStatusCode);
|
Assert.False(response.IsSuccessStatusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ShouldAcceptTexture() {
|
public async Task ShouldAcceptTexture()
|
||||||
|
{
|
||||||
HttpResponseMessage response = await this.UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/textureTest", "ExampleFiles/TestTexture.tex");
|
HttpResponseMessage response = await this.UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/textureTest", "ExampleFiles/TestTexture.tex");
|
||||||
Assert.True(response.IsSuccessStatusCode);
|
Assert.True(response.IsSuccessStatusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ShouldAcceptLevel() {
|
public async Task ShouldAcceptLevel()
|
||||||
|
{
|
||||||
HttpResponseMessage response = await this.UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/levelTest", "ExampleFiles/TestLevel.lvl");
|
HttpResponseMessage response = await this.UploadFileRequest("/LITTLEBIGPLANETPS3_XML/upload/levelTest", "ExampleFiles/TestLevel.lvl");
|
||||||
Assert.True(response.IsSuccessStatusCode);
|
Assert.True(response.IsSuccessStatusCode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,81 @@
|
||||||
<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">
|
<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/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/=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/=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: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/=Braaains/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=brun/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=brun/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=ezoiar/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=ezoiar/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
@ -11,6 +84,7 @@
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=lbpme/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=lbpme/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=LBPU/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=LBPU/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=lolcatftw/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=lolcatftw/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=mmpick/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Swingy/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Swingy/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=thumbsup/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=thumbsup/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=unfavourite/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=unfavourite/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using LBPUnion.ProjectLighthouse.Types.Settings;
|
using LBPUnion.ProjectLighthouse.Types.Settings;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Controllers
|
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
|
@ -13,24 +14,20 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
[SuppressMessage("ReSharper", "StringLiteralTypo")]
|
[SuppressMessage("ReSharper", "StringLiteralTypo")]
|
||||||
public IActionResult NetworkSettings()
|
public IActionResult NetworkSettings()
|
||||||
{
|
{
|
||||||
var hostname = this.Request.Host;
|
HostString hostname = this.Request.Host;
|
||||||
return this.Ok(
|
return this.Ok
|
||||||
"ProbabilityOfPacketDelay 0.0\nMinPacketDelayFrames 0\nMaxPacketDelayFrames 3\nProbabilityOfPacketDrop 0.0\nEnableFakeConditionsForLoopback true\nNumberOfFramesPredictionAllowedForNonLocalPlayer 1000\nEnablePrediction true\nMinPredictedFrames 0\nMaxPredictedFrames 10\nAllowGameRendCameraSplit true\nFramesBeforeAgressiveCatchup 30\nPredictionPadSides 200\nPredictionPadTop 200\nPredictionPadBottom 200\nShowErrorNumbers true\nAllowModeratedLevels 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\n"
|
(
|
||||||
+ $"TelemetryServer {hostname}\nCDNHostName {hostname}");
|
"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\n" +
|
||||||
|
$"TelemetryServer {hostname}\nCDNHostName {hostname}"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("t_conf")]
|
[HttpGet("t_conf")]
|
||||||
[Produces("text/json")]
|
[Produces("text/json")]
|
||||||
public IActionResult Conf()
|
public IActionResult Conf() => this.Ok("[{\"StatusCode\":200}]");
|
||||||
{
|
|
||||||
return this.Ok("[{\"StatusCode\":200}]");
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("farc_hashes")]
|
[HttpGet("farc_hashes")]
|
||||||
public IActionResult FarcHashes()
|
public IActionResult FarcHashes() => this.Ok();
|
||||||
{
|
|
||||||
return this.Ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("privacySettings")]
|
[HttpGet("privacySettings")]
|
||||||
[Produces("text/xml")]
|
[Produces("text/xml")]
|
||||||
|
|
|
@ -3,28 +3,34 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
|
using LBPUnion.ProjectLighthouse.Helpers;
|
||||||
using LBPUnion.ProjectLighthouse.Serialization;
|
using LBPUnion.ProjectLighthouse.Serialization;
|
||||||
using LBPUnion.ProjectLighthouse.Types;
|
using LBPUnion.ProjectLighthouse.Types;
|
||||||
using LBPUnion.ProjectLighthouse.Types.Profiles;
|
using LBPUnion.ProjectLighthouse.Types.Profiles;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
|
{
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("LITTLEBIGPLANETPS3_XML/")]
|
[Route("LITTLEBIGPLANETPS3_XML/")]
|
||||||
[Produces("text/xml")]
|
[Produces("text/xml")]
|
||||||
public class CommentController : ControllerBase {
|
public class CommentController : ControllerBase
|
||||||
|
{
|
||||||
private readonly Database database;
|
private readonly Database database;
|
||||||
public CommentController(Database database) {
|
public CommentController(Database database)
|
||||||
|
{
|
||||||
this.database = database;
|
this.database = database;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("userComments/{username}")]
|
[HttpGet("userComments/{username}")]
|
||||||
public async Task<IActionResult> GetComments(string username) {
|
public async Task<IActionResult> GetComments(string username)
|
||||||
List<Comment> comments = await this.database.Comments
|
{
|
||||||
.Include(c => c.Target)
|
List<Comment> comments = await this.database.Comments.Include
|
||||||
|
(c => c.Target)
|
||||||
.Include(c => c.Poster)
|
.Include(c => c.Poster)
|
||||||
.Where(c => c.Target.Username == username)
|
.Where(c => c.Target.Username == username)
|
||||||
|
.OrderByDescending(c => c.Timestamp)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
string outputXml = comments.Aggregate(string.Empty, (current, comment) => current + comment.Serialize());
|
string outputXml = comments.Aggregate(string.Empty, (current, comment) => current + comment.Serialize());
|
||||||
|
@ -32,7 +38,8 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("postUserComment/{username}")]
|
[HttpPost("postUserComment/{username}")]
|
||||||
public async Task<IActionResult> PostComment(string username) {
|
public async Task<IActionResult> PostComment(string username)
|
||||||
|
{
|
||||||
this.Request.Body.Position = 0;
|
this.Request.Body.Position = 0;
|
||||||
string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync();
|
string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync();
|
||||||
|
|
||||||
|
@ -41,18 +48,36 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||||
|
|
||||||
User poster = await this.database.UserFromRequest(this.Request);
|
User poster = await this.database.UserFromRequest(this.Request);
|
||||||
|
|
||||||
if(poster == null) return this.StatusCode(403, "");
|
if (poster == null) return this.StatusCode(403, "");
|
||||||
|
|
||||||
User target = await this.database.Users.FirstOrDefaultAsync(u => u.Username == username);
|
User target = await this.database.Users.FirstOrDefaultAsync(u => u.Username == username);
|
||||||
|
|
||||||
if(comment == null || target == null) return this.BadRequest();
|
if (comment == null || target == null) return this.BadRequest();
|
||||||
|
|
||||||
comment.PosterUserId = poster.UserId;
|
comment.PosterUserId = poster.UserId;
|
||||||
comment.TargetUserId = target.UserId;
|
comment.TargetUserId = target.UserId;
|
||||||
|
|
||||||
|
comment.Timestamp = TimeHelper.UnixTimeMilliseconds();
|
||||||
|
|
||||||
this.database.Comments.Add(comment);
|
this.database.Comments.Add(comment);
|
||||||
await this.database.SaveChangesAsync();
|
await this.database.SaveChangesAsync();
|
||||||
return this.Ok();
|
return this.Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost("deleteUserComment/{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);
|
||||||
|
|
||||||
|
if (comment.TargetUserId != user.UserId && comment.PosterUserId != user.UserId) return this.StatusCode(403, "");
|
||||||
|
|
||||||
|
this.database.Comments.Remove(comment);
|
||||||
|
await this.database.SaveChangesAsync();
|
||||||
|
|
||||||
|
return this.Ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
using System.Threading.Tasks;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Controllers
|
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
{
|
{
|
||||||
|
@ -8,9 +7,6 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
public class DeveloperController : Controller
|
public class DeveloperController : Controller
|
||||||
{
|
{
|
||||||
[HttpGet("/developer_videos")]
|
[HttpGet("/developer_videos")]
|
||||||
public IActionResult DeveloperVideos()
|
public IActionResult DeveloperVideos() => this.Ok();
|
||||||
{
|
|
||||||
return this.Ok();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,13 +1,13 @@
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
|
{
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("LITTLEBIGPLANETPS3_XML/enterLevel")]
|
[Route("LITTLEBIGPLANETPS3_XML/enterLevel")]
|
||||||
// [Produces("text/plain")]
|
// [Produces("text/plain")]
|
||||||
public class EnterLevelController : ControllerBase {
|
public class EnterLevelController : ControllerBase
|
||||||
|
{
|
||||||
[HttpGet("enterLevel/{id}")]
|
[HttpGet("enterLevel/{id}")]
|
||||||
public IActionResult EnterLevel(string id) {
|
public IActionResult EnterLevel(string id) => this.Ok();
|
||||||
return this.Ok();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,17 +2,21 @@ using System;
|
||||||
using LBPUnion.ProjectLighthouse.Types.Levels;
|
using LBPUnion.ProjectLighthouse.Types.Levels;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
|
{
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("LITTLEBIGPLANETPS3_XML/tags")]
|
[Route("LITTLEBIGPLANETPS3_XML/tags")]
|
||||||
[Produces("text/plain")]
|
[Produces("text/plain")]
|
||||||
public class LevelTagsController : ControllerBase {
|
public class LevelTagsController : ControllerBase
|
||||||
|
{
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public IActionResult Get() {
|
public IActionResult Get()
|
||||||
|
{
|
||||||
string[] tags = Enum.GetNames(typeof(LevelTags));
|
string[] tags = Enum.GetNames(typeof(LevelTags));
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach(string tag in tags) {
|
foreach (string tag in tags)
|
||||||
|
{
|
||||||
tags[i] = $"TAG_{tag.Replace("_", "-")}";
|
tags[i] = $"TAG_{tag.Replace("_", "-")}";
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,23 +8,28 @@ using LBPUnion.ProjectLighthouse.Types.Levels;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
|
{
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("LITTLEBIGPLANETPS3_XML/")]
|
[Route("LITTLEBIGPLANETPS3_XML/")]
|
||||||
[Produces("text/xml")]
|
[Produces("text/xml")]
|
||||||
public class ListController : ControllerBase {
|
public class ListController : ControllerBase
|
||||||
|
{
|
||||||
private readonly Database database;
|
private readonly Database database;
|
||||||
public ListController(Database database) {
|
public ListController(Database database)
|
||||||
|
{
|
||||||
this.database = database;
|
this.database = database;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Levels
|
#region Levels
|
||||||
|
|
||||||
#region Level Queue (lolcatftw)
|
#region Level Queue (lolcatftw)
|
||||||
|
|
||||||
[HttpGet("slots/lolcatftw/{username}")]
|
[HttpGet("slots/lolcatftw/{username}")]
|
||||||
public IActionResult GetLevelQueue(string username) {
|
public IActionResult GetLevelQueue(string username)
|
||||||
IEnumerable<QueuedLevel> queuedLevels = new Database().QueuedLevels
|
{
|
||||||
.Include(q => q.User)
|
IEnumerable<QueuedLevel> queuedLevels = new Database().QueuedLevels.Include
|
||||||
|
(q => q.User)
|
||||||
.Include(q => q.Slot)
|
.Include(q => q.Slot)
|
||||||
.Include(q => q.Slot.Location)
|
.Include(q => q.Slot.Location)
|
||||||
.Where(q => q.User.Username == username)
|
.Where(q => q.User.Username == username)
|
||||||
|
@ -36,30 +41,36 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("lolcatftw/add/user/{id:int}")]
|
[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);
|
User? user = await this.database.UserFromRequest(this.Request);
|
||||||
if(user == null) return this.StatusCode(403, "");
|
if (user == null) return this.StatusCode(403, "");
|
||||||
|
|
||||||
QueuedLevel queuedLevel = await this.database.QueuedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == id);
|
QueuedLevel queuedLevel = await this.database.QueuedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == id);
|
||||||
if(queuedLevel != null) return this.Ok();
|
if (queuedLevel != null) return this.Ok();
|
||||||
|
|
||||||
this.database.QueuedLevels.Add(new QueuedLevel {
|
this.database.QueuedLevels.Add
|
||||||
SlotId = id,
|
(
|
||||||
UserId = user.UserId,
|
new QueuedLevel
|
||||||
});
|
{
|
||||||
|
SlotId = id,
|
||||||
|
UserId = user.UserId,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
await this.database.SaveChangesAsync();
|
await this.database.SaveChangesAsync();
|
||||||
|
|
||||||
return this.Ok();
|
return this.Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("lolcatftw/remove/user/{id:int}")]
|
[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);
|
User? user = await this.database.UserFromRequest(this.Request);
|
||||||
if(user == null) return this.StatusCode(403, "");
|
if (user == null) return this.StatusCode(403, "");
|
||||||
|
|
||||||
QueuedLevel queuedLevel = await this.database.QueuedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == id);
|
QueuedLevel queuedLevel = await this.database.QueuedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == id);
|
||||||
if(queuedLevel != null) this.database.QueuedLevels.Remove(queuedLevel);
|
if (queuedLevel != null) this.database.QueuedLevels.Remove(queuedLevel);
|
||||||
|
|
||||||
await this.database.SaveChangesAsync();
|
await this.database.SaveChangesAsync();
|
||||||
|
|
||||||
|
@ -71,9 +82,10 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||||
#region Hearted Levels
|
#region Hearted Levels
|
||||||
|
|
||||||
[HttpGet("favouriteSlots/{username}")]
|
[HttpGet("favouriteSlots/{username}")]
|
||||||
public IActionResult GetFavouriteSlots(string username) {
|
public IActionResult GetFavouriteSlots(string username)
|
||||||
IEnumerable<HeartedLevel> heartedLevels = new Database().HeartedLevels
|
{
|
||||||
.Include(q => q.User)
|
IEnumerable<HeartedLevel> heartedLevels = new Database().HeartedLevels.Include
|
||||||
|
(q => q.User)
|
||||||
.Include(q => q.Slot)
|
.Include(q => q.Slot)
|
||||||
.Include(q => q.Slot.Location)
|
.Include(q => q.Slot.Location)
|
||||||
.Include(q => q.Slot.Creator)
|
.Include(q => q.Slot.Creator)
|
||||||
|
@ -86,17 +98,22 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("favourite/slot/user/{id:int}")]
|
[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);
|
User? user = await this.database.UserFromRequest(this.Request);
|
||||||
if(user == null) return this.StatusCode(403, "");
|
if (user == null) return this.StatusCode(403, "");
|
||||||
|
|
||||||
HeartedLevel heartedLevel = await this.database.HeartedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == id);
|
HeartedLevel heartedLevel = await this.database.HeartedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == id);
|
||||||
if(heartedLevel != null) return this.Ok();
|
if (heartedLevel != null) return this.Ok();
|
||||||
|
|
||||||
this.database.HeartedLevels.Add(new HeartedLevel {
|
this.database.HeartedLevels.Add
|
||||||
SlotId = id,
|
(
|
||||||
UserId = user.UserId,
|
new HeartedLevel
|
||||||
});
|
{
|
||||||
|
SlotId = id,
|
||||||
|
UserId = user.UserId,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
await this.database.SaveChangesAsync();
|
await this.database.SaveChangesAsync();
|
||||||
|
|
||||||
|
@ -104,12 +121,13 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("unfavourite/slot/user/{id:int}")]
|
[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);
|
User? user = await this.database.UserFromRequest(this.Request);
|
||||||
if(user == null) return this.StatusCode(403, "");
|
if (user == null) return this.StatusCode(403, "");
|
||||||
|
|
||||||
HeartedLevel heartedLevel = await this.database.HeartedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == id);
|
HeartedLevel heartedLevel = await this.database.HeartedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == id);
|
||||||
if(heartedLevel != null) this.database.HeartedLevels.Remove(heartedLevel);
|
if (heartedLevel != null) this.database.HeartedLevels.Remove(heartedLevel);
|
||||||
|
|
||||||
await this.database.SaveChangesAsync();
|
await this.database.SaveChangesAsync();
|
||||||
|
|
||||||
|
@ -117,16 +135,16 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#endregion Levels
|
#endregion Levels
|
||||||
|
|
||||||
#region Users
|
#region Users
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[HttpGet("favouriteUsers/{username}")]
|
[HttpGet("favouriteUsers/{username}")]
|
||||||
public IActionResult GetFavouriteUsers(string username) {
|
public IActionResult GetFavouriteUsers(string username)
|
||||||
IEnumerable<HeartedProfile> heartedProfiles = new Database().HeartedProfiles
|
{
|
||||||
.Include(q => q.User)
|
IEnumerable<HeartedProfile> heartedProfiles = new Database().HeartedProfiles.Include
|
||||||
|
(q => q.User)
|
||||||
.Include(q => q.HeartedUser)
|
.Include(q => q.HeartedUser)
|
||||||
.Include(q => q.HeartedUser.Location)
|
.Include(q => q.HeartedUser.Location)
|
||||||
.Where(q => q.User.Username == username)
|
.Where(q => q.User.Username == username)
|
||||||
|
@ -136,42 +154,46 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||||
|
|
||||||
return this.Ok(LbpSerializer.TaggedStringElement("favouriteUsers", response, "total", 1));
|
return this.Ok(LbpSerializer.TaggedStringElement("favouriteUsers", response, "total", 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("favourite/user/{username}")]
|
[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);
|
User? user = await this.database.UserFromRequest(this.Request);
|
||||||
if(user == null) return this.StatusCode(403, "");
|
if (user == null) return this.StatusCode(403, "");
|
||||||
|
|
||||||
User? heartedUser = await this.database.Users
|
User? heartedUser = await this.database.Users.FirstOrDefaultAsync(u => u.Username == username);
|
||||||
.FirstOrDefaultAsync(u => u.Username == username);
|
if (heartedUser == null) return this.NotFound();
|
||||||
if(heartedUser == null) return this.NotFound();
|
|
||||||
|
|
||||||
HeartedProfile heartedProfile = await this.database.HeartedProfiles
|
HeartedProfile heartedProfile = await this.database.HeartedProfiles.FirstOrDefaultAsync
|
||||||
.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.HeartedUserId == heartedUser.UserId);
|
(q => q.UserId == user.UserId && q.HeartedUserId == heartedUser.UserId);
|
||||||
if(heartedProfile != null) return this.Ok();
|
if (heartedProfile != null) return this.Ok();
|
||||||
|
|
||||||
this.database.HeartedProfiles.Add(new HeartedProfile {
|
this.database.HeartedProfiles.Add
|
||||||
HeartedUserId = heartedUser.UserId,
|
(
|
||||||
UserId = user.UserId,
|
new HeartedProfile
|
||||||
});
|
{
|
||||||
|
HeartedUserId = heartedUser.UserId,
|
||||||
|
UserId = user.UserId,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
await this.database.SaveChangesAsync();
|
await this.database.SaveChangesAsync();
|
||||||
|
|
||||||
return this.Ok();
|
return this.Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("unfavourite/user/{username}")]
|
[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);
|
User? user = await this.database.UserFromRequest(this.Request);
|
||||||
if(user == null) return this.StatusCode(403, "");
|
if (user == null) return this.StatusCode(403, "");
|
||||||
|
|
||||||
User? heartedUser = await this.database.Users
|
User? heartedUser = await this.database.Users.FirstOrDefaultAsync(u => u.Username == username);
|
||||||
.FirstOrDefaultAsync(u => u.Username == username);
|
if (heartedUser == null) return this.NotFound();
|
||||||
if(heartedUser == null) return this.NotFound();
|
|
||||||
|
|
||||||
HeartedProfile heartedProfile = await this.database.HeartedProfiles
|
HeartedProfile heartedProfile = await this.database.HeartedProfiles.FirstOrDefaultAsync
|
||||||
.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.HeartedUserId == heartedUser.UserId);
|
(q => q.UserId == user.UserId && q.HeartedUserId == heartedUser.UserId);
|
||||||
if(heartedProfile != null) this.database.HeartedProfiles.Remove(heartedProfile);
|
if (heartedProfile != null) this.database.HeartedProfiles.Remove(heartedProfile);
|
||||||
|
|
||||||
await this.database.SaveChangesAsync();
|
await this.database.SaveChangesAsync();
|
||||||
|
|
||||||
|
@ -179,5 +201,6 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -24,25 +24,30 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
{
|
{
|
||||||
string body = await new StreamReader(this.Request.Body).ReadToEndAsync();
|
string body = await new StreamReader(this.Request.Body).ReadToEndAsync();
|
||||||
|
|
||||||
LoginData loginData;
|
LoginData? loginData;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
loginData = LoginData.CreateFromString(body);
|
loginData = LoginData.CreateFromString(body);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
return this.BadRequest();
|
loginData = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (loginData == null) return this.BadRequest();
|
||||||
|
|
||||||
Token? token = await this.database.AuthenticateUser(loginData);
|
Token? token = await this.database.AuthenticateUser(loginData);
|
||||||
|
|
||||||
if (token == null) return this.StatusCode(403, "");
|
if (token == null) return this.StatusCode(403, "");
|
||||||
|
|
||||||
return this.Ok(new LoginResult
|
return this.Ok
|
||||||
{
|
(
|
||||||
AuthTicket = "MM_AUTH=" + token.UserToken,
|
new LoginResult
|
||||||
LbpEnvVer = ServerSettings.ServerName,
|
{
|
||||||
}.Serialize());
|
AuthTicket = "MM_AUTH=" + token.UserToken,
|
||||||
|
LbpEnvVer = ServerSettings.ServerName,
|
||||||
|
}.Serialize()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -40,10 +40,10 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
|
|
||||||
string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync();
|
string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync();
|
||||||
if (bodyString.Contains("FindBestRoom"))
|
if (bodyString.Contains("FindBestRoom"))
|
||||||
{
|
return this.Ok
|
||||||
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\":[]}]");
|
"[{\"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[0] != '[') return this.BadRequest();
|
if (bodyString[0] != '[') return this.BadRequest();
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
{
|
{
|
||||||
matchData = MatchHelper.Deserialize(bodyString);
|
matchData = MatchHelper.Deserialize(bodyString);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
Logger.Log("Exception while parsing MatchData: " + e);
|
Logger.Log("Exception while parsing MatchData: " + e);
|
||||||
Logger.Log("Data: " + bodyString);
|
Logger.Log("Data: " + bodyString);
|
||||||
|
@ -66,8 +66,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
|
|
||||||
#region Update LastMatch
|
#region Update LastMatch
|
||||||
|
|
||||||
LastMatch? lastMatch = await this.database.LastMatches
|
LastMatch? lastMatch = await this.database.LastMatches.Where(l => l.UserId == user.UserId).FirstOrDefaultAsync();
|
||||||
.Where(l => l.UserId == user.UserId).FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
// below makes it not look like trash
|
// below makes it not look like trash
|
||||||
// ReSharper disable once ConvertIfStatementToNullCoalescingExpression
|
// ReSharper disable once ConvertIfStatementToNullCoalescingExpression
|
||||||
|
@ -88,16 +87,5 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
|
|
||||||
return this.Ok("[{\"StatusCode\":200}]");
|
return this.Ok("[{\"StatusCode\":200}]");
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("playersInPodCount")]
|
|
||||||
[HttpGet("totalPlayerCount")]
|
|
||||||
public async Task<IActionResult> TotalPlayerCount()
|
|
||||||
{
|
|
||||||
int recentMatches = await this.database.LastMatches
|
|
||||||
.Where(l => TimestampHelper.Timestamp - l.Timestamp < 60)
|
|
||||||
.CountAsync();
|
|
||||||
|
|
||||||
return this.Ok(recentMatches.ToString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,8 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Kettu;
|
||||||
|
using LBPUnion.ProjectLighthouse.Helpers;
|
||||||
|
using LBPUnion.ProjectLighthouse.Logging;
|
||||||
using LBPUnion.ProjectLighthouse.Types;
|
using LBPUnion.ProjectLighthouse.Types;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
@ -22,34 +25,36 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
{
|
{
|
||||||
User user = await this.database.UserFromRequest(this.Request);
|
User user = await this.database.UserFromRequest(this.Request);
|
||||||
return user == null
|
return user == null
|
||||||
? this.Forbid()
|
? this.StatusCode(403, "")
|
||||||
: this.Ok($"You are now logged in as user {user.Username} (id {user.UserId}).\n" +
|
: this.Ok
|
||||||
"This is a private testing instance. Please do not make anything public for now, and keep in mind security isn't as tight as a full release would.");
|
(
|
||||||
|
$"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"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("announce")]
|
[HttpGet("announce")]
|
||||||
public async Task<IActionResult> Announce()
|
public IActionResult Announce() => this.Ok("");
|
||||||
{
|
|
||||||
User user = await this.database.UserFromRequest(this.Request);
|
|
||||||
return user == null
|
|
||||||
? this.Forbid()
|
|
||||||
: this.Ok($"You are now logged in as user {user.Username} (id {user.UserId}).\n" +
|
|
||||||
"This is a private testing instance. Please do not make anything public for now, and keep in mind security isn't as tight as a full release would.");
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("notification")]
|
[HttpGet("notification")]
|
||||||
public IActionResult Notification()
|
public IActionResult Notification() => this.Ok();
|
||||||
{
|
|
||||||
return this.Ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Filters chat messages sent by a user.
|
/// Filters chat messages sent by a user.
|
||||||
|
/// The reponse sent is the text that will appear in-game.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HttpPost("filter")]
|
[HttpPost("filter")]
|
||||||
public async Task<IActionResult> Filter()
|
public async Task<IActionResult> Filter()
|
||||||
{
|
{
|
||||||
return this.Ok(await new StreamReader(this.Request.Body).ReadToEndAsync());
|
User user = await this.database.UserFromRequest(this.Request);
|
||||||
|
if (user == null) return this.StatusCode(403, "");
|
||||||
|
|
||||||
|
string loggedText = await new StreamReader(this.Request.Body).ReadToEndAsync();
|
||||||
|
|
||||||
|
Logger.Log($"{user.Username}: {loggedText}", LoggerLevelFilter.Instance);
|
||||||
|
return this.Ok(loggedText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
using System.Threading.Tasks;
|
|
||||||
using LBPUnion.ProjectLighthouse.Serialization;
|
using LBPUnion.ProjectLighthouse.Serialization;
|
||||||
using LBPUnion.ProjectLighthouse.Types.News;
|
using LBPUnion.ProjectLighthouse.Types.News;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
@ -13,20 +12,24 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public IActionResult Get()
|
public IActionResult Get()
|
||||||
{
|
{
|
||||||
string newsEntry = LbpSerializer.StringElement("item", new NewsEntry
|
string newsEntry = LbpSerializer.StringElement
|
||||||
{
|
(
|
||||||
Category = "no_category",
|
"item",
|
||||||
Summary = "test summary",
|
new NewsEntry
|
||||||
Image = new NewsImage
|
|
||||||
{
|
{
|
||||||
Hash = "4947269c5f7061b27225611ee58a9a91a8031bbe",
|
Category = "no_category",
|
||||||
Alignment = "right",
|
Summary = "test summary",
|
||||||
},
|
Image = new NewsImage
|
||||||
Id = 1,
|
{
|
||||||
Title = "Test Title",
|
Hash = "4947269c5f7061b27225611ee58a9a91a8031bbe",
|
||||||
Text = "Test Text",
|
Alignment = "right",
|
||||||
Date = 1348755214000,
|
},
|
||||||
}.Serialize());
|
Id = 1,
|
||||||
|
Title = "Test Title",
|
||||||
|
Text = "Test Text",
|
||||||
|
Date = 1348755214000,
|
||||||
|
}.Serialize()
|
||||||
|
);
|
||||||
|
|
||||||
return this.Ok(LbpSerializer.StringElement("news", newsEntry));
|
return this.Ok(LbpSerializer.StringElement("news", newsEntry));
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,64 +10,102 @@ using LBPUnion.ProjectLighthouse.Types.Profiles;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
|
{
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("LITTLEBIGPLANETPS3_XML/")]
|
[Route("LITTLEBIGPLANETPS3_XML/")]
|
||||||
[Produces("text/xml")]
|
[Produces("text/xml")]
|
||||||
public class PublishController : ControllerBase {
|
public class PublishController : ControllerBase
|
||||||
|
{
|
||||||
private readonly Database database;
|
private readonly Database database;
|
||||||
|
|
||||||
public PublishController(Database database) {
|
public PublishController(Database database)
|
||||||
|
{
|
||||||
this.database = database;
|
this.database = database;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Endpoint the game uses to verify that the level is compatible (?)
|
/// Endpoint the game uses to check what resources need to be uploaded and if the level can be uploaded
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HttpPost("startPublish")]
|
[HttpPost("startPublish")]
|
||||||
public async Task<IActionResult> StartPublish() {
|
public async Task<IActionResult> StartPublish()
|
||||||
Slot slot = await this.GetSlotFromBody();
|
{
|
||||||
if(slot == null) return this.BadRequest(); // if the level cant be parsed then it obviously cant be uploaded
|
User user = await this.database.UserFromRequest(this.Request);
|
||||||
|
if (user == null) return this.StatusCode(403, "");
|
||||||
|
|
||||||
string resources = slot.Resources
|
Slot slot = await this.GetSlotFromBody();
|
||||||
.Where(hash => !FileHelper.ResourceExists(hash))
|
if (slot == null) return this.BadRequest(); // if the level cant be parsed then it obviously cant be uploaded
|
||||||
.Aggregate("", (current, hash) =>
|
|
||||||
current + LbpSerializer.StringElement("resource", hash));
|
// Republish logic
|
||||||
|
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));
|
||||||
|
|
||||||
return this.Ok(LbpSerializer.TaggedStringElement("slot", resources, "type", "user"));
|
return this.Ok(LbpSerializer.TaggedStringElement("slot", resources, "type", "user"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Endpoint actually used to publish a level
|
/// Endpoint actually used to publish a level
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HttpPost("publish")]
|
[HttpPost("publish")]
|
||||||
public async Task<IActionResult> Publish() {
|
public async Task<IActionResult> Publish()
|
||||||
|
{
|
||||||
User user = await this.database.UserFromRequest(this.Request);
|
User user = await this.database.UserFromRequest(this.Request);
|
||||||
if(user == null) return this.StatusCode(403, "");
|
if (user == null) return this.StatusCode(403, "");
|
||||||
|
|
||||||
Slot slot = await this.GetSlotFromBody();
|
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 (oldSlot == null) return this.NotFound();
|
||||||
|
if (oldSlot.CreatorId != user.UserId) return this.BadRequest();
|
||||||
|
|
||||||
|
oldSlot.Location.X = slot.Location.X;
|
||||||
|
oldSlot.Location.Y = slot.Location.Y;
|
||||||
|
|
||||||
|
slot.CreatorId = oldSlot.CreatorId;
|
||||||
|
slot.LocationId = oldSlot.LocationId;
|
||||||
|
slot.SlotId = oldSlot.SlotId;
|
||||||
|
slot.FirstUploaded = oldSlot.FirstUploaded;
|
||||||
|
slot.LastUpdated = TimeHelper.UnixTimeMilliseconds();
|
||||||
|
|
||||||
|
this.database.Entry(oldSlot).CurrentValues.SetValues(slot);
|
||||||
|
await this.database.SaveChangesAsync();
|
||||||
|
return this.Ok(oldSlot.Serialize());
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: parse location in body
|
//TODO: parse location in body
|
||||||
Location l = new() {
|
Location l = new()
|
||||||
X = 0,
|
{
|
||||||
Y = 0,
|
X = slot.Location.X,
|
||||||
|
Y = slot.Location.Y,
|
||||||
};
|
};
|
||||||
this.database.Locations.Add(l);
|
this.database.Locations.Add(l);
|
||||||
await this.database.SaveChangesAsync();
|
await this.database.SaveChangesAsync();
|
||||||
slot.LocationId = l.Id;
|
slot.LocationId = l.Id;
|
||||||
slot.CreatorId = user.UserId;
|
slot.CreatorId = user.UserId;
|
||||||
|
slot.FirstUploaded = TimeHelper.UnixTimeMilliseconds();
|
||||||
|
slot.LastUpdated = TimeHelper.UnixTimeMilliseconds();
|
||||||
|
|
||||||
this.database.Slots.Add(slot);
|
this.database.Slots.Add(slot);
|
||||||
await this.database.SaveChangesAsync();
|
await this.database.SaveChangesAsync();
|
||||||
|
|
||||||
return this.Ok(slot.Serialize());
|
return this.Ok(slot.Serialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("unpublish/{id:int}")]
|
[HttpPost("unpublish/{id:int}")]
|
||||||
public async Task<IActionResult> Unpublish(int id) {
|
public async Task<IActionResult> Unpublish(int id)
|
||||||
Slot slot = await this.database.Slots
|
{
|
||||||
.Include(s => s.Location)
|
Slot slot = await this.database.Slots.Include(s => s.Location).FirstOrDefaultAsync(s => s.SlotId == id);
|
||||||
.FirstOrDefaultAsync(s => s.SlotId == id);
|
|
||||||
|
|
||||||
this.database.Locations.Remove(slot.Location);
|
this.database.Locations.Remove(slot.Location);
|
||||||
this.database.Slots.Remove(slot);
|
this.database.Slots.Remove(slot);
|
||||||
|
@ -76,8 +114,9 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||||
|
|
||||||
return this.Ok();
|
return this.Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Slot> GetSlotFromBody() {
|
public async Task<Slot> GetSlotFromBody()
|
||||||
|
{
|
||||||
this.Request.Body.Position = 0;
|
this.Request.Body.Position = 0;
|
||||||
string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync();
|
string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync();
|
||||||
|
|
||||||
|
|
|
@ -18,10 +18,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
public class ResourcesController : ControllerBase
|
public class ResourcesController : ControllerBase
|
||||||
{
|
{
|
||||||
[HttpPost("showModerated")]
|
[HttpPost("showModerated")]
|
||||||
public IActionResult ShowModerated()
|
public IActionResult ShowModerated() => this.Ok(LbpSerializer.BlankElement("resources"));
|
||||||
{
|
|
||||||
return this.Ok(LbpSerializer.BlankElement("resources"));
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("filterResources")]
|
[HttpPost("filterResources")]
|
||||||
[HttpPost("showNotUploaded")]
|
[HttpPost("showNotUploaded")]
|
||||||
|
@ -30,14 +27,13 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync();
|
string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync();
|
||||||
|
|
||||||
XmlSerializer serializer = new(typeof(ResourceList));
|
XmlSerializer serializer = new(typeof(ResourceList));
|
||||||
ResourceList resourceList = (ResourceList) serializer.Deserialize(new StringReader(bodyString));
|
ResourceList resourceList = (ResourceList)serializer.Deserialize(new StringReader(bodyString));
|
||||||
|
|
||||||
if (resourceList == null) return this.BadRequest();
|
if (resourceList == null) return this.BadRequest();
|
||||||
|
|
||||||
string resources = resourceList.Resources
|
string resources = resourceList.Resources.Where
|
||||||
.Where(s => !FileHelper.ResourceExists(s))
|
(s => !FileHelper.ResourceExists(s))
|
||||||
.Aggregate("", (current, hash) =>
|
.Aggregate("", (current, hash) => current + LbpSerializer.StringElement("resource", hash));
|
||||||
current + LbpSerializer.StringElement("resource", hash));
|
|
||||||
|
|
||||||
return this.Ok(LbpSerializer.StringElement("resources", resources));
|
return this.Ok(LbpSerializer.StringElement("resources", resources));
|
||||||
}
|
}
|
||||||
|
@ -47,10 +43,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
{
|
{
|
||||||
string path = FileHelper.GetResourcePath(hash);
|
string path = FileHelper.GetResourcePath(hash);
|
||||||
|
|
||||||
if (FileHelper.ResourceExists(hash))
|
if (FileHelper.ResourceExists(hash)) return this.File(IOFile.OpenRead(path), "application/octet-stream");
|
||||||
{
|
|
||||||
return this.File(IOFile.OpenRead(path), "application/octet-stream");
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.NotFound();
|
return this.NotFound();
|
||||||
}
|
}
|
||||||
|
@ -68,7 +61,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
if (FileHelper.ResourceExists(hash)) this.Ok(); // no reason to fail if it's already uploaded
|
if (FileHelper.ResourceExists(hash)) this.Ok(); // no reason to fail if it's already uploaded
|
||||||
|
|
||||||
Logger.Log($"Processing resource upload (hash: {hash})");
|
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();
|
if (!FileHelper.IsFileSafe(file)) return this.UnprocessableEntity();
|
||||||
|
|
||||||
|
|
|
@ -6,18 +6,24 @@ using LBPUnion.ProjectLighthouse.Types.Levels;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
|
{
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("LITTLEBIGPLANETPS3_XML/")]
|
[Route("LITTLEBIGPLANETPS3_XML/")]
|
||||||
[Produces("text/xml")]
|
[Produces("text/xml")]
|
||||||
public class SearchController : ControllerBase {
|
public class SearchController : ControllerBase
|
||||||
|
{
|
||||||
private readonly Database database;
|
private readonly Database database;
|
||||||
public SearchController(Database database) {
|
public SearchController(Database database)
|
||||||
|
{
|
||||||
this.database = database;
|
this.database = database;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("slots/search")]
|
[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();
|
query = query.ToLower();
|
||||||
|
|
||||||
string[] keywords = query.Split(" ");
|
string[] keywords = query.Split(" ");
|
||||||
|
@ -26,16 +32,16 @@ namespace LBPUnion.ProjectLighthouse.Controllers {
|
||||||
.Include(s => s.Creator)
|
.Include(s => s.Creator)
|
||||||
.Include(s => s.Location)
|
.Include(s => s.Location)
|
||||||
.Where(s => s.SlotId >= 0); // dumb query to conv into IQueryable
|
.Where(s => s.SlotId >= 0); // dumb query to conv into IQueryable
|
||||||
|
|
||||||
// ReSharper disable once LoopCanBeConvertedToQuery
|
// ReSharper disable once LoopCanBeConvertedToQuery
|
||||||
foreach(string keyword in keywords) {
|
foreach (string keyword in keywords)
|
||||||
dbQuery = dbQuery.Where(s =>
|
dbQuery = dbQuery.Where
|
||||||
s.Name.ToLower().Contains(keyword) ||
|
(
|
||||||
s.Description.ToLower().Contains(keyword) ||
|
s => s.Name.ToLower().Contains(keyword) ||
|
||||||
s.Creator.Username.ToLower().Contains(keyword) ||
|
s.Description.ToLower().Contains(keyword) ||
|
||||||
s.SlotId.ToString().Equals(keyword)
|
s.Creator.Username.ToLower().Contains(keyword) ||
|
||||||
|
s.SlotId.ToString().Equals(keyword)
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
List<Slot> slots = await dbQuery.ToListAsync();
|
List<Slot> slots = await dbQuery.ToListAsync();
|
||||||
string response = slots.Aggregate("", (current, slot) => current + slot.Serialize());
|
string response = slots.Aggregate("", (current, slot) => current + slot.Serialize());
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using LBPUnion.ProjectLighthouse.Serialization;
|
using LBPUnion.ProjectLighthouse.Serialization;
|
||||||
|
@ -5,35 +6,54 @@ using LBPUnion.ProjectLighthouse.Types.Levels;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Controllers {
|
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
|
{
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("LITTLEBIGPLANETPS3_XML/")]
|
[Route("LITTLEBIGPLANETPS3_XML/")]
|
||||||
[Produces("text/xml")]
|
[Produces("text/xml")]
|
||||||
public class SlotsController : ControllerBase {
|
public class SlotsController : ControllerBase
|
||||||
|
{
|
||||||
private readonly Database database;
|
private readonly Database database;
|
||||||
public SlotsController(Database database) {
|
public SlotsController(Database database)
|
||||||
|
{
|
||||||
this.database = database;
|
this.database = database;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("slots/by")]
|
[HttpGet("slots/by")]
|
||||||
public IActionResult SlotsBy([FromQuery] string u) {
|
public IActionResult SlotsBy([FromQuery] string u)
|
||||||
string response = Enumerable.Aggregate(
|
{
|
||||||
this.database.Slots
|
string response = Enumerable.Aggregate
|
||||||
.Include(s => s.Creator)
|
(
|
||||||
.Include(s => s.Location)
|
this.database.Slots.Include(s => s.Creator).Include(s => s.Location).Where(s => s.Creator.Username == u),
|
||||||
.Where(s => s.Creator.Username == u)
|
string.Empty,
|
||||||
, string.Empty, (current, slot) => current + slot.Serialize());
|
(current, slot) => current + slot.Serialize()
|
||||||
|
);
|
||||||
|
|
||||||
return this.Ok(LbpSerializer.TaggedStringElement("slots", response, "total", 1));
|
return this.Ok(LbpSerializer.TaggedStringElement("slots", response, "total", 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IActionResult> SUser(int id) {
|
[HttpGet("s/user/{id:int}")]
|
||||||
Slot slot = await this.database.Slots
|
public async Task<IActionResult> SUser(int id)
|
||||||
.Include(s => s.Creator)
|
{
|
||||||
.Include(s => s.Location)
|
Slot slot = await this.database.Slots.Include(s => s.Creator).Include(s => s.Location).FirstOrDefaultAsync(s => s.SlotId == id);
|
||||||
.FirstOrDefaultAsync(s => s.SlotId == id);
|
|
||||||
|
if (slot == null) return this.NotFound();
|
||||||
|
|
||||||
return this.Ok(slot.Serialize());
|
return this.Ok(slot.Serialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("slots")]
|
||||||
|
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)
|
||||||
|
.Take(Math.Min(pageSize, 30));
|
||||||
|
string response = Enumerable.Aggregate(slots, string.Empty, (current, slot) => current + slot.Serialize());
|
||||||
|
|
||||||
|
return this.Ok(LbpSerializer.TaggedStringElement("slots", response, "hint_start", pageStart + Math.Min(pageSize, 30)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
43
ProjectLighthouse/Controllers/StatisticsController.cs
Normal file
43
ProjectLighthouse/Controllers/StatisticsController.cs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using LBPUnion.ProjectLighthouse.Helpers;
|
||||||
|
using LBPUnion.ProjectLighthouse.Serialization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
|
{
|
||||||
|
[ApiController]
|
||||||
|
[Route("LITTLEBIGPLANETPS3_XML/")]
|
||||||
|
[Produces("text/plain")]
|
||||||
|
public class StatisticsController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly 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();
|
||||||
|
|
||||||
|
return this.Ok(recentMatches.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("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))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
using System.Threading.Tasks;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Controllers
|
namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
{
|
{
|
||||||
|
@ -9,9 +8,6 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
public class StoreController : Controller
|
public class StoreController : Controller
|
||||||
{
|
{
|
||||||
[HttpGet("promotions")]
|
[HttpGet("promotions")]
|
||||||
public IActionResult Promotions()
|
public IActionResult Promotions() => this.Ok();
|
||||||
{
|
|
||||||
return Ok();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -25,25 +25,18 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
[HttpGet("user/{username}")]
|
[HttpGet("user/{username}")]
|
||||||
public async Task<IActionResult> GetUser(string username)
|
public async Task<IActionResult> GetUser(string username)
|
||||||
{
|
{
|
||||||
User user = await this.database.Users
|
User user = await this.database.Users.Include(u => u.Location).FirstOrDefaultAsync(u => u.Username == username);
|
||||||
.Include(u => u.Location)
|
|
||||||
.FirstOrDefaultAsync(u => u.Username == username);
|
|
||||||
|
|
||||||
if (user == null) return this.NotFound();
|
if (user == null) return this.NotFound();
|
||||||
|
|
||||||
return this.Ok(user.Serialize());
|
return this.Ok(user.Serialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("user/{username}/playlists")]
|
[HttpGet("users")]
|
||||||
public IActionResult GetUserPlaylists(string username)
|
public async Task<IActionResult> GetUserAlt([FromQuery] string u) => await this.GetUser(u);
|
||||||
{
|
|
||||||
return this.Ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
// [HttpPost("user/{username}")]
|
[HttpGet("user/{username}/playlists")]
|
||||||
// public async Task<IActionResult> CreateUser(string username) {
|
public IActionResult GetUserPlaylists(string username) => this.Ok();
|
||||||
// await new Database().CreateUser(username);
|
|
||||||
// return await GetUser(username);
|
|
||||||
// }
|
|
||||||
|
|
||||||
[HttpPost("updateUser")]
|
[HttpPost("updateUser")]
|
||||||
public async Task<IActionResult> UpdateUser()
|
public async Task<IActionResult> UpdateUser()
|
||||||
|
@ -77,11 +70,8 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
// if you find a way to make it not stupid feel free to replace this
|
// 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>
|
List<string> path = new(); // you can think of this as a file path in the XML, like <updateUser> -> <location> -> <x>
|
||||||
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
|
||||||
while (await reader.ReadAsync())
|
|
||||||
{
|
|
||||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
|
||||||
switch (reader.NodeType)
|
switch (reader.NodeType)
|
||||||
{
|
{
|
||||||
case XmlNodeType.Element:
|
case XmlNodeType.Element:
|
||||||
|
@ -97,21 +87,12 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
}
|
}
|
||||||
case "location":
|
case "location":
|
||||||
{
|
{
|
||||||
locationChanged =
|
locationChanged = true; // if we're here then we're probably about to change the location.
|
||||||
true; // if we're here then we're probably about to change the location.
|
|
||||||
// ReSharper disable once ConvertIfStatementToSwitchStatement
|
// ReSharper disable once ConvertIfStatementToSwitchStatement
|
||||||
if (path[2] == "x")
|
if (path[2] == "x")
|
||||||
{
|
user.Location.X = Convert.ToInt32
|
||||||
user.Location.X =
|
(await reader.GetValueAsync()); // GetValue only returns a string, i guess we just hope its a number lol
|
||||||
Convert.ToInt32(
|
else if (path[2] == "y") user.Location.Y = Convert.ToInt32(await reader.GetValueAsync());
|
||||||
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;
|
break;
|
||||||
}
|
}
|
||||||
case "icon":
|
case "icon":
|
||||||
|
@ -131,14 +112,12 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
path.RemoveAt(path.Count - 1);
|
path.RemoveAt(path.Count - 1);
|
||||||
break;
|
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:
|
// 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)
|
Location l = await this.database.Locations.Where(l => l.Id == user.LocationId).FirstOrDefaultAsync(); // find the location in the database again
|
||||||
.FirstOrDefaultAsync(); // find the location in the database again
|
|
||||||
|
|
||||||
// set the location in the database to the one we modified above
|
// set the location in the database to the one we modified above
|
||||||
l.X = user.Location.X;
|
l.X = user.Location.X;
|
||||||
|
@ -147,8 +126,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
||||||
// now both are in sync, and will update in the database.
|
// now both are in sync, and will update in the database.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.database.ChangeTracker.HasChanges())
|
if (this.database.ChangeTracker.HasChanges()) await this.database.SaveChangesAsync(); // save the user to the database if we changed anything
|
||||||
await this.database.SaveChangesAsync(); // save the user to the database if we changed anything
|
|
||||||
return this.Ok();
|
return this.Ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,16 +23,13 @@ namespace LBPUnion.ProjectLighthouse
|
||||||
|
|
||||||
public DbSet<LastMatch> LastMatches { get; set; }
|
public DbSet<LastMatch> LastMatches { get; set; }
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseMySql(
|
protected override void OnConfiguring(DbContextOptionsBuilder options)
|
||||||
ServerSettings.DbConnectionString,
|
=> options.UseMySql(ServerSettings.DbConnectionString, MySqlServerVersion.LatestSupportedServerVersion);
|
||||||
MySqlServerVersion.LatestSupportedServerVersion
|
|
||||||
);
|
|
||||||
|
|
||||||
public async Task<User> CreateUser(string username)
|
public async Task<User> CreateUser(string username)
|
||||||
{
|
{
|
||||||
User user;
|
User user;
|
||||||
if ((user = await this.Users.Where(u => u.Username == username).FirstOrDefaultAsync()) != null)
|
if ((user = await this.Users.Where(u => u.Username == username).FirstOrDefaultAsync()) != null) return user;
|
||||||
return user;
|
|
||||||
|
|
||||||
Location l = new(); // store to get id after submitting
|
Location l = new(); // store to get id after submitting
|
||||||
this.Locations.Add(l); // add to table
|
this.Locations.Add(l); // add to table
|
||||||
|
@ -51,12 +48,11 @@ namespace LBPUnion.ProjectLighthouse
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
#nullable enable
|
#nullable enable
|
||||||
public async Task<Token?> AuthenticateUser(LoginData loginData)
|
public async Task<Token?> AuthenticateUser(LoginData loginData)
|
||||||
{
|
{
|
||||||
// TODO: don't use psn name to authenticate
|
// TODO: don't use psn name to authenticate
|
||||||
User user = await this.Users.FirstOrDefaultAsync(u => u.Username == loginData.Username)
|
User user = await this.Users.FirstOrDefaultAsync(u => u.Username == loginData.Username) ?? await this.CreateUser(loginData.Username);
|
||||||
?? await this.CreateUser(loginData.Username);
|
|
||||||
|
|
||||||
Token token = new()
|
Token token = new()
|
||||||
{
|
{
|
||||||
|
@ -74,20 +70,16 @@ namespace LBPUnion.ProjectLighthouse
|
||||||
{
|
{
|
||||||
Token? token = await this.Tokens.FirstOrDefaultAsync(t => t.UserToken == authToken);
|
Token? token = await this.Tokens.FirstOrDefaultAsync(t => t.UserToken == authToken);
|
||||||
if (token == null) return null;
|
if (token == null) return null;
|
||||||
return await this.Users
|
|
||||||
.Include(u => u.Location)
|
return await this.Users.Include(u => u.Location).FirstOrDefaultAsync(u => u.UserId == token.UserId);
|
||||||
.FirstOrDefaultAsync(u => u.UserId == token.UserId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<User?> UserFromRequest(HttpRequest request)
|
public async Task<User?> UserFromRequest(HttpRequest request)
|
||||||
{
|
{
|
||||||
if (!request.Cookies.TryGetValue("MM_AUTH", out string? mmAuth) || mmAuth == null)
|
if (!request.Cookies.TryGetValue("MM_AUTH", out string? mmAuth) || mmAuth == null) return null;
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.UserFromAuthToken(mmAuth);
|
return await this.UserFromAuthToken(mmAuth);
|
||||||
}
|
}
|
||||||
#nullable disable
|
#nullable disable
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,17 +2,20 @@ using System;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Helpers {
|
namespace LBPUnion.ProjectLighthouse.Helpers
|
||||||
|
{
|
||||||
// Yoinked from https://stackoverflow.com/a/68530667
|
// Yoinked from https://stackoverflow.com/a/68530667
|
||||||
// Thanks to T-moty!
|
// Thanks to T-moty!
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allows synchronous stream operations for this request.
|
/// Allows synchronous stream operations for this request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||||
public class AllowSynchronousIoAttribute : ActionFilterAttribute {
|
public class AllowSynchronousIoAttribute : ActionFilterAttribute
|
||||||
public override void OnResultExecuting(ResultExecutingContext context) {
|
{
|
||||||
|
public override void OnResultExecuting(ResultExecutingContext context)
|
||||||
|
{
|
||||||
IHttpBodyControlFeature syncIoFeature = context.HttpContext.Features.Get<IHttpBodyControlFeature>();
|
IHttpBodyControlFeature syncIoFeature = context.HttpContext.Features.Get<IHttpBodyControlFeature>();
|
||||||
if(syncIoFeature != null) syncIoFeature.AllowSynchronousIO = true;
|
if (syncIoFeature != null) syncIoFeature.AllowSynchronousIO = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,52 +6,57 @@ using System.IO.Pipelines;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Helpers {
|
namespace LBPUnion.ProjectLighthouse.Helpers
|
||||||
public static class BinaryHelper {
|
{
|
||||||
public static string ReadString(BinaryReader reader) {
|
public static class BinaryHelper
|
||||||
|
{
|
||||||
|
public static string ReadString(BinaryReader reader)
|
||||||
|
{
|
||||||
List<byte> readBytes = new();
|
List<byte> readBytes = new();
|
||||||
|
|
||||||
byte readByte;
|
byte readByte;
|
||||||
do {
|
do readBytes.Add(readByte = reader.ReadByte());
|
||||||
readBytes.Add(readByte = reader.ReadByte());
|
while (readByte != 0x00);
|
||||||
} while(readByte != 0x00);
|
|
||||||
|
|
||||||
return Encoding.UTF8.GetString(readBytes.ToArray());
|
return Encoding.UTF8.GetString(readBytes.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ReadUntilByte(BinaryReader reader, byte byteToReadTo) {
|
public static void ReadUntilByte(BinaryReader reader, byte byteToReadTo)
|
||||||
|
{
|
||||||
byte readByte;
|
byte readByte;
|
||||||
do {
|
do readByte = reader.ReadByte();
|
||||||
readByte = reader.ReadByte();
|
while (readByte != byteToReadTo);
|
||||||
} 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;
|
long oldPosition = reader.BaseStream.Position;
|
||||||
|
|
||||||
if(reader.BaseStream.Length < count) return Array.Empty<byte>();
|
if (reader.BaseStream.Length < count) return Array.Empty<byte>();
|
||||||
|
|
||||||
reader.BaseStream.Position = reader.BaseStream.Length - count;
|
reader.BaseStream.Position = reader.BaseStream.Length - count;
|
||||||
byte[] data = reader.ReadBytes(count);
|
byte[] data = reader.ReadBytes(count);
|
||||||
|
|
||||||
if(restoreOldPosition) reader.BaseStream.Position = oldPosition;
|
if (restoreOldPosition) reader.BaseStream.Position = oldPosition;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Written with reference from
|
// Written with reference from
|
||||||
// https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/request-response?view=aspnetcore-5.0
|
// 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)
|
// 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();
|
List<byte> data = new();
|
||||||
while(true) {
|
while (true)
|
||||||
|
{
|
||||||
ReadResult readResult = await reader.ReadAsync();
|
ReadResult readResult = await reader.ReadAsync();
|
||||||
ReadOnlySequence<byte> buffer = readResult.Buffer;
|
ReadOnlySequence<byte> buffer = readResult.Buffer;
|
||||||
|
|
||||||
if(readResult.IsCompleted && buffer.Length > 0) data.AddRange(buffer.ToArray());
|
if (readResult.IsCompleted && buffer.Length > 0) data.AddRange(buffer.ToArray());
|
||||||
|
|
||||||
reader.AdvanceTo(buffer.Start, buffer.End);
|
reader.AdvanceTo(buffer.Start, buffer.End);
|
||||||
|
|
||||||
if(readResult.IsCompleted) break;
|
if (readResult.IsCompleted) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return data.ToArray();
|
return data.ToArray();
|
||||||
|
|
24
ProjectLighthouse/Helpers/EulaHelper.cs
Normal file
24
ProjectLighthouse/Helpers/EulaHelper.cs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
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
|
||||||
|
published by the Free Software Foundation, either version 3 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.";
|
||||||
|
|
||||||
|
public const string PrivateInstanceNotice = @"This server is a private testing instance.
|
||||||
|
Please do not make anything public for now, and keep in mind security isn't as tight as a full release would.";
|
||||||
|
|
||||||
|
public const bool ShowPrivateInstanceNotice = false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,17 +3,23 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Helpers.Extensions {
|
namespace LBPUnion.ProjectLighthouse.Helpers.Extensions
|
||||||
|
{
|
||||||
// https://stackoverflow.com/a/8039737
|
// https://stackoverflow.com/a/8039737
|
||||||
public static class ExceptionExtensions {
|
public static class ExceptionExtensions
|
||||||
public static string ToDetailedException(this Exception exception) {
|
{
|
||||||
|
public static string ToDetailedException(this Exception exception)
|
||||||
|
{
|
||||||
PropertyInfo[] properties = exception.GetType().GetProperties();
|
PropertyInfo[] properties = exception.GetType().GetProperties();
|
||||||
|
|
||||||
IEnumerable<string> fields = properties
|
IEnumerable<string> fields = properties.Select
|
||||||
.Select(property => new {
|
(
|
||||||
property.Name,
|
property => new
|
||||||
Value = property.GetValue(exception, null),
|
{
|
||||||
})
|
property.Name,
|
||||||
|
Value = property.GetValue(exception, null),
|
||||||
|
}
|
||||||
|
)
|
||||||
.Select(x => $"{x.Name} = {(x.Value != null ? x.Value.ToString() : string.Empty)}");
|
.Select(x => $"{x.Name} = {(x.Value != null ? x.Value.ToString() : string.Empty)}");
|
||||||
|
|
||||||
return string.Join("\n", fields);
|
return string.Join("\n", fields);
|
||||||
|
|
|
@ -4,17 +4,22 @@ using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using LBPUnion.ProjectLighthouse.Types.Files;
|
using LBPUnion.ProjectLighthouse.Types.Files;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Helpers {
|
namespace LBPUnion.ProjectLighthouse.Helpers
|
||||||
public static class FileHelper {
|
{
|
||||||
|
public static class FileHelper
|
||||||
|
{
|
||||||
public static readonly string ResourcePath = Path.Combine(Environment.CurrentDirectory, "r");
|
public static readonly string ResourcePath = Path.Combine(Environment.CurrentDirectory, "r");
|
||||||
|
|
||||||
public static string GetResourcePath(string hash) => Path.Combine(ResourcePath, hash);
|
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);
|
{
|
||||||
|
if (file.FileType == LbpFileType.Unknown) file.FileType = DetermineFileType(file.Data);
|
||||||
return file.FileType switch {
|
|
||||||
|
return file.FileType switch
|
||||||
|
{
|
||||||
LbpFileType.FileArchive => false,
|
LbpFileType.FileArchive => false,
|
||||||
|
LbpFileType.Painting => true,
|
||||||
LbpFileType.Unknown => false,
|
LbpFileType.Unknown => false,
|
||||||
LbpFileType.Texture => true,
|
LbpFileType.Texture => true,
|
||||||
LbpFileType.Script => false,
|
LbpFileType.Script => false,
|
||||||
|
@ -29,16 +34,19 @@ namespace LBPUnion.ProjectLighthouse.Helpers {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LbpFileType DetermineFileType(byte[] data) {
|
public static LbpFileType DetermineFileType(byte[] data)
|
||||||
|
{
|
||||||
using MemoryStream ms = new(data);
|
using MemoryStream ms = new(data);
|
||||||
using BinaryReader reader = new(ms);
|
using BinaryReader reader = new(ms);
|
||||||
|
|
||||||
string footer = Encoding.ASCII.GetString(BinaryHelper.ReadLastBytes(reader, 4));
|
string footer = Encoding.ASCII.GetString(BinaryHelper.ReadLastBytes(reader, 4));
|
||||||
if(footer == "FARC") return LbpFileType.FileArchive;
|
if (footer == "FARC") return LbpFileType.FileArchive;
|
||||||
|
|
||||||
byte[] header = reader.ReadBytes(3);
|
byte[] header = reader.ReadBytes(3);
|
||||||
|
|
||||||
return Encoding.ASCII.GetString(header) switch {
|
return Encoding.ASCII.GetString(header) switch
|
||||||
|
{
|
||||||
|
"PTG" => LbpFileType.Painting,
|
||||||
"TEX" => LbpFileType.Texture,
|
"TEX" => LbpFileType.Texture,
|
||||||
"FSH" => LbpFileType.Script,
|
"FSH" => LbpFileType.Script,
|
||||||
"VOP" => LbpFileType.Voice,
|
"VOP" => LbpFileType.Voice,
|
||||||
|
@ -50,8 +58,9 @@ namespace LBPUnion.ProjectLighthouse.Helpers {
|
||||||
|
|
||||||
public static bool ResourceExists(string hash) => File.Exists(GetResourcePath(hash));
|
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)));
|
{
|
||||||
|
if (!Directory.Exists(path)) Directory.CreateDirectory(path ?? throw new ArgumentNullException(nameof(path)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string[] ResourcesNotUploaded(params string[] hashes) => hashes.Where(hash => !ResourceExists(hash)).ToArray();
|
public static string[] ResourcesNotUploaded(params string[] hashes) => hashes.Where(hash => !ResourceExists(hash)).ToArray();
|
||||||
|
|
|
@ -6,32 +6,22 @@ using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Helpers {
|
namespace LBPUnion.ProjectLighthouse.Helpers
|
||||||
|
{
|
||||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||||
public static class HashHelper {
|
public static class HashHelper
|
||||||
|
{
|
||||||
// private static readonly SHA1 sha1 = SHA1.Create();
|
// private static readonly SHA1 sha1 = SHA1.Create();
|
||||||
private static readonly SHA256 sha256 = SHA256.Create();
|
private static readonly SHA256 sha256 = SHA256.Create();
|
||||||
private static readonly Random random = new();
|
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>
|
/// <summary>
|
||||||
/// Generates a specified amount of random bytes in an array.
|
/// Generates a specified amount of random bytes in an array.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="count">The amount of bytes to generate.</param>
|
/// <param name="count">The amount of bytes to generate.</param>
|
||||||
/// <returns>The bytes generated</returns>
|
/// <returns>The bytes generated</returns>
|
||||||
public static IEnumerable<byte> GenerateRandomBytes(int count) {
|
public static IEnumerable<byte> GenerateRandomBytes(int count)
|
||||||
|
{
|
||||||
byte[] b = new byte[count];
|
byte[] b = new byte[count];
|
||||||
random.NextBytes(b);
|
random.NextBytes(b);
|
||||||
|
|
||||||
|
@ -39,34 +29,31 @@ namespace LBPUnion.ProjectLighthouse.Helpers {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generates a random SHA256 & BCrypted token
|
/// Generates a random SHA256 & BCrypted token
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The token as a string.</returns>
|
/// <returns>The token as a string.</returns>
|
||||||
public static string GenerateAuthToken() {
|
public static string GenerateAuthToken()
|
||||||
byte[] bytes = (byte[]) GenerateRandomBytes(256);
|
{
|
||||||
|
byte[] bytes = (byte[])GenerateRandomBytes(256);
|
||||||
|
|
||||||
return BCryptHash(Sha256Hash(bytes));
|
return BCryptHash(Sha256Hash(bytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<string> ComputeDigest(string path, string authCookie, Stream body,
|
public static async Task<string> ComputeDigest(string path, string authCookie, Stream body, string digestKey)
|
||||||
string digestKey)
|
|
||||||
{
|
{
|
||||||
MemoryStream memoryStream = new MemoryStream();
|
MemoryStream memoryStream = new();
|
||||||
|
|
||||||
byte[] pathBytes = Encoding.UTF8.GetBytes(path);
|
byte[] pathBytes = Encoding.UTF8.GetBytes(path);
|
||||||
byte[] cookieBytes = string.IsNullOrEmpty(authCookie)
|
byte[] cookieBytes = string.IsNullOrEmpty(authCookie) ? Array.Empty<byte>() : Encoding.UTF8.GetBytes(authCookie);
|
||||||
? Array.Empty<byte>()
|
|
||||||
: Encoding.UTF8.GetBytes(authCookie);
|
|
||||||
byte[] keyBytes = Encoding.UTF8.GetBytes(digestKey);
|
byte[] keyBytes = Encoding.UTF8.GetBytes(digestKey);
|
||||||
|
|
||||||
await body.CopyToAsync(memoryStream);
|
await body.CopyToAsync(memoryStream);
|
||||||
|
|
||||||
byte[] bodyBytes = memoryStream.ToArray();
|
byte[] bodyBytes = memoryStream.ToArray();
|
||||||
|
|
||||||
using IncrementalHash sha1 = IncrementalHash.CreateHash(HashAlgorithmName.SHA1);
|
using IncrementalHash sha1 = IncrementalHash.CreateHash(HashAlgorithmName.SHA1);
|
||||||
sha1.AppendData(bodyBytes);
|
sha1.AppendData(bodyBytes);
|
||||||
if (cookieBytes.Length > 0)
|
if (cookieBytes.Length > 0) sha1.AppendData(cookieBytes);
|
||||||
sha1.AppendData(cookieBytes);
|
|
||||||
sha1.AppendData(pathBytes);
|
sha1.AppendData(pathBytes);
|
||||||
sha1.AppendData(keyBytes);
|
sha1.AppendData(keyBytes);
|
||||||
|
|
||||||
|
@ -75,5 +62,22 @@ namespace LBPUnion.ProjectLighthouse.Helpers {
|
||||||
|
|
||||||
return digestString;
|
return digestString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
13
ProjectLighthouse/Helpers/TimeHelper.cs
Normal file
13
ProjectLighthouse/Helpers/TimeHelper.cs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace LBPUnion.ProjectLighthouse.Helpers
|
||||||
|
{
|
||||||
|
public static class TimeHelper
|
||||||
|
{
|
||||||
|
public static long UnixTimeMilliseconds() => DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
||||||
|
public static long UnixTimeSeconds() => DateTimeOffset.Now.ToUnixTimeSeconds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1397109686193
|
||||||
|
// 1635389749454
|
|
@ -1,7 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Helpers {
|
namespace LBPUnion.ProjectLighthouse.Helpers
|
||||||
public static class TimestampHelper {
|
{
|
||||||
|
public static class TimestampHelper
|
||||||
|
{
|
||||||
public static long Timestamp => (long)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
|
public static long Timestamp => (long)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,32 +3,23 @@ using Kettu;
|
||||||
using LBPUnion.ProjectLighthouse.Helpers.Extensions;
|
using LBPUnion.ProjectLighthouse.Helpers.Extensions;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Logging {
|
namespace LBPUnion.ProjectLighthouse.Logging
|
||||||
public class AspNetToKettuLogger : ILogger {
|
{
|
||||||
|
public class AspNetToKettuLogger : ILogger
|
||||||
|
{
|
||||||
|
|
||||||
public IDisposable BeginScope<TState>(TState state) {
|
public IDisposable BeginScope<TState>(TState state) => NullScope.Instance;
|
||||||
return NullScope.Instance;
|
|
||||||
}
|
|
||||||
public bool IsEnabled(LogLevel logLevel) => true;
|
public bool IsEnabled(LogLevel logLevel) => true;
|
||||||
|
|
||||||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) {
|
|
||||||
LoggerLevel loggerLevel = logLevel switch {
|
|
||||||
|
|
||||||
LogLevel.Trace => LoggerLevelAspNetTrace.Instance,
|
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
|
||||||
LogLevel.Debug => LoggerLevelAspNetDebug.Instance,
|
{
|
||||||
LogLevel.Information => LoggerLevelAspNetInformation.Instance,
|
LoggerLevel loggerLevel = new LoggerLevelAspNet(logLevel);
|
||||||
LogLevel.Warning => LoggerLevelAspNetWarning.Instance,
|
|
||||||
LogLevel.Error => LoggerLevelAspNetError.Instance,
|
|
||||||
LogLevel.Critical => LoggerLevelAspNetCritical.Instance,
|
|
||||||
LogLevel.None => LoggerLevelAspNetNone.Instance,
|
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(logLevel), logLevel, null),
|
|
||||||
};
|
|
||||||
|
|
||||||
Logger.Log(state.ToString(), loggerLevel);
|
Logger.Log(state.ToString(), loggerLevel);
|
||||||
if(exception == null) return;
|
if (exception == null) return;
|
||||||
|
|
||||||
string[] lines = exception.ToDetailedException().Replace("\r", "").Split("\n");
|
string[] lines = exception.ToDetailedException().Replace("\r", "").Split("\n");
|
||||||
foreach(string line in lines) Logger.Log(line, loggerLevel);
|
foreach (string line in lines) Logger.Log(line, loggerLevel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,15 +1,16 @@
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Logging {
|
namespace LBPUnion.ProjectLighthouse.Logging
|
||||||
|
{
|
||||||
[ProviderAlias("Kettu")]
|
[ProviderAlias("Kettu")]
|
||||||
public class AspNetToKettuLoggerProvider : ILoggerProvider, IDisposable {
|
public class AspNetToKettuLoggerProvider : ILoggerProvider, IDisposable
|
||||||
public void Dispose() {
|
{
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ILogger CreateLogger(string categoryName) {
|
public ILogger CreateLogger(string categoryName) => new AspNetToKettuLogger();
|
||||||
return new AspNetToKettuLogger();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,16 +3,23 @@ using System.IO;
|
||||||
using Kettu;
|
using Kettu;
|
||||||
using LBPUnion.ProjectLighthouse.Helpers;
|
using LBPUnion.ProjectLighthouse.Helpers;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Logging {
|
namespace LBPUnion.ProjectLighthouse.Logging
|
||||||
public class LighthouseFileLogger : LoggerBase {
|
{
|
||||||
|
public class LighthouseFileLogger : LoggerBase
|
||||||
|
{
|
||||||
private static readonly string logsDirectory = Path.Combine(Environment.CurrentDirectory, "logs");
|
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);
|
FileHelper.EnsureDirectoryCreated(logsDirectory);
|
||||||
|
|
||||||
File.AppendAllText(Path.Combine(logsDirectory, line.LoggerLevel + ".log"), line.LineData + "\n");
|
string channel = string.IsNullOrEmpty(line.LoggerLevel.Channel) ? "" : $"[{line.LoggerLevel.Channel}] ";
|
||||||
File.AppendAllText(Path.Combine(logsDirectory, "all.log"), line.LineData + "\n");
|
|
||||||
|
string contentFile = $"{channel}{line.LineData}\n";
|
||||||
|
string contentAll = $"[{$"{line.LoggerLevel.Name} {channel}".TrimEnd()}] {line.LineData}\n";
|
||||||
|
|
||||||
|
File.AppendAllText(Path.Combine(logsDirectory, line.LoggerLevel.Name + ".log"), contentFile);
|
||||||
|
File.AppendAllText(Path.Combine(logsDirectory, "all.log"), contentAll);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,55 +1,39 @@
|
||||||
using Kettu;
|
using Kettu;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Logging {
|
namespace LBPUnion.ProjectLighthouse.Logging
|
||||||
public class LoggerLevelStartup : LoggerLevel {
|
{
|
||||||
public override string Name => "Startup";
|
public class LoggerLevelStartup : LoggerLevel
|
||||||
|
{
|
||||||
public static readonly LoggerLevelStartup Instance = new();
|
public static readonly LoggerLevelStartup Instance = new();
|
||||||
|
public override string Name => "Startup";
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LoggerLevelDatabase : LoggerLevel {
|
public class LoggerLevelDatabase : LoggerLevel
|
||||||
public override string Name => "Database";
|
{
|
||||||
public static readonly LoggerLevelDatabase Instance = new();
|
public static readonly LoggerLevelDatabase Instance = new();
|
||||||
|
public override string Name => "Database";
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LoggerLevelHttp : LoggerLevel {
|
public class LoggerLevelHttp : LoggerLevel
|
||||||
public override string Name => "HTTP";
|
{
|
||||||
public static readonly LoggerLevelHttp Instance = new();
|
public static readonly LoggerLevelHttp Instance = new();
|
||||||
|
public override string Name => "HTTP";
|
||||||
}
|
}
|
||||||
|
|
||||||
#region ASP.NET
|
public class LoggerLevelFilter : LoggerLevel
|
||||||
public class LoggerLevelAspNetTrace : LoggerLevel {
|
{
|
||||||
public override string Name => "ASP.NET: Trace";
|
public static readonly LoggerLevelFilter Instance = new();
|
||||||
public static readonly LoggerLevelAspNetTrace Instance = new();
|
public override string Name => "Filter";
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LoggerLevelAspNetDebug : LoggerLevel {
|
public class LoggerLevelAspNet : LoggerLevel
|
||||||
public override string Name => "ASP.NET: Debug";
|
{
|
||||||
public static readonly LoggerLevelAspNetDebug Instance = new();
|
|
||||||
|
public LoggerLevelAspNet(LogLevel level)
|
||||||
|
{
|
||||||
|
this.Channel = level.ToString();
|
||||||
|
}
|
||||||
|
public override string Name => "AspNet";
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LoggerLevelAspNetInformation : LoggerLevel {
|
|
||||||
public override string Name => "ASP.NET: Information";
|
|
||||||
public static readonly LoggerLevelAspNetInformation Instance = new();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LoggerLevelAspNetWarning : LoggerLevel {
|
|
||||||
public override string Name => "ASP.NET: Warning";
|
|
||||||
public static readonly LoggerLevelAspNetWarning Instance = new();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LoggerLevelAspNetError : LoggerLevel {
|
|
||||||
public override string Name => "ASP.NET: Error";
|
|
||||||
public static readonly LoggerLevelAspNetError Instance = new();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LoggerLevelAspNetCritical : LoggerLevel {
|
|
||||||
public override string Name => "ASP.NET: Critical";
|
|
||||||
public static readonly LoggerLevelAspNetCritical Instance = new();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LoggerLevelAspNetNone : LoggerLevel {
|
|
||||||
public override string Name => "ASP.NET: None";
|
|
||||||
public static readonly LoggerLevelAspNetNone Instance = new();
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
|
@ -1,12 +1,16 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Logging {
|
namespace LBPUnion.ProjectLighthouse.Logging
|
||||||
public class NullScope : IDisposable{
|
{
|
||||||
|
public class NullScope : IDisposable
|
||||||
|
{
|
||||||
|
|
||||||
|
private NullScope()
|
||||||
|
{}
|
||||||
public static NullScope Instance { get; } = new();
|
public static NullScope Instance { get; } = new();
|
||||||
|
|
||||||
private NullScope() {}
|
public void Dispose()
|
||||||
|
{
|
||||||
public void Dispose() {
|
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
421
ProjectLighthouse/Migrations/20211028015915_AddSlotTimestamp.Designer.cs
generated
Normal file
421
ProjectLighthouse/Migrations/20211028015915_AddSlotTimestamp.Designer.cs
generated
Normal file
|
@ -0,0 +1,421 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using LBPUnion.ProjectLighthouse;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
namespace ProjectLighthouse.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(Database))]
|
||||||
|
[Migration("20211028015915_AddSlotTimestamp")]
|
||||||
|
partial class AddSlotTimestamp
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64)
|
||||||
|
.HasAnnotation("ProductVersion", "5.0.11");
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("HeartedProfileId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("HeartedUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("HeartedProfileId");
|
||||||
|
|
||||||
|
b.HasIndex("HeartedUserId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("HeartedProfiles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("HeartedLevelId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("SlotId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("HeartedLevelId");
|
||||||
|
|
||||||
|
b.HasIndex("SlotId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("HeartedLevels");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("QueuedLevelId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("SlotId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("QueuedLevelId");
|
||||||
|
|
||||||
|
b.HasIndex("SlotId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("QueuedLevels");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("SlotId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("AuthorLabels")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("BackgroundHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("CreatorId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("IconHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("InitiallyLocked")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<bool>("Lbp1Only")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("LocationId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MaximumPlayers")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MinimumPlayers")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("MoveRequired")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("ResourceCollection")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("RootLevel")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("Shareable")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("SubLevel")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<long>("Timestamp")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.HasKey("SlotId");
|
||||||
|
|
||||||
|
b.HasIndex("CreatorId");
|
||||||
|
|
||||||
|
b.HasIndex("LocationId");
|
||||||
|
|
||||||
|
b.ToTable("Slots");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("CommentId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("PosterUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("TargetUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ThumbsDown")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ThumbsUp")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Timestamp")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.HasKey("CommentId");
|
||||||
|
|
||||||
|
b.HasIndex("PosterUserId");
|
||||||
|
|
||||||
|
b.HasIndex("TargetUserId");
|
||||||
|
|
||||||
|
b.ToTable("Comments");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.LastMatch", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Timestamp")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.HasKey("UserId");
|
||||||
|
|
||||||
|
b.ToTable("LastMatches");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Location", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("X")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Y")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Locations");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("TokenId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("UserToken")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("TokenId");
|
||||||
|
|
||||||
|
b.ToTable("Tokens");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Biography")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("BooHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("CommentCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("CommentsEnabled")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("FavouriteSlotCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("FavouriteUserCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Game")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("HeartCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("IconHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("Lists")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("LocationId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("LolCatFtwCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("PhotosByMeCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("PhotosWithMeCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Pins")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("PlanetHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("ReviewCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("StaffChallengeBronzeCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("StaffChallengeGoldCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("StaffChallengeSilverCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UsedSlots")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("YayHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("UserId");
|
||||||
|
|
||||||
|
b.HasIndex("LocationId");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "HeartedUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("HeartedUserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("HeartedUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("SlotId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Slot");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("SlotId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Slot");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CreatorId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("LocationId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Creator");
|
||||||
|
|
||||||
|
b.Navigation("Location");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Poster")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("PosterUserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Target")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("TargetUserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Poster");
|
||||||
|
|
||||||
|
b.Navigation("Target");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("LocationId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Location");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
using LBPUnion.ProjectLighthouse.Helpers;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace ProjectLighthouse.Migrations
|
||||||
|
{
|
||||||
|
public partial class AddSlotTimestamp : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<long>(
|
||||||
|
name: "Timestamp",
|
||||||
|
table: "Slots",
|
||||||
|
type: "bigint",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: TimeHelper.UnixTimeMilliseconds());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "Timestamp",
|
||||||
|
table: "Slots");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
424
ProjectLighthouse/Migrations/20211028021513_AddSlotFirstUploadedAndLastUpdated.Designer.cs
generated
Normal file
424
ProjectLighthouse/Migrations/20211028021513_AddSlotFirstUploadedAndLastUpdated.Designer.cs
generated
Normal file
|
@ -0,0 +1,424 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using LBPUnion.ProjectLighthouse;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
namespace ProjectLighthouse.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(Database))]
|
||||||
|
[Migration("20211028021513_AddSlotFirstUploadedAndLastUpdated")]
|
||||||
|
partial class AddSlotFirstUploadedAndLastUpdated
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64)
|
||||||
|
.HasAnnotation("ProductVersion", "5.0.11");
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("HeartedProfileId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("HeartedUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("HeartedProfileId");
|
||||||
|
|
||||||
|
b.HasIndex("HeartedUserId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("HeartedProfiles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("HeartedLevelId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("SlotId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("HeartedLevelId");
|
||||||
|
|
||||||
|
b.HasIndex("SlotId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("HeartedLevels");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("QueuedLevelId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("SlotId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("QueuedLevelId");
|
||||||
|
|
||||||
|
b.HasIndex("SlotId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("QueuedLevels");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("SlotId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("AuthorLabels")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("BackgroundHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("CreatorId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<long>("FirstUploaded")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("IconHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("InitiallyLocked")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<long>("LastUpdated")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<bool>("Lbp1Only")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("LocationId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MaximumPlayers")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MinimumPlayers")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("MoveRequired")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("ResourceCollection")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("RootLevel")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("Shareable")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("SubLevel")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.HasKey("SlotId");
|
||||||
|
|
||||||
|
b.HasIndex("CreatorId");
|
||||||
|
|
||||||
|
b.HasIndex("LocationId");
|
||||||
|
|
||||||
|
b.ToTable("Slots");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("CommentId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("PosterUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("TargetUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ThumbsDown")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ThumbsUp")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Timestamp")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.HasKey("CommentId");
|
||||||
|
|
||||||
|
b.HasIndex("PosterUserId");
|
||||||
|
|
||||||
|
b.HasIndex("TargetUserId");
|
||||||
|
|
||||||
|
b.ToTable("Comments");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.LastMatch", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Timestamp")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.HasKey("UserId");
|
||||||
|
|
||||||
|
b.ToTable("LastMatches");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Location", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("X")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Y")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Locations");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("TokenId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("UserToken")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("TokenId");
|
||||||
|
|
||||||
|
b.ToTable("Tokens");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Biography")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("BooHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("CommentCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("CommentsEnabled")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("FavouriteSlotCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("FavouriteUserCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Game")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("HeartCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("IconHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("Lists")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("LocationId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("LolCatFtwCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("PhotosByMeCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("PhotosWithMeCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Pins")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("PlanetHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("ReviewCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("StaffChallengeBronzeCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("StaffChallengeGoldCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("StaffChallengeSilverCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UsedSlots")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("YayHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("UserId");
|
||||||
|
|
||||||
|
b.HasIndex("LocationId");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "HeartedUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("HeartedUserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("HeartedUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("SlotId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Slot");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("SlotId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Slot");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CreatorId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("LocationId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Creator");
|
||||||
|
|
||||||
|
b.Navigation("Location");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Poster")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("PosterUserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Target")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("TargetUserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Poster");
|
||||||
|
|
||||||
|
b.Navigation("Target");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("LocationId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Location");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
using LBPUnion.ProjectLighthouse.Helpers;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace ProjectLighthouse.Migrations
|
||||||
|
{
|
||||||
|
public partial class AddSlotFirstUploadedAndLastUpdated : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "Timestamp",
|
||||||
|
table: "Slots",
|
||||||
|
newName: "LastUpdated");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<long>(
|
||||||
|
name: "FirstUploaded",
|
||||||
|
table: "Slots",
|
||||||
|
type: "bigint",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: TimeHelper.UnixTimeMilliseconds());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "FirstUploaded",
|
||||||
|
table: "Slots");
|
||||||
|
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "LastUpdated",
|
||||||
|
table: "Slots",
|
||||||
|
newName: "Timestamp");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
421
ProjectLighthouse/Migrations/20211029213334_RemoveUsedSlotsFromDb.Designer.cs
generated
Normal file
421
ProjectLighthouse/Migrations/20211029213334_RemoveUsedSlotsFromDb.Designer.cs
generated
Normal file
|
@ -0,0 +1,421 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using LBPUnion.ProjectLighthouse;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
namespace ProjectLighthouse.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(Database))]
|
||||||
|
[Migration("20211029213334_RemoveUsedSlotsFromDb")]
|
||||||
|
partial class RemoveUsedSlotsFromDb
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64)
|
||||||
|
.HasAnnotation("ProductVersion", "5.0.11");
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("HeartedProfileId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("HeartedUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("HeartedProfileId");
|
||||||
|
|
||||||
|
b.HasIndex("HeartedUserId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("HeartedProfiles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("HeartedLevelId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("SlotId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("HeartedLevelId");
|
||||||
|
|
||||||
|
b.HasIndex("SlotId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("HeartedLevels");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("QueuedLevelId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("SlotId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("QueuedLevelId");
|
||||||
|
|
||||||
|
b.HasIndex("SlotId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("QueuedLevels");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("SlotId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("AuthorLabels")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("BackgroundHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("CreatorId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<long>("FirstUploaded")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("IconHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("InitiallyLocked")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<long>("LastUpdated")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<bool>("Lbp1Only")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("LocationId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MaximumPlayers")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MinimumPlayers")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("MoveRequired")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("ResourceCollection")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("RootLevel")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("Shareable")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("SubLevel")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.HasKey("SlotId");
|
||||||
|
|
||||||
|
b.HasIndex("CreatorId");
|
||||||
|
|
||||||
|
b.HasIndex("LocationId");
|
||||||
|
|
||||||
|
b.ToTable("Slots");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("CommentId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("PosterUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("TargetUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ThumbsDown")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ThumbsUp")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Timestamp")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.HasKey("CommentId");
|
||||||
|
|
||||||
|
b.HasIndex("PosterUserId");
|
||||||
|
|
||||||
|
b.HasIndex("TargetUserId");
|
||||||
|
|
||||||
|
b.ToTable("Comments");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.LastMatch", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Timestamp")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.HasKey("UserId");
|
||||||
|
|
||||||
|
b.ToTable("LastMatches");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Location", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("X")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Y")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Locations");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("TokenId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("UserToken")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("TokenId");
|
||||||
|
|
||||||
|
b.ToTable("Tokens");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Biography")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("BooHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("CommentCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("CommentsEnabled")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("FavouriteSlotCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("FavouriteUserCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Game")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("HeartCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("IconHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("Lists")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("LocationId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("LolCatFtwCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("PhotosByMeCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("PhotosWithMeCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Pins")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("PlanetHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("ReviewCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("StaffChallengeBronzeCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("StaffChallengeGoldCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("StaffChallengeSilverCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("YayHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("UserId");
|
||||||
|
|
||||||
|
b.HasIndex("LocationId");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "HeartedUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("HeartedUserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("HeartedUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("SlotId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Slot");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("SlotId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Slot");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CreatorId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("LocationId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Creator");
|
||||||
|
|
||||||
|
b.Navigation("Location");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Poster")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("PosterUserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Target")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("TargetUserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Poster");
|
||||||
|
|
||||||
|
b.Navigation("Target");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("LocationId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Location");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace ProjectLighthouse.Migrations
|
||||||
|
{
|
||||||
|
public partial class RemoveUsedSlotsFromDb : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "UsedSlots",
|
||||||
|
table: "Users");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "UsedSlots",
|
||||||
|
table: "Users",
|
||||||
|
type: "int",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
424
ProjectLighthouse/Migrations/20211030203837_AddMMPickToSlot.Designer.cs
generated
Normal file
424
ProjectLighthouse/Migrations/20211030203837_AddMMPickToSlot.Designer.cs
generated
Normal file
|
@ -0,0 +1,424 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using LBPUnion.ProjectLighthouse;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
namespace ProjectLighthouse.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(Database))]
|
||||||
|
[Migration("20211030203837_AddMMPickToSlot")]
|
||||||
|
partial class AddMMPickToSlot
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64)
|
||||||
|
.HasAnnotation("ProductVersion", "5.0.11");
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("HeartedProfileId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("HeartedUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("HeartedProfileId");
|
||||||
|
|
||||||
|
b.HasIndex("HeartedUserId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("HeartedProfiles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("HeartedLevelId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("SlotId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("HeartedLevelId");
|
||||||
|
|
||||||
|
b.HasIndex("SlotId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("HeartedLevels");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("QueuedLevelId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("SlotId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("QueuedLevelId");
|
||||||
|
|
||||||
|
b.HasIndex("SlotId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("QueuedLevels");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("SlotId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("AuthorLabels")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("BackgroundHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("CreatorId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<long>("FirstUploaded")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("IconHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("InitiallyLocked")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<long>("LastUpdated")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<bool>("Lbp1Only")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("LocationId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("MMPick")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("MaximumPlayers")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MinimumPlayers")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("MoveRequired")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("ResourceCollection")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("RootLevel")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("Shareable")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("SubLevel")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.HasKey("SlotId");
|
||||||
|
|
||||||
|
b.HasIndex("CreatorId");
|
||||||
|
|
||||||
|
b.HasIndex("LocationId");
|
||||||
|
|
||||||
|
b.ToTable("Slots");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("CommentId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("PosterUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("TargetUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ThumbsDown")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ThumbsUp")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Timestamp")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.HasKey("CommentId");
|
||||||
|
|
||||||
|
b.HasIndex("PosterUserId");
|
||||||
|
|
||||||
|
b.HasIndex("TargetUserId");
|
||||||
|
|
||||||
|
b.ToTable("Comments");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.LastMatch", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Timestamp")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.HasKey("UserId");
|
||||||
|
|
||||||
|
b.ToTable("LastMatches");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Location", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("X")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Y")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Locations");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("TokenId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("UserToken")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("TokenId");
|
||||||
|
|
||||||
|
b.ToTable("Tokens");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Biography")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("BooHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("CommentCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("CommentsEnabled")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("FavouriteSlotCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("FavouriteUserCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Game")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("HeartCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("IconHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("Lists")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("LocationId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("LolCatFtwCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("PhotosByMeCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("PhotosWithMeCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Pins")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("PlanetHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("ReviewCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("StaffChallengeBronzeCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("StaffChallengeGoldCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("StaffChallengeSilverCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("YayHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("UserId");
|
||||||
|
|
||||||
|
b.HasIndex("LocationId");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "HeartedUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("HeartedUserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("HeartedUser");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("SlotId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Slot");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("SlotId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Slot");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CreatorId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("LocationId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Creator");
|
||||||
|
|
||||||
|
b.Navigation("Location");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Poster")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("PosterUserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Target")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("TargetUserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Poster");
|
||||||
|
|
||||||
|
b.Navigation("Target");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("LocationId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Location");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace ProjectLighthouse.Migrations
|
||||||
|
{
|
||||||
|
public partial class AddMMPickToSlot : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "MMPick",
|
||||||
|
table: "Slots",
|
||||||
|
type: "tinyint(1)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "MMPick",
|
||||||
|
table: "Slots");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -97,18 +97,27 @@ namespace ProjectLighthouse.Migrations
|
||||||
b.Property<string>("Description")
|
b.Property<string>("Description")
|
||||||
.HasColumnType("longtext");
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<long>("FirstUploaded")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
b.Property<string>("IconHash")
|
b.Property<string>("IconHash")
|
||||||
.HasColumnType("longtext");
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
b.Property<bool>("InitiallyLocked")
|
b.Property<bool>("InitiallyLocked")
|
||||||
.HasColumnType("tinyint(1)");
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<long>("LastUpdated")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
b.Property<bool>("Lbp1Only")
|
b.Property<bool>("Lbp1Only")
|
||||||
.HasColumnType("tinyint(1)");
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
b.Property<int>("LocationId")
|
b.Property<int>("LocationId")
|
||||||
.HasColumnType("int");
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("MMPick")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
b.Property<int>("MaximumPlayers")
|
b.Property<int>("MaximumPlayers")
|
||||||
.HasColumnType("int");
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
@ -289,9 +298,6 @@ namespace ProjectLighthouse.Migrations
|
||||||
b.Property<int>("StaffChallengeSilverCount")
|
b.Property<int>("StaffChallengeSilverCount")
|
||||||
.HasColumnType("int");
|
.HasColumnType("int");
|
||||||
|
|
||||||
b.Property<int>("UsedSlots")
|
|
||||||
.HasColumnType("int");
|
|
||||||
|
|
||||||
b.Property<string>("Username")
|
b.Property<string>("Username")
|
||||||
.HasColumnType("longtext");
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
using Kettu;
|
using Kettu;
|
||||||
|
using LBPUnion.ProjectLighthouse.Helpers;
|
||||||
using LBPUnion.ProjectLighthouse.Logging;
|
using LBPUnion.ProjectLighthouse.Logging;
|
||||||
|
using LBPUnion.ProjectLighthouse.Types.Levels;
|
||||||
|
using LBPUnion.ProjectLighthouse.Types.Profiles;
|
||||||
using LBPUnion.ProjectLighthouse.Types.Settings;
|
using LBPUnion.ProjectLighthouse.Types.Settings;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
@ -17,8 +21,8 @@ namespace LBPUnion.ProjectLighthouse
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
// Log startup time
|
// Log startup time
|
||||||
Stopwatch startupStopwatch = new();
|
Stopwatch stopwatch = new();
|
||||||
startupStopwatch.Start();
|
stopwatch.Start();
|
||||||
|
|
||||||
// Setup logging
|
// Setup logging
|
||||||
|
|
||||||
|
@ -30,39 +34,67 @@ namespace LBPUnion.ProjectLighthouse
|
||||||
Logger.Log("Welcome to Project Lighthouse!", LoggerLevelStartup.Instance);
|
Logger.Log("Welcome to Project Lighthouse!", LoggerLevelStartup.Instance);
|
||||||
Logger.Log("Determining if the database is available...", LoggerLevelStartup.Instance);
|
Logger.Log("Determining if the database is available...", LoggerLevelStartup.Instance);
|
||||||
bool dbConnected = ServerSettings.DbConnected;
|
bool dbConnected = ServerSettings.DbConnected;
|
||||||
Logger.Log(dbConnected ? "Connected to the database." : "Database unavailable! Exiting.",
|
Logger.Log(dbConnected ? "Connected to the database." : "Database unavailable! Exiting.", LoggerLevelStartup.Instance);
|
||||||
LoggerLevelStartup.Instance);
|
|
||||||
|
|
||||||
if (dbConnected)
|
if (!dbConnected) Environment.Exit(1);
|
||||||
{
|
using Database database = new();
|
||||||
Stopwatch migrationStopwatch = new();
|
|
||||||
migrationStopwatch.Start();
|
|
||||||
|
|
||||||
Logger.Log("Migrating database...", LoggerLevelDatabase.Instance);
|
Logger.Log("Migrating database...", LoggerLevelDatabase.Instance);
|
||||||
using Database database = new();
|
MigrateDatabase(database);
|
||||||
database.Database.Migrate();
|
|
||||||
|
|
||||||
migrationStopwatch.Stop();
|
Logger.Log("Fixing broken timestamps...", LoggerLevelDatabase.Instance);
|
||||||
Logger.Log($"Migration took {migrationStopwatch.ElapsedMilliseconds}ms.", LoggerLevelDatabase.Instance);
|
FixTimestamps(database);
|
||||||
}
|
|
||||||
else Environment.Exit(1);
|
|
||||||
|
|
||||||
startupStopwatch.Stop();
|
stopwatch.Stop();
|
||||||
Logger.Log(
|
Logger.Log($"Ready! Startup took {stopwatch.ElapsedMilliseconds}ms. Passing off control to ASP.NET...", LoggerLevelStartup.Instance);
|
||||||
$"Ready! Startup took {startupStopwatch.ElapsedMilliseconds}ms. Passing off control to ASP.NET...",
|
|
||||||
LoggerLevelStartup.Instance);
|
|
||||||
|
|
||||||
CreateHostBuilder(args).Build().Run();
|
CreateHostBuilder(args).Build().Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
public static void MigrateDatabase(Database database)
|
||||||
Host.CreateDefaultBuilder(args)
|
{
|
||||||
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); })
|
Stopwatch stopwatch = new();
|
||||||
.ConfigureLogging(logging =>
|
stopwatch.Start();
|
||||||
{
|
|
||||||
logging.ClearProviders();
|
database.Database.Migrate();
|
||||||
logging.Services.TryAddEnumerable(ServiceDescriptor
|
|
||||||
.Singleton<ILoggerProvider, AspNetToKettuLoggerProvider>());
|
stopwatch.Stop();
|
||||||
});
|
Logger.Log($"Migration took {stopwatch.ElapsedMilliseconds}ms.", LoggerLevelDatabase.Instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
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.LastUpdated == 0)) slot.LastUpdated = TimeHelper.UnixTimeMilliseconds();
|
||||||
|
|
||||||
|
foreach (Comment comment in database.Comments.Where(c => c.Timestamp == 0)) comment.Timestamp = TimeHelper.UnixTimeMilliseconds();
|
||||||
|
|
||||||
|
database.SaveChanges();
|
||||||
|
|
||||||
|
stopwatch.Stop();
|
||||||
|
Logger.Log($"Fixing timestamps took {stopwatch.ElapsedMilliseconds}ms.", LoggerLevelDatabase.Instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IHostBuilder CreateHostBuilder(string[] args)
|
||||||
|
=> Host.CreateDefaultBuilder(args)
|
||||||
|
.ConfigureWebHostDefaults
|
||||||
|
(
|
||||||
|
webBuilder =>
|
||||||
|
{
|
||||||
|
webBuilder.UseStartup<Startup>();
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.ConfigureLogging
|
||||||
|
(
|
||||||
|
logging =>
|
||||||
|
{
|
||||||
|
logging.ClearProviders();
|
||||||
|
logging.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, AspNetToKettuLoggerProvider>());
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,19 +8,23 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.2" />
|
<PackageReference Include="BCrypt.Net-Next" Version="4.0.2"/>
|
||||||
<PackageReference Include="Kettu" Version="1.0.2" />
|
<PackageReference Include="Kettu" Version="1.1.0"/>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="5.0.11" />
|
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="5.0.11"/>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.11" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.11"/>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.11">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.11">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="5.0.2" />
|
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="5.0.2"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Remove="Types\SlotXsd.cs" />
|
<Compile Remove="Types\SlotXsd.cs"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="logs"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
"ProjectLighthouse": {
|
"ProjectLighthouse": {
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
"dotnetRunMessages": "true",
|
"dotnetRunMessages": "true",
|
||||||
"applicationUrl": "http://localhost:10060;http://localhost:10061;http://localhost:1062",
|
"applicationUrl": "http://localhost:10060",
|
||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||||
"LIGHTHOUSE_DB_CONNECTION_STRING": "server=127.0.0.1;uid=root;pwd=lighthouse;database=lighthouse"
|
"LIGHTHOUSE_DB_CONNECTION_STRING": "server=127.0.0.1;uid=root;pwd=lighthouse;database=lighthouse"
|
||||||
|
|
|
@ -2,26 +2,30 @@ using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Serialization {
|
namespace LBPUnion.ProjectLighthouse.Serialization
|
||||||
|
{
|
||||||
/// <summary>
|
/// <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
|
||||||
/// so I wrote my own crappy one.
|
/// elements),
|
||||||
|
/// so I wrote my own crappy one.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||||
public static class LbpSerializer {
|
public static class LbpSerializer
|
||||||
|
{
|
||||||
public static string BlankElement(string key) => $"<{key}></{key}>";
|
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(KeyValuePair<string, object> pair) => $"<{pair.Key}>{pair.Value}</{pair.Key}>";
|
||||||
|
|
||||||
public static string StringElement(string key, object value) => $"<{key}>{value}</{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(string key, object value, string tagKey, object tagValue) =>
|
|
||||||
$"<{key} {tagKey}=\"{tagValue}\">{value}</{key}>";
|
|
||||||
|
|
||||||
public static string Elements(params KeyValuePair<string, object>[] pairs) =>
|
public static string TaggedStringElement
|
||||||
pairs.Aggregate(string.Empty, (current, pair) => current + StringElement(pair));
|
(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 Elements
|
||||||
|
(params KeyValuePair<string, object>[] pairs)
|
||||||
|
=> pairs.Aggregate(string.Empty, (current, pair) => current + StringElement(pair));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,8 +1,11 @@
|
||||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Serialization {
|
namespace LBPUnion.ProjectLighthouse.Serialization
|
||||||
public class XmlOutputFormatter : StringOutputFormatter {
|
{
|
||||||
public XmlOutputFormatter() {
|
public class XmlOutputFormatter : StringOutputFormatter
|
||||||
|
{
|
||||||
|
public XmlOutputFormatter()
|
||||||
|
{
|
||||||
this.SupportedMediaTypes.Add("text/xml");
|
this.SupportedMediaTypes.Add("text/xml");
|
||||||
this.SupportedMediaTypes.Add("application/xml");
|
this.SupportedMediaTypes.Add("application/xml");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection.Metadata.Ecma335;
|
|
||||||
using System.Runtime.InteropServices.ComTypes;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Kettu;
|
using Kettu;
|
||||||
using LBPUnion.ProjectLighthouse.Helpers;
|
using LBPUnion.ProjectLighthouse.Helpers;
|
||||||
using LBPUnion.ProjectLighthouse.Logging;
|
using LBPUnion.ProjectLighthouse.Logging;
|
||||||
|
@ -14,7 +12,7 @@ using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Primitives;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse
|
namespace LBPUnion.ProjectLighthouse
|
||||||
{
|
{
|
||||||
|
@ -31,8 +29,8 @@ namespace LBPUnion.ProjectLighthouse
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddControllers();
|
services.AddControllers();
|
||||||
services.AddMvc(options =>
|
|
||||||
options.OutputFormatters.Add(new XmlOutputFormatter()));
|
services.AddMvc(options => options.OutputFormatters.Add(new XmlOutputFormatter()));
|
||||||
|
|
||||||
services.AddDbContext<Database>();
|
services.AddDbContext<Database>();
|
||||||
}
|
}
|
||||||
|
@ -44,100 +42,96 @@ namespace LBPUnion.ProjectLighthouse
|
||||||
string serverDigestKey = Environment.GetEnvironmentVariable("SERVER_DIGEST_KEY");
|
string serverDigestKey = Environment.GetEnvironmentVariable("SERVER_DIGEST_KEY");
|
||||||
if (string.IsNullOrWhiteSpace(serverDigestKey))
|
if (string.IsNullOrWhiteSpace(serverDigestKey))
|
||||||
{
|
{
|
||||||
Logger.Log(
|
Logger.Log
|
||||||
|
(
|
||||||
"The SERVER_DIGEST_KEY environment variable wasn't set, so digest headers won't be set or verified. This will prevent LBP 1 and LBP 3 from working. " +
|
"The SERVER_DIGEST_KEY environment variable wasn't set, so digest headers won't be set or verified. This will prevent LBP 1 and LBP 3 from working. " +
|
||||||
"To increase security, it is recommended that you find and set this variable."
|
"To increase security, it is recommended that you find and set this variable."
|
||||||
);
|
);
|
||||||
computeDigests = false;
|
computeDigests = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment()) app.UseDeveloperExceptionPage();
|
||||||
{
|
|
||||||
app.UseDeveloperExceptionPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Logs every request and the response to it
|
// Logs every request and the response to it
|
||||||
// Example: "200, 13ms: GET /LITTLEBIGPLANETPS3_XML/news"
|
// Example: "200, 13ms: GET /LITTLEBIGPLANETPS3_XML/news"
|
||||||
// Example: "404, 127ms: GET /asdasd?query=osucookiezi727ppbluezenithtopplayhdhr"
|
// Example: "404, 127ms: GET /asdasd?query=osucookiezi727ppbluezenithtopplayhdhr"
|
||||||
app.Use(async (context, next) =>
|
app.Use
|
||||||
{
|
(
|
||||||
Stopwatch requestStopwatch = new();
|
async (context, next) =>
|
||||||
requestStopwatch.Start();
|
|
||||||
|
|
||||||
// Log all headers.
|
|
||||||
foreach (var header in context.Request.Headers)
|
|
||||||
Logger.Log($"{header.Key}: {header.Value}");
|
|
||||||
|
|
||||||
context.Request.EnableBuffering(); // Allows us to reset the position of Request.Body for later logging
|
|
||||||
|
|
||||||
// Client digest check.
|
|
||||||
string authCookie;
|
|
||||||
if (!context.Request.Cookies.TryGetValue("MM_AUTH", out authCookie))
|
|
||||||
authCookie = string.Empty;
|
|
||||||
string digestPath = context.Request.Path;
|
|
||||||
Stream body = context.Request.Body;
|
|
||||||
|
|
||||||
if (computeDigests)
|
|
||||||
{
|
{
|
||||||
string clientRequestDigest =
|
Stopwatch requestStopwatch = new();
|
||||||
await HashHelper.ComputeDigest(digestPath, authCookie, body, serverDigestKey);
|
requestStopwatch.Start();
|
||||||
|
|
||||||
// Check the digest we've just calculated against the X-Digest-A header if the game set the header. They should match.
|
// Log all headers.
|
||||||
if (context.Request.Headers.TryGetValue("X-Digest-A", out var sentDigest))
|
foreach (KeyValuePair<string, StringValues> header in context.Request.Headers) Logger.Log($"{header.Key}: {header.Value}");
|
||||||
|
|
||||||
|
context.Request.EnableBuffering(); // Allows us to reset the position of Request.Body for later logging
|
||||||
|
|
||||||
|
// Client digest check.
|
||||||
|
string authCookie;
|
||||||
|
if (!context.Request.Cookies.TryGetValue("MM_AUTH", out authCookie)) authCookie = string.Empty;
|
||||||
|
string digestPath = context.Request.Path;
|
||||||
|
Stream body = context.Request.Body;
|
||||||
|
|
||||||
|
if (computeDigests)
|
||||||
{
|
{
|
||||||
if (clientRequestDigest != sentDigest)
|
string clientRequestDigest = await HashHelper.ComputeDigest(digestPath, authCookie, body, serverDigestKey);
|
||||||
{
|
|
||||||
context.Response.StatusCode = 403;
|
// Check the digest we've just calculated against the X-Digest-A header if the game set the header. They should match.
|
||||||
context.Abort();
|
if (context.Request.Headers.TryGetValue("X-Digest-A", out StringValues sentDigest))
|
||||||
return;
|
if (clientRequestDigest != sentDigest)
|
||||||
}
|
{
|
||||||
|
context.Response.StatusCode = 403;
|
||||||
|
context.Abort();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Response.Headers.Add("X-Digest-B", clientRequestDigest);
|
||||||
|
context.Request.Body.Position = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.Response.Headers.Add("X-Digest-B", clientRequestDigest);
|
// This does the same as above, but for the response stream.
|
||||||
context.Request.Body.Position = 0;
|
using MemoryStream responseBuffer = new();
|
||||||
}
|
Stream oldResponseStream = context.Response.Body;
|
||||||
|
context.Response.Body = responseBuffer;
|
||||||
|
|
||||||
// This does the same as above, but for the response stream.
|
await next(); // Handle the request so we can get the status code from it
|
||||||
using MemoryStream responseBuffer = new MemoryStream();
|
|
||||||
Stream oldResponseStream = context.Response.Body;
|
|
||||||
context.Response.Body = responseBuffer;
|
|
||||||
|
|
||||||
await next(); // Handle the request so we can get the status code from it
|
// Compute the server digest hash.
|
||||||
|
if (computeDigests)
|
||||||
|
{
|
||||||
|
responseBuffer.Position = 0;
|
||||||
|
|
||||||
// Compute the server digest hash.
|
// Compute the digest for the response.
|
||||||
if (computeDigests)
|
string serverDigest = await HashHelper.ComputeDigest(context.Request.Path, authCookie, responseBuffer, serverDigestKey);
|
||||||
{
|
context.Response.Headers.Add("X-Digest-A", serverDigest);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the X-Original-Content-Length header to the length of the response buffer.
|
||||||
|
context.Response.Headers.Add("X-Original-Content-Length", responseBuffer.Length.ToString());
|
||||||
|
|
||||||
|
// Copy the buffered response to the actual respose stream.
|
||||||
responseBuffer.Position = 0;
|
responseBuffer.Position = 0;
|
||||||
|
|
||||||
// Compute the digest for the response.
|
await responseBuffer.CopyToAsync(oldResponseStream);
|
||||||
string serverDigest = await HashHelper.ComputeDigest(context.Request.Path, authCookie,
|
|
||||||
responseBuffer, serverDigestKey);
|
context.Response.Body = oldResponseStream;
|
||||||
context.Response.Headers.Add("X-Digest-A", serverDigest);
|
|
||||||
|
requestStopwatch.Stop();
|
||||||
|
|
||||||
|
Logger.Log
|
||||||
|
(
|
||||||
|
$"{context.Response.StatusCode}, {requestStopwatch.ElapsedMilliseconds}ms: {context.Request.Method} {context.Request.Path}{context.Request.QueryString}",
|
||||||
|
LoggerLevelHttp.Instance
|
||||||
|
);
|
||||||
|
|
||||||
|
if (context.Request.Method == "POST")
|
||||||
|
{
|
||||||
|
context.Request.Body.Position = 0;
|
||||||
|
Logger.Log(await new StreamReader(context.Request.Body).ReadToEndAsync(), LoggerLevelHttp.Instance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
);
|
||||||
// Set the X-Original-Content-Length header to the length of the response buffer.
|
|
||||||
context.Response.Headers.Add("X-Original-Content-Length", responseBuffer.Length.ToString());
|
|
||||||
|
|
||||||
// Copy the buffered response to the actual respose stream.
|
|
||||||
responseBuffer.Position = 0;
|
|
||||||
|
|
||||||
await responseBuffer.CopyToAsync(oldResponseStream);
|
|
||||||
|
|
||||||
context.Response.Body = oldResponseStream;
|
|
||||||
|
|
||||||
requestStopwatch.Stop();
|
|
||||||
|
|
||||||
Logger.Log(
|
|
||||||
$"{context.Response.StatusCode}, {requestStopwatch.ElapsedMilliseconds}ms: {context.Request.Method} {context.Request.Path}{context.Request.QueryString}",
|
|
||||||
LoggerLevelHttp.Instance
|
|
||||||
);
|
|
||||||
|
|
||||||
if (context.Request.Method == "POST")
|
|
||||||
{
|
|
||||||
context.Request.Body.Position = 0;
|
|
||||||
Logger.Log(await new StreamReader(context.Request.Body).ReadToEndAsync(), LoggerLevelHttp.Instance);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,24 @@
|
||||||
using LBPUnion.ProjectLighthouse.Helpers;
|
using LBPUnion.ProjectLighthouse.Helpers;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types.Files {
|
namespace LBPUnion.ProjectLighthouse.Types.Files
|
||||||
public class LbpFile {
|
{
|
||||||
public LbpFile(byte[] data) {
|
public class LbpFile
|
||||||
this.Data = data;
|
{
|
||||||
this.FileType = FileHelper.DetermineFileType(this.Data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The type of file.
|
|
||||||
/// </summary>
|
|
||||||
public LbpFileType FileType;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A buffer of the file's data.
|
/// A buffer of the file's data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly byte[] Data;
|
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,11 +1,14 @@
|
||||||
namespace LBPUnion.ProjectLighthouse.Types.Files {
|
namespace LBPUnion.ProjectLighthouse.Types.Files
|
||||||
public enum LbpFileType {
|
{
|
||||||
|
public enum LbpFileType
|
||||||
|
{
|
||||||
Script, // .ff, FSH
|
Script, // .ff, FSH
|
||||||
Texture, // TEX
|
Texture, // TEX
|
||||||
Level, // LVL
|
Level, // LVL
|
||||||
FileArchive, // .farc, (ends with FARC)
|
FileArchive, // .farc, (ends with FARC)
|
||||||
Plan, // PLN, uploaded with levels
|
Plan, // PLN, uploaded with levels
|
||||||
Voice, // VOP, voice data
|
Voice, // VOP, voice data
|
||||||
|
Painting, // PTG, paintings
|
||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,22 +2,27 @@ using System;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types {
|
namespace LBPUnion.ProjectLighthouse.Types
|
||||||
public class HeartedProfile {
|
{
|
||||||
|
public class HeartedProfile
|
||||||
|
{
|
||||||
// ReSharper disable once UnusedMember.Global
|
// ReSharper disable once UnusedMember.Global
|
||||||
#if NET6_0_OR_GREATER
|
#if NET6_0_OR_GREATER
|
||||||
[Obsolete($"Use {nameof(HeartedUserId)} instead, this is a key which you should never need to use.")]
|
[Obsolete($"Use {nameof(HeartedUserId)} instead, this is a key which you should never need to use.")]
|
||||||
#else
|
#else
|
||||||
[Obsolete("Use HeartedUserId instead, this is a key which you should never need to use.")]
|
[Obsolete("Use HeartedUserId instead, this is a key which you should never need to use.")]
|
||||||
#endif
|
#endif
|
||||||
[Key] public int HeartedProfileId { get; set; }
|
[Key]
|
||||||
|
public int HeartedProfileId { get; set; }
|
||||||
|
|
||||||
public int UserId { 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; }
|
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;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types.Levels {
|
namespace LBPUnion.ProjectLighthouse.Types.Levels
|
||||||
public class HeartedLevel {
|
{
|
||||||
|
public class HeartedLevel
|
||||||
|
{
|
||||||
// ReSharper disable once UnusedMember.Global
|
// ReSharper disable once UnusedMember.Global
|
||||||
[Key] public int HeartedLevelId { get; set; }
|
[Key]
|
||||||
|
public int HeartedLevelId { get; set; }
|
||||||
|
|
||||||
public int UserId { 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; }
|
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;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types.Levels {
|
namespace LBPUnion.ProjectLighthouse.Types.Levels
|
||||||
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A series of tags that can be applied to a level
|
/// A series of tags that can be applied to a level
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||||
public enum LevelTags {
|
public enum LevelTags
|
||||||
|
{
|
||||||
Brilliant,
|
Brilliant,
|
||||||
Beautiful,
|
Beautiful,
|
||||||
Funky,
|
Funky,
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types.Levels {
|
namespace LBPUnion.ProjectLighthouse.Types.Levels
|
||||||
public class QueuedLevel {
|
{
|
||||||
|
public class QueuedLevel
|
||||||
|
{
|
||||||
// ReSharper disable once UnusedMember.Global
|
// ReSharper disable once UnusedMember.Global
|
||||||
[Key] public int QueuedLevelId { get; set; }
|
[Key]
|
||||||
|
public int QueuedLevelId { get; set; }
|
||||||
|
|
||||||
public int UserId { get; set; }
|
public int UserId { get; set; }
|
||||||
|
|
||||||
[ForeignKey(nameof(UserId))]
|
[ForeignKey(nameof(UserId))]
|
||||||
public User User { get; set; }
|
public User User { get; set; }
|
||||||
|
|
||||||
public int SlotId { get; set; }
|
public int SlotId { get; set; }
|
||||||
|
|
||||||
[ForeignKey(nameof(SlotId))]
|
[ForeignKey(nameof(SlotId))]
|
||||||
|
|
|
@ -5,92 +5,103 @@ using System.Xml.Serialization;
|
||||||
using LBPUnion.ProjectLighthouse.Serialization;
|
using LBPUnion.ProjectLighthouse.Serialization;
|
||||||
using LBPUnion.ProjectLighthouse.Types.Profiles;
|
using LBPUnion.ProjectLighthouse.Types.Profiles;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types.Levels {
|
namespace LBPUnion.ProjectLighthouse.Types.Levels
|
||||||
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A LittleBigPlanet level.
|
/// A LittleBigPlanet level.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[XmlRoot("slot"), XmlType("slot")]
|
[XmlRoot("slot")]
|
||||||
public class Slot {
|
[XmlType("slot")]
|
||||||
|
public class Slot
|
||||||
|
{
|
||||||
[XmlAttribute("type")]
|
[XmlAttribute("type")]
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
|
|
||||||
[Key]
|
[Key]
|
||||||
[XmlIgnore]
|
[XmlElement("id")]
|
||||||
public int SlotId { get; set; }
|
public int SlotId { get; set; }
|
||||||
|
|
||||||
|
|
||||||
[XmlElement("name")]
|
[XmlElement("name")]
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
[XmlElement("description")]
|
[XmlElement("description")]
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
|
|
||||||
[XmlElement("icon")]
|
[XmlElement("icon")]
|
||||||
public string IconHash { get; set; }
|
public string IconHash { get; set; }
|
||||||
|
|
||||||
[XmlElement("rootLevel")]
|
[XmlElement("rootLevel")]
|
||||||
public string RootLevel { get; set; }
|
public string RootLevel { get; set; }
|
||||||
|
|
||||||
public string ResourceCollection { get; set; }
|
public string ResourceCollection { get; set; }
|
||||||
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
[XmlElement("resource")]
|
[XmlElement("resource")]
|
||||||
public string[] Resources {
|
public string[] Resources {
|
||||||
get => this.ResourceCollection.Split(",");
|
get => this.ResourceCollection.Split(",");
|
||||||
set => this.ResourceCollection = string.Join(',', value);
|
set => this.ResourceCollection = string.Join(',', value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[XmlIgnore]
|
[XmlIgnore]
|
||||||
public int LocationId { get; set; }
|
public int LocationId { get; set; }
|
||||||
|
|
||||||
[XmlIgnore]
|
[XmlIgnore]
|
||||||
public int CreatorId { get; set; }
|
public int CreatorId { get; set; }
|
||||||
|
|
||||||
[ForeignKey(nameof(CreatorId))]
|
[ForeignKey(nameof(CreatorId))]
|
||||||
public User Creator { get; set; }
|
public User Creator { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The location of the level on the creator's earth
|
/// The location of the level on the creator's earth
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[XmlElement("location")]
|
[XmlElement("location")]
|
||||||
[ForeignKey(nameof(LocationId))]
|
[ForeignKey(nameof(LocationId))]
|
||||||
public Location Location { get; set; }
|
public Location Location { get; set; }
|
||||||
|
|
||||||
[XmlElement("initiallyLocked")]
|
[XmlElement("initiallyLocked")]
|
||||||
public bool InitiallyLocked { get; set; }
|
public bool InitiallyLocked { get; set; }
|
||||||
|
|
||||||
[XmlElement("isSubLevel")]
|
[XmlElement("isSubLevel")]
|
||||||
public bool SubLevel { get; set; }
|
public bool SubLevel { get; set; }
|
||||||
|
|
||||||
[XmlElement("isLBP1Only")]
|
[XmlElement("isLBP1Only")]
|
||||||
public bool Lbp1Only { get; set; }
|
public bool Lbp1Only { get; set; }
|
||||||
|
|
||||||
[XmlElement("shareable")]
|
[XmlElement("shareable")]
|
||||||
public int Shareable { get; set; }
|
public int Shareable { get; set; }
|
||||||
|
|
||||||
[XmlElement("authorLabels")]
|
[XmlElement("authorLabels")]
|
||||||
public string AuthorLabels { get; set; }
|
public string AuthorLabels { get; set; }
|
||||||
|
|
||||||
[XmlElement("background")]
|
[XmlElement("background")]
|
||||||
public string BackgroundHash { get; set; } = "";
|
public string BackgroundHash { get; set; } = "";
|
||||||
|
|
||||||
[XmlElement("minPlayers")]
|
[XmlElement("minPlayers")]
|
||||||
public int MinimumPlayers { get; set; }
|
public int MinimumPlayers { get; set; }
|
||||||
|
|
||||||
[XmlElement("maxPlayers")]
|
[XmlElement("maxPlayers")]
|
||||||
public int MaximumPlayers { get; set; }
|
public int MaximumPlayers { get; set; }
|
||||||
|
|
||||||
[XmlElement("moveRequired")]
|
[XmlElement("moveRequired")]
|
||||||
public bool MoveRequired { get; set; }
|
public bool MoveRequired { get; set; }
|
||||||
|
|
||||||
public string SerializeResources() {
|
[XmlIgnore]
|
||||||
return this.Resources
|
public long FirstUploaded { get; set; }
|
||||||
.Aggregate("", (current, resource) =>
|
|
||||||
current + LbpSerializer.StringElement("resource", resource));
|
[XmlIgnore]
|
||||||
|
public long LastUpdated { get; set; }
|
||||||
|
|
||||||
|
[XmlIgnore]
|
||||||
|
public bool MMPick { get; set; }
|
||||||
|
|
||||||
|
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) +
|
string slotData = LbpSerializer.StringElement("name", this.Name) +
|
||||||
LbpSerializer.StringElement("id", this.SlotId) +
|
LbpSerializer.StringElement("id", this.SlotId) +
|
||||||
LbpSerializer.StringElement("game", 1) +
|
LbpSerializer.StringElement("game", 1) +
|
||||||
|
@ -107,8 +118,11 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels {
|
||||||
LbpSerializer.StringElement("background", this.BackgroundHash) +
|
LbpSerializer.StringElement("background", this.BackgroundHash) +
|
||||||
LbpSerializer.StringElement("minPlayers", this.MinimumPlayers) +
|
LbpSerializer.StringElement("minPlayers", this.MinimumPlayers) +
|
||||||
LbpSerializer.StringElement("maxPlayers", this.MaximumPlayers) +
|
LbpSerializer.StringElement("maxPlayers", this.MaximumPlayers) +
|
||||||
LbpSerializer.StringElement("moveRequired", this.MoveRequired);
|
LbpSerializer.StringElement("moveRequired", this.MoveRequired) +
|
||||||
|
LbpSerializer.StringElement("firstPublished", this.FirstUploaded) +
|
||||||
|
LbpSerializer.StringElement("lastUpdated", this.LastUpdated) +
|
||||||
|
LbpSerializer.StringElement("mmpick", this.MMPick);
|
||||||
|
|
||||||
return LbpSerializer.TaggedStringElement("slot", slotData, "type", "user");
|
return LbpSerializer.TaggedStringElement("slot", slotData, "type", "user");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,39 +1,43 @@
|
||||||
|
#nullable enable
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using LBPUnion.ProjectLighthouse.Helpers;
|
using LBPUnion.ProjectLighthouse.Helpers;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types {
|
namespace LBPUnion.ProjectLighthouse.Types
|
||||||
// This is all the information I can understand for now. More testing is required.
|
{
|
||||||
// Example data:
|
|
||||||
// - LBP2 digital, with the RPCN username `literally1984`
|
|
||||||
// POST /LITTLEBIGPLANETPS3_XML/login?applicationID=21414&languageID=1&lbp2=1&beta=0&titleID=NPUA80662&country=us
|
|
||||||
// !<21>0256333||x||<7C><>Y literally198bruUP9000-NPUA80662_008D
|
|
||||||
// - LBP2 digital, with the RPCN username `jvyden`
|
|
||||||
// POST /LITTLEBIGPLANETPS3_XML/login?applicationID=21414&languageID=1&lbp2=1&beta=0&titleID=NPUA80662&country=us
|
|
||||||
// !<21>0220333||/u||=0<> jvydebruUP9000-NPUA80662_008D
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The data sent from POST /LOGIN.
|
/// The data sent from POST /LOGIN.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class LoginData {
|
public class LoginData
|
||||||
public string Username { get; set; }
|
{
|
||||||
// public string GameVersion { get; set; }
|
|
||||||
// public int UnknownNumber { get; set; } // Seems to increment by 1000 every login attempt
|
|
||||||
|
|
||||||
public static LoginData CreateFromString(string str) {
|
public static readonly string UsernamePrefix = Encoding.ASCII.GetString
|
||||||
do {
|
(
|
||||||
str = str.Replace("\b", string.Empty); // Trim backspace characters
|
new byte[]
|
||||||
} while(str.Contains('\b'));
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
str = str.Replace("\b", ""); // Remove backspace characters
|
||||||
|
|
||||||
using MemoryStream ms = new(Encoding.ASCII.GetBytes(str));
|
using MemoryStream ms = new(Encoding.ASCII.GetBytes(str));
|
||||||
using BinaryReader reader = new(ms);
|
using BinaryReader reader = new(ms);
|
||||||
|
|
||||||
|
if (!str.Contains(UsernamePrefix)) return null;
|
||||||
|
|
||||||
LoginData loginData = new();
|
LoginData loginData = new();
|
||||||
|
|
||||||
BinaryHelper.ReadUntilByte(reader, 0x20); // Skips to relevant part
|
reader.BaseStream.Position = str.IndexOf(UsernamePrefix, StringComparison.Ordinal) + UsernamePrefix.Length;
|
||||||
|
|
||||||
// byte[] endBytes = reader.ReadBytes((int)(ms.Length - reader.BaseStream.Position));
|
|
||||||
// string end = Encoding.ASCII.GetString(endBytes);
|
|
||||||
|
|
||||||
loginData.Username = BinaryHelper.ReadString(reader).Replace("\0", string.Empty);
|
loginData.Username = BinaryHelper.ReadString(reader).Replace("\0", string.Empty);
|
||||||
|
|
||||||
return loginData;
|
return loginData;
|
||||||
|
|
|
@ -2,23 +2,23 @@ using System.Collections.Generic;
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
using LBPUnion.ProjectLighthouse.Serialization;
|
using LBPUnion.ProjectLighthouse.Serialization;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types {
|
namespace LBPUnion.ProjectLighthouse.Types
|
||||||
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Response to POST /login
|
/// Response to POST /login
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[XmlRoot("loginResult"), XmlType("loginResult")]
|
[XmlRoot("loginResult")]
|
||||||
public class LoginResult {
|
[XmlType("loginResult")]
|
||||||
|
public class LoginResult
|
||||||
|
{
|
||||||
[XmlElement("authTicket")]
|
[XmlElement("authTicket")]
|
||||||
public string AuthTicket { get; set; }
|
public string AuthTicket { get; set; }
|
||||||
|
|
||||||
[XmlElement("lbpEnvVer")]
|
[XmlElement("lbpEnvVer")]
|
||||||
public string LbpEnvVer { get; set; }
|
public string LbpEnvVer { get; set; }
|
||||||
|
|
||||||
public string Serialize() {
|
public string Serialize()
|
||||||
return LbpSerializer.Elements(
|
=> LbpSerializer.Elements
|
||||||
new KeyValuePair<string, object>("authTicket", this.AuthTicket),
|
(new KeyValuePair<string, object>("authTicket", this.AuthTicket), new KeyValuePair<string, object>("lbpEnvVer", this.LbpEnvVer));
|
||||||
new KeyValuePair<string, object>("lbpEnvVer", this.LbpEnvVer)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
namespace LBPUnion.ProjectLighthouse.Types.Match {
|
namespace LBPUnion.ProjectLighthouse.Types.Match
|
||||||
public interface IMatchData {
|
{
|
||||||
|
public interface IMatchData
|
||||||
}
|
{}
|
||||||
}
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
namespace LBPUnion.ProjectLighthouse.Types.Match {
|
namespace LBPUnion.ProjectLighthouse.Types.Match
|
||||||
public enum RoomState {
|
{
|
||||||
|
public enum RoomState
|
||||||
|
{
|
||||||
Idle = 0,
|
Idle = 0,
|
||||||
LookingForPlayersForLevel = 1,
|
LookingForPlayersForLevel = 1,
|
||||||
Unknown = 2,
|
Unknown = 2,
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
namespace LBPUnion.ProjectLighthouse.Types.Match {
|
namespace LBPUnion.ProjectLighthouse.Types.Match
|
||||||
public class UpdateMyPlayerData : IMatchData {
|
{
|
||||||
|
public class UpdateMyPlayerData : IMatchData
|
||||||
|
{
|
||||||
public string Player;
|
public string Player;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types.Match {
|
namespace LBPUnion.ProjectLighthouse.Types.Match
|
||||||
public class UpdatePlayersInRoom : IMatchData {
|
{
|
||||||
|
public class UpdatePlayersInRoom : IMatchData
|
||||||
|
{
|
||||||
public List<string> Players;
|
public List<string> Players;
|
||||||
public List<string> Reservations;
|
public List<string> Reservations;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
using LBPUnion.ProjectLighthouse.Serialization;
|
using LBPUnion.ProjectLighthouse.Serialization;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types.News {
|
namespace LBPUnion.ProjectLighthouse.Types.News
|
||||||
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used on the info moon on LBP1. Broken for unknown reasons
|
/// Used on the info moon on LBP1. Broken for unknown reasons
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class NewsEntry {
|
public class NewsEntry
|
||||||
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
public string Summary { get; set; }
|
public string Summary { get; set; }
|
||||||
|
@ -13,14 +15,13 @@ namespace LBPUnion.ProjectLighthouse.Types.News {
|
||||||
public string Category { get; set; }
|
public string Category { get; set; }
|
||||||
public long Date { get; set; }
|
public long Date { get; set; }
|
||||||
|
|
||||||
public string Serialize() {
|
public string Serialize()
|
||||||
return LbpSerializer.StringElement("id", this.Id) +
|
=> LbpSerializer.StringElement("id", this.Id) +
|
||||||
LbpSerializer.StringElement("title", this.Title) +
|
LbpSerializer.StringElement("title", this.Title) +
|
||||||
LbpSerializer.StringElement("summary", this.Summary) +
|
LbpSerializer.StringElement("summary", this.Summary) +
|
||||||
LbpSerializer.StringElement("text", this.Text) +
|
LbpSerializer.StringElement("text", this.Text) +
|
||||||
LbpSerializer.StringElement("date", this.Date) +
|
LbpSerializer.StringElement("date", this.Date) +
|
||||||
this.Image.Serialize() +
|
this.Image.Serialize() +
|
||||||
LbpSerializer.StringElement("category", this.Category);
|
LbpSerializer.StringElement("category", this.Category);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,14 +1,13 @@
|
||||||
using LBPUnion.ProjectLighthouse.Serialization;
|
using LBPUnion.ProjectLighthouse.Serialization;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types.News {
|
namespace LBPUnion.ProjectLighthouse.Types.News
|
||||||
public class NewsImage {
|
{
|
||||||
|
public class NewsImage
|
||||||
|
{
|
||||||
public string Hash { get; set; }
|
public string Hash { get; set; }
|
||||||
public string Alignment { get; set; }
|
public string Alignment { get; set; }
|
||||||
|
|
||||||
public string Serialize() {
|
public string Serialize()
|
||||||
return LbpSerializer.StringElement("image",
|
=> LbpSerializer.StringElement("image", LbpSerializer.StringElement("hash", this.Hash) + LbpSerializer.StringElement("alignment", this.Alignment));
|
||||||
LbpSerializer.StringElement("hash", this.Hash) +
|
|
||||||
LbpSerializer.StringElement("alignment", this.Alignment));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,22 +1,26 @@
|
||||||
using LBPUnion.ProjectLighthouse.Serialization;
|
using LBPUnion.ProjectLighthouse.Serialization;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types.Profiles {
|
namespace LBPUnion.ProjectLighthouse.Types.Profiles
|
||||||
|
{
|
||||||
[Keyless]
|
[Keyless]
|
||||||
public class ClientsConnected {
|
public class ClientsConnected
|
||||||
|
{
|
||||||
public bool Lbp1 { get; set; }
|
public bool Lbp1 { get; set; }
|
||||||
public bool Lbp2 { get; set; }
|
public bool Lbp2 { get; set; }
|
||||||
public bool LbpMe { get; set; }
|
public bool LbpMe { get; set; }
|
||||||
public bool Lbp3Ps3 { get; set; }
|
public bool Lbp3Ps3 { get; set; }
|
||||||
public bool Lbp3Ps4 { get; set; }
|
public bool Lbp3Ps4 { get; set; }
|
||||||
|
|
||||||
public string Serialize() {
|
public string Serialize()
|
||||||
return LbpSerializer.StringElement("clientsConnected",
|
=> LbpSerializer.StringElement
|
||||||
|
(
|
||||||
|
"clientsConnected",
|
||||||
LbpSerializer.StringElement("lbp1", this.Lbp1) +
|
LbpSerializer.StringElement("lbp1", this.Lbp1) +
|
||||||
LbpSerializer.StringElement("lbp2", this.Lbp2) +
|
LbpSerializer.StringElement("lbp2", this.Lbp2) +
|
||||||
LbpSerializer.StringElement("lbpme", this.LbpMe) +
|
LbpSerializer.StringElement("lbpme", this.LbpMe) +
|
||||||
LbpSerializer.StringElement("lbp3ps3", this.Lbp3Ps3) +
|
LbpSerializer.StringElement("lbp3ps3", this.Lbp3Ps3) +
|
||||||
LbpSerializer.StringElement("lbp3ps4", this.Lbp3Ps4));
|
LbpSerializer.StringElement("lbp3ps4", this.Lbp3Ps4)
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,20 +3,23 @@ using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
using LBPUnion.ProjectLighthouse.Serialization;
|
using LBPUnion.ProjectLighthouse.Serialization;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types.Profiles {
|
namespace LBPUnion.ProjectLighthouse.Types.Profiles
|
||||||
[XmlRoot("comment"), XmlType("comment")]
|
{
|
||||||
public class Comment {
|
[XmlRoot("comment")]
|
||||||
|
[XmlType("comment")]
|
||||||
|
public class Comment
|
||||||
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[XmlAttribute("id")]
|
[XmlAttribute("id")]
|
||||||
public int CommentId { get; set; }
|
public int CommentId { get; set; }
|
||||||
|
|
||||||
public int PosterUserId { get; set; }
|
public int PosterUserId { get; set; }
|
||||||
|
|
||||||
public int TargetUserId { get; set; }
|
public int TargetUserId { get; set; }
|
||||||
|
|
||||||
[ForeignKey(nameof(PosterUserId))]
|
[ForeignKey(nameof(PosterUserId))]
|
||||||
public User Poster { get; set; }
|
public User Poster { get; set; }
|
||||||
|
|
||||||
[ForeignKey(nameof(TargetUserId))]
|
[ForeignKey(nameof(TargetUserId))]
|
||||||
public User Target { get; set; }
|
public User Target { get; set; }
|
||||||
|
|
||||||
|
@ -24,24 +27,22 @@ namespace LBPUnion.ProjectLighthouse.Types.Profiles {
|
||||||
|
|
||||||
[XmlElement("message")]
|
[XmlElement("message")]
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
|
|
||||||
public int ThumbsUp { get; set; }
|
public int ThumbsUp { get; set; }
|
||||||
public int ThumbsDown { get; set; }
|
public int ThumbsDown { get; set; }
|
||||||
|
|
||||||
private string serialize() {
|
private string serialize()
|
||||||
return LbpSerializer.StringElement("id", this.CommentId) +
|
=> LbpSerializer.StringElement("id", this.CommentId) +
|
||||||
LbpSerializer.StringElement("npHandle", this.Poster.Username) +
|
LbpSerializer.StringElement("npHandle", this.Poster.Username) +
|
||||||
LbpSerializer.StringElement("timestamp", this.Timestamp) +
|
LbpSerializer.StringElement("timestamp", this.Timestamp) +
|
||||||
LbpSerializer.StringElement("message", this.Message) +
|
LbpSerializer.StringElement("message", this.Message) +
|
||||||
LbpSerializer.StringElement("thumbsup", this.ThumbsUp) +
|
LbpSerializer.StringElement("thumbsup", this.ThumbsUp) +
|
||||||
LbpSerializer.StringElement("thumbsdown", this.ThumbsDown);
|
LbpSerializer.StringElement("thumbsdown", this.ThumbsDown);
|
||||||
}
|
|
||||||
|
|
||||||
public string Serialize(int yourThumb) {
|
public string Serialize
|
||||||
return LbpSerializer.StringElement("comment", this.serialize() + LbpSerializer.StringElement("yourthumb", yourThumb));
|
(int yourThumb)
|
||||||
}
|
=> LbpSerializer.StringElement("comment", this.serialize() + LbpSerializer.StringElement("yourthumb", yourThumb));
|
||||||
|
|
||||||
public string Serialize() {
|
public string Serialize() => LbpSerializer.StringElement("comment", this.serialize());
|
||||||
return LbpSerializer.StringElement("comment", this.serialize());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,8 +1,12 @@
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types.Profiles {
|
namespace LBPUnion.ProjectLighthouse.Types.Profiles
|
||||||
public class LastMatch {
|
{
|
||||||
[Key] public int UserId { get; set; }
|
public class LastMatch
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int UserId { get; set; }
|
||||||
|
|
||||||
public long Timestamp { get; set; }
|
public long Timestamp { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,17 +1,24 @@
|
||||||
|
using System.Xml.Serialization;
|
||||||
using LBPUnion.ProjectLighthouse.Serialization;
|
using LBPUnion.ProjectLighthouse.Serialization;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types.Profiles {
|
namespace LBPUnion.ProjectLighthouse.Types.Profiles
|
||||||
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The location of a slot on a planet.
|
/// The location of a slot on a planet.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Location {
|
[XmlRoot("location")]
|
||||||
|
[XmlType("location")]
|
||||||
|
public class Location
|
||||||
|
{
|
||||||
|
[XmlIgnore]
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[XmlElement("x")]
|
||||||
public int X { get; set; }
|
public int X { get; set; }
|
||||||
|
|
||||||
|
[XmlElement("y")]
|
||||||
public int Y { get; set; }
|
public int Y { get; set; }
|
||||||
|
|
||||||
public string Serialize() {
|
public string Serialize() => LbpSerializer.StringElement("x", this.X) + LbpSerializer.StringElement("y", this.Y);
|
||||||
return LbpSerializer.StringElement("x", this.X) +
|
|
||||||
LbpSerializer.StringElement("y", this.Y);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,12 @@
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types {
|
namespace LBPUnion.ProjectLighthouse.Types
|
||||||
[XmlRoot("resources"), XmlType("resources")]
|
{
|
||||||
public class ResourceList {
|
[XmlRoot("resources")]
|
||||||
[XmlElement("resource")]
|
[XmlType("resources")]
|
||||||
|
public class ResourceList
|
||||||
|
{
|
||||||
|
[XmlElement("resource")]
|
||||||
public string[] Resources;
|
public string[] Resources;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,15 +1,17 @@
|
||||||
using LBPUnion.ProjectLighthouse.Serialization;
|
using LBPUnion.ProjectLighthouse.Serialization;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types.Settings {
|
namespace LBPUnion.ProjectLighthouse.Types.Settings
|
||||||
public class PrivacySettings {
|
{
|
||||||
|
public class PrivacySettings
|
||||||
|
{
|
||||||
public string LevelVisibility { get; set; }
|
public string LevelVisibility { get; set; }
|
||||||
public string ProfileVisibility { get; set; }
|
public string ProfileVisibility { get; set; }
|
||||||
|
|
||||||
public string Serialize() {
|
public string Serialize()
|
||||||
return LbpSerializer.StringElement("privacySettings",
|
=> LbpSerializer.StringElement
|
||||||
LbpSerializer.StringElement("levelVisibility", this.LevelVisibility) +
|
(
|
||||||
LbpSerializer.StringElement("profileVisibility", this.ProfileVisibility)
|
"privacySettings",
|
||||||
|
LbpSerializer.StringElement("levelVisibility", this.LevelVisibility) + LbpSerializer.StringElement("profileVisibility", this.ProfileVisibility)
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,23 +3,25 @@ using System;
|
||||||
using Kettu;
|
using Kettu;
|
||||||
using LBPUnion.ProjectLighthouse.Logging;
|
using LBPUnion.ProjectLighthouse.Logging;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types.Settings {
|
namespace LBPUnion.ProjectLighthouse.Types.Settings
|
||||||
public static class ServerSettings {
|
{
|
||||||
|
public static class ServerSettings
|
||||||
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The maximum amount of slots allowed on users' earth
|
/// The maximum amount of slots allowed on users' earth
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int EntitledSlots = int.MaxValue;
|
public const int EntitledSlots = 50;
|
||||||
|
|
||||||
public const int ListsQuota = 20;
|
public const int ListsQuota = 50;
|
||||||
|
|
||||||
public const string ServerName = "ProjectLighthouse";
|
public const string ServerName = "ProjectLighthouse";
|
||||||
|
|
||||||
private static string? dbConnectionString;
|
private static string? dbConnectionString;
|
||||||
|
|
||||||
public static string DbConnectionString {
|
public static string DbConnectionString {
|
||||||
get {
|
get {
|
||||||
if(dbConnectionString == null) {
|
if (dbConnectionString == null) return dbConnectionString = Environment.GetEnvironmentVariable("LIGHTHOUSE_DB_CONNECTION_STRING") ?? "";
|
||||||
return dbConnectionString = Environment.GetEnvironmentVariable("LIGHTHOUSE_DB_CONNECTION_STRING") ?? "";
|
|
||||||
}
|
|
||||||
return dbConnectionString;
|
return dbConnectionString;
|
||||||
}
|
}
|
||||||
set => dbConnectionString = value;
|
set => dbConnectionString = value;
|
||||||
|
@ -27,10 +29,12 @@ namespace LBPUnion.ProjectLighthouse.Types.Settings {
|
||||||
|
|
||||||
public static bool DbConnected {
|
public static bool DbConnected {
|
||||||
get {
|
get {
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
return new Database().Database.CanConnect();
|
return new Database().Database.CanConnect();
|
||||||
}
|
}
|
||||||
catch(Exception e) {
|
catch(Exception e)
|
||||||
|
{
|
||||||
Logger.Log(e.ToString(), LoggerLevelDatabase.Instance);
|
Logger.Log(e.ToString(), LoggerLevelDatabase.Instance);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types {
|
namespace LBPUnion.ProjectLighthouse.Types
|
||||||
public class Token {
|
{
|
||||||
|
public class Token
|
||||||
|
{
|
||||||
// ReSharper disable once UnusedMember.Global
|
// ReSharper disable once UnusedMember.Global
|
||||||
[Key] public int TokenId { get; set; }
|
[Key]
|
||||||
|
public int TokenId { get; set; }
|
||||||
|
|
||||||
public int UserId { get; set; }
|
public int UserId { get; set; }
|
||||||
public string UserToken { get; set; }
|
public string UserToken { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.Linq;
|
||||||
using LBPUnion.ProjectLighthouse.Serialization;
|
using LBPUnion.ProjectLighthouse.Serialization;
|
||||||
using LBPUnion.ProjectLighthouse.Types.Profiles;
|
using LBPUnion.ProjectLighthouse.Types.Profiles;
|
||||||
using LBPUnion.ProjectLighthouse.Types.Settings;
|
using LBPUnion.ProjectLighthouse.Types.Settings;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types {
|
namespace LBPUnion.ProjectLighthouse.Types
|
||||||
public class User {
|
{
|
||||||
|
public class User
|
||||||
|
{
|
||||||
|
|
||||||
|
// [NotMapped]
|
||||||
|
public readonly ClientsConnected ClientsConnected = new();
|
||||||
public int UserId { get; set; }
|
public int UserId { get; set; }
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
public string IconHash { get; set; }
|
public string IconHash { get; set; }
|
||||||
|
@ -13,21 +19,22 @@ namespace LBPUnion.ProjectLighthouse.Types {
|
||||||
public int HeartCount { get; set; }
|
public int HeartCount { get; set; }
|
||||||
public string YayHash { get; set; }
|
public string YayHash { get; set; }
|
||||||
public string BooHash { get; set; }
|
public string BooHash { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A user-customizable biography shown on the profile card
|
/// A user-customizable biography shown on the profile card
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Biography { get; set; }
|
public string Biography { get; set; }
|
||||||
|
|
||||||
public int ReviewCount { get; set; }
|
public int ReviewCount { get; set; }
|
||||||
public int CommentCount { get; set; }
|
public int CommentCount { get; set; }
|
||||||
public int PhotosByMeCount { get; set; }
|
public int PhotosByMeCount { get; set; }
|
||||||
public int PhotosWithMeCount { get; set; }
|
public int PhotosWithMeCount { get; set; }
|
||||||
public bool CommentsEnabled { get; set; }
|
public bool CommentsEnabled { get; set; }
|
||||||
|
|
||||||
public int LocationId { get; set; }
|
public int LocationId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The location of the profile card on the user's earth
|
/// The location of the profile card on the user's earth
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ForeignKey("LocationId")]
|
[ForeignKey("LocationId")]
|
||||||
public Location Location { get; set; }
|
public Location Location { get; set; }
|
||||||
|
@ -41,50 +48,9 @@ namespace LBPUnion.ProjectLighthouse.Types {
|
||||||
public int StaffChallengeBronzeCount { get; set; }
|
public int StaffChallengeBronzeCount { get; set; }
|
||||||
|
|
||||||
public string PlanetHash { get; set; } = "";
|
public string PlanetHash { get; set; } = "";
|
||||||
|
|
||||||
// [NotMapped]
|
|
||||||
public readonly ClientsConnected ClientsConnected = new();
|
|
||||||
|
|
||||||
#region Slots
|
|
||||||
|
|
||||||
/// <summary>
|
public string Serialize()
|
||||||
/// The number of used slots on the earth
|
{
|
||||||
/// </summary>
|
|
||||||
public int UsedSlots { get; set; }
|
|
||||||
|
|
||||||
/// <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() {
|
|
||||||
string user = LbpSerializer.TaggedStringElement("npHandle", this.Username, "icon", this.IconHash) +
|
string user = LbpSerializer.TaggedStringElement("npHandle", this.Username, "icon", this.IconHash) +
|
||||||
LbpSerializer.StringElement("game", this.Game) +
|
LbpSerializer.StringElement("game", this.Game) +
|
||||||
this.SerializeSlots() +
|
this.SerializeSlots() +
|
||||||
|
@ -110,8 +76,55 @@ namespace LBPUnion.ProjectLighthouse.Types {
|
||||||
LbpSerializer.StringElement("planets", this.PlanetHash) +
|
LbpSerializer.StringElement("planets", this.PlanetHash) +
|
||||||
LbpSerializer.BlankElement("photos") +
|
LbpSerializer.BlankElement("photos") +
|
||||||
this.ClientsConnected.Serialize();
|
this.ClientsConnected.Serialize();
|
||||||
|
|
||||||
return LbpSerializer.TaggedStringElement("user", user, "type", "user");
|
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
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
64
README.md
64
README.md
|
@ -1,58 +1,84 @@
|
||||||
# Project Lighthouse
|
# Project Lighthouse
|
||||||
|
|
||||||
Project Lighthouse is an umbrella project for all work to investigate and develop private servers for LittleBigPlanet.
|
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.
|
This project is the main server component that LittleBigPlanet games connect to.
|
||||||
|
|
||||||
## WARNING!
|
## 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!
|
That said, feel free to develop privately!
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
This will be written when we're out of beta. Consider this your barrier to entry ;).
|
This will be written when we're out of beta. Consider this your barrier to entry ;).
|
||||||
|
|
||||||
## Running
|
## 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.
|
Lighthouse requires a MySQL database at this time. For Linux users running docker, one can be set up using
|
||||||
By default, it is `server=127.0.0.1;uid=root;pwd=lighthouse;database=lighthouse`. If you are running the database via
|
the `docker-compose.yml` file in the root of the project folder.
|
||||||
the above `docker-compose.yml` you shouldn't need to change this. For other development/especially production environments
|
|
||||||
|
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.
|
you will need to change this.
|
||||||
|
|
||||||
Once you've gotten MySQL running you can run Lighthouse. It will take care of the rest.
|
Once you've gotten MySQL running you can run Lighthouse. It will take care of the rest.
|
||||||
|
|
||||||
## Connecting
|
## 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).
|
*Note: This requires a modified copy of RPCS3. You can find a working
|
||||||
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.
|
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.
|
This should give you a file named `EBOOT.elf` in the same folder. Next, fire up UnionPatcher (making sure to select the
|
||||||
For this guide I'll use `EBOOTlocalhost.elf`.
|
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.
|
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`.
|
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.
|
Finally, take a break. Chances are that took a while.
|
||||||
|
|
||||||
## Contributing Tips
|
## Contributing Tips
|
||||||
|
|
||||||
### Database
|
### Database
|
||||||
|
|
||||||
Some modifications may require updates to the database schema. You can automatically create a migration file by:
|
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`.
|
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.
|
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`.
|
4. Running `dotnet ef migrations add <NameOfMigrationInPascalCase> --project ProjectLighthouse`.
|
||||||
|
|
||||||
|
## Compatibility across games and platforms
|
||||||
|
|
||||||
|
| Game | Console (PS3/Vita) | Emulator (RPCS3) | Next-Gen (PS4/PS5) |
|
||||||
|
|----------|------------------------|------------------------------------------------|--------------------|
|
||||||
|
| LBP1 | Somewhat compatible | Incompatible, crashes on entering pod computer | N/A |
|
||||||
|
| LBP2 | Compatible | Compatible with patched RPCS3 | N/A |
|
||||||
|
| LBP3 | Somewhat compatible | Somewhat compatible with workaround | Incompatible |
|
||||||
|
| LBP Vita | Potentially compatible | N/A | N/A |
|
||||||
|
|
||||||
|
Project Lighthouse is still a heavy work in progress, so this is subject to change at any point.
|
|
@ -14,6 +14,6 @@ services:
|
||||||
- '3306' # Expose port to localhost:3306
|
- '3306' # Expose port to localhost:3306
|
||||||
volumes:
|
volumes:
|
||||||
- lighthouse-db:/var/lib/mysql
|
- lighthouse-db:/var/lib/mysql
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
lighthouse-db:
|
lighthouse-db:
|
Loading…
Add table
Add a link
Reference in a new issue