mirror of
https://github.com/EpinelPS/EpinelPS.git
synced 2025-12-13 07:24:52 +01:00
Compare commits
74 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c733dfb5e | ||
|
|
a94878bce8 | ||
|
|
52b66947fc | ||
|
|
fa531385d1 | ||
|
|
6325cdf70a | ||
|
|
d5ae01af40 | ||
|
|
7a09c5960e | ||
|
|
d00ab6d185 | ||
|
|
7ddaef38df | ||
|
|
107e6b2eed | ||
|
|
d09b887879 | ||
|
|
01a0e70ae3 | ||
|
|
eee538f97f | ||
|
|
e2a0712889 | ||
|
|
42b17682b8 | ||
|
|
fc0e2801ed | ||
|
|
10fc4c3941 | ||
|
|
a1c910f444 | ||
|
|
f41cb1533d | ||
|
|
c1dc421e16 | ||
|
|
8a9447dc09 | ||
|
|
1c29003eaa | ||
|
|
239c4f293f | ||
|
|
0990f46266 | ||
|
|
6fb6c7b1ee | ||
|
|
467a20170f | ||
|
|
8157d5ea3c | ||
|
|
0ebc235a93 | ||
|
|
6f8497e60b | ||
|
|
a139373320 | ||
|
|
8467a5fce9 | ||
|
|
e185b7d87e | ||
|
|
35221356f8 | ||
|
|
766a8605b7 | ||
|
|
9d203958c3 | ||
|
|
78659f9c6e | ||
|
|
cce8179e8d | ||
|
|
8ba6d69ade | ||
|
|
9e331c487a | ||
|
|
e83dcdbfa8 | ||
|
|
8ea17003e6 | ||
|
|
643d3a5c7c | ||
|
|
49df23798f | ||
|
|
a8b13f8539 | ||
|
|
dea8d98db4 | ||
|
|
22d19cf38b | ||
|
|
1670142226 | ||
|
|
6ed393714f | ||
|
|
fcf9396b86 | ||
|
|
10f0641e77 | ||
|
|
9cf99754d6 | ||
|
|
7a1f361d25 | ||
|
|
db70b5068e | ||
|
|
005ad80095 | ||
|
|
15778751af | ||
|
|
645697f713 | ||
|
|
56c526cec1 | ||
|
|
702995bcfd | ||
|
|
181d1433cf | ||
|
|
1c7292b68b | ||
|
|
3dfcac2cef | ||
|
|
5134ac187b | ||
|
|
367cd64b8e | ||
|
|
01f86a7d24 | ||
|
|
ecbb9dfe3b | ||
|
|
b63478f0b4 | ||
|
|
9e79ae0e80 | ||
|
|
b34383883b | ||
|
|
71f975b5ce | ||
|
|
20213153ab | ||
|
|
9356d347bd | ||
|
|
c1d783b1e7 | ||
|
|
3865b403b4 | ||
|
|
618619e36d |
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -1,3 +1,2 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
cert.sh eol=lf
|
||||
* text=auto
|
||||
4
.github/workflows/dotnet-desktop.yml
vendored
4
.github/workflows/dotnet-desktop.yml
vendored
@@ -39,10 +39,10 @@ jobs:
|
||||
run: dotnet publish ServerSelector.Desktop
|
||||
|
||||
- name: Publish Server
|
||||
run: dotnet publish nksrv
|
||||
run: dotnet publish EpinelPS
|
||||
|
||||
- name: Copy to output
|
||||
run: echo ${{ github.workspace }} && md ${{ github.workspace }}/out/ && xcopy "${{ github.workspace }}\ServerSelector.Desktop\bin\Release\net8.0\win-x64\publish\" "${{ github.workspace }}\out\" && xcopy "${{ github.workspace }}\nksrv\bin\Release\net8.0\win-x64\publish\" "${{ github.workspace }}\out\" && copy "${{ github.workspace }}\ServerSelector.Desktop\sodium.dll" "${{ github.workspace }}\out\sodium.dll"
|
||||
run: echo ${{ github.workspace }} && md ${{ github.workspace }}/out/ && xcopy /s /e "${{ github.workspace }}\ServerSelector.Desktop\bin\Release\net8.0\win-x64\publish\" "${{ github.workspace }}\out\" && xcopy /s /e "${{ github.workspace }}\EpinelPS\bin\Release\net8.0\win-x64\publish\" "${{ github.workspace }}\out\" && copy "${{ github.workspace }}\ServerSelector.Desktop\sodium.dll" "${{ github.workspace }}\out\sodium.dll"
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -454,6 +454,8 @@ $RECYCLE.BIN/
|
||||
!.vscode/extensions.json
|
||||
|
||||
# Allow pregenerated ssl cert
|
||||
!nksrv/site.pfx
|
||||
!EpinelPS/site.pfx
|
||||
!ServerSelector/myCA.pfx
|
||||
!ServerSelector/sodium.dll
|
||||
!ServerSelector/sodium.dll
|
||||
|
||||
EpinelPS/Protos/allmsgs.proto
|
||||
@@ -1,10 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,57 +0,0 @@
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
|
||||
namespace DataFixupUtil
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Hello, World!");
|
||||
|
||||
foreach(var arg in Directory.GetFiles("C:\\NIKKE\\NIKKE\\Game"))
|
||||
{
|
||||
var fileName = Path.GetFileName(arg);
|
||||
if (fileName.StartsWith("input"))
|
||||
{
|
||||
byte[] FileContents = File.ReadAllBytes(arg);
|
||||
using MemoryStream ms = new MemoryStream(FileContents);
|
||||
File.WriteAllBytes("fullPkt-decr", ms.ToArray());
|
||||
|
||||
var unkVal1 = ms.ReadByte();
|
||||
var pktLen = ms.ReadByte() & 0x1f;
|
||||
|
||||
|
||||
var seqNumB = ms.ReadByte();
|
||||
var seqNum = seqNumB;
|
||||
if (seqNumB >= 24)
|
||||
{
|
||||
var b = ms.ReadByte();
|
||||
|
||||
seqNum = BitConverter.ToUInt16(new byte[] { (byte)b, (byte)seqNumB }, 0);
|
||||
|
||||
// todo support uint32
|
||||
}
|
||||
|
||||
var startPos = (int)ms.Position;
|
||||
|
||||
var contents = FileContents.Skip(startPos).ToArray();
|
||||
if (contents.Length > 2 && contents[0] == 0x1f && contents[1] == 0x8b)
|
||||
{
|
||||
// gzip compression is used
|
||||
using Stream csStream = new GZipStream(new MemoryStream(contents), CompressionMode.Decompress);
|
||||
using MemoryStream decoded = new MemoryStream();
|
||||
csStream.CopyTo(decoded);
|
||||
|
||||
contents = decoded.ToArray();
|
||||
File.WriteAllBytes(arg, contents);
|
||||
}
|
||||
else
|
||||
{
|
||||
File.WriteAllBytes(arg, contents);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,11 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.10.34928.147
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "nksrv", "nksrv\nksrv.csproj", "{5C24A07E-9B8D-4625-BF91-0E9CCBEF5CB0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataFixupUtil", "DataFixupUtil\DataFixupUtil.csproj", "{13124DFB-448B-4F4F-A479-537EE067D836}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProtobufViewUtil", "ProtobufViewUtil\ProtobufViewUtil.csproj", "{FDEDD0D6-9C02-4E58-8110-04E8D5639881}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EpinelPS", "EpinelPS\EpinelPS.csproj", "{5C24A07E-9B8D-4625-BF91-0E9CCBEF5CB0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServerSelector", "ServerSelector\ServerSelector.csproj", "{EC613C24-8A35-42E8-92C1-9A8431F74F58}"
|
||||
EndProject
|
||||
@@ -55,54 +51,6 @@ Global
|
||||
{5C24A07E-9B8D-4625-BF91-0E9CCBEF5CB0}.ReleaseDLL|x64.Build.0 = Release|Any CPU
|
||||
{5C24A07E-9B8D-4625-BF91-0E9CCBEF5CB0}.ReleaseDLL|x86.ActiveCfg = Release|Any CPU
|
||||
{5C24A07E-9B8D-4625-BF91-0E9CCBEF5CB0}.ReleaseDLL|x86.Build.0 = Release|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.DebugDLL|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.DebugDLL|Any CPU.Build.0 = Debug|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.DebugDLL|x64.ActiveCfg = Debug|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.DebugDLL|x64.Build.0 = Debug|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.DebugDLL|x86.ActiveCfg = Debug|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.DebugDLL|x86.Build.0 = Debug|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.Release|x64.Build.0 = Release|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.Release|x86.Build.0 = Release|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.ReleaseDLL|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.ReleaseDLL|Any CPU.Build.0 = Release|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.ReleaseDLL|x64.ActiveCfg = Release|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.ReleaseDLL|x64.Build.0 = Release|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.ReleaseDLL|x86.ActiveCfg = Release|Any CPU
|
||||
{13124DFB-448B-4F4F-A479-537EE067D836}.ReleaseDLL|x86.Build.0 = Release|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.DebugDLL|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.DebugDLL|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.DebugDLL|x64.ActiveCfg = Debug|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.DebugDLL|x64.Build.0 = Debug|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.DebugDLL|x86.ActiveCfg = Debug|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.DebugDLL|x86.Build.0 = Debug|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.Release|x64.Build.0 = Release|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.Release|x86.Build.0 = Release|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.ReleaseDLL|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.ReleaseDLL|Any CPU.Build.0 = Release|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.ReleaseDLL|x64.ActiveCfg = Release|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.ReleaseDLL|x64.Build.0 = Release|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.ReleaseDLL|x86.ActiveCfg = Release|Any CPU
|
||||
{FDEDD0D6-9C02-4E58-8110-04E8D5639881}.ReleaseDLL|x86.Build.0 = Release|Any CPU
|
||||
{EC613C24-8A35-42E8-92C1-9A8431F74F58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EC613C24-8A35-42E8-92C1-9A8431F74F58}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EC613C24-8A35-42E8-92C1-9A8431F74F58}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
106
EpinelPS/Controllers/AccountController.cs
Normal file
106
EpinelPS/Controllers/AccountController.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EpinelPS.Controllers
|
||||
{
|
||||
[Route("account")]
|
||||
[ApiController]
|
||||
public class AccountController : ControllerBase
|
||||
{
|
||||
private const string BadAuthToken = "{\"msg\":\"the account does not exists!\",\"ret\":2001,\"seq\":\"123" + "\"}";
|
||||
|
||||
[HttpPost]
|
||||
[Route("login")]
|
||||
public string Login(string seq, [FromBody] LoginEndpoint2Req req)
|
||||
{
|
||||
foreach (var item in JsonDb.Instance.Users)
|
||||
{
|
||||
if (item.Username == req.account && item.Password == req.password)
|
||||
{
|
||||
var tok = CreateLauncherTokenForUser(item);
|
||||
item.LastLogin = DateTime.UtcNow;
|
||||
JsonDb.Save();
|
||||
|
||||
return "{\"expire\":" + tok.ExpirationTime + ",\"is_login\":true,\"msg\":\"Success\",\"register_time\":" + item.RegisterTime + ",\"ret\":0,\"seq\":\"" + seq + "\",\"token\":\"" + tok.Token + "\",\"uid\":\"" + item.ID + "\"}";
|
||||
}
|
||||
}
|
||||
|
||||
return "{\"msg\":\"the account does not exists!\",\"ret\":2001,\"seq\":\"" + seq + "\"}";
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
[Route("sendcode")]
|
||||
public string SendCode(string seq, [FromBody] SendCodeRequest req)
|
||||
{
|
||||
// Pretend that we send a code.
|
||||
return "{\"expire_time\":898,\"msg\":\"Success\",\"ret\":0,\"seq\":\"" + seq + "\"}";
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("codestatus")]
|
||||
public string CodeStatus(string seq, [FromBody] SendCodeRequest req)
|
||||
{
|
||||
// Pretend that code is valid
|
||||
return "{\"expire_time\":759,\"msg\":\"Success\",\"ret\":0,\"seq\":\"" + seq + "\"}";
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("getuserinfo")]
|
||||
public string GetUserInfo(string seq, [FromBody] AuthPkt2 req)
|
||||
{
|
||||
(User?, AccessToken?) res;
|
||||
if ((res = NetUtils.GetUser(req.token)).Item1 == null) return BadAuthToken;
|
||||
User user = res.Item1;
|
||||
AccessToken? tok = res.Item2;
|
||||
|
||||
// Pretend that code is valid
|
||||
return "{\"account_type\":1,\"birthday\":\"1970-01\",\"email\":\"" + user.Username + "\",\"expire\":" + tok.ExpirationTime + ",\"is_receive_email\":1,\"is_receive_email_in_night\":0,\"is_receive_video\":-1,\"lang_type\":\"en\",\"msg\":\"Success\",\"nick_name\":\"\",\"phone\":\"\",\"phone_area_code\":\"\",\"privacy_policy\":\"1\",\"privacy_update_time\":1717783097,\"region\":\"724\",\"ret\":0,\"seq\":\"" + seq + "\",\"terms_of_service\":\"\",\"terms_update_time\":0,\"uid\":\"" + user.ID + "\",\"user_agreed_dt\":\"\",\"user_agreed_pp\":\"1\",\"user_agreed_tos\":\"\",\"user_name\":\"" + user.PlayerName + "\",\"username_pass_verify\":0}";
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("register")]
|
||||
public string RegisterAccount(string seq, [FromBody] RegisterEPReq req)
|
||||
{
|
||||
// check if the account already exists
|
||||
foreach (var item in JsonDb.Instance.Users)
|
||||
{
|
||||
if (item.Username == req.account)
|
||||
{
|
||||
return "{\"msg\":\"send code failed; invalid account\",\"ret\":2112,\"seq\":\"" + seq + "\"}";
|
||||
}
|
||||
}
|
||||
|
||||
var uid = (ulong)new Random().Next(1, int.MaxValue);
|
||||
|
||||
// Check if we havent generated a UID that exists
|
||||
foreach (var item in JsonDb.Instance.Users)
|
||||
{
|
||||
if (item.ID == uid)
|
||||
{
|
||||
uid -= (ulong)new Random().Next(1, 1221);
|
||||
}
|
||||
}
|
||||
|
||||
var user = new User() { ID = uid, Password = req.password, RegisterTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds(), Username = req.account, PlayerName = "Player_" + Rng.RandomString(8) };
|
||||
|
||||
JsonDb.Instance.Users.Add(user);
|
||||
|
||||
var tok = CreateLauncherTokenForUser(user);
|
||||
|
||||
return "{\"expire\":" + tok.ExpirationTime + ",\"is_login\":false,\"msg\":\"Success\",\"register_time\":" + user.RegisterTime + ",\"ret\":0,\"seq\":\"" + seq + "\",\"token\":\"" + tok.Token + "\",\"uid\":\"" + user.ID + "\"}";
|
||||
}
|
||||
public static AccessToken CreateLauncherTokenForUser(User user)
|
||||
{
|
||||
// TODO: implement access token expiration
|
||||
AccessToken token = new() { ExpirationTime = DateTimeOffset.UtcNow.AddYears(1).ToUnixTimeSeconds() };
|
||||
token.Token = Rng.RandomString(64);
|
||||
token.UserID = user.ID;
|
||||
JsonDb.Instance.LauncherAccessTokens.Add(token);
|
||||
JsonDb.Save();
|
||||
|
||||
return token;
|
||||
}
|
||||
}
|
||||
}
|
||||
98
EpinelPS/Controllers/AdminApiController.cs
Normal file
98
EpinelPS/Controllers/AdminApiController.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.LobbyServer;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace EpinelPS.Controllers
|
||||
{
|
||||
[Route("adminapi")]
|
||||
[ApiController]
|
||||
public class AdminApiController : ControllerBase
|
||||
{
|
||||
public static Dictionary<string, User> AdminAuthTokens = new();
|
||||
private static MD5 md5 = MD5.Create();
|
||||
|
||||
[HttpPost]
|
||||
[Route("login")]
|
||||
public LoginApiResponse Login([FromBody] LoginApiBody b)
|
||||
{
|
||||
User? user = null;
|
||||
bool nullusernames = false;
|
||||
if (b.Username != null && b.Password != null)
|
||||
{
|
||||
var passwordHash = Convert.ToHexString(md5.ComputeHash(Encoding.ASCII.GetBytes(b.Password))).ToLower();
|
||||
foreach (var item in JsonDb.Instance.Users)
|
||||
{
|
||||
if (item.Username == b.Username)
|
||||
{
|
||||
if (item.Password.ToLower() == passwordHash)
|
||||
{
|
||||
user = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nullusernames = true;
|
||||
}
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
if (nullusernames)
|
||||
{
|
||||
return new LoginApiResponse() { Message = "Please enter a username and password" };
|
||||
}
|
||||
else
|
||||
{
|
||||
return new LoginApiResponse() { Message = "Username or password is incorrect" };
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (user.IsAdmin)
|
||||
{
|
||||
var tok = CreateAuthToken(user);
|
||||
HttpContext.Response.Cookies.Append("token", tok);
|
||||
return new LoginApiResponse() { OK = true, Token = tok };
|
||||
}
|
||||
else
|
||||
{
|
||||
return new LoginApiResponse() { Message = "User is not an administrator." };
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static string CreateAuthToken(User user)
|
||||
{
|
||||
var tok = RandomString(128);
|
||||
AdminAuthTokens.Add(tok, user);
|
||||
return tok;
|
||||
}
|
||||
|
||||
public static string RandomString(int length)
|
||||
{
|
||||
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
return new string(Enumerable.Repeat(chars, length)
|
||||
.Select(s => s[new Random().Next(s.Length)]).ToArray());
|
||||
}
|
||||
|
||||
public class LoginApiBody
|
||||
{
|
||||
[Required]
|
||||
public string Username { get; set; } = "";
|
||||
[Required]
|
||||
public string Password { get; set; } = "";
|
||||
}
|
||||
public class LoginApiResponse
|
||||
{
|
||||
public string Message { get; set; } = "";
|
||||
public bool OK { get; set; }
|
||||
public string Token { get; set; } = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
58
EpinelPS/Controllers/AdminController.cs
Normal file
58
EpinelPS/Controllers/AdminController.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using EpinelPS.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace EpinelPS.Controllers
|
||||
{
|
||||
[Route("admin")]
|
||||
public class AdminController : Controller
|
||||
{
|
||||
private readonly ILogger<AdminController> _logger;
|
||||
|
||||
public AdminController(ILogger<AdminController> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
[Route("index")]
|
||||
public IActionResult Index()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
[Route("dashboard")]
|
||||
public IActionResult Dashboard()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
[Route("Events")]
|
||||
public IActionResult Events()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
[Route("Configuration")]
|
||||
public IActionResult Configuration()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
[Route("Users")]
|
||||
public IActionResult Users()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
[Route("Mail")]
|
||||
public IActionResult Mail()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
[Route("Database")]
|
||||
public IActionResult Database()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
public IActionResult Error()
|
||||
{
|
||||
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
|
||||
}
|
||||
}
|
||||
}
|
||||
97
EpinelPS/Controllers/LauncherController.cs
Normal file
97
EpinelPS/Controllers/LauncherController.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EpinelPS.Controllers
|
||||
{
|
||||
[Route("/api/v1")]
|
||||
[ApiController]
|
||||
public class LauncherController : Controller
|
||||
{
|
||||
[HttpPost]
|
||||
[Route("fleet.auth.game.AuthSvr/Login")]
|
||||
public string LauncherLogin()
|
||||
{
|
||||
return @"{
|
||||
""result"": {
|
||||
""error_code"": 0,
|
||||
""error_message"": ""COMM_SUCC""
|
||||
},
|
||||
""channel"": 0,
|
||||
""game_id"": ""0"",
|
||||
""openid"": """",
|
||||
""uid"": """",
|
||||
""biz_ticket"": """",
|
||||
""expire_interval"": 0,
|
||||
""refresh_interval"": 0,
|
||||
""login_key"": """",
|
||||
""login_ticket"": """",
|
||||
""third_uid"": """"
|
||||
}";
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("fleet.repo.game.RepoSVC/GetRegion")]
|
||||
public string LauncherGetRegion()
|
||||
{
|
||||
return @"{
|
||||
""result"": {
|
||||
""error_code"": 0,
|
||||
""error_message"": ""success""
|
||||
},
|
||||
""region_info"": [
|
||||
{
|
||||
""game_id"": ""16601"",
|
||||
""region_id"": ""10001"",
|
||||
""region_name_en_us"": ""Global"",
|
||||
""region_name_i18n"": """",
|
||||
""region_description_en_us"": ""Nikke Global Version"",
|
||||
""region_description_i18n"": """",
|
||||
""bind_branches"": """",
|
||||
""meta_data"": """",
|
||||
""sequence"": 0,
|
||||
""status"": 2,
|
||||
""branch_info"": [
|
||||
{
|
||||
""game_id"": ""16601"",
|
||||
""branch_id"": ""1"",
|
||||
""branch_name"": ""Official_release"",
|
||||
""branch_type"": 0,
|
||||
""description"": ""正式发布环境 release包""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}";
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("fleet.repo.game.RepoSVC/GetGameLauncher")]
|
||||
public string LauncherGetLauncher()
|
||||
{
|
||||
return @"{
|
||||
""result"": {
|
||||
""error_code"": 0,
|
||||
""error_message"": ""COMM_SUCC""
|
||||
},
|
||||
""game_launcher_info"": [
|
||||
{
|
||||
""id"": 27,
|
||||
""execute_file"": ""NIKKE\\Game\\NIKKE.exe"",
|
||||
""param"": """",
|
||||
""description"": ""Nikke main process"",
|
||||
""os"": ""any"",
|
||||
""branch_id"": 0,
|
||||
""status"": 1,
|
||||
""param_type"": 1
|
||||
}
|
||||
]
|
||||
}";
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("fleet.repo.game.RepoSVC/GetVersion")]
|
||||
public string LauncherGetVersion()
|
||||
{
|
||||
return System.IO.File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "gameversion.json"));
|
||||
}
|
||||
}
|
||||
}
|
||||
129
EpinelPS/Controllers/LevelInfiniteControlller.cs
Normal file
129
EpinelPS/Controllers/LevelInfiniteControlller.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EpinelPS.Controllers
|
||||
{
|
||||
[Route("/v2")]
|
||||
[ApiController]
|
||||
public class LevelInfiniteControlller : Controller
|
||||
{
|
||||
private const string BadAuthToken = "{\"msg\":\"the account does not exists!\",\"ret\":2001,\"seq\":\"123" + "\"}";
|
||||
|
||||
[HttpPost]
|
||||
[Route("conf/get_conf")]
|
||||
public string GetConfig(string sig)
|
||||
{
|
||||
return "{\"conf_version\":\"102\",\"msg\":\"\",\"ret\":1,\"seq\":\"" + sig + "\"}";
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
[Route("auth/login")]
|
||||
public string AuthLogin(string seq, [FromBody] LoginEndpoint1Req req)
|
||||
{
|
||||
foreach (var tok in JsonDb.Instance.LauncherAccessTokens)
|
||||
{
|
||||
if (tok.Token == req.channel_info.account_token)
|
||||
{
|
||||
var user = JsonDb.Instance.Users.Find(x => x.ID == tok.UserID);
|
||||
if (user != null)
|
||||
{
|
||||
// todo: they use another token here, but we will reuse the same one.
|
||||
// todo: use a class for this, this is a mess
|
||||
return "{\"birthday\":\"1970-01\",\"channel_info\":{\"account\":\"" + user.Username + "\",\"account_plat_type\":131,\"account_token\":\"" + req.channel_info.account_token + "\",\"account_type\":1,\"account_uid\":\"" + user.ID + "\",\"expire_ts\":1721667004,\"is_login\":true,\"lang_type\":\"en\",\"phone_area_code\":\"\",\"token\":\"" + req.channel_info.account_token + "\"},\"del_account_info\":\"{\\\"ret\\\":0,\\\"msg\\\":\\\"\\\",\\\"status\\\":0,\\\"created_at\\\":\\\"0\\\",\\\"target_destroy_at\\\":\\\"0\\\",\\\"destroyed_at\\\":\\\"0\\\",\\\"err_code\\\":0,\\\"seq\\\":\\\"1719075066-0339089836-025921-1161847390\\\"}\",\"del_account_status\":0,\"del_li_account_status\":0,\"email\":\"" + user.Username + "\",\"extra_json\":{\"del_li_account_info\":\"{\\\"ret\\\":0,\\\"msg\\\":\\\"\\\",\\\"status\\\":0,\\\"created_at\\\":\\\"0\\\",\\\"target_destroy_at\\\":\\\"0\\\",\\\"destroyed_at\\\":\\\"0\\\",\\\"err_code\\\":0,\\\"seq\\\":\\\"" + seq + "\\\"}\",\"get_status_rsp\":{\"adult_age\":14,\"adult_age_map\":{},\"adult_check_status\":1,\"adult_check_status_expiration\":\"0\",\"adult_status_map\":{},\"certificate_type\":3,\"email\":\"\",\"eu_user_agree_status\":0,\"game_grade\":0,\"game_grade_map\":{},\"is_dma\":true,\"is_eea\":false,\"is_need_li_cert\":false,\"msg\":\"success\",\"need_parent_control\":0,\"need_realname_auth\":0,\"parent_certificate_status\":0,\"parent_certificate_status_expiration\":\"0\",\"parent_control_map\":{},\"qr_code_ret\":0,\"realname_auth_status\":0,\"region\":\"724\",\"ret\":0,\"ts\":\"1719075065\"},\"need_notify_rsp\":{\"game_sacc_openid\":\"\",\"game_sacc_uid\":\"\",\"has_game_sacc_openid\":false,\"has_game_sacc_uid\":false,\"has_li_openid\":true,\"has_li_uid\":true,\"is_receive_email\":1,\"is_receive_email_in_night\":0,\"li_openid\":\"" + user.ID + "\",\"li_uid\":\"2752409592679849\",\"need_notify\":false,\"user_agreed_game_dma\":\"2\",\"user_agreed_game_pp\":\"1\",\"user_agreed_game_tos\":\"1\",\"user_agreed_li_dt\":\"\",\"user_agreed_li_pp\":\"1\",\"user_agreed_li_tos\":\"\"}},\"first_login\":0,\"gender\":0,\"msg\":\"success\",\"need_name_auth\":false,\"openid\":\"" + user.ID + "\",\"pf\":\"LevelInfinite_LevelInfinite-Windows-windows-Windows-LevelInfinite-09af79d65d6e4fdf2d2569f0d365739d-" + user.ID + "\",\"pf_key\":\"abc\",\"picture_url\":\"\",\"reg_channel_dis\":\"Windows\",\"ret\":0,\"seq\":\"29080-2d28ea26-d71f-4822-9118-0156f1e2dba4-1719075060-99\",\"token\":\"" + tok.Token + "\",\"token_expire_time\":" + tok.ExpirationTime + ",\"uid\":\"" + user.ID + "\",\"user_name\":\"" + user.PlayerName + "\"}";
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: proper token expired message
|
||||
return "{\"msg\":\"the account does not exists!\",\"ret\":2001,\"seq\":\"" + seq + "\"}";
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("auth/auto_login")]
|
||||
public string AutoLogin(string seq)
|
||||
{
|
||||
return "{\"del_account_info\":\"{\\\"ret\\\":0,\\\"msg\\\":\\\"\\\",\\\"status\\\":0,\\\"created_at\\\":\\\"0\\\",\\\"target_destroy_at\\\":\\\"0\\\",\\\"destroyed_at\\\":\\\"0\\\",\\\"err_code\\\":0,\\\"seq\\\":\\\"" + seq + "\\\"}\",\"del_account_status\":0,\"del_li_account_status\":0,\"extra_json\":{\"del_li_account_info\":\"{\\\"ret\\\":0,\\\"msg\\\":\\\"\\\",\\\"status\\\":0,\\\"created_at\\\":\\\"0\\\",\\\"target_destroy_at\\\":\\\"0\\\",\\\"destroyed_at\\\":\\\"0\\\",\\\"err_code\\\":0,\\\"seq\\\":\\\"" + seq + "\\\"}\",\"get_status_msg\":\"success\",\"get_status_ret\":0,\"get_status_rsp\":{\"adult_age\":14,\"adult_age_map\":{},\"adult_check_status\":1,\"adult_check_status_expiration\":\"0\",\"adult_status_map\":{},\"certificate_type\":3,\"email\":\"\",\"eu_user_agree_status\":0,\"game_grade\":0,\"game_grade_map\":{},\"is_dma\":true,\"is_eea\":false,\"is_need_li_cert\":false,\"msg\":\"success\",\"need_parent_control\":0,\"need_realname_auth\":0,\"parent_certificate_status\":0,\"parent_certificate_status_expiration\":\"0\",\"parent_control_map\":{},\"qr_code_ret\":0,\"realname_auth_status\":0,\"region\":\"724\",\"ret\":0,\"ts\":\"" + DateTimeOffset.UtcNow.ToUnixTimeSeconds()
|
||||
+ "\"},\"need_notify_msg\":\"success\",\"need_notify_ret\":0,\"need_notify_rsp\":{\"has_bind_li\":true,\"is_receive_email\":1,\"is_receive_email_in_night\":0,\"user_agreed_game_dma\":\"2\",\"user_agreed_game_pp\":\"1\",\"user_agreed_game_tos\":\"1\",\"user_agreed_li_dt\":\"\",\"user_agreed_li_pp\":\"1\",\"user_agreed_li_tos\":\"\"}},\"msg\":\"success\",\"ret\":0,\"seq\":\"" + seq + "\"}";
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("minorcer/get_status")]
|
||||
public string MinorcerStatus(string seq)
|
||||
{
|
||||
return "{\"adult_age\":15,\"adult_age_map\":{},\"adult_check_status\":1,\"adult_check_status_expiration\":\"0\",\"adult_status_map\":{},\"certificate_type\":3,\"email\":\"\",\"eu_user_agree_status\":0,\"game_grade\":0,\"game_grade_map\":{},\"is_dma\":true,\"is_eea\":false,\"is_need_li_cert\":false,\"msg\":\"success\",\"need_parent_control\":0,\"need_realname_auth\":0,\"parent_certificate_status\":0,\"parent_certificate_status_expiration\":\"0\",\"parent_control_map\":{},\"qr_code_ret\":0,\"realname_auth_status\":0,\"region\":\"300\",\"ret\":0,\"seq\":\"" + seq + "\",\"ts\":\"1719156511\"}";
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("profile/userinfo")]
|
||||
public string QueryUserInfo(string seq, [FromBody] AuthPkt2 req)
|
||||
{
|
||||
User? user;
|
||||
if ((user = NetUtils.GetUser(req.token).Item1) == null) return BadAuthToken;
|
||||
|
||||
return "{\"bind_list\":[{\"channel_info\":{\"birthday\":\"1970-01\",\"email\":\"" + user.Username + "\",\"is_receive_email\":1,\"lang_type\":\"en\",\"last_login_time\":1719075003,\"nick_name\":\"\",\"phone\":\"\",\"phone_area_code\":\"\",\"region\":\"724\",\"register_account\":\"" + user.Username + "\",\"register_account_type\":1,\"register_time\":" + user.RegisterTime + ",\"seq\":\"abc\",\"uid\":\"" + user.ID + "\",\"user_name\":\"" + user.PlayerName + "\",\"username_pass_verify\":0},\"channelid\":131,\"email\":\"" + user.Username + "\",\"picture_url\":\"\",\"user_name\":\"" + user.PlayerName + "\"}],\"birthday\":\"1970-01\",\"email\":\"" + user.Username + "\",\"gender\":0,\"msg\":\"success\",\"picture_url\":\"\",\"ret\":0,\"seq\":\"" + seq + "\",\"user_name\":\"" + user.PlayerName + "\"}";
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("profile/query_account_info")]
|
||||
public string QueryAccountInfo(string seq, [FromBody] AuthPkt req)
|
||||
{
|
||||
User? user;
|
||||
if ((user = NetUtils.GetUser(req.channel_info.token).Item1) == null) return BadAuthToken;
|
||||
|
||||
// Pretend that code is valid
|
||||
return "{\"game_sacc_openid\":\"\",\"game_sacc_uid\":\"\",\"has_game_sacc_openid\":false,\"has_game_sacc_uid\":false,\"has_li_openid\":false,\"has_li_uid\":true,\"is_receive_email\":-1,\"is_receive_email_in_night\":-1,\"li_openid\":\"\",\"li_uid\":\"" + user.ID + "\",\"msg\":\"success\",\"need_notify\":false,\"ret\":0,\"seq\":\"" + seq + "\",\"user_agreed_game_dma\":\"\",\"user_agreed_game_pp\":\"\",\"user_agreed_game_tos\":\"\",\"user_agreed_li_dt\":\"\",\"user_agreed_li_pp\":\"\",\"user_agreed_li_tos\":\"\"}";
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
[Route("reward/send")]
|
||||
public string SendDailyReward(string seq)
|
||||
{
|
||||
// Level infinite pass daily reward coints, not implemented as they are inaccessible currently
|
||||
return "{\"msg\":\"success\",\"ret\":0,\"seq\":\"" + seq + "\"}";
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("profile/set_protocol")]
|
||||
public string SetProtocol(string seq)
|
||||
{
|
||||
// Enable encryption, not used in this server.
|
||||
return "{\"msg\":\"success\",\"ret\":0,\"seq\":\"" + seq + "\"}";
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("notice/get_notice_content")]
|
||||
public string GetNotices(string seq)
|
||||
{
|
||||
return "{\r\n \"msg\": \"success\",\r\n \"notice_list\": [\r\n {\r\n \"app_id\": \"3001001\",\r\n \"app_notice_id\": \"post-6rpvwgrdx1b\",\r\n \"area_list\": \"[\\\"81\\\",\\\"82\\\",\\\"83\\\",\\\"84\\\",\\\"85\\\"]\",\r\n \"content_list\": [\r\n {\r\n \"app_content_id\": \"post-9ilpu79xxzp\",\r\n \"content\": \"This isn't working\",\r\n \"extra_data\": \"{}\",\r\n \"id\": 48706,\r\n \"lang_type\": \"en\",\r\n \"picture_list\": [\r\n {\r\n \"extra_data\": \"{\\\"id\\\":\\\"TitleImage\\\"}\",\r\n \"hash\": \"44a99a61152b5b80a0466ff9f0cee2bc\",\r\n \"redirect_url\": \"\",\r\n \"url\": \"pnt-console-cdn.playernetwork.intlgame.com/prod/29080/notice/022681b1121a40259a575fbe587651b4.jpg\"\r\n }\r\n ],\r\n \"title\": \"New Character\",\r\n \"update_time\": 1717637493\r\n }\r\n ],\r\n \"end_time\": 1819431999,\r\n \"extra_data\": \"{\\\"NoticeType\\\":\\\"Event\\\",\\\"Order\\\":\\\"11\\\",\\\"extra_reserved\\\":\\\"{\\\\\\\"Author\\\\\\\":\\\\\\\"\\\\\\\",\\\\\\\"Category\\\\\\\":\\\\\\\"\\\\\\\",\\\\\\\"CreateType\\\\\\\":\\\\\\\"4\\\\\\\",\\\\\\\"IsOpenService\\\\\\\":\\\\\\\"0\\\\\\\",\\\\\\\"IsToping\\\\\\\":true,\\\\\\\"Keyword\\\\\\\":\\\\\\\"\\\\\\\",\\\\\\\"Sort\\\\\\\":\\\\\\\"\\\\\\\",\\\\\\\"TopEnd\\\\\\\":\\\\\\\"2030-01-01 00:00:01\\\\\\\",\\\\\\\"TopStart\\\\\\\":\\\\\\\"2000-01-01 00:00:01\\\\\\\"}\\\"}\",\r\n \"id\": 7560,\r\n \"picture_list\": [],\r\n \"start_time\": 1717617599,\r\n \"status\": 1,\r\n \"update_time\": 1717637494\r\n }\r\n ],\r\n \"ret\": 0,\r\n \"seq\": \"" + seq + "\"\r\n}";
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("lbs/ipregion")]
|
||||
public string GetIpRegion(string seq)
|
||||
{
|
||||
return "{\"alpha2\":\"GR\",\"extra_json\":{\"certificate_type_map\":{}},\"msg\":\"success\",\"region\":\"300\",\"ret\":0,\"seq\":\"" + seq + "\",\"timestamp\":324234322}";
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("gnconfig/acquire_config")]
|
||||
public string AcquireConfig(string seq)
|
||||
{
|
||||
return "{\"ret\":23111202,\"msg\":\"no matched config error( [match logic]no match )\",\"rule_id\":\"\",\"resource_list\":\"\",\"sdk_enable\":0,\"sdk_debug_enable\":0,\"report_log_enable\":0,\"log_level\":0,\"inner_seq\":\"" + seq + "\",\"ab_test\":{\"id\":\"\",\"group\":\"\"},\"seq\":\"" + seq + "\"}";
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("profile/get_bind_info")]
|
||||
public string GetProfileBindInfo(string seq, [FromBody] AuthPkt req)
|
||||
{
|
||||
User? user;
|
||||
if ((user = NetUtils.GetUser(req.channel_info.token).Item1) == null) return BadAuthToken;
|
||||
|
||||
return "{\"bind_list\":[{\"bind_ts\":1717783095,\"channel_info\":{\"birthday\":\"1970-01\",\"email\":\"" + user.Username + "\",\"is_receive_email\":1,\"lang_type\":\"en\",\"last_login_time\":171000000,\"nick_name\":\"\",\"phone\":\"\",\"phone_area_code\":\"\",\"region\":\"724\",\"register_account\":\"" + user.Username + "\",\"register_account_type\":1,\"register_time\":" + user.RegisterTime + ",\"seq\":\"" + seq + "\",\"uid\":\"2752409592679849\",\"user_name\":\"" + user.PlayerName + "\",\"username_pass_verify\":0},\"channelid\":131,\"email\":\"" + user.Username + "\",\"history_scopes\":[],\"is_primary\":1,\"picture_url\":\"\",\"user_name\":\"" + user.PlayerName + "\"}],\"create_ts\":" + user.RegisterTime + ",\"last_login_ts\":171000000,\"msg\":\"success\",\"ret\":0,\"seq\":\"" + seq + "\"}";
|
||||
}
|
||||
}
|
||||
}
|
||||
18
EpinelPS/Controllers/LobbyApiController.cs
Normal file
18
EpinelPS/Controllers/LobbyApiController.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using EpinelPS.LobbyServer;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EpinelPS.Controllers
|
||||
{
|
||||
[Route("v1")]
|
||||
[ApiController]
|
||||
public class LobbyApiController : ControllerBase
|
||||
{
|
||||
[HttpPost]
|
||||
[Route("{**all}", Order = int.MaxValue)]
|
||||
[Consumes("application/octet-stream+protobuf")]
|
||||
public async Task CatchAll(string all)
|
||||
{
|
||||
await LobbyHandler.DispatchSingle(HttpContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
405
EpinelPS/Database/JsonDb.cs
Normal file
405
EpinelPS/Database/JsonDb.cs
Normal file
@@ -0,0 +1,405 @@
|
||||
using EpinelPS.LobbyServer;
|
||||
using EpinelPS.StaticInfo;
|
||||
using EpinelPS.Utils;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace EpinelPS.Database
|
||||
{
|
||||
public class AccessToken
|
||||
{
|
||||
public string Token = "";
|
||||
public long ExpirationTime;
|
||||
public ulong UserID;
|
||||
}
|
||||
public class FieldInfo
|
||||
{
|
||||
public List<NetFieldStageData> CompletedStages = [];
|
||||
public List<NetFieldObject> CompletedObjects = [];
|
||||
}
|
||||
|
||||
public class FieldInfoNew
|
||||
{
|
||||
public List<int> CompletedStages = [];
|
||||
public List<NetFieldObject> CompletedObjects = [];
|
||||
}
|
||||
|
||||
public class Character
|
||||
{
|
||||
public int Csn = 0;
|
||||
public int Tid = 0;
|
||||
public int CostumeId = 0;
|
||||
|
||||
public int Level = 1;
|
||||
public int UltimateLevel = 1;
|
||||
public int Skill1Lvl = 1;
|
||||
public int Skill2Lvl = 1;
|
||||
public int Grade = 0;
|
||||
}
|
||||
public class MainQuestData
|
||||
{
|
||||
public int TableId = 0;
|
||||
public bool IsReceieved = false;
|
||||
}
|
||||
|
||||
public class UserPointData
|
||||
{
|
||||
public int UserLevel = 1;
|
||||
public int ExperiencePoint = 0;
|
||||
}
|
||||
|
||||
public class ItemData
|
||||
{
|
||||
public int ItemType;
|
||||
public long Csn;
|
||||
public int Count;
|
||||
public int Level;
|
||||
public int Exp;
|
||||
public int Position;
|
||||
public int Corp;
|
||||
public long Isn;
|
||||
}
|
||||
public class EventData
|
||||
{
|
||||
public List<string> CompletedScenarios = new();
|
||||
}
|
||||
|
||||
public class SynchroSlot
|
||||
{
|
||||
/// <summary>
|
||||
/// Index of slot, 1 based
|
||||
/// </summary>
|
||||
public int Slot;
|
||||
/// <summary>
|
||||
/// Character CSN
|
||||
/// </summary>
|
||||
public long CharacterSerialNumber;
|
||||
/// <summary>
|
||||
/// Time when slot cooldown expires
|
||||
/// </summary>
|
||||
public long AvailableAt;
|
||||
}
|
||||
public class User
|
||||
{
|
||||
// User info
|
||||
public string Username = "";
|
||||
public string Password = "";
|
||||
public string PlayerName = "";
|
||||
public ulong ID;
|
||||
public long RegisterTime;
|
||||
public int LastNormalStageCleared;
|
||||
public int LastHardStageCleared;
|
||||
public string Nickname = "SomePlayer";
|
||||
public int ProfileIconId = 39900;
|
||||
public bool ProfileIconIsPrism = false;
|
||||
public int ProfileFrame = 1;
|
||||
public bool IsAdmin = false;
|
||||
|
||||
public bool IsBanned = false;
|
||||
public DateTime BanStart;
|
||||
public DateTime BanEnd;
|
||||
public int BanId = 0;
|
||||
|
||||
// Game data
|
||||
public List<string> CompletedScenarios = [];
|
||||
public Dictionary<string, FieldInfo> FieldInfo = []; // here for backwards compatibility
|
||||
|
||||
public Dictionary<string, FieldInfoNew> FieldInfoNew = [];
|
||||
public Dictionary<string, string> MapJson = [];
|
||||
public Dictionary<CurrencyType, long> Currency = new() {
|
||||
{ CurrencyType.ContentStamina, 2 }
|
||||
};
|
||||
public List<SynchroSlot> SynchroSlots = new List<SynchroSlot>();
|
||||
public bool SynchroDeviceUpgraded = false;
|
||||
public int SynchroDeviceLevel = 200;
|
||||
|
||||
public List<ItemData> Items = new();
|
||||
public List<Character> Characters = [];
|
||||
public NetWholeUserTeamData RepresentationTeamData = new();
|
||||
public Dictionary<int, ClearedTutorialData> ClearedTutorialData = [];
|
||||
public NetWallpaperData[] WallpaperList = [];
|
||||
public Dictionary<int, NetUserTeamData> UserTeams = new Dictionary<int, NetUserTeamData>();
|
||||
public Dictionary<int, bool> MainQuestData = new();
|
||||
public int InfraCoreExp = 0;
|
||||
public int InfraCoreLvl = 1;
|
||||
public UserPointData userPointData = new();
|
||||
public DateTime LastLogin = DateTime.UtcNow;
|
||||
public DateTime BattleTime = DateTime.UtcNow;
|
||||
|
||||
public NetOutpostBattleLevel OutpostBattleLevel = new() { Level = 1 };
|
||||
public int GachaTutorialPlayCount = 0;
|
||||
public List<int> CompletedTacticAcademyLessons = [];
|
||||
public List<int> CompletedSideStoryStages = new();
|
||||
|
||||
public List<int> Memorial = new();
|
||||
public List<int> JukeboxBgm = new();
|
||||
|
||||
// Event data
|
||||
public Dictionary<int, EventData> EventInfo = new();
|
||||
|
||||
public void SetQuest(int tid, bool recievedReward)
|
||||
{
|
||||
if (MainQuestData.ContainsKey(tid))
|
||||
{
|
||||
MainQuestData[tid] = recievedReward;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
MainQuestData.Add(tid, recievedReward);
|
||||
}
|
||||
}
|
||||
|
||||
public int GenerateUniqueItemId()
|
||||
{
|
||||
var num = Rng.RandomId();
|
||||
|
||||
while (Items.Any(x => x.Isn == num))
|
||||
{
|
||||
num = Rng.RandomId();
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
public int GenerateUniqueCharacterId()
|
||||
{
|
||||
var num = Rng.RandomId();
|
||||
|
||||
while (Characters.Any(x => x.Csn == num))
|
||||
{
|
||||
num = Rng.RandomId();
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
public bool IsStageCompleted(int id, bool isNorm)
|
||||
{
|
||||
foreach (var item in FieldInfoNew)
|
||||
{
|
||||
if (item.Key.Contains("hard") && isNorm) continue;
|
||||
if (item.Key.Contains("normal") && !isNorm) continue;
|
||||
if (item.Value.CompletedStages.Contains(id))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public long GetCurrencyVal(CurrencyType type)
|
||||
{
|
||||
if (Currency.ContainsKey(type))
|
||||
return Currency[type];
|
||||
else
|
||||
{
|
||||
Currency.Add(type, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
public void AddCurrency(CurrencyType type, long val)
|
||||
{
|
||||
if (Currency.ContainsKey(type)) Currency[type] += val;
|
||||
else Currency.Add(type, val);
|
||||
}
|
||||
public bool SubtractCurrency(CurrencyType type, long val)
|
||||
{
|
||||
if (Currency.ContainsKey(type)) Currency[type] -= val;
|
||||
else return false;
|
||||
|
||||
if (Currency[type] < 0)
|
||||
{
|
||||
Currency[type] += val;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public bool CanSubtractCurrency(CurrencyType type, long val)
|
||||
{
|
||||
if (Currency.ContainsKey(type))
|
||||
{
|
||||
if (Currency[type] >= val) return true;
|
||||
else return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (val == 0) return true;
|
||||
else return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasCharacter(int c)
|
||||
{
|
||||
return Characters.Any(x => x.Tid == c);
|
||||
}
|
||||
|
||||
public Character? GetCharacterBySerialNumber(long value)
|
||||
{
|
||||
return Characters.Where(x => x.Csn == value).FirstOrDefault();
|
||||
}
|
||||
|
||||
internal bool GetSynchro(long csn)
|
||||
{
|
||||
return SynchroSlots.Where(x => x.CharacterSerialNumber == csn).Count() >= 1;
|
||||
}
|
||||
internal int GetCharacterLevel(int csn)
|
||||
{
|
||||
var c = GetCharacterBySerialNumber(csn);
|
||||
if (c == null) throw new Exception("failed to lookup character");
|
||||
|
||||
return GetCharacterLevel(csn, c.Level);
|
||||
}
|
||||
internal int GetCharacterLevel(int csn, int characterLevel)
|
||||
{
|
||||
foreach (var item in SynchroSlots)
|
||||
{
|
||||
if (item.CharacterSerialNumber == csn)
|
||||
{
|
||||
return GetSynchroLevel();
|
||||
}
|
||||
}
|
||||
return characterLevel;
|
||||
}
|
||||
internal int GetSynchroLevel()
|
||||
{
|
||||
if (SynchroDeviceUpgraded)
|
||||
return SynchroDeviceLevel;
|
||||
var highestLevelCharacters = Characters.OrderByDescending(x => x.Level).Take(5).ToList();
|
||||
|
||||
|
||||
if (highestLevelCharacters.Count > 0)
|
||||
{
|
||||
return highestLevelCharacters.Last().Level;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
public class CoreInfo
|
||||
{
|
||||
public int DbVersion = 3;
|
||||
public List<User> Users = [];
|
||||
|
||||
public List<AccessToken> LauncherAccessTokens = [];
|
||||
|
||||
public Dictionary<string, GameClientInfo> GameClientTokens = [];
|
||||
public string ServerName = "<color=\"green\">Private Server</color>";
|
||||
}
|
||||
internal class JsonDb
|
||||
{
|
||||
public static CoreInfo Instance { get; internal set; }
|
||||
|
||||
// Note: change this in sodium
|
||||
public static byte[] ServerPrivateKey = Convert.FromBase64String("FSUY8Ohd942n5LWAfxn6slK3YGwc8OqmyJoJup9nNos=");
|
||||
public static byte[] ServerPublicKey = Convert.FromBase64String("04hFDd1e/BOEF2h4b0MdkX2h6W5REeqyW+0r9+eSeh0=");
|
||||
|
||||
static JsonDb()
|
||||
{
|
||||
if (!File.Exists(AppDomain.CurrentDomain.BaseDirectory + "/db.json"))
|
||||
{
|
||||
Console.WriteLine("users: warning: configuration not found, writing default data");
|
||||
Instance = new CoreInfo();
|
||||
Save();
|
||||
}
|
||||
|
||||
var j = JsonConvert.DeserializeObject<CoreInfo>(File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + "/db.json"));
|
||||
if (j != null)
|
||||
{
|
||||
Instance = j;
|
||||
|
||||
if (Instance.DbVersion == 0)
|
||||
{
|
||||
Instance.DbVersion = 1;
|
||||
// In older versions, field info key used chapter number, but now difficultly is appened.
|
||||
Console.WriteLine("Starting database update...");
|
||||
|
||||
foreach (var user in Instance.Users)
|
||||
{
|
||||
foreach (var f in user.FieldInfoNew.ToList())
|
||||
{
|
||||
var isNumeric = int.TryParse(f.Key, out int n);
|
||||
if (isNumeric)
|
||||
{
|
||||
var val = f.Value;
|
||||
user.FieldInfoNew.Remove(f.Key);
|
||||
user.FieldInfoNew.Add(n + "_Normal", val);
|
||||
}
|
||||
}
|
||||
}
|
||||
Console.WriteLine("Database update completed");
|
||||
}
|
||||
else if (Instance.DbVersion == 1)
|
||||
{
|
||||
Console.WriteLine("Starting database update...");
|
||||
// there was a bug where equipment position was not saved, so remove all items from each characters
|
||||
Instance.DbVersion = 2;
|
||||
foreach (var user in Instance.Users)
|
||||
{
|
||||
foreach (var f in user.Items.ToList())
|
||||
{
|
||||
f.Csn = 0;
|
||||
}
|
||||
}
|
||||
Console.WriteLine("Database update completed");
|
||||
}
|
||||
else if (Instance.DbVersion == 2)
|
||||
{
|
||||
Console.WriteLine("Starting database update...");
|
||||
// I used to use a class for FieldInfo cleared stages, but now int list is used
|
||||
Instance.DbVersion = 3;
|
||||
foreach (var user in Instance.Users)
|
||||
{
|
||||
foreach (var f in user.FieldInfo)
|
||||
{
|
||||
var newField = new FieldInfoNew();
|
||||
foreach (var stage in f.Value.CompletedStages)
|
||||
{
|
||||
newField.CompletedStages.Add(stage.StageId);
|
||||
}
|
||||
user.FieldInfoNew.Add(f.Key, newField);
|
||||
}
|
||||
user.FieldInfo.Clear();
|
||||
}
|
||||
Console.WriteLine("Database update completed");
|
||||
}
|
||||
Save();
|
||||
|
||||
ValidateDb();
|
||||
Console.WriteLine("Loaded db");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Failed to read configuration json file");
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateDb()
|
||||
{
|
||||
// check if character level is valid
|
||||
foreach (var item in Instance.Users)
|
||||
{
|
||||
foreach (var c in item.Characters)
|
||||
{
|
||||
if (c.Level > 1000)
|
||||
{
|
||||
Console.WriteLine($"Warning: Character level for character {c.Tid} cannot be above 1000, setting to 1000");
|
||||
c.Level = 1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static User? GetUser(ulong id)
|
||||
{
|
||||
return Instance.Users.Where(x => x.ID == id).FirstOrDefault();
|
||||
}
|
||||
public static void Save()
|
||||
{
|
||||
if (Instance != null)
|
||||
{
|
||||
File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + "/db.json", JsonConvert.SerializeObject(Instance, Formatting.Indented));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
@@ -13,11 +13,12 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ASodium" Version="0.6.1" />
|
||||
<PackageReference Include="EmbedIO" Version="3.5.2" />
|
||||
<PackageReference Include="DnsClient" Version="1.8.0" />
|
||||
<PackageReference Include="Google.Api.CommonProtos" Version="2.15.0" />
|
||||
<PackageReference Include="Google.Protobuf.Tools" Version="3.27.1" />
|
||||
<PackageReference Include="Grpc.AspNetCore" Version="2.63.0" />
|
||||
<PackageReference Include="Google.Protobuf.Tools" Version="3.27.3" />
|
||||
<PackageReference Include="Grpc.AspNetCore" Version="2.65.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="Paseto.Core" Version="1.3.0" />
|
||||
<PackageReference Include="PeterO.Cbor" Version="5.0.0-alpha1" />
|
||||
<PackageReference Include="SharpZipLib" Version="1.4.2" />
|
||||
<PackageReference Include="Sodium.Core" Version="1.4.0-preview.1" />
|
||||
@@ -29,8 +30,32 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Remove="Views\Shared\error.cshtml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="Views\Shared\error.cshtml" />
|
||||
<None Include="wwwroot\admin\assets\login.css" />
|
||||
<None Include="wwwroot\admin\assets\login.jpg" />
|
||||
<None Include="wwwroot\admin\assets\style.css" />
|
||||
<None Include="wwwroot\admin\dashbrd.html" />
|
||||
<None Include="wwwroot\admin\index.html" />
|
||||
<None Include="wwwroot\admin\nav.html" />
|
||||
<None Include="wwwroot\nikke_launcher\index.html" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="gameconfig.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="gameversion.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="site.pfx">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="wwwroot\**\*">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
520
EpinelPS/GameData/GameData.cs
Normal file
520
EpinelPS/GameData/GameData.cs
Normal file
@@ -0,0 +1,520 @@
|
||||
using EpinelPS.Utils;
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace EpinelPS.StaticInfo
|
||||
{
|
||||
public class GameData
|
||||
{
|
||||
private static GameData? _instance;
|
||||
public static GameData Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = BuildAsync().Result;
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
private ZipFile MainZip;
|
||||
private MemoryStream ZipStream;
|
||||
private Dictionary<int, MainQuestCompletionRecord> questDataRecords;
|
||||
private Dictionary<int, CampaignStageRecord> stageDataRecords;
|
||||
private Dictionary<int, RewardTableRecord> rewardDataRecords;
|
||||
private JArray userExpDataRecords;
|
||||
private Dictionary<int, CampaignChapterRecord> chapterCampaignData;
|
||||
private JArray characterCostumeTable;
|
||||
private Dictionary<int, CharacterRecord> characterTable;
|
||||
private Dictionary<int, ClearedTutorialData> tutorialTable;
|
||||
private Dictionary<int, ItemEquipRecord> itemEquipTable;
|
||||
private Dictionary<string, JArray> FieldMapData = [];
|
||||
private Dictionary<int, CharacterLevelData> LevelData = [];
|
||||
private Dictionary<int, TacticAcademyLessonRecord> TacticAcademyLessons = [];
|
||||
public Dictionary<int, int> SidestoryRewardTable = [];
|
||||
public Dictionary<string, int> PositionReward = new Dictionary<string, int>();
|
||||
public Dictionary<int, FieldItemRecord> FieldItems = [];
|
||||
|
||||
public byte[] Sha256Hash;
|
||||
public int Size;
|
||||
|
||||
static async Task<GameData> BuildAsync()
|
||||
{
|
||||
await Load();
|
||||
|
||||
Console.WriteLine("Preparing");
|
||||
var stopWatch = new Stopwatch();
|
||||
stopWatch.Start();
|
||||
await Instance.Parse();
|
||||
|
||||
stopWatch.Stop();
|
||||
Console.WriteLine("Preparing took " + stopWatch.Elapsed);
|
||||
return Instance;
|
||||
}
|
||||
|
||||
public GameData(string filePath)
|
||||
{
|
||||
if (!File.Exists(filePath)) throw new ArgumentException("Static data file must exist", nameof(filePath));
|
||||
|
||||
// disable warnings
|
||||
questDataRecords = new();
|
||||
stageDataRecords = new();
|
||||
rewardDataRecords = new();
|
||||
userExpDataRecords = new();
|
||||
chapterCampaignData = new();
|
||||
characterCostumeTable = new();
|
||||
characterTable = new();
|
||||
ZipStream = new();
|
||||
tutorialTable = new();
|
||||
itemEquipTable = new();
|
||||
|
||||
var rawBytes = File.ReadAllBytes(filePath);
|
||||
Sha256Hash = SHA256.HashData(rawBytes);
|
||||
Size = rawBytes.Length;
|
||||
|
||||
LoadGameData(filePath);
|
||||
if (MainZip == null) throw new Exception("failed to read zip file");
|
||||
}
|
||||
#region Data loading
|
||||
private static byte[] PresharedValue = [0xCB, 0xC2, 0x1C, 0x6F, 0xF3, 0xF5, 0x07, 0xF5, 0x05, 0xBA, 0xCA, 0xD4, 0x98, 0x28, 0x84, 0x1F, 0xF0, 0xD1, 0x38, 0xC7, 0x61, 0xDF, 0xD6, 0xE6, 0x64, 0x9A, 0x85, 0x13, 0x3E, 0x1A, 0x6A, 0x0C, 0x68, 0x0E, 0x2B, 0xC4, 0xDF, 0x72, 0xF8, 0xC6, 0x55, 0xE4, 0x7B, 0x14, 0x36, 0x18, 0x3B, 0xA7, 0xD1, 0x20, 0x81, 0x22, 0xD1, 0xA9, 0x18, 0x84, 0x65, 0x13, 0x0B, 0xED, 0xA3, 0x00, 0xE5, 0xD9];
|
||||
private static RSAParameters LoadParameters = new RSAParameters()
|
||||
{
|
||||
Exponent = [0x01, 0x00, 0x01],
|
||||
Modulus = [0x89, 0xD6, 0x66, 0x00, 0x7D, 0xFC, 0x7D, 0xCE, 0x83, 0xA6, 0x62, 0xE3, 0x1A, 0x5E, 0x9A, 0x53, 0xC7, 0x8A, 0x27, 0xF3, 0x67, 0xC1, 0xF3, 0xD4, 0x37, 0xFE, 0x50, 0x6D, 0x38, 0x45, 0xDF, 0x7E, 0x73, 0x5C, 0xF4, 0x9D, 0x40, 0x4C, 0x8C, 0x63, 0x21, 0x97, 0xDF, 0x46, 0xFF, 0xB2, 0x0D, 0x0E, 0xDB, 0xB2, 0x72, 0xB4, 0xA8, 0x42, 0xCD, 0xEE, 0x48, 0x06, 0x74, 0x4F, 0xE9, 0x56, 0x6E, 0x9A, 0xB1, 0x60, 0x18, 0xBC, 0x86, 0x0B, 0xB6, 0x32, 0xA7, 0x51, 0x00, 0x85, 0x7B, 0xC8, 0x72, 0xCE, 0x53, 0x71, 0x3F, 0x64, 0xC2, 0x25, 0x58, 0xEF, 0xB0, 0xC9, 0x1D, 0xE3, 0xB3, 0x8E, 0xFC, 0x55, 0xCF, 0x8B, 0x02, 0xA5, 0xC8, 0x1E, 0xA7, 0x0E, 0x26, 0x59, 0xA8, 0x33, 0xA5, 0xF1, 0x11, 0xDB, 0xCB, 0xD3, 0xA7, 0x1F, 0xB1, 0xC6, 0x10, 0x39, 0xC8, 0x31, 0x1D, 0x60, 0xDB, 0x0D, 0xA4, 0x13, 0x4B, 0x2B, 0x0E, 0xF3, 0x6F, 0x69, 0xCB, 0xA8, 0x62, 0x03, 0x69, 0xE6, 0x95, 0x6B, 0x8D, 0x11, 0xF6, 0xAF, 0xD9, 0xC2, 0x27, 0x3A, 0x32, 0x12, 0x05, 0xC3, 0xB1, 0xE2, 0x81, 0x4B, 0x40, 0xF8, 0x8B, 0x8D, 0xBA, 0x1F, 0x55, 0x60, 0x2C, 0x09, 0xC6, 0xED, 0x73, 0x96, 0x32, 0xAF, 0x5F, 0xEE, 0x8F, 0xEB, 0x5B, 0x93, 0xCF, 0x73, 0x13, 0x15, 0x6B, 0x92, 0x7B, 0x27, 0x0A, 0x13, 0xF0, 0x03, 0x4D, 0x6F, 0x5E, 0x40, 0x7B, 0x9B, 0xD5, 0xCE, 0xFC, 0x04, 0x97, 0x7E, 0xAA, 0xA3, 0x53, 0x2A, 0xCF, 0xD2, 0xD5, 0xCF, 0x52, 0xB2, 0x40, 0x61, 0x28, 0xB1, 0xA6, 0xF6, 0x78, 0xFB, 0x69, 0x9A, 0x85, 0xD6, 0xB9, 0x13, 0x14, 0x6D, 0xC4, 0x25, 0x36, 0x17, 0xDB, 0x54, 0x0C, 0xD8, 0x77, 0x80, 0x9A, 0x00, 0x62, 0x83, 0xDD, 0xB0, 0x06, 0x64, 0xD0, 0x81, 0x5B, 0x0D, 0x23, 0x9E, 0x88, 0xBD],
|
||||
DP = null
|
||||
};
|
||||
private void LoadGameData(string file)
|
||||
{
|
||||
using var fileStream = File.Open(file, FileMode.Open, FileAccess.Read);
|
||||
|
||||
var a = new Rfc2898DeriveBytes(PresharedValue, GameConfig.Root.StaticData.GetSalt2Bytes(), 10000, HashAlgorithmName.SHA256);
|
||||
var key2 = a.GetBytes(32);
|
||||
|
||||
byte[] decryptionKey = key2[0..16];
|
||||
byte[] iv = key2[16..32];
|
||||
var aes = Aes.Create();
|
||||
aes.KeySize = 128;
|
||||
aes.BlockSize = 128;
|
||||
aes.Mode = CipherMode.CBC;
|
||||
aes.Key = decryptionKey;
|
||||
aes.IV = iv;
|
||||
var transform = aes.CreateDecryptor();
|
||||
using CryptoStream stream = new CryptoStream(fileStream, transform, CryptoStreamMode.Read);
|
||||
|
||||
using MemoryStream ms = new MemoryStream();
|
||||
stream.CopyTo(ms);
|
||||
|
||||
var bytes = ms.ToArray();
|
||||
var zip = new ZipFile(ms, false);
|
||||
|
||||
var signEntry = zip.GetEntry("sign");
|
||||
if (signEntry == null) throw new Exception("error 1");
|
||||
var dataEntry = zip.GetEntry("data");
|
||||
if (dataEntry == null) throw new Exception("error 2");
|
||||
|
||||
var signStream = zip.GetInputStream(signEntry);
|
||||
var dataStream = zip.GetInputStream(dataEntry);
|
||||
|
||||
using MemoryStream signMs = new MemoryStream();
|
||||
signStream.CopyTo(signMs);
|
||||
|
||||
using MemoryStream dataMs = new MemoryStream();
|
||||
dataStream.CopyTo(dataMs);
|
||||
dataMs.Position = 0;
|
||||
|
||||
var rsa = RSA.Create(LoadParameters);
|
||||
if (!rsa.VerifyData(dataMs, signMs.ToArray(), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1))
|
||||
throw new Exception("error 3");
|
||||
|
||||
dataMs.Position = 0;
|
||||
var keyDecryptor2 = new Rfc2898DeriveBytes(PresharedValue, GameConfig.Root.StaticData.GetSalt1Bytes(), 10000, HashAlgorithmName.SHA256);
|
||||
var key3 = keyDecryptor2.GetBytes(32);
|
||||
|
||||
byte[] val2 = key3[0..16];
|
||||
byte[] iv2 = key3[16..32];
|
||||
|
||||
ZipStream = new MemoryStream();
|
||||
DoTransformation(val2, iv2, dataMs, ZipStream);
|
||||
|
||||
ZipStream.Position = 0;
|
||||
|
||||
MainZip = new ZipFile(ZipStream, false);
|
||||
}
|
||||
|
||||
public static void DoTransformation(byte[] key, byte[] salt, Stream inputStream, Stream outputStream)
|
||||
{
|
||||
SymmetricAlgorithm aes = Aes.Create();
|
||||
aes.Mode = CipherMode.ECB;
|
||||
aes.Padding = PaddingMode.None;
|
||||
|
||||
int blockSize = aes.BlockSize / 8;
|
||||
|
||||
if (salt.Length != blockSize)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Salt size must be same as block size " +
|
||||
$"(actual: {salt.Length}, expected: {blockSize})");
|
||||
}
|
||||
|
||||
var counter = (byte[])salt.Clone();
|
||||
|
||||
var xorMask = new Queue<byte>();
|
||||
|
||||
var zeroIv = new byte[blockSize];
|
||||
ICryptoTransform counterEncryptor = aes.CreateEncryptor(key, zeroIv);
|
||||
|
||||
int b;
|
||||
while ((b = inputStream.ReadByte()) != -1)
|
||||
{
|
||||
if (xorMask.Count == 0)
|
||||
{
|
||||
var counterModeBlock = new byte[blockSize];
|
||||
|
||||
counterEncryptor.TransformBlock(
|
||||
counter, 0, counter.Length, counterModeBlock, 0);
|
||||
|
||||
for (var i2 = counter.Length - 1; i2 >= 0; i2--)
|
||||
{
|
||||
if (++counter[i2] != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var b2 in counterModeBlock)
|
||||
{
|
||||
xorMask.Enqueue(b2);
|
||||
}
|
||||
}
|
||||
|
||||
var mask = xorMask.Dequeue();
|
||||
outputStream.WriteByte((byte)(((byte)b) ^ mask));
|
||||
}
|
||||
}
|
||||
public static async Task Load()
|
||||
{
|
||||
var targetFile = await AssetDownloadUtil.DownloadOrGetFileAsync(GameConfig.Root.StaticData.Url, CancellationToken.None);
|
||||
if (targetFile == null) throw new Exception("static data download fail");
|
||||
|
||||
_instance = new(targetFile);
|
||||
}
|
||||
#endregion
|
||||
private async Task<T> LoadZip<T>(string entry, ProgressBar bar)
|
||||
{
|
||||
var mainQuestData = MainZip.GetEntry(entry);
|
||||
if (mainQuestData == null) throw new Exception(entry + " does not exist in static data");
|
||||
|
||||
using StreamReader mainQuestReader = new StreamReader(MainZip.GetInputStream(mainQuestData));
|
||||
var mainQuestDataString = await mainQuestReader.ReadToEndAsync();
|
||||
|
||||
|
||||
var questdata = JsonConvert.DeserializeObject<T>(mainQuestDataString);
|
||||
if (questdata == null) throw new Exception("failed to parse " + entry);
|
||||
|
||||
currentFile++;
|
||||
bar.Report((double)currentFile / totalFiles);
|
||||
|
||||
return questdata;
|
||||
}
|
||||
private async Task<JArray> LoadZip(string entry, ProgressBar bar)
|
||||
{
|
||||
var mainQuestData = MainZip.GetEntry(entry);
|
||||
if (mainQuestData == null) throw new Exception(entry + " does not exist in static data");
|
||||
|
||||
using StreamReader mainQuestReader = new StreamReader(MainZip.GetInputStream(mainQuestData));
|
||||
var mainQuestDataString = await mainQuestReader.ReadToEndAsync();
|
||||
|
||||
|
||||
var questdata = JObject.Parse(mainQuestDataString);
|
||||
if (questdata == null) throw new Exception("failed to parse " + entry);
|
||||
|
||||
var records = (JArray?)questdata["records"];
|
||||
if (records == null) throw new Exception(entry + " is missing records element");
|
||||
|
||||
currentFile++;
|
||||
bar.Report((double)currentFile / totalFiles);
|
||||
|
||||
return records;
|
||||
}
|
||||
int totalFiles = 14;
|
||||
int currentFile = 0;
|
||||
|
||||
public async Task Parse()
|
||||
{
|
||||
using var progress = new ProgressBar();
|
||||
|
||||
var questDataRecords = await LoadZip<MainQuestCompletionTable>("MainQuestTable.json", progress);
|
||||
foreach (var obj in questDataRecords.records)
|
||||
{
|
||||
this.questDataRecords.Add(obj.id, obj);
|
||||
}
|
||||
|
||||
var stageDataRecords = await LoadZip<CampaignStageTable>("CampaignStageTable.json", progress);
|
||||
foreach (var obj in stageDataRecords.records)
|
||||
{
|
||||
this.stageDataRecords.Add(obj.id, obj);
|
||||
}
|
||||
|
||||
var rewardDataRecords = await LoadZip<RewardTable>("RewardTable.json", progress);
|
||||
foreach (var obj in rewardDataRecords.records)
|
||||
{
|
||||
this.rewardDataRecords.Add(obj.id, obj);
|
||||
}
|
||||
|
||||
var chapterCampaignData = await LoadZip<CampaignChapterTable>("CampaignChapterTable.json", progress);
|
||||
foreach (var obj in chapterCampaignData.records)
|
||||
{
|
||||
this.chapterCampaignData.Add(obj.chapter, obj);
|
||||
}
|
||||
|
||||
userExpDataRecords = await LoadZip("UserExpTable.json", progress);
|
||||
characterCostumeTable = await LoadZip("CharacterCostumeTable.json", progress);
|
||||
|
||||
var characterTable = await LoadZip<CharacterTable>("CharacterTable.json", progress);
|
||||
foreach (var obj in characterTable.records)
|
||||
{
|
||||
this.characterTable.Add(obj.id, obj);
|
||||
}
|
||||
|
||||
var tutorialTable = await LoadZip<TutorialTable>("ContentsTutorialTable.json", progress);
|
||||
foreach (var obj in tutorialTable.records)
|
||||
{
|
||||
this.tutorialTable.Add(obj.id, obj);
|
||||
}
|
||||
|
||||
var itemEquipTable = await LoadZip<ItemEquipTable>("ItemEquipTable.json", progress);
|
||||
foreach (var obj in itemEquipTable.records)
|
||||
{
|
||||
this.itemEquipTable.Add(obj.id, obj);
|
||||
}
|
||||
|
||||
var characterLevelTable = await LoadZip("CharacterLevelTable.json", progress);
|
||||
|
||||
foreach (JToken item in characterLevelTable)
|
||||
{
|
||||
var obj = item.ToObject<CharacterLevelData>();
|
||||
if (obj != null)
|
||||
LevelData.Add(obj.level, obj);
|
||||
else
|
||||
Console.WriteLine("failed to read character level table entry");
|
||||
}
|
||||
|
||||
var tacticLessonTable = await LoadZip("TacticAcademyFunctionTable.json", progress);
|
||||
|
||||
foreach (JToken item in tacticLessonTable)
|
||||
{
|
||||
var idRaw = item["id"];
|
||||
var groupidRaw = item["group_id"];
|
||||
var currencyIdRaw = item["currency_id"];
|
||||
var currencyValueRaw = item["currency_value"];
|
||||
|
||||
if (idRaw == null) throw new InvalidDataException();
|
||||
if (groupidRaw == null) throw new InvalidDataException();
|
||||
if (currencyIdRaw == null) throw new InvalidDataException();
|
||||
if (currencyValueRaw == null) throw new InvalidDataException();
|
||||
|
||||
var id = idRaw.ToObject<int>();
|
||||
var currencyId = currencyIdRaw.ToObject<int>();
|
||||
var currencyValue = currencyValueRaw.ToObject<int>();
|
||||
var groupid = groupidRaw.ToObject<int>();
|
||||
|
||||
var fullId = int.Parse(groupid.ToString() + id.ToString());
|
||||
TacticAcademyLessons.Add(id, new TacticAcademyLessonRecord() { CurrencyId = (CurrencyType)currencyId, CurrencyValue = currencyValue, GroupId = groupid, Id = id });
|
||||
}
|
||||
|
||||
var sideStoryTable = await LoadZip("SideStoryStageTable.json", progress);
|
||||
|
||||
foreach (JToken item in sideStoryTable)
|
||||
{
|
||||
var idRaw = item["id"];
|
||||
var rewardIdRaw = item["first_clear_reward"];
|
||||
|
||||
if (idRaw == null) throw new InvalidDataException();
|
||||
if (rewardIdRaw != null)
|
||||
{
|
||||
var id2 = idRaw.ToObject<int>();
|
||||
var reward = rewardIdRaw.ToObject<int>();
|
||||
|
||||
SidestoryRewardTable.Add(id2, reward);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach (ZipEntry item in MainZip)
|
||||
{
|
||||
if (item.Name.StartsWith("CampaignMap/"))
|
||||
{
|
||||
var x = await LoadZip(item.Name, progress);
|
||||
|
||||
var items = x[0]["ItemSpawner"];
|
||||
foreach (var item2 in items)
|
||||
{
|
||||
var id = item2["positionId"].ToObject<string>();
|
||||
var reward = item2["itemId"].ToObject<int>();
|
||||
|
||||
if (!PositionReward.ContainsKey(id))
|
||||
PositionReward.Add(id, reward);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var fieldItems = await LoadZip<FieldItemTable>("FieldItemTable.json", progress);
|
||||
foreach (var obj in fieldItems.records)
|
||||
{
|
||||
FieldItems.Add(obj.id, obj);
|
||||
}
|
||||
}
|
||||
|
||||
public MainQuestCompletionRecord? GetMainQuestForStageClearCondition(int stage)
|
||||
{
|
||||
foreach (var item in questDataRecords)
|
||||
{
|
||||
if (item.Value.condition_id == stage)
|
||||
{
|
||||
return item.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
public MainQuestCompletionRecord? GetMainQuestByTableId(int tid)
|
||||
{
|
||||
return questDataRecords[tid];
|
||||
}
|
||||
public CampaignStageRecord? GetStageData(int stage)
|
||||
{
|
||||
return stageDataRecords[stage];
|
||||
}
|
||||
public RewardTableRecord? GetRewardTableEntry(int rewardId)
|
||||
{
|
||||
return rewardDataRecords[rewardId];
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns the level and its minimum value for XP value
|
||||
/// </summary>
|
||||
/// <param name="targetExp"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public (int, int) GetUserLevelFromUserExp(int targetExp)
|
||||
{
|
||||
int prevLevel = 0;
|
||||
int prevValue = 0;
|
||||
for (int i = 0; i < userExpDataRecords.Count; i++)
|
||||
{
|
||||
var item = userExpDataRecords[i];
|
||||
|
||||
var level = item["level"];
|
||||
if (level == null) throw new Exception("expected level field in user exp table data");
|
||||
|
||||
int levelValue = level.ToObject<int>();
|
||||
|
||||
var exp = item["exp"];
|
||||
if (exp == null) throw new Exception("expected exp field in user exp table data");
|
||||
|
||||
int expValue = exp.ToObject<int>();
|
||||
|
||||
if (prevValue < targetExp)
|
||||
{
|
||||
prevLevel = levelValue;
|
||||
prevValue = expValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (prevLevel, prevValue);
|
||||
}
|
||||
}
|
||||
return (-1, -1);
|
||||
}
|
||||
public int GetUserMinXpForLevel(int targetLevel)
|
||||
{
|
||||
for (int i = 0; i < userExpDataRecords.Count; i++)
|
||||
{
|
||||
var item = userExpDataRecords[i];
|
||||
|
||||
var level = item["level"];
|
||||
if (level == null) throw new Exception("expected level field in user exp table data");
|
||||
|
||||
int levelValue = level.ToObject<int>();
|
||||
if (targetLevel == levelValue)
|
||||
{
|
||||
var exp = item["exp"];
|
||||
if (exp == null) throw new Exception("expected exp field in user exp table data");
|
||||
|
||||
int expValue = exp.ToObject<int>();
|
||||
return expValue;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
public int GetNormalChapterNumberFromFieldName(string field)
|
||||
{
|
||||
foreach (var item in chapterCampaignData)
|
||||
{
|
||||
if (item.Value.field_id == field)
|
||||
{
|
||||
return item.Value.chapter;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public IEnumerable<int> GetAllCharacterTids()
|
||||
{
|
||||
return characterTable.Keys;
|
||||
}
|
||||
public IEnumerable<int> GetAllCostumes()
|
||||
{
|
||||
foreach (JObject item in characterCostumeTable)
|
||||
{
|
||||
var id = item["id"];
|
||||
if (id == null) throw new Exception("expected id field in reward data");
|
||||
|
||||
int value = id.ToObject<int>();
|
||||
yield return value;
|
||||
}
|
||||
}
|
||||
|
||||
internal ClearedTutorialData GetTutorialDataById(int TableId)
|
||||
{
|
||||
return tutorialTable[TableId];
|
||||
}
|
||||
|
||||
public string? GetItemSubType(int itemType)
|
||||
{
|
||||
return itemEquipTable[itemType].item_sub_type;
|
||||
}
|
||||
|
||||
internal IEnumerable<int> GetStageIdsForChapter(int chapterNumber, bool normal)
|
||||
{
|
||||
string mod = normal ? "Normal" : "Hard";
|
||||
foreach (var item in stageDataRecords)
|
||||
{
|
||||
var data = item.Value;
|
||||
|
||||
int chVal = data.chapter_id - 1;
|
||||
|
||||
if (chapterNumber == chVal && data.chapter_mod == mod && data.stage_type == "Main")
|
||||
{
|
||||
yield return data.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<int, CharacterLevelData> GetCharacterLevelUpData()
|
||||
{
|
||||
return LevelData;
|
||||
}
|
||||
|
||||
public TacticAcademyLessonRecord GetTacticAcademyLesson(int lessonId)
|
||||
{
|
||||
return TacticAcademyLessons[lessonId];
|
||||
}
|
||||
}
|
||||
}
|
||||
150
EpinelPS/GameData/JsonStaticData.cs
Normal file
150
EpinelPS/GameData/JsonStaticData.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
namespace EpinelPS.StaticInfo
|
||||
{
|
||||
public class MainQuestCompletionRecord
|
||||
{
|
||||
public int id;
|
||||
public int group_id;
|
||||
public string category = "";
|
||||
public int condition_id;
|
||||
public int next_main_quest_id = 0;
|
||||
public int reward_id = 0;
|
||||
public int target_chapter_id;
|
||||
}
|
||||
public class MainQuestCompletionTable
|
||||
{
|
||||
public List<MainQuestCompletionRecord> records;
|
||||
}
|
||||
public class CampaignStageRecord
|
||||
{
|
||||
public int id;
|
||||
public int chapter_id;
|
||||
public string stage_category = "";
|
||||
public int reward_id = 0;
|
||||
/// <summary>
|
||||
/// Can be Normal or Hard
|
||||
/// </summary>
|
||||
public string chapter_mod = "";
|
||||
public string stage_type = "";
|
||||
public string enter_scenario = "";
|
||||
public string exit_scenario = "";
|
||||
}
|
||||
public class CampaignStageTable
|
||||
{
|
||||
public List<CampaignStageRecord> records;
|
||||
}
|
||||
public class RewardTableRecord
|
||||
{
|
||||
public int id;
|
||||
public int user_exp;
|
||||
public int character_exp;
|
||||
public RewardEntry[]? rewards;
|
||||
}
|
||||
public class RewardTable
|
||||
{
|
||||
public List<RewardTableRecord> records;
|
||||
}
|
||||
|
||||
public class RewardEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// example: 1000000
|
||||
/// </summary>
|
||||
public int reward_percent;
|
||||
public string percent_display_type = "";
|
||||
public string reward_type = "";
|
||||
public int reward_id;
|
||||
public int reward_value;
|
||||
}
|
||||
|
||||
|
||||
public class ClearedTutorialData
|
||||
{
|
||||
public int id;
|
||||
public int VersionGroup = 0;
|
||||
public int GroupId;
|
||||
public int ClearedStageId;
|
||||
public int NextId;
|
||||
public bool SaveTutorial;
|
||||
}
|
||||
public class TutorialTable
|
||||
{
|
||||
public List<ClearedTutorialData> records;
|
||||
}
|
||||
|
||||
public class CharacterLevelData
|
||||
{
|
||||
/// <summary>
|
||||
/// level
|
||||
/// </summary>
|
||||
public int level;
|
||||
/// <summary>
|
||||
/// can be CharacterLevel or SynchroLevel
|
||||
/// </summary>
|
||||
public string type = "";
|
||||
/// <summary>
|
||||
/// amount of credits required
|
||||
/// </summary>
|
||||
public int gold = 0;
|
||||
/// <summary>
|
||||
/// amount of battle data required
|
||||
/// </summary>
|
||||
public int character_exp = 0;
|
||||
/// <summary>
|
||||
/// amount of core dust required
|
||||
/// </summary>
|
||||
public int character_exp2 = 0;
|
||||
}
|
||||
|
||||
public class TacticAcademyLessonRecord
|
||||
{
|
||||
public CurrencyType CurrencyId;
|
||||
public int CurrencyValue;
|
||||
public int Id;
|
||||
public int GroupId;
|
||||
}
|
||||
|
||||
public class CampaignChapterRecord
|
||||
{
|
||||
public int id;
|
||||
public int chapter;
|
||||
public string field_id;
|
||||
public string hard_field_id;
|
||||
}
|
||||
public class CampaignChapterTable
|
||||
{
|
||||
public List<CampaignChapterRecord> records;
|
||||
}
|
||||
|
||||
public class CharacterRecord
|
||||
{
|
||||
public int id;
|
||||
// TODO: There is more stuff here but it isn't needed yet
|
||||
}
|
||||
public class CharacterTable
|
||||
{
|
||||
public List<CharacterRecord> records;
|
||||
}
|
||||
|
||||
public class ItemEquipRecord
|
||||
{
|
||||
public int id;
|
||||
public string item_sub_type;
|
||||
}
|
||||
public class ItemEquipTable
|
||||
{
|
||||
public List<ItemEquipRecord> records;
|
||||
}
|
||||
|
||||
public class FieldItemRecord
|
||||
{
|
||||
public int id;
|
||||
public string item_type;
|
||||
public int type_value;
|
||||
public bool is_final_reward;
|
||||
public string difficulty;
|
||||
}
|
||||
public class FieldItemTable
|
||||
{
|
||||
public List<FieldItemRecord> records;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
using ASodium;
|
||||
using EmbedIO;
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
using Google.Protobuf;
|
||||
using nksrv.Utils;
|
||||
using Swan.Logging;
|
||||
|
||||
namespace nksrv.LobbyServer
|
||||
namespace EpinelPS.LobbyServer
|
||||
{
|
||||
public static class LobbyHandler
|
||||
{
|
||||
@@ -18,7 +17,7 @@ namespace nksrv.LobbyServer
|
||||
var attrib = (PacketPathAttribute?)Attribute.GetCustomAttribute(type, typeof(PacketPathAttribute));
|
||||
if (attrib == null)
|
||||
{
|
||||
Logger.Error("WARNING: Failed to get attribute for " + type.FullName);
|
||||
Console.WriteLine("WARNING: Failed to get attribute for " + type.FullName);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -30,17 +29,18 @@ namespace nksrv.LobbyServer
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Error($"WARNING: Type {type.FullName} has PacketPathAttribute but does not implement LobbyMsgHandler");
|
||||
Console.WriteLine($"WARNING: Type {type.FullName} has PacketPathAttribute but does not implement LobbyMsgHandler");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public static async Task DispatchSingle(IHttpContext ctx)
|
||||
public static async Task DispatchSingle(HttpContext ctx)
|
||||
{
|
||||
LobbyMsgHandler? handler = null;
|
||||
string path = ctx.Request.Path.Value.Replace("/v1", "");
|
||||
foreach (var item in Handlers)
|
||||
{
|
||||
if (ctx.RequestedPath == item.Key)
|
||||
if (path == item.Key)
|
||||
{
|
||||
handler = item.Value;
|
||||
}
|
||||
@@ -104,7 +104,7 @@ namespace nksrv.LobbyServer
|
||||
{
|
||||
NetUserData ret = new()
|
||||
{
|
||||
Lv = user.userPointData.UserLevel,
|
||||
Level = user.userPointData.UserLevel,
|
||||
Exp = user.userPointData.ExperiencePoint,
|
||||
CommanderRoomJukebox = 5,
|
||||
CostumeLv = 1,
|
||||
@@ -114,7 +114,6 @@ namespace nksrv.LobbyServer
|
||||
LobbyJukebox = 2,
|
||||
InfraCoreExp = user.InfraCoreExp,
|
||||
InfraCoreLv = user.InfraCoreLvl,
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -133,14 +132,14 @@ namespace nksrv.LobbyServer
|
||||
{
|
||||
var ret = new NetWholeUserData()
|
||||
{
|
||||
Lv = user.userPointData.UserLevel,
|
||||
Frame = 1,
|
||||
Level = user.userPointData.UserLevel,
|
||||
Frame = user.ProfileFrame,
|
||||
Icon = user.ProfileIconId,
|
||||
IconPrism = user.ProfileIconIsPrism,
|
||||
Nickname = user.Nickname,
|
||||
Usn = (long)user.ID,
|
||||
LastActionAt = DateTimeOffset.UtcNow.Ticks,
|
||||
|
||||
Server = 1001
|
||||
};
|
||||
|
||||
return ret;
|
||||
@@ -1,17 +1,12 @@
|
||||
using EmbedIO;
|
||||
using Google.Protobuf;
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Google.Protobuf;
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer
|
||||
namespace EpinelPS.LobbyServer
|
||||
{
|
||||
public abstract class LobbyMsgHandler
|
||||
{
|
||||
protected IHttpContext? ctx;
|
||||
protected HttpContext? ctx;
|
||||
protected ulong UserId;
|
||||
protected string UsedAuthToken = "";
|
||||
public byte[] ReturnBytes = [];
|
||||
@@ -29,12 +24,12 @@ namespace nksrv.LobbyServer
|
||||
ctx = null;
|
||||
}
|
||||
|
||||
public async Task HandleAsync(IHttpContext ctx)
|
||||
public async Task HandleAsync(HttpContext ctx)
|
||||
{
|
||||
this.ctx = ctx;
|
||||
if (ctx.Request.Headers.AllKeys.Contains("Authorization"))
|
||||
if (ctx.Request.Headers.Keys.Contains("Authorization"))
|
||||
{
|
||||
var token = ctx.Request.Headers["Authorization"];
|
||||
var token = ctx.Request.Headers.Authorization.FirstOrDefault();
|
||||
if (token != null)
|
||||
{
|
||||
UsedAuthToken = token;
|
||||
@@ -53,7 +48,7 @@ namespace nksrv.LobbyServer
|
||||
UserId = item.Value.UserId;
|
||||
}
|
||||
}
|
||||
if (UserId == 0) throw new HttpException(403);
|
||||
if (UserId == 0) throw new Exception("403");
|
||||
await HandleAsync();
|
||||
}
|
||||
|
||||
@@ -72,20 +67,20 @@ namespace nksrv.LobbyServer
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.Response.ContentEncoding = null;
|
||||
ctx.Response.ContentType = "application/octet-stream+protobuf";
|
||||
ctx.Response.ContentLength64 = data.CalculateSize();
|
||||
ctx.Response.ContentLength = data.CalculateSize();
|
||||
bool encrypted = false;
|
||||
var responseBytes = encrypted ? new MemoryStream() : ctx.Response.OutputStream;
|
||||
var responseBytes = encrypted ? new MemoryStream() : ctx.Response.Body;
|
||||
var x = new CodedOutputStream(responseBytes);
|
||||
data.WriteTo(x);
|
||||
|
||||
x.Flush();
|
||||
|
||||
if (encrypted)
|
||||
{
|
||||
ctx.Response.Headers.Set(System.Net.HttpRequestHeader.ContentEncoding, "gzip,enc");
|
||||
ctx.Response.Headers.ContentEncoding = new Microsoft.Extensions.Primitives.StringValues("gzip,enc");
|
||||
var enc = PacketDecryption.EncryptData(((MemoryStream)responseBytes).ToArray(), UsedAuthToken);
|
||||
await ctx.Response.OutputStream.WriteAsync(enc, ctx.CancellationToken);
|
||||
await ctx.Response.Body.WriteAsync(enc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,5 +111,9 @@ namespace nksrv.LobbyServer
|
||||
{
|
||||
return JsonDb.GetUser(UserId) ?? throw new Exception("null user");
|
||||
}
|
||||
public User? GetUser(ulong id)
|
||||
{
|
||||
return JsonDb.GetUser(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Antibot
|
||||
namespace EpinelPS.LobbyServer.Msgs.Antibot
|
||||
{
|
||||
[PacketPath("/antibot/battlereportdata")]
|
||||
public class BattleReportData : LobbyMsgHandler
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Antibot
|
||||
namespace EpinelPS.LobbyServer.Msgs.Antibot
|
||||
{
|
||||
[PacketPath("/antibot/recvdata")]
|
||||
public class RecieveAntibotData : LobbyMsgHandler
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Archive
|
||||
namespace EpinelPS.LobbyServer.Msgs.Archive
|
||||
{
|
||||
[PacketPath("/bookmark/scenario/exist")]
|
||||
public class CheckBookmarkScenarioExists : LobbyMsgHandler
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Archive
|
||||
namespace EpinelPS.LobbyServer.Msgs.Archive
|
||||
{
|
||||
[PacketPath("/archive/get")]
|
||||
public class GetArchives : LobbyMsgHandler
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Arena
|
||||
namespace EpinelPS.LobbyServer.Msgs.Arena
|
||||
{
|
||||
[PacketPath("/arena/getbaninfo")]
|
||||
public class GetArenaBanInfo : LobbyMsgHandler
|
||||
17
EpinelPS/LobbyServer/Msgs/Arena/ShowSpecialArenaReward.cs
Normal file
17
EpinelPS/LobbyServer/Msgs/Arena/ShowSpecialArenaReward.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Arena
|
||||
{
|
||||
[PacketPath("/arena/special/showreward")]
|
||||
public class ShowSpecialArenaReward : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqShowSpecialArenaReward>();
|
||||
|
||||
var response = new ResShowSpecialArenaReward();
|
||||
// TODO
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,7 @@
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using Google.Protobuf;
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Auth
|
||||
namespace EpinelPS.LobbyServer.Msgs.Auth
|
||||
{
|
||||
[PacketPath("/auth/logout")]
|
||||
public class AuthLogout : LobbyMsgHandler
|
||||
@@ -1,21 +1,16 @@
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
using Google.Protobuf;
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EmbedIO;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Auth
|
||||
namespace EpinelPS.LobbyServer.Msgs.Auth
|
||||
{
|
||||
[PacketPath("/auth/enterserver")]
|
||||
public class GetUserOnlineStateLog : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<EnterServerRequest>();
|
||||
var req = await ReadData<ReqEnterServer>();
|
||||
|
||||
// request has auth token
|
||||
UsedAuthToken = req.AuthToken;
|
||||
@@ -26,11 +21,11 @@ namespace nksrv.LobbyServer.Msgs.Auth
|
||||
UserId = item.UserID;
|
||||
}
|
||||
}
|
||||
if (UserId == 0) throw new HttpException(403);
|
||||
if (UserId == 0) throw new BadHttpRequestException("unknown auth token", 403);
|
||||
|
||||
var user = GetUser();
|
||||
|
||||
var response = new EnterServerResponse();
|
||||
var response = new ResEnterServer();
|
||||
var rsp = LobbyHandler.GenGameClientTok(req.ClientPublicKey, req.AuthToken);
|
||||
response.GameClientToken = rsp.ClientAuthToken;
|
||||
response.FeatureDataInfo = new NetFeatureDataInfo() { UseFeatureData = true };
|
||||
53
EpinelPS/LobbyServer/Msgs/Auth/DoIntlAuth.cs
Normal file
53
EpinelPS/LobbyServer/Msgs/Auth/DoIntlAuth.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Auth
|
||||
{
|
||||
[PacketPath("/auth/intl")]
|
||||
public class DoIntlAuth : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqAuthIntl>();
|
||||
var response = new ResAuth();
|
||||
|
||||
UsedAuthToken = req.Token;
|
||||
foreach (var item in JsonDb.Instance.LauncherAccessTokens)
|
||||
{
|
||||
if (item.Token == UsedAuthToken)
|
||||
{
|
||||
UserId = item.UserID;
|
||||
}
|
||||
}
|
||||
if (UserId == 0)
|
||||
{
|
||||
response.AuthError = new NetAuthError() { ErrorCode = AuthErrorCode.AuthErrorCodeError };
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = GetUser();
|
||||
|
||||
if (user.IsBanned && user.BanEnd < DateTime.UtcNow)
|
||||
{
|
||||
user.IsBanned = false;
|
||||
user.BanId = 0;
|
||||
user.BanStart = DateTime.MinValue;
|
||||
user.BanEnd = DateTime.MinValue;
|
||||
JsonDb.Save();
|
||||
}
|
||||
|
||||
if (user.IsBanned)
|
||||
{
|
||||
response.BanInfo = new NetBanInfo() { BanId = user.BanId, Description = "The server admin is sad today because the hinge on his HP laptop broke which happened to be an HP Elitebook 8470p, and the RAM controller exploded and then fixed itself, please contact him", StartAt = Timestamp.FromDateTime(DateTime.SpecifyKind(user.BanStart, DateTimeKind.Utc)), EndAt = Timestamp.FromDateTime(DateTime.SpecifyKind(user.BanEnd, DateTimeKind.Utc)) };
|
||||
}
|
||||
else
|
||||
{
|
||||
response.AuthSuccess = new NetAuthSuccess() { AuthToken = req.Token, CentauriZoneId = "84", FirstAuth = false, PurchaseRestriction = new NetUserPurchaseRestriction() { PurchaseRestriction = PurchaseRestriction.PurchaseRestrictionChild, UpdatedAt = 638546758794611090 } };
|
||||
}
|
||||
}
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Badge
|
||||
namespace EpinelPS.LobbyServer.Msgs.Badge
|
||||
{
|
||||
[PacketPath("/badge/delete")]
|
||||
public class DeleteBadge : LobbyMsgHandler
|
||||
@@ -1,6 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Badge
|
||||
namespace EpinelPS.LobbyServer.Msgs.Badge
|
||||
{
|
||||
[PacketPath("/badge/sync")]
|
||||
public class SyncBadge : LobbyMsgHandler
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Campaign
|
||||
namespace EpinelPS.LobbyServer.Msgs.Campaign
|
||||
{
|
||||
[PacketPath("/shutdownflags/campaignpackage/getall")]
|
||||
public class CampaignPackageGetAll : LobbyMsgHandler
|
||||
@@ -1,14 +1,8 @@
|
||||
using nksrv.LobbyServer.Msgs.Stage;
|
||||
using nksrv.StaticInfo;
|
||||
using nksrv.Utils;
|
||||
using Swan.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.LobbyServer.Msgs.Stage;
|
||||
using EpinelPS.StaticInfo;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Campaign
|
||||
namespace EpinelPS.LobbyServer.Msgs.Campaign
|
||||
{
|
||||
[PacketPath("/campaign/getfield")]
|
||||
public class GetCampaignField : LobbyMsgHandler
|
||||
@@ -17,11 +11,11 @@ namespace nksrv.LobbyServer.Msgs.Campaign
|
||||
{
|
||||
var req = await ReadData<ReqGetCampaignFieldData>();
|
||||
var user = GetUser();
|
||||
|
||||
|
||||
Console.WriteLine("Map ID: " + req.MapId);
|
||||
|
||||
var response = new ResGetCampaignFieldData();
|
||||
response.Field = GetStage.CreateFieldInfo(user, StaticDataParser.Instance.GetNormalChapterNumberFromFieldName(req.MapId), req.MapId.Contains("hard") ? "Hard" : "Normal");
|
||||
response.Field = GetStage.CreateFieldInfo(user, GameData.Instance.GetNormalChapterNumberFromFieldName(req.MapId), req.MapId.Contains("hard") ? "Hard" : "Normal");
|
||||
|
||||
// todo save this data
|
||||
response.Team = new NetUserTeamData() { LastContentsTeamNumber = 1, Type = 1 };
|
||||
50
EpinelPS/LobbyServer/Msgs/Campaign/ObtainItem.cs
Normal file
50
EpinelPS/LobbyServer/Msgs/Campaign/ObtainItem.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.LobbyServer.Msgs.Stage;
|
||||
using EpinelPS.StaticInfo;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Campaign
|
||||
{
|
||||
[PacketPath("/campaign/obtain/item")]
|
||||
public class ObtainItem : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqObtainCampaignItem>();
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResObtainCampaignItem();
|
||||
|
||||
var chapter = GameData.Instance.GetNormalChapterNumberFromFieldName(req.MapId);
|
||||
var mod = req.MapId.Contains("hard") ? "Hard" : "Normal";
|
||||
var key = chapter + "_" + mod;
|
||||
var field = user.FieldInfoNew[key];
|
||||
|
||||
|
||||
foreach (var item in field.CompletedObjects)
|
||||
{
|
||||
if (item.PositionId == req.FieldObject.PositionId)
|
||||
{
|
||||
Console.WriteLine("attempted to collect campaign field object twice!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Register and return reward
|
||||
|
||||
if (!GameData.Instance.PositionReward.ContainsKey(req.FieldObject.PositionId)) throw new Exception("bad position id");
|
||||
var fieldReward = GameData.Instance.PositionReward[req.FieldObject.PositionId];
|
||||
var positionReward = GameData.Instance.FieldItems[fieldReward];
|
||||
var reward = GameData.Instance.GetRewardTableEntry(positionReward.type_value);
|
||||
if (reward == null) throw new Exception("failed to get reward");
|
||||
response.Reward = ClearStage.RegisterRewardsForUser(user, reward);
|
||||
|
||||
// Hide it from the field
|
||||
field.CompletedObjects.Add(new NetFieldObject() { PositionId = req.FieldObject.PositionId, Type = req.FieldObject.Type});
|
||||
|
||||
JsonDb.Save();
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Campaign
|
||||
namespace EpinelPS.LobbyServer.Msgs.Campaign
|
||||
{
|
||||
[PacketPath("/campaign/savefield")]
|
||||
public class SaveField : LobbyMsgHandler
|
||||
@@ -20,7 +20,7 @@ namespace nksrv.LobbyServer.Msgs.Campaign
|
||||
}
|
||||
else
|
||||
{
|
||||
user.MapJson[req.MapId] = req.Json;
|
||||
user.MapJson[req.MapId] = req.Json;
|
||||
}
|
||||
|
||||
await WriteDataAsync(response);
|
||||
@@ -1,12 +1,8 @@
|
||||
using nksrv.StaticInfo;
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.StaticInfo;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Campaign
|
||||
namespace EpinelPS.LobbyServer.Msgs.Campaign
|
||||
{
|
||||
[PacketPath("/campaign/savefieldobject")]
|
||||
public class SaveFieldObject : LobbyMsgHandler
|
||||
@@ -20,14 +16,14 @@ namespace nksrv.LobbyServer.Msgs.Campaign
|
||||
|
||||
var response = new ResSaveCampaignFieldObject();
|
||||
|
||||
Console.WriteLine($"save {req.MapId} with {req.FieldObject.PositionID}");
|
||||
Console.WriteLine($"save {req.MapId} with {req.FieldObject.PositionId}");
|
||||
|
||||
var chapter = StaticDataParser.Instance.GetNormalChapterNumberFromFieldName(req.MapId);
|
||||
var chapter = GameData.Instance.GetNormalChapterNumberFromFieldName(req.MapId);
|
||||
var mod = req.MapId.Contains("hard") ? "Hard" : "Normal";
|
||||
var key = chapter + "_" + mod;
|
||||
var field = user.FieldInfo[key];
|
||||
var field = user.FieldInfoNew[key];
|
||||
|
||||
field.CompletedObjects.Add(new NetFieldObject() { PositionId = req.FieldObject.PositionID, Json = req.FieldObject.Json, Type = req.FieldObject.Type });
|
||||
field.CompletedObjects.Add(new NetFieldObject() { PositionId = req.FieldObject.PositionId, Json = req.FieldObject.Json, Type = req.FieldObject.Type });
|
||||
JsonDb.Save();
|
||||
|
||||
await WriteDataAsync(response);
|
||||
54
EpinelPS/LobbyServer/Msgs/Character/ChangeSynchroDevice.cs
Normal file
54
EpinelPS/LobbyServer/Msgs/Character/ChangeSynchroDevice.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using EpinelPS.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
{
|
||||
[PacketPath("/character/SynchroDevice/Change")]
|
||||
public class ChangeSynchroDevice : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqSynchroChange>();
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResSynchroChange();
|
||||
|
||||
var highestLevelCharacters = user.Characters.OrderByDescending(x => x.Level).Take(5).ToList();
|
||||
|
||||
int slot = 1;
|
||||
foreach (var item in highestLevelCharacters)
|
||||
{
|
||||
if (item.Level != 200)
|
||||
{
|
||||
throw new Exception("expected level to be 200");
|
||||
}
|
||||
|
||||
response.Characters.Add(new NetUserCharacterData() { Default = new() { Csn = item.Csn, Skill1Lv = item.Skill1Lvl, Skill2Lv = item.Skill2Lvl, CostumeId = item.CostumeId, Level = item.Level, Grade = item.Grade, Tid = item.Tid, UltiSkillLv = item.UltimateLevel }, IsSynchro = user.GetSynchro(item.Csn) });
|
||||
|
||||
|
||||
|
||||
foreach (var s in user.SynchroSlots)
|
||||
{
|
||||
if (s.Slot == slot)
|
||||
{
|
||||
s.CharacterSerialNumber = item.Csn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
slot++;
|
||||
}
|
||||
|
||||
user.SynchroDeviceUpgraded = true;
|
||||
|
||||
foreach (var item in user.SynchroSlots)
|
||||
{
|
||||
response.Slots.Add(new NetSynchroSlot() { Slot = item.Slot, AvailableRegisterAt = item.AvailableAt, Csn = item.CharacterSerialNumber });
|
||||
}
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Character
|
||||
namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
{
|
||||
[PacketPath("/character/attractive/get")]
|
||||
public class GetCharacterAttractiveList : LobbyMsgHandler
|
||||
@@ -1,12 +1,7 @@
|
||||
using nksrv.StaticInfo;
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.StaticInfo;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Character
|
||||
namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
{
|
||||
[PacketPath("/character/costume/get")]
|
||||
public class GetCharacterCostume : LobbyMsgHandler
|
||||
@@ -18,7 +13,7 @@ namespace nksrv.LobbyServer.Msgs.Character
|
||||
var response = new ResGetCharacterCostumeData();
|
||||
|
||||
// return all
|
||||
response.CostumeIds.AddRange(StaticDataParser.Instance.GetAllCostumes());
|
||||
response.CostumeIds.AddRange(GameData.Instance.GetAllCostumes());
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
30
EpinelPS/LobbyServer/Msgs/Character/GetCharacterData.cs
Normal file
30
EpinelPS/LobbyServer/Msgs/Character/GetCharacterData.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
{
|
||||
[PacketPath("/character/get")]
|
||||
public class GetCharacterData : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqGetCharacterData>();
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResGetCharacterData();
|
||||
// TODO: When Squad view opens in the game, or this request is sent, all character levels reset to 1 as well as costume IDs
|
||||
//foreach (var item in user.Characters)
|
||||
//{
|
||||
// response.Character.Add(new NetUserCharacterData() { Default = new() { Csn = item.Csn, Skill1Lv = item.Skill1Lvl, Skill2Lv = item.Skill2Lvl, CostumeId = item.CostumeId, Level = user.GetCharacterLevel(item.Csn, item.Level), Grade = item.Grade, Tid = item.Tid, UltiSkillLv = item.UltimateLevel }, IsSynchro = user.GetSynchro(item.Csn) });
|
||||
//}
|
||||
|
||||
var highestLevelCharacters = user.Characters.OrderByDescending(x => x.Level).Take(5).ToList();
|
||||
|
||||
foreach (var c in highestLevelCharacters)
|
||||
{
|
||||
response.SynchroStandardCharacters.Add(c.Csn);
|
||||
}
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
54
EpinelPS/LobbyServer/Msgs/Character/GetSynchrodevice.cs
Normal file
54
EpinelPS/LobbyServer/Msgs/Character/GetSynchrodevice.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
{
|
||||
[PacketPath("/character/synchrodevice/get")]
|
||||
public class GetSynchrodevice : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqGetSynchroData>();
|
||||
var user = GetUser();
|
||||
|
||||
if (user.SynchroSlots.Count == 0)
|
||||
{
|
||||
|
||||
user.SynchroSlots = new() {
|
||||
new SynchroSlot() { Slot = 1 },
|
||||
new SynchroSlot() { Slot = 2},
|
||||
new SynchroSlot() { Slot = 3 },
|
||||
new SynchroSlot() { Slot = 4 },
|
||||
new SynchroSlot() { Slot = 5 },
|
||||
|
||||
new SynchroSlot() { Slot = 6 },
|
||||
new SynchroSlot() { Slot = 7 },
|
||||
new SynchroSlot() { Slot = 8 },
|
||||
new SynchroSlot() { Slot = 9 },
|
||||
new SynchroSlot() { Slot = 10 },
|
||||
};
|
||||
}
|
||||
|
||||
var highestLevelCharacters = user.Characters.OrderByDescending(x => x.Level).Take(5).ToList();
|
||||
|
||||
var response = new ResGetSynchroData();
|
||||
response.Synchro = new NetUserSynchroData();
|
||||
|
||||
foreach (var item in highestLevelCharacters)
|
||||
{
|
||||
response.Synchro.StandardCharacters.Add(new NetUserCharacterData() { Default = new() { Csn = item.Csn, Skill1Lv = item.Skill1Lvl, Skill2Lv = item.Skill2Lvl, CostumeId = item.CostumeId, Level = item.Level, Grade = item.Grade, Tid = item.Tid, UltiSkillLv = item.UltimateLevel }, IsSynchro = user.GetSynchro(item.Csn) });
|
||||
}
|
||||
|
||||
foreach (var item in user.SynchroSlots)
|
||||
{
|
||||
response.Synchro.Slots.Add(new NetSynchroSlot() { Slot = item.Slot, AvailableRegisterAt = 1, Csn = item.CharacterSerialNumber });
|
||||
}
|
||||
|
||||
response.Synchro.SynchroMaxLv = 1000;
|
||||
response.Synchro.SynchroLv = user.GetSynchroLevel();
|
||||
response.Synchro.IsChanged = user.SynchroDeviceUpgraded;
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
81
EpinelPS/LobbyServer/Msgs/Character/LevelUp.cs
Normal file
81
EpinelPS/LobbyServer/Msgs/Character/LevelUp.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.StaticInfo;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
{
|
||||
[PacketPath("/character/levelup")]
|
||||
public class LevelUp : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqCharacterLevelUp>();
|
||||
var user = GetUser();
|
||||
var response = new ResCharacterLevelUp();
|
||||
var data = GameData.Instance.GetCharacterLevelUpData();
|
||||
|
||||
foreach (var item in user.Characters.ToArray())
|
||||
{
|
||||
if (item.Csn == req.Csn)
|
||||
{
|
||||
int requiredCredit = 0;
|
||||
int requiredBattleData = 0;
|
||||
int requiredCoreDust = 0;
|
||||
for (int i = item.Level; i < req.Level; i++)
|
||||
{
|
||||
var levelUpData = data[i];
|
||||
requiredCredit += levelUpData.gold;
|
||||
requiredBattleData += levelUpData.character_exp;
|
||||
requiredCoreDust += levelUpData.character_exp2;
|
||||
}
|
||||
|
||||
if (user.CanSubtractCurrency(CurrencyType.Gold, requiredCredit) &&
|
||||
user.CanSubtractCurrency(CurrencyType.CharacterExp, requiredBattleData) &&
|
||||
user.CanSubtractCurrency(CurrencyType.CharacterExp2, requiredCoreDust))
|
||||
{
|
||||
user.SubtractCurrency(CurrencyType.Gold, requiredCredit);
|
||||
user.SubtractCurrency(CurrencyType.CharacterExp, requiredBattleData);
|
||||
user.SubtractCurrency(CurrencyType.CharacterExp2, requiredCoreDust);
|
||||
item.Level = req.Level;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TOOD: log this
|
||||
Console.WriteLine("ERROR: Not enough currency for upgrade");
|
||||
return;
|
||||
}
|
||||
|
||||
response.Character = new()
|
||||
{
|
||||
CostumeId = item.CostumeId,
|
||||
Csn = item.Csn,
|
||||
Level = item.Level,
|
||||
Skill1Lv = item.Skill1Lvl,
|
||||
Skill2Lv = item.Skill2Lvl,
|
||||
UltiSkillLv = item.UltimateLevel,
|
||||
Grade = item.Grade,
|
||||
Tid = item.Tid
|
||||
};
|
||||
var highestLevelCharacters = user.Characters.OrderByDescending(x => x.Level).Take(5).ToList();
|
||||
|
||||
response.SynchroLv = user.GetSynchroLevel();
|
||||
|
||||
foreach (var c in highestLevelCharacters)
|
||||
{
|
||||
response.SynchroStandardCharacters.Add(c.Csn);
|
||||
}
|
||||
|
||||
foreach (var currency in user.Currency)
|
||||
{
|
||||
response.Currencies.Add(new NetUserCurrencyData() { Type = (int)currency.Key, Value = currency.Value });
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
JsonDb.Save();
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
48
EpinelPS/LobbyServer/Msgs/Character/RegisterSynchroDevice.cs
Normal file
48
EpinelPS/LobbyServer/Msgs/Character/RegisterSynchroDevice.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
{
|
||||
[PacketPath("/character/SynchroDevice/Regist")]
|
||||
public class RegisterSynchroDevice : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqSynchroRegister>();
|
||||
var user = GetUser();
|
||||
var targetCharacter = user.GetCharacterBySerialNumber(req.Csn);
|
||||
if (targetCharacter == null) throw new Exception("target character does not exist");
|
||||
|
||||
var response = new ResSynchroRegister();
|
||||
foreach (var item in user.SynchroSlots)
|
||||
{
|
||||
if (item.Slot == req.Slot)
|
||||
{
|
||||
if (item.CharacterSerialNumber != 0)
|
||||
{
|
||||
Console.WriteLine("must remove character from synchrodevice first");
|
||||
}
|
||||
else
|
||||
{
|
||||
item.CharacterSerialNumber = req.Csn;
|
||||
response.IsSynchro = true;
|
||||
response.Character = new NetUserCharacterDefaultData()
|
||||
{
|
||||
Csn = item.CharacterSerialNumber,
|
||||
CostumeId = targetCharacter.CostumeId,
|
||||
Grade = targetCharacter.Grade,
|
||||
Level = user.GetSynchroLevel(),
|
||||
Skill1Lv = targetCharacter.Skill1Lvl,
|
||||
Skill2Lv = targetCharacter.Skill2Lvl,
|
||||
Tid = targetCharacter.Tid,
|
||||
UltiSkillLv = targetCharacter.UltimateLevel
|
||||
};
|
||||
response.Slot = new NetSynchroSlot() { AvailableRegisterAt = item.AvailableAt, Csn = item.CharacterSerialNumber, Slot = item.Slot };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
81
EpinelPS/LobbyServer/Msgs/Character/ResetLevel.cs
Normal file
81
EpinelPS/LobbyServer/Msgs/Character/ResetLevel.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.StaticInfo;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
{
|
||||
[PacketPath("/character/growreset")]
|
||||
public class ResetLevel : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqCharacterGrowReset>();
|
||||
var user = GetUser();
|
||||
var response = new ResCharacterGrowReset();
|
||||
var data = GameData.Instance.GetCharacterLevelUpData();
|
||||
|
||||
foreach (var item in user.Characters.ToArray())
|
||||
{
|
||||
if (item.Csn == req.Csn)
|
||||
{
|
||||
if (item.Level == 1)
|
||||
{
|
||||
Console.WriteLine("Character level is already 1 - cannot reset");
|
||||
return;
|
||||
}
|
||||
if (item.Level == 200)
|
||||
{
|
||||
Console.WriteLine("Character level is 200 - cannot reset");
|
||||
return;
|
||||
}
|
||||
|
||||
int requiredCredit = 0;
|
||||
int requiredBattleData = 0;
|
||||
int requiredCoreDust = 0;
|
||||
for (int i = 1; i < item.Level; i++)
|
||||
{
|
||||
var levelUpData = data[i];
|
||||
requiredCredit += levelUpData.gold;
|
||||
requiredBattleData += levelUpData.character_exp;
|
||||
requiredCoreDust += levelUpData.character_exp2;
|
||||
}
|
||||
|
||||
user.AddCurrency(CurrencyType.Gold, requiredCredit);
|
||||
user.AddCurrency(CurrencyType.CharacterExp, requiredBattleData);
|
||||
user.AddCurrency(CurrencyType.CharacterExp2, requiredCoreDust);
|
||||
item.Level = 1;
|
||||
|
||||
response.Character = new()
|
||||
{
|
||||
CostumeId = item.CostumeId,
|
||||
Csn = item.Csn,
|
||||
Level = item.Level,
|
||||
Skill1Lv = item.Skill1Lvl,
|
||||
Skill2Lv = item.Skill2Lvl,
|
||||
UltiSkillLv = item.UltimateLevel,
|
||||
Grade = item.Grade,
|
||||
Tid = item.Tid
|
||||
};
|
||||
var highestLevelCharacters = user.Characters.OrderByDescending(x => x.Level).Take(5).ToList();
|
||||
|
||||
response.SynchroLv = highestLevelCharacters.Last().Level;
|
||||
|
||||
foreach (var c in highestLevelCharacters)
|
||||
{
|
||||
response.SynchroStandardCharacters.Add(c.Csn);
|
||||
}
|
||||
|
||||
foreach (var currency in user.Currency)
|
||||
{
|
||||
response.Currencies.Add(new NetUserCurrencyData() { Type = (int)currency.Key, Value = currency.Value });
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
JsonDb.Save();
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,7 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Character
|
||||
namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
{
|
||||
[PacketPath("/character/costume/set")]
|
||||
public class SetCharacterCostume : LobbyMsgHandler
|
||||
@@ -17,7 +13,7 @@ namespace nksrv.LobbyServer.Msgs.Character
|
||||
|
||||
foreach (var item in user.Characters)
|
||||
{
|
||||
if(item.Csn == req.Csn)
|
||||
if (item.Csn == req.Csn)
|
||||
{
|
||||
item.CostumeId = req.CostumeId;
|
||||
break;
|
||||
@@ -27,7 +23,7 @@ namespace nksrv.LobbyServer.Msgs.Character
|
||||
|
||||
var response = new ResSetCharacterCostume();
|
||||
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
54
EpinelPS/LobbyServer/Msgs/Character/SynchroLevelUp.cs
Normal file
54
EpinelPS/LobbyServer/Msgs/Character/SynchroLevelUp.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.StaticInfo;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
{
|
||||
[PacketPath("/character/SynchroDevice/LevelUp")]
|
||||
public class SynchroLevelUp : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqSynchroLevelUp>();
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResSynchroLevelUp();
|
||||
var data = GameData.Instance.GetCharacterLevelUpData();
|
||||
|
||||
|
||||
int requiredCredit = 0;
|
||||
int requiredBattleData = 0;
|
||||
int requiredCoreDust = 0;
|
||||
var levelUpData = data[user.SynchroDeviceLevel + 1];
|
||||
requiredCredit += levelUpData.gold;
|
||||
requiredBattleData += levelUpData.character_exp;
|
||||
requiredCoreDust += levelUpData.character_exp2;
|
||||
|
||||
if (user.CanSubtractCurrency(CurrencyType.Gold, requiredCredit) &&
|
||||
user.CanSubtractCurrency(CurrencyType.CharacterExp, requiredBattleData) &&
|
||||
user.CanSubtractCurrency(CurrencyType.CharacterExp2, requiredCoreDust))
|
||||
{
|
||||
user.SubtractCurrency(CurrencyType.Gold, requiredCredit);
|
||||
user.SubtractCurrency(CurrencyType.CharacterExp, requiredBattleData);
|
||||
user.SubtractCurrency(CurrencyType.CharacterExp2, requiredCoreDust);
|
||||
user.SynchroDeviceLevel++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TOOD: log this
|
||||
Console.WriteLine("ERROR: Not enough currency for upgrade");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
foreach (var currency in user.Currency)
|
||||
{
|
||||
response.Currencies.Add(new NetUserCurrencyData() { Type = (int)currency.Key, Value = currency.Value });
|
||||
}
|
||||
response.SynchroLv = user.SynchroDeviceLevel;
|
||||
|
||||
JsonDb.Save();
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
{
|
||||
[PacketPath("/character/SynchroDevice/Unregist")]
|
||||
public class UnregisterSynchroDevice : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqSynchroUnregist>();
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResSynchroUnregist();
|
||||
|
||||
foreach (var item in user.SynchroSlots)
|
||||
{
|
||||
if (item.Slot == req.Slot)
|
||||
{
|
||||
if (item.CharacterSerialNumber == 0)
|
||||
{
|
||||
Console.WriteLine("must add character from synchrodevice first");
|
||||
}
|
||||
else
|
||||
{
|
||||
var oldCSN = item.CharacterSerialNumber;
|
||||
item.CharacterSerialNumber = 0;
|
||||
var data = user.GetCharacterBySerialNumber(oldCSN);
|
||||
if (data == null) throw new Exception("failed to lookup character");
|
||||
|
||||
response.Character = new NetUserCharacterDefaultData()
|
||||
{
|
||||
Csn = data.Csn,
|
||||
CostumeId = data.CostumeId,
|
||||
Grade = data.Grade,
|
||||
Level = data.Level,
|
||||
Skill1Lv = data.Skill1Lvl,
|
||||
Skill2Lv = data.Skill2Lvl,
|
||||
Tid = data.Tid,
|
||||
UltiSkillLv = data.UltimateLevel
|
||||
};
|
||||
response.Slot = new NetSynchroSlot() { AvailableRegisterAt = item.AvailableAt, Csn = item.CharacterSerialNumber, Slot = item.Slot };
|
||||
|
||||
response.IsSynchro = false;
|
||||
var highestLevelCharacters = user.Characters.OrderByDescending(x => x.Level).Take(5).ToList();
|
||||
|
||||
|
||||
foreach (var item2 in highestLevelCharacters)
|
||||
{
|
||||
response.SynchroStandardCharacters.Add(item2.Csn);
|
||||
}
|
||||
|
||||
response.SynchroLv = user.GetSynchroLevel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JsonDb.Save();
|
||||
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,7 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Event
|
||||
namespace EpinelPS.LobbyServer.Msgs.Event
|
||||
{
|
||||
[PacketPath("/event/scenario/complete")]
|
||||
public class CompleteEventScenario : LobbyMsgHandler
|
||||
@@ -15,23 +11,23 @@ namespace nksrv.LobbyServer.Msgs.Event
|
||||
var req = await ReadData<ReqSetEventScenarioComplete>();
|
||||
var user = GetUser();
|
||||
|
||||
if (user.EventInfo.ContainsKey(req.EventID))
|
||||
if (user.EventInfo.ContainsKey(req.EventId))
|
||||
{
|
||||
var evt = user.EventInfo[req.EventID];
|
||||
var evt = user.EventInfo[req.EventId];
|
||||
evt.CompletedScenarios.Add(req.ScenarioId);
|
||||
}
|
||||
else
|
||||
{
|
||||
var evt = new EventData();
|
||||
evt.CompletedScenarios.Add(req.ScenarioId);
|
||||
user.EventInfo.Add(req.EventID, evt);
|
||||
user.EventInfo.Add(req.EventId, evt);
|
||||
}
|
||||
|
||||
var response = new ResSetEventScenarioComplete();
|
||||
|
||||
// TODO reward
|
||||
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Event
|
||||
namespace EpinelPS.LobbyServer.Msgs.Event
|
||||
{
|
||||
[PacketPath("/eventfield/enter")]
|
||||
public class EnterEventField : LobbyMsgHandler
|
||||
@@ -18,7 +13,7 @@ namespace nksrv.LobbyServer.Msgs.Event
|
||||
|
||||
// TOOD
|
||||
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Event
|
||||
namespace EpinelPS.LobbyServer.Msgs.Event
|
||||
{
|
||||
[PacketPath("/event/mission/getclear")]
|
||||
public class GetClearedMissions : LobbyMsgHandler
|
||||
@@ -16,7 +11,7 @@ namespace nksrv.LobbyServer.Msgs.Event
|
||||
|
||||
var response = new ResGetEventMissionClear();
|
||||
// TODO
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,7 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Event
|
||||
namespace EpinelPS.LobbyServer.Msgs.Event
|
||||
{
|
||||
[PacketPath("/event/scenario/get")]
|
||||
public class GetEventScenario : LobbyMsgHandler
|
||||
@@ -16,17 +12,17 @@ namespace nksrv.LobbyServer.Msgs.Event
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResGetEventScenarioData();
|
||||
if (user.EventInfo.ContainsKey(req.EventID))
|
||||
if (user.EventInfo.ContainsKey(req.EventId))
|
||||
{
|
||||
var evt = user.EventInfo[req.EventID];
|
||||
var evt = user.EventInfo[req.EventId];
|
||||
response.ScenarioIdList.AddRange(evt.CompletedScenarios);
|
||||
}
|
||||
else
|
||||
{
|
||||
user.EventInfo.Add(req.EventID, new EventData());
|
||||
user.EventInfo.Add(req.EventId, new EventData());
|
||||
}
|
||||
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Event
|
||||
namespace EpinelPS.LobbyServer.Msgs.Event
|
||||
{
|
||||
[PacketPath("/event/getjoinedevent")]
|
||||
public class GetJoinedEvent : LobbyMsgHandler
|
||||
@@ -69,7 +64,7 @@ namespace nksrv.LobbyServer.Msgs.Event
|
||||
JoinAt = 0
|
||||
});
|
||||
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Event
|
||||
namespace EpinelPS.LobbyServer.Msgs.Event
|
||||
{
|
||||
[PacketPath("/event/list")]
|
||||
public class ListEvents : LobbyMsgHandler
|
||||
@@ -19,10 +14,10 @@ namespace nksrv.LobbyServer.Msgs.Event
|
||||
response.EventList.Add(new NetEventData()
|
||||
{
|
||||
Id = 81301,
|
||||
EventDisableDate = 1000000000000000,
|
||||
EventStartDate = 1,
|
||||
EventEndDate = 1000000000000000,
|
||||
EventVisibleDate = 0,
|
||||
EventDisableDate = DateTime.Now.AddDays(20).Ticks,
|
||||
EventStartDate = DateTime.UtcNow.Subtract(TimeSpan.FromDays(1)).Ticks,
|
||||
EventEndDate = DateTime.Now.AddDays(20).Ticks,
|
||||
EventVisibleDate = DateTime.UtcNow.Subtract(TimeSpan.FromDays(1)).Ticks,
|
||||
EventSystemType = 34
|
||||
});
|
||||
|
||||
@@ -32,10 +27,10 @@ namespace nksrv.LobbyServer.Msgs.Event
|
||||
response.EventList.Add(new NetEventData()
|
||||
{
|
||||
Id = 20001,
|
||||
EventDisableDate = 1000000000000000,
|
||||
EventStartDate = 1,
|
||||
EventEndDate = 1000000000000000,
|
||||
EventVisibleDate = 0,
|
||||
EventDisableDate = DateTime.Now.AddDays(20).Ticks,
|
||||
EventStartDate = DateTime.UtcNow.Subtract(TimeSpan.FromDays(1)).Ticks,
|
||||
EventEndDate = DateTime.Now.AddDays(20).Ticks,
|
||||
EventVisibleDate = DateTime.UtcNow.Subtract(TimeSpan.FromDays(1)).Ticks,
|
||||
EventSystemType = 1
|
||||
});
|
||||
|
||||
@@ -102,7 +97,26 @@ namespace nksrv.LobbyServer.Msgs.Event
|
||||
EventEndDate = DateTime.Now.AddDays(20).Ticks,
|
||||
EventDisableDate = DateTime.Now.AddDays(20).Ticks,
|
||||
});
|
||||
await WriteDataAsync(response);
|
||||
|
||||
response.EventList.Add(new NetEventData()
|
||||
{
|
||||
Id = 40053,
|
||||
EventSystemType = 5,
|
||||
EventVisibleDate = DateTime.UtcNow.Subtract(TimeSpan.FromDays(1)).Ticks,
|
||||
EventStartDate = DateTime.UtcNow.Subtract(TimeSpan.FromDays(1)).Ticks,
|
||||
EventEndDate = DateTime.Now.AddDays(20).Ticks,
|
||||
EventDisableDate = DateTime.Now.AddDays(20).Ticks,
|
||||
});
|
||||
//response.EventList.Add(new NetEventData()
|
||||
//{
|
||||
// Id = 40054,
|
||||
// EventSystemType = 5,
|
||||
// EventVisibleDate = DateTime.UtcNow.Subtract(TimeSpan.FromDays(1)).Ticks,
|
||||
// EventStartDate = DateTime.UtcNow.Subtract(TimeSpan.FromDays(1)).Ticks,
|
||||
// EventEndDate = DateTime.Now.AddDays(20).Ticks,
|
||||
// EventDisableDate = DateTime.Now.AddDays(20).Ticks,
|
||||
//});
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using EpinelPS.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Event.StoryEvent
|
||||
{
|
||||
[PacketPath("/event/storydungeon/get")]
|
||||
public class GetStoryDungeon : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqStoryDungeonEventData>();
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResStoryDungeonEventData()
|
||||
{
|
||||
TeamData = new NetUserTeamData(),
|
||||
RemainTicket = 10,
|
||||
};
|
||||
|
||||
// TOOD
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.FavoriteItem
|
||||
{
|
||||
[PacketPath("/favoriteitem/library")]
|
||||
public class GetFavoriteItemLibrary : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqGetFavoriteItemLibrary>();
|
||||
|
||||
var response = new ResGetFavoriteItemLibrary();
|
||||
var user = GetUser();
|
||||
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
18
EpinelPS/LobbyServer/Msgs/FavoriteItem/ListFavoriteItem.cs
Normal file
18
EpinelPS/LobbyServer/Msgs/FavoriteItem/ListFavoriteItem.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.FavoriteItem
|
||||
{
|
||||
[PacketPath("/favoriteitem/list")]
|
||||
public class ListFavoriteItem : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqListFavoriteItem>();
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResListFavoriteItem();
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.FavoriteItem
|
||||
{
|
||||
[PacketPath("/favoriteitem/quest/list")]
|
||||
public class ListFavoriteItemQuests : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqListFavoriteItemQuest>();
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResListFavoriteItemQuest();
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Friend
|
||||
namespace EpinelPS.LobbyServer.Msgs.Friend
|
||||
{
|
||||
[PacketPath("/friend/get")]
|
||||
public class GetFriends : LobbyMsgHandler
|
||||
@@ -16,7 +11,7 @@ namespace nksrv.LobbyServer.Msgs.Friend
|
||||
var response = new ResGetFriendData();
|
||||
|
||||
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Gacha
|
||||
namespace EpinelPS.LobbyServer.Msgs.Gacha
|
||||
{
|
||||
[PacketPath("/gacha/event/check")]
|
||||
public class CheckGachaDailyEvent : LobbyMsgHandler
|
||||
@@ -20,7 +15,7 @@ namespace nksrv.LobbyServer.Msgs.Gacha
|
||||
response.FreeCount = 0;
|
||||
response.EventData = new NetEventData() { Id = 1 };
|
||||
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
46
EpinelPS/LobbyServer/Msgs/Gacha/ExecGacha.cs
Normal file
46
EpinelPS/LobbyServer/Msgs/Gacha/ExecGacha.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.StaticInfo;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Gacha
|
||||
{
|
||||
[PacketPath("/gacha/execute")]
|
||||
public class ExecGacha : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqExecuteGacha>();
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResExecuteGacha();
|
||||
|
||||
// TODO: Pick random character that player does not have unless it supports limit break.
|
||||
|
||||
// TODO implement reward
|
||||
response.Reward = new NetRewardData();
|
||||
|
||||
foreach (var c in GameData.Instance.GetAllCharacterTids())
|
||||
{
|
||||
if (!user.HasCharacter(c))
|
||||
{
|
||||
var id = user.GenerateUniqueCharacterId();
|
||||
response.Gacha.Add(new NetGachaEntityData() { Corporation = 1, PieceCount = 1, CurrencyValue = 5, Sn = id, Tid = c, Type = 1 });
|
||||
|
||||
response.Characters.Add(new NetUserCharacterDefaultData() { CostumeId = 0, Csn = id, Grade = 0, Level = 1, Skill1Lv = 1, Skill2Lv = 1, Tid = c, UltiSkillLv = 1 });
|
||||
|
||||
user.Characters.Add(new Database.Character() { CostumeId = 0, Csn = id, Grade = 0, Level = 1, Skill1Lvl = 1, Skill2Lvl = 1, Tid = c, UltimateLevel = 1 });
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO add spare body
|
||||
}
|
||||
}
|
||||
user.GachaTutorialPlayCount++;
|
||||
|
||||
JsonDb.Save();
|
||||
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using nksrv.Utils;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs
|
||||
namespace EpinelPS.LobbyServer.Msgs
|
||||
{
|
||||
[PacketPath("/now")]
|
||||
public class GetCurrentTime : LobbyMsgHandler
|
||||
@@ -16,7 +16,7 @@ namespace nksrv.LobbyServer.Msgs
|
||||
response.CheatShiftDuration = Duration.FromTimeSpan(TimeSpan.FromSeconds(0));
|
||||
// todo: validate response with actual server
|
||||
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,6 @@
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs
|
||||
namespace EpinelPS.LobbyServer.Msgs
|
||||
{
|
||||
[PacketPath("/Gacha/Get")]
|
||||
public class GetGacha : LobbyMsgHandler
|
||||
@@ -19,7 +13,7 @@ namespace nksrv.LobbyServer.Msgs
|
||||
var response = new ResGetGachaData();
|
||||
if (user.GachaTutorialPlayCount > 0)
|
||||
response.Gacha.Add(new NetUserGachaData() { GachaType = 3, PlayCount = 1 });
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
23
EpinelPS/LobbyServer/Msgs/Intercept/GetInterceptData.cs
Normal file
23
EpinelPS/LobbyServer/Msgs/Intercept/GetInterceptData.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Intercept
|
||||
{
|
||||
[PacketPath("/intercept/get")]
|
||||
public class GetInterceptData : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqGetInterceptData>();
|
||||
|
||||
var response = new ResGetInterceptData
|
||||
{
|
||||
NormalInterceptGroup = 1,
|
||||
SpecialInterceptId = 1,
|
||||
TicketCount = 5,
|
||||
MaxTicketCount = 10
|
||||
};
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
20
EpinelPS/LobbyServer/Msgs/Intercept/InterceptCheck.cs
Normal file
20
EpinelPS/LobbyServer/Msgs/Intercept/InterceptCheck.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Intercept
|
||||
{
|
||||
[PacketPath("/intercept/check")]
|
||||
public class CheckClearInterceptToday : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqCheckClearInterceptToday>();
|
||||
|
||||
var response = new ResCheckClearInterceptToday
|
||||
{
|
||||
Clear = true
|
||||
};
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
23
EpinelPS/LobbyServer/Msgs/Intercept/InterceptClear.cs
Normal file
23
EpinelPS/LobbyServer/Msgs/Intercept/InterceptClear.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Intercept
|
||||
{
|
||||
[PacketPath("/intercept/clear")]
|
||||
public class ClearInterceptData : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqClearIntercept>();
|
||||
|
||||
var response = new ResClearIntercept
|
||||
{
|
||||
Intercept = 1,
|
||||
InterceptId = 1,
|
||||
TicketCount = 5,
|
||||
MaxTicketCount = 10
|
||||
};
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
17
EpinelPS/LobbyServer/Msgs/Intercept/InterceptEnter.cs
Normal file
17
EpinelPS/LobbyServer/Msgs/Intercept/InterceptEnter.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Intercept
|
||||
{
|
||||
[PacketPath("/intercept/enter")]
|
||||
public class EnterInterceptData : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqEnterIntercept>();
|
||||
|
||||
var response = new ResEnterIntercept();
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
22
EpinelPS/LobbyServer/Msgs/Intercept/InterceptFastClear.cs
Normal file
22
EpinelPS/LobbyServer/Msgs/Intercept/InterceptFastClear.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Intercept
|
||||
{
|
||||
[PacketPath("/intercept/fastclear")]
|
||||
public class FastClearInterceptData : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqFastClearIntercept>();
|
||||
|
||||
var response = new ResFastClearIntercept
|
||||
{
|
||||
TicketCount = 3,
|
||||
MaxTicketCount = 10,
|
||||
Damage = 2
|
||||
};
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,7 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Inventory
|
||||
namespace EpinelPS.LobbyServer.Msgs.Inventory
|
||||
{
|
||||
[PacketPath("/inventory/allclearequipment")]
|
||||
public class ClearAllEquipment : LobbyMsgHandler
|
||||
@@ -28,9 +24,10 @@ namespace nksrv.LobbyServer.Msgs.Inventory
|
||||
response.Items.Add(NetUtils.ToNet(item));
|
||||
}
|
||||
}
|
||||
|
||||
JsonDb.Save();
|
||||
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,7 @@
|
||||
using nksrv.LobbyServer.Msgs.User;
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Inventory
|
||||
namespace EpinelPS.LobbyServer.Msgs.Inventory
|
||||
{
|
||||
[PacketPath("/inventory/clearequipment")]
|
||||
public class ClearEquipment : LobbyMsgHandler
|
||||
@@ -26,12 +21,13 @@ namespace nksrv.LobbyServer.Msgs.Inventory
|
||||
item.Csn = 0;
|
||||
|
||||
response.Item = NetUtils.ToNet(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
JsonDb.Save();
|
||||
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Inventory
|
||||
namespace EpinelPS.LobbyServer.Msgs.Inventory
|
||||
{
|
||||
[PacketPath("/inventory/get")]
|
||||
public class GetInventoryData : LobbyMsgHandler
|
||||
@@ -18,12 +13,11 @@ namespace nksrv.LobbyServer.Msgs.Inventory
|
||||
var response = new ResGetInventoryData();
|
||||
foreach (var item in user.Items)
|
||||
{
|
||||
response.Items.Add(new NetUserItemData() { Count = item.Count, Tid = item.ItemType, Csn = item.Csn, Lv = item.Level, Exp = item.Exp, Corporation = item.Corp, Isn = item.Isn, Position = item.Position });
|
||||
response.Items.Add(new NetUserItemData() { Count = item.Count, Tid = item.ItemType, Csn = item.Csn, Level = item.Level, Exp = item.Exp, Corporation = item.Corp, Isn = item.Isn, Position = item.Position });
|
||||
}
|
||||
// TODO: HarmonyCubes, RunAwakeningIsnList, UserRedeems
|
||||
|
||||
// TODO implement
|
||||
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,7 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Inventory
|
||||
namespace EpinelPS.LobbyServer.Msgs.Inventory
|
||||
{
|
||||
[PacketPath("/inventory/wearequipment")]
|
||||
public class WearEquipment : LobbyMsgHandler
|
||||
@@ -17,25 +13,32 @@ namespace nksrv.LobbyServer.Msgs.Inventory
|
||||
|
||||
var response = new ResWearEquipment();
|
||||
|
||||
var pos = NetUtils.GetItemPos(user, req.Isn);
|
||||
|
||||
// unequip old item
|
||||
|
||||
foreach (var item in user.Items.ToArray())
|
||||
{
|
||||
if (item.Csn == req.Csn && item.Position == pos)
|
||||
{
|
||||
item.Csn = 0;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var item in user.Items.ToArray())
|
||||
{
|
||||
if (item.Isn == req.Isn)
|
||||
{
|
||||
// update character id
|
||||
item.Csn = req.Csn;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach (var item in user.Items.ToArray())
|
||||
{
|
||||
if (item.Csn == req.Csn)
|
||||
{
|
||||
item.Position = pos;
|
||||
response.Items.Add(NetUtils.ToNet(item));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
JsonDb.Save();
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,7 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Inventory
|
||||
namespace EpinelPS.LobbyServer.Msgs.Inventory
|
||||
{
|
||||
[PacketPath("/inventory/wearequipmentlist")]
|
||||
public class WearEquipmentList : LobbyMsgHandler
|
||||
@@ -17,14 +13,27 @@ namespace nksrv.LobbyServer.Msgs.Inventory
|
||||
|
||||
var response = new ResWearEquipmentList();
|
||||
|
||||
foreach (var item in user.Items.ToArray())
|
||||
// TODO optimize
|
||||
foreach (var item2 in req.IsnList)
|
||||
{
|
||||
foreach (var item2 in req.IsnList)
|
||||
var pos = NetUtils.GetItemPos(user, item2);
|
||||
|
||||
// unequip previous items
|
||||
foreach (var item in user.Items.ToArray())
|
||||
{
|
||||
if (item.Position == pos && item.Csn == req.Csn)
|
||||
{
|
||||
item.Csn = 0;
|
||||
item.Position = 0;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var item in user.Items.ToArray())
|
||||
{
|
||||
if (item2 == item.Isn)
|
||||
{
|
||||
item.Csn = req.Csn;
|
||||
|
||||
item.Position = pos;
|
||||
response.Items.Add(NetUtils.ToNet(item));
|
||||
}
|
||||
}
|
||||
24
EpinelPS/LobbyServer/Msgs/Liberate/ChooseCharacter.cs
Normal file
24
EpinelPS/LobbyServer/Msgs/Liberate/ChooseCharacter.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Liberate
|
||||
{
|
||||
[PacketPath("/liberate/choosecharacter")]
|
||||
public class ChooseCharacter : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqChooseLiberateCharacter>();
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResChooseLiberateCharacter();
|
||||
|
||||
// TODO
|
||||
response.Data = new NetLiberateData() { CharacterId = req.CharacterId };
|
||||
response.Data.MissionData.Add(new NetLiberateMissionData() { MissionState = LiberateMissionState.LiberateMissionStateRunning, Id = 1 });
|
||||
response.Data.MissionData.Add(new NetLiberateMissionData() { MissionState = LiberateMissionState.LiberateMissionStateRunning, Id = 2 });
|
||||
response.Data.MissionData.Add(new NetLiberateMissionData() { MissionState = LiberateMissionState.LiberateMissionStateRunning, Id = 3 });
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
20
EpinelPS/LobbyServer/Msgs/Liberate/GetLiberateData.cs
Normal file
20
EpinelPS/LobbyServer/Msgs/Liberate/GetLiberateData.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Liberate
|
||||
{
|
||||
[PacketPath("/liberate/get")]
|
||||
public class GetLiberateData : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqGetLiberateData>();
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResGetLiberateData() { };
|
||||
|
||||
// TODO
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
20
EpinelPS/LobbyServer/Msgs/Liberate/GetProgressList.cs
Normal file
20
EpinelPS/LobbyServer/Msgs/Liberate/GetProgressList.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Liberate
|
||||
{
|
||||
[PacketPath("/liberate/getprogresslist")]
|
||||
public class GetProgressList : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqGetLiberateProgressList>();
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResGetLiberateProgressList();
|
||||
|
||||
// TODO
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
20
EpinelPS/LobbyServer/Msgs/Lostsector/GetLostSectorData.cs
Normal file
20
EpinelPS/LobbyServer/Msgs/Lostsector/GetLostSectorData.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Lostsector
|
||||
{
|
||||
[PacketPath("/lostsector/get")]
|
||||
public class GetLostSectorData : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqGetLostSectorData>();
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResGetLostSectorData();
|
||||
|
||||
// TODO
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Messenger
|
||||
namespace EpinelPS.LobbyServer.Msgs.Messenger
|
||||
{
|
||||
[PacketPath("/messenger/daily/pick")]
|
||||
public class GetDailyMessage : LobbyMsgHandler
|
||||
@@ -17,7 +12,7 @@ namespace nksrv.LobbyServer.Msgs.Messenger
|
||||
// TODO: save these things
|
||||
var response = new ResPickTodayDailyMessage();
|
||||
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Messenger
|
||||
namespace EpinelPS.LobbyServer.Msgs.Messenger
|
||||
{
|
||||
[PacketPath("/messenger/get")]
|
||||
public class GetMessages : LobbyMsgHandler
|
||||
@@ -17,7 +12,7 @@ namespace nksrv.LobbyServer.Msgs.Messenger
|
||||
// TODO: save these things
|
||||
var response = new ResGetMessages();
|
||||
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Messenger
|
||||
namespace EpinelPS.LobbyServer.Msgs.Messenger
|
||||
{
|
||||
[PacketPath("/messenger/picked/get")]
|
||||
public class GetPickedMessage : LobbyMsgHandler
|
||||
@@ -17,7 +12,7 @@ namespace nksrv.LobbyServer.Msgs.Messenger
|
||||
// TODO: get proper response
|
||||
var response = new ResGetPickedMessageList();
|
||||
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
18
EpinelPS/LobbyServer/Msgs/Messenger/GetRandomPick.cs
Normal file
18
EpinelPS/LobbyServer/Msgs/Messenger/GetRandomPick.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Messenger
|
||||
{
|
||||
[PacketPath("/messenger/random/pick")]
|
||||
public class GetRandomPick : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqPickTodayRandomMessage>();
|
||||
|
||||
// TODO: get proper response
|
||||
var response = new ResPickTodayRandomMessage();
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Messenger
|
||||
namespace EpinelPS.LobbyServer.Msgs.Messenger
|
||||
{
|
||||
[PacketPath("/messenger/proceed")]
|
||||
public class ProceedMsg : LobbyMsgHandler
|
||||
@@ -12,7 +12,7 @@ namespace nksrv.LobbyServer.Msgs.Messenger
|
||||
// TODO: save these things
|
||||
var response = new ResProceedMessage();
|
||||
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Minigame.Dave
|
||||
namespace EpinelPS.LobbyServer.Msgs.Minigame.Dave
|
||||
{
|
||||
[PacketPath("/event/minigame/dave/getalldavetrigger")]
|
||||
public class GetAllDaveTrigger : LobbyMsgHandler
|
||||
@@ -16,7 +11,7 @@ namespace nksrv.LobbyServer.Msgs.Minigame.Dave
|
||||
|
||||
var response = new ResGetAllMiniGameDaveTriggers();
|
||||
// TODO
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Minigame
|
||||
namespace EpinelPS.LobbyServer.Msgs.Minigame
|
||||
{
|
||||
[PacketPath("/minigame/nksv2/get")]
|
||||
public class GetNksv2Minigame : LobbyMsgHandler
|
||||
@@ -16,7 +11,7 @@ namespace nksrv.LobbyServer.Msgs.Minigame
|
||||
|
||||
var response = new ResGetMiniGameNKSV2Data();
|
||||
// TODO
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Minigame.IslandAdventure
|
||||
namespace EpinelPS.LobbyServer.Msgs.Minigame.IslandAdventure
|
||||
{
|
||||
[PacketPath("/event/minigame/islandadventure/get/fishing/stepupreward")]
|
||||
public class GetFishingStepUpRewardStatus : LobbyMsgHandler
|
||||
@@ -16,7 +11,7 @@ namespace nksrv.LobbyServer.Msgs.Minigame.IslandAdventure
|
||||
|
||||
var response = new ResGetIslandAdventureFishingStepUpRewardStatus();
|
||||
// TODO
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Minigame.IslandAdventure
|
||||
namespace EpinelPS.LobbyServer.Msgs.Minigame.IslandAdventure
|
||||
{
|
||||
[PacketPath("/event/minigame/islandadventure/get/photo/stepupreward")]
|
||||
public class GetPhotoStepUpRewardStatus : LobbyMsgHandler
|
||||
@@ -16,7 +11,7 @@ namespace nksrv.LobbyServer.Msgs.Minigame.IslandAdventure
|
||||
|
||||
var response = new ResGetIslandAdventurePhotoStepUpRewardStatus();
|
||||
// TODO
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Minigame.IslandAdventure
|
||||
namespace EpinelPS.LobbyServer.Msgs.Minigame.IslandAdventure
|
||||
{
|
||||
[PacketPath("/event/minigame/islandadventure/list/mission")]
|
||||
public class ListMission : LobbyMsgHandler
|
||||
@@ -16,7 +11,7 @@ namespace nksrv.LobbyServer.Msgs.Minigame.IslandAdventure
|
||||
|
||||
var response = new ResGetIslandAdventureMissionProgress();
|
||||
// TODO
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Minigame.PlaySoda
|
||||
namespace EpinelPS.LobbyServer.Msgs.Minigame.PlaySoda
|
||||
{
|
||||
[PacketPath("/event/minigame/playsoda/challenge/getinfo")]
|
||||
public class GetChallengeInfo : LobbyMsgHandler
|
||||
@@ -16,7 +11,7 @@ namespace nksrv.LobbyServer.Msgs.Minigame.PlaySoda
|
||||
|
||||
var response = new ResGetPlaySodaChallengeModeInfo();
|
||||
// TODO
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Misc
|
||||
namespace EpinelPS.LobbyServer.Msgs.Misc
|
||||
{
|
||||
[PacketPath("/enterlobbyping")]
|
||||
public class EnterLobbyPing : LobbyMsgHandler
|
||||
@@ -11,7 +11,7 @@ namespace nksrv.LobbyServer.Msgs.Misc
|
||||
|
||||
var response = new ResEnterLobbyPing();
|
||||
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Misc
|
||||
namespace EpinelPS.LobbyServer.Msgs.Misc
|
||||
{
|
||||
[PacketPath("/shutdownflags/gacha/getall")]
|
||||
public class GachaGetAllShutdownFlags : LobbyMsgHandler
|
||||
@@ -14,8 +14,8 @@ namespace nksrv.LobbyServer.Msgs.Misc
|
||||
if (user.GachaTutorialPlayCount > 0)
|
||||
response.Unavailables.Add(3);
|
||||
|
||||
// TODO: Validate response from real server and pull info from user info
|
||||
await WriteDataAsync(response);
|
||||
// TODO: Validate response from real server and pull info from user info
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,6 @@
|
||||
using Google.Protobuf;
|
||||
using nksrv.StaticInfo;
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Misc
|
||||
namespace EpinelPS.LobbyServer.Msgs.Misc
|
||||
{
|
||||
[PacketPath("/featureflags/get")]
|
||||
public class GetFeatureFlags : LobbyMsgHandler
|
||||
@@ -19,7 +12,7 @@ namespace nksrv.LobbyServer.Msgs.Misc
|
||||
var r = new ResGetFeatureFlag();
|
||||
r.IsOpen = true;
|
||||
|
||||
await WriteDataAsync(r);
|
||||
await WriteDataAsync(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
15
EpinelPS/LobbyServer/Msgs/Misc/GetMaintenanceNotice.cs
Normal file
15
EpinelPS/LobbyServer/Msgs/Misc/GetMaintenanceNotice.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Misc
|
||||
{
|
||||
[PacketPath("/maintenancenotice")]
|
||||
public class GetMaintenanceNotice : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var r = new ResMaintenanceNotice();
|
||||
|
||||
await WriteDataAsync(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
19
EpinelPS/LobbyServer/Msgs/Misc/GetResourceHosts2.cs
Normal file
19
EpinelPS/LobbyServer/Msgs/Misc/GetResourceHosts2.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Misc
|
||||
{
|
||||
[PacketPath("/resourcehosts2")]
|
||||
public class CheckClientVersion : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqGetResourceHosts2>();
|
||||
|
||||
var r = new ResGetResourceHosts2();
|
||||
r.BaseUrl = GameConfig.Root.ResourceBaseURL;
|
||||
r.Version = req.Version;
|
||||
|
||||
await WriteDataAsync(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
17
EpinelPS/LobbyServer/Msgs/Misc/GetSentryParams.cs
Normal file
17
EpinelPS/LobbyServer/Msgs/Misc/GetSentryParams.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Misc
|
||||
{
|
||||
[PacketPath("/system/sentry/getparams")]
|
||||
public class GetSentryParams : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var r = new ResGetSentryParams();
|
||||
// TODO: Figure out a way so that the game developers would not be annoyed by bogus errors in Sentry dashboard
|
||||
r.SamplingRate = 1E-06;
|
||||
r.TraceSamplingRate = 1E-06;
|
||||
await WriteDataAsync(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,6 @@
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Misc
|
||||
namespace EpinelPS.LobbyServer.Msgs.Misc
|
||||
{
|
||||
[PacketPath("/getserverinfo")]
|
||||
public class GetServerInfo : LobbyMsgHandler
|
||||
@@ -19,7 +13,7 @@ namespace nksrv.LobbyServer.Msgs.Misc
|
||||
r.MatchUrl = "https://global-match.nikke-kr.com";
|
||||
r.WorldId = 84;
|
||||
|
||||
await WriteDataAsync(r);
|
||||
await WriteDataAsync(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
25
EpinelPS/LobbyServer/Msgs/Misc/GetStaticDataPack.cs
Normal file
25
EpinelPS/LobbyServer/Msgs/Misc/GetStaticDataPack.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using EpinelPS.StaticInfo;
|
||||
using EpinelPS.Utils;
|
||||
using Google.Protobuf;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Misc
|
||||
{
|
||||
[PacketPath("/staticdatapack")]
|
||||
public class GetStaticDataPack : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqStaticDataPackInfo>();
|
||||
|
||||
var r = new ResStaticDataPackInfo();
|
||||
r.Url = GameConfig.Root.StaticData.Url;
|
||||
r.Version = GameConfig.Root.StaticData.Version;
|
||||
r.Size = GameData.Instance.Size;
|
||||
r.Sha256Sum = ByteString.CopyFrom(GameData.Instance.Sha256Hash);
|
||||
r.Salt1 = ByteString.CopyFrom(Convert.FromBase64String(GameConfig.Root.StaticData.Salt1));
|
||||
r.Salt2 = ByteString.CopyFrom(Convert.FromBase64String(GameConfig.Root.StaticData.Salt2));
|
||||
|
||||
await WriteDataAsync(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Misc
|
||||
namespace EpinelPS.LobbyServer.Msgs.Misc
|
||||
{
|
||||
[PacketPath("/useronlinestatelog")]
|
||||
public class GetUserOnlineStateLog : LobbyMsgHandler
|
||||
@@ -13,10 +8,11 @@ namespace nksrv.LobbyServer.Msgs.Misc
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqUserOnlineStateLog>();
|
||||
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResUserOnlineStateLog();
|
||||
await WriteDataAsync(response);
|
||||
user.LastLogin = DateTime.UtcNow;
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
22
EpinelPS/LobbyServer/Msgs/Misc/Retroactive.cs
Normal file
22
EpinelPS/LobbyServer/Msgs/Misc/Retroactive.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using EpinelPS.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Misc
|
||||
{
|
||||
[PacketPath("/lobby/retroactive")]
|
||||
public class LobbyRetroactive : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqRetroactive>();
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResRetroactive();
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Mission
|
||||
namespace EpinelPS.LobbyServer.Msgs.Mission
|
||||
{
|
||||
[PacketPath("/mission/getrewarded/achievement")]
|
||||
public class GetAchievementRewardedData : LobbyMsgHandler
|
||||
@@ -17,7 +12,7 @@ namespace nksrv.LobbyServer.Msgs.Mission
|
||||
var response = new ResGetAchievementRewardedData();
|
||||
|
||||
// TODO
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Mission.Rewards
|
||||
namespace EpinelPS.LobbyServer.Msgs.Mission.Rewards
|
||||
{
|
||||
[PacketPath("/mission/getrewarded/daily")]
|
||||
public class GetDailyRewards : LobbyMsgHandler
|
||||
@@ -17,7 +12,7 @@ namespace nksrv.LobbyServer.Msgs.Mission.Rewards
|
||||
// TODO: implement
|
||||
var response = new ResGetDailyRewardedData();
|
||||
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Outpost
|
||||
namespace EpinelPS.LobbyServer.Msgs.Outpost
|
||||
{
|
||||
[PacketPath("/mission/getrewarded/jukebox")]
|
||||
public class GetJukeboxRewards : LobbyMsgHandler
|
||||
@@ -12,7 +12,7 @@ namespace nksrv.LobbyServer.Msgs.Outpost
|
||||
// TODO: save these things
|
||||
var response = new ResGetJukeboxRewardedData();
|
||||
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Mission.Rewards
|
||||
namespace EpinelPS.LobbyServer.Msgs.Mission.Rewards
|
||||
{
|
||||
[PacketPath("/mission/getrewarded/weekly")]
|
||||
public class GetWeeklyRewards : LobbyMsgHandler
|
||||
@@ -17,7 +12,7 @@ namespace nksrv.LobbyServer.Msgs.Mission.Rewards
|
||||
// TODO: implement
|
||||
var response = new ResGetWeeklyRewardedData();
|
||||
|
||||
await WriteDataAsync(response);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
24
EpinelPS/LobbyServer/Msgs/Outpost/BuildBuilding.cs
Normal file
24
EpinelPS/LobbyServer/Msgs/Outpost/BuildBuilding.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using EpinelPS.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Outpost
|
||||
{
|
||||
[PacketPath("/outpost/building")]
|
||||
public class BuildBuilding : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqBuilding>();
|
||||
|
||||
var response = new ResBuilding();
|
||||
response.StartAt = DateTime.UtcNow.Ticks;
|
||||
response.CompleteAt = DateTime.UtcNow.AddDays(1).Ticks;
|
||||
// TODO
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user