21 Commits

Author SHA1 Message Date
Mikhail
01a0e70ae3 release v0.1.4 2024-08-08 10:24:45 -04:00
Mikhail
eee538f97f Update game version to 123.8.10M 2024-08-08 10:14:13 -04:00
Mikhail
e2a0712889 Fix missing ssl cert 2024-07-31 14:12:10 -04:00
Mikhail
42b17682b8 Synchro device 2024-07-31 13:47:16 -04:00
Mikhail
fc0e2801ed BuildBuilding 2024-07-31 10:23:32 -04:00
Mikhail
10fc4c3941 implement campaign lost relic 2024-07-31 10:18:12 -04:00
Mikhail
a1c910f444 Use pregenerated proto file 2024-07-31 09:19:30 -04:00
Mikhail
f41cb1533d Update dotnet-desktop.yml 2024-07-30 15:06:50 -04:00
Mikhail
c1dc421e16 Update gameconfig.json 2024-07-30 13:10:22 -04:00
Mikhail
8a9447dc09 update 2024-07-30 13:09:33 -04:00
Mikhail
1c29003eaa Update GetSentryParams.cs 2024-07-30 13:07:55 -04:00
Mikhail
239c4f293f Rename project to EpinelPS 2024-07-30 13:04:25 -04:00
Mikhail
0990f46266 remove unneeded projects 2024-07-30 12:55:45 -04:00
Mikhail
6fb6c7b1ee SetProfileData 2024-07-30 10:35:42 -04:00
Mikhail
467a20170f implement SetProfileTeam & GetProfile, outpost bug fix 2024-07-29 14:34:02 -04:00
Mikhail
8157d5ea3c Update StaticDataParser.cs 2024-07-29 10:07:27 -04:00
Mikhail
0ebc235a93 improve performance and ram usage 2024-07-29 10:06:42 -04:00
SELEKCJONER
6f8497e60b Add intercept support (#14)
* Add files via upload

---------

Co-authored-by: Mikhail <mishakeys20@gmail.com>
2024-07-29 09:47:01 -04:00
Mikhail
a139373320 fix team saving for interception 2024-07-27 20:41:47 -04:00
Mikhail
8467a5fce9 Implement level reset, bug fixes 2024-07-27 17:06:19 -04:00
Mikhail
e185b7d87e Forgot to update changelog in launcher 2024-07-26 15:53:39 -04:00
231 changed files with 435670 additions and 3805 deletions

View File

@@ -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 /s /e "${{ github.workspace }}\ServerSelector.Desktop\bin\Release\net8.0\win-x64\publish\" "${{ github.workspace }}\out\" && xcopy /s /e "${{ 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
View File

@@ -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

View File

@@ -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>

View File

@@ -1,56 +0,0 @@
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);
}
}
}
}
}
}

View File

@@ -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
@@ -15,8 +11,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServerSelector.Desktop", "S
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Client", "Client", "{4BB2E77F-84A6-4644-9FB3-38E2A7DCDEC0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameDownloader", "GameDownloader\GameDownloader.csproj", "{E3512D9F-CB94-4C80-B673-0EB83CA21D12}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -57,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
@@ -153,30 +99,6 @@ Global
{01D0A73A-A881-439D-9318-54DB5B00D6F5}.ReleaseDLL|x64.Build.0 = Release|Any CPU
{01D0A73A-A881-439D-9318-54DB5B00D6F5}.ReleaseDLL|x86.ActiveCfg = Release|Any CPU
{01D0A73A-A881-439D-9318-54DB5B00D6F5}.ReleaseDLL|x86.Build.0 = Release|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.Debug|x64.ActiveCfg = Debug|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.Debug|x64.Build.0 = Debug|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.Debug|x86.ActiveCfg = Debug|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.Debug|x86.Build.0 = Debug|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.DebugDLL|Any CPU.ActiveCfg = Debug|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.DebugDLL|Any CPU.Build.0 = Debug|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.DebugDLL|x64.ActiveCfg = Debug|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.DebugDLL|x64.Build.0 = Debug|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.DebugDLL|x86.ActiveCfg = Debug|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.DebugDLL|x86.Build.0 = Debug|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.Release|Any CPU.Build.0 = Release|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.Release|x64.ActiveCfg = Release|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.Release|x64.Build.0 = Release|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.Release|x86.ActiveCfg = Release|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.Release|x86.Build.0 = Release|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.ReleaseDLL|Any CPU.ActiveCfg = Release|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.ReleaseDLL|Any CPU.Build.0 = Release|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.ReleaseDLL|x64.ActiveCfg = Release|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.ReleaseDLL|x64.Build.0 = Release|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.ReleaseDLL|x86.ActiveCfg = Release|Any CPU
{E3512D9F-CB94-4C80-B673-0EB83CA21D12}.ReleaseDLL|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -184,7 +106,6 @@ Global
GlobalSection(NestedProjects) = preSolution
{EC613C24-8A35-42E8-92C1-9A8431F74F58} = {4BB2E77F-84A6-4644-9FB3-38E2A7DCDEC0}
{01D0A73A-A881-439D-9318-54DB5B00D6F5} = {4BB2E77F-84A6-4644-9FB3-38E2A7DCDEC0}
{E3512D9F-CB94-4C80-B673-0EB83CA21D12} = {4BB2E77F-84A6-4644-9FB3-38E2A7DCDEC0}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F779F2DC-B207-4091-83B8-0EA250461DCE}

View File

@@ -1,11 +1,11 @@
using EmbedIO;
using EmbedIO.Routing;
using EmbedIO.WebApi;
using nksrv.Database;
using EpinelPS.Database;
using System.Security.Cryptography;
using System.Text;
namespace nksrv
namespace EpinelPS
{
public class AdminApiController : WebApiController
{

View File

@@ -1,10 +1,12 @@
using Newtonsoft.Json;
using nksrv.LobbyServer;
using nksrv.StaticInfo;
using nksrv.Utils;
using EpinelPS.LobbyServer;
using EpinelPS.StaticInfo;
using EpinelPS.Utils;
using Swan.Logging;
using Google.Protobuf.WellKnownTypes;
using static Google.Rpc.Context.AttributeContext.Types;
namespace nksrv.Database
namespace EpinelPS.Database
{
public class AccessToken
{
@@ -64,6 +66,21 @@ namespace nksrv.Database
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
@@ -77,6 +94,7 @@ namespace nksrv.Database
public string Nickname = "SomePlayer";
public int ProfileIconId = 39900;
public bool ProfileIconIsPrism = false;
public int ProfileFrame = 1;
public bool IsAdmin = false;
public bool IsBanned = false;
@@ -93,6 +111,9 @@ namespace nksrv.Database
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 = [];
@@ -112,9 +133,12 @@ namespace nksrv.Database
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))
@@ -139,7 +163,17 @@ namespace nksrv.Database
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)
@@ -195,6 +229,55 @@ namespace nksrv.Database
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
{

View File

@@ -29,13 +29,6 @@
<Protobuf Include="Protos\*.*" GrpcServices="Server" />
</ItemGroup>
<ItemGroup>
<None Remove="Protos\intercept.proto" />
<None Remove="Protos\liberate.proto" />
<None Remove="Protos\shop.proto" />
<None Remove="Protos\sidestory.proto" />
</ItemGroup>
<ItemGroup>
<None Update="gameconfig.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>

View File

@@ -1,29 +1,18 @@
using ICSharpCode.SharpZipLib.Zip;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using nksrv.Utils;
using EpinelPS.Utils;
using Swan.Logging;
using System.Collections.Generic;
using System.Diagnostics;
using System.Security.Cryptography;
namespace nksrv.StaticInfo
namespace EpinelPS.StaticInfo
{
/// <summary>
/// "Static data" which is what the game calls it, contains data such as map info, characters, quests, rewards and a lot more.
/// </summary>
public class StaticDataParser
public class GameData
{
// These fields were extracted from the game.
public static byte[] PresharedKey = [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];
public static RSAParameters RSAParameters = 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
};
// Fields
private static StaticDataParser? _instance;
public static StaticDataParser Instance
private static GameData? _instance;
public static GameData Instance
{
get
{
@@ -37,35 +26,40 @@ namespace nksrv.StaticInfo
}
private ZipFile MainZip;
private MemoryStream ZipStream;
private JArray questDataRecords;
private JArray stageDataRecords;
private JArray rewardDataRecords;
private Dictionary<int, MainQuestCompletionRecord> questDataRecords;
private Dictionary<int, CampaignStageRecord> stageDataRecords;
private Dictionary<int, RewardTableRecord> rewardDataRecords;
private JArray userExpDataRecords;
private JArray chapterCampaignData;
private Dictionary<int, CampaignChapterRecord> chapterCampaignData;
private JArray characterCostumeTable;
private JArray characterTable;
private JArray tutorialTable;
private JArray itemEquipTable;
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<StaticDataParser> BuildAsync()
static async Task<GameData> BuildAsync()
{
Logger.Info("Decrypting static data");
await Load();
Logger.Info("Loading static data");
Logger.Info("Preparing");
var stopWatch = new Stopwatch();
stopWatch.Start();
await Instance.Parse();
stopWatch.Stop();
Console.WriteLine("Preparing took " + stopWatch.Elapsed);
return Instance;
}
public StaticDataParser(string filePath)
public GameData(string filePath)
{
if (!File.Exists(filePath)) throw new ArgumentException("Static data file must exist", nameof(filePath));
@@ -85,16 +79,23 @@ namespace nksrv.StaticInfo
Sha256Hash = SHA256.HashData(rawBytes);
Size = rawBytes.Length;
DecryptStaticDataAndLoadZip(filePath);
LoadGameData(filePath);
if (MainZip == null) throw new Exception("failed to read zip file");
}
#region Decryption
private void DecryptStaticDataAndLoadZip(string 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 keyDecryptor = new Rfc2898DeriveBytes(PresharedKey, GameConfig.Root.StaticData.GetSalt2Bytes(), 10000, HashAlgorithmName.SHA256);
var key2 = keyDecryptor.GetBytes(32);
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];
@@ -105,22 +106,18 @@ namespace nksrv.StaticInfo
aes.Key = decryptionKey;
aes.IV = iv;
var transform = aes.CreateDecryptor();
// Decryption layer 1
using CryptoStream stream = new CryptoStream(fileStream, transform, CryptoStreamMode.Read);
using MemoryStream ms = new MemoryStream();
stream.CopyTo(ms);
var bytes = ms.ToArray();
// Decryption of layer 2
var zip = new ZipFile(ms, false);
var signEntry = zip.GetEntry("sign");
if (signEntry == null) throw new Exception("Sign entry not found in decrypted static data pack");
if (signEntry == null) throw new Exception("error 1");
var dataEntry = zip.GetEntry("data");
if (dataEntry == null) throw new Exception("Data entry not found in decrypted static data pack");
if (dataEntry == null) throw new Exception("error 2");
var signStream = zip.GetInputStream(signEntry);
var dataStream = zip.GetInputStream(dataEntry);
@@ -132,28 +129,26 @@ namespace nksrv.StaticInfo
dataStream.CopyTo(dataMs);
dataMs.Position = 0;
var rsa = RSA.Create(RSAParameters);
var rsa = RSA.Create(LoadParameters);
if (!rsa.VerifyData(dataMs, signMs.ToArray(), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1))
throw new Exception("failed to decrypt static data (round 2)");
throw new Exception("error 3");
dataMs.Position = 0;
// Decryption of layer 3
var keyDecryptor2 = new Rfc2898DeriveBytes(PresharedKey, GameConfig.Root.StaticData.GetSalt1Bytes(), 10000, HashAlgorithmName.SHA256);
var keyDecryptor2 = new Rfc2898DeriveBytes(PresharedValue, GameConfig.Root.StaticData.GetSalt1Bytes(), 10000, HashAlgorithmName.SHA256);
var key3 = keyDecryptor2.GetBytes(32);
byte[] decryptionKey2 = key3[0..16];
byte[] val2 = key3[0..16];
byte[] iv2 = key3[16..32];
ZipStream = new MemoryStream();
AesCtrTransform(decryptionKey2, iv2, dataMs, ZipStream);
DoTransformation(val2, iv2, dataMs, ZipStream);
ZipStream.Position = 0;
MainZip = new ZipFile(ZipStream, false);
}
public static void AesCtrTransform(byte[] key, byte[] salt, Stream inputStream, Stream outputStream)
public static void DoTransformation(byte[] key, byte[] salt, Stream inputStream, Stream outputStream)
{
SymmetricAlgorithm aes = Aes.Create();
aes.Mode = CipherMode.ECB;
@@ -211,7 +206,23 @@ namespace nksrv.StaticInfo
_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);
@@ -232,21 +243,58 @@ namespace nksrv.StaticInfo
return records;
}
int totalFiles = 12;
int totalFiles = 14;
int currentFile = 0;
public async Task Parse()
{
using var progress = new ProgressBar();
questDataRecords = await LoadZip("MainQuestTable.json", progress);
stageDataRecords = await LoadZip("CampaignStageTable.json", progress);
rewardDataRecords = await LoadZip("RewardTable.json", progress);
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);
chapterCampaignData = await LoadZip("CampaignChapterTable.json", progress);
characterCostumeTable = await LoadZip("CharacterCostumeTable.json", progress);
characterTable = await LoadZip("CharacterTable.json", progress);
tutorialTable = await LoadZip("ContentsTutorialTable.json", progress);
itemEquipTable = await LoadZip("ItemEquipTable.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)
@@ -297,79 +345,57 @@ namespace nksrv.StaticInfo
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 MainQuestCompletionData? GetMainQuestForStageClearCondition(int stage)
public MainQuestCompletionRecord? GetMainQuestForStageClearCondition(int stage)
{
foreach (JObject item in questDataRecords)
foreach (var item in questDataRecords)
{
var id = item["condition_id"];
if (id == null) throw new Exception("expected condition_id field in quest data");
int value = id.ToObject<int>();
if (value == stage)
if (item.Value.condition_id == stage)
{
MainQuestCompletionData? data = item.ToObject<MainQuestCompletionData>();
if (data == null) throw new Exception("failed to deserialize main quest data item");
return data;
return item.Value;
}
}
return null;
}
public MainQuestCompletionData? GetMainQuestByTableId(int tid)
public MainQuestCompletionRecord? GetMainQuestByTableId(int tid)
{
foreach (JObject item in questDataRecords)
{
var id = item["id"];
if (id == null) throw new Exception("expected condition_id field in quest data");
int value = id.ToObject<int>();
if (value == tid)
{
MainQuestCompletionData? data = item.ToObject<MainQuestCompletionData>();
if (data == null) throw new Exception("failed to deserialize main quest data item");
return data;
}
}
return null;
return questDataRecords[tid];
}
public CampaignStageRecord? GetStageData(int stage)
{
foreach (JObject item in stageDataRecords)
{
var id = item["id"];
if (id == null) throw new Exception("expected id field in campaign data");
int value = id.ToObject<int>();
if (value == stage)
{
CampaignStageRecord? data = JsonConvert.DeserializeObject<CampaignStageRecord>(item.ToString());
if (data == null) throw new Exception("failed to deserialize stage data");
return data;
}
}
return null;
return stageDataRecords[stage];
}
public RewardTableRecord? GetRewardTableEntry(int rewardId)
{
foreach (JObject item in rewardDataRecords)
{
var id = item["id"];
if (id == null) throw new Exception("expected id field in reward data");
int value = id.ToObject<int>();
if (value == rewardId)
{
RewardTableRecord? data = JsonConvert.DeserializeObject<RewardTableRecord>(item.ToString());
if (data == null) throw new Exception("failed to deserialize reward data");
return data;
}
}
return null;
return rewardDataRecords[rewardId];
}
/// <summary>
/// Returns the level and its minimum value for XP value
@@ -430,24 +456,11 @@ namespace nksrv.StaticInfo
}
public int GetNormalChapterNumberFromFieldName(string field)
{
foreach (JObject item in chapterCampaignData)
foreach (var item in chapterCampaignData)
{
var id = item["field_id"];
if (id == null)
if (item.Value.field_id == field)
{
throw new Exception("expected id field in reward data");
}
string? value = id.ToObject<string>();
if (value == field)
{
var chapter = item["chapter"];
if (chapter == null)
{
throw new Exception("expected id field in reward data");
}
return chapter.ToObject<int>();
return item.Value.chapter;
}
}
@@ -456,14 +469,7 @@ namespace nksrv.StaticInfo
public IEnumerable<int> GetAllCharacterTids()
{
foreach (JObject item in characterTable)
{
var id = item["id"];
if (id == null) throw new Exception("expected id field in reward data");
int value = id.ToObject<int>();
yield return value;
}
return characterTable.Keys;
}
public IEnumerable<int> GetAllCostumes()
{
@@ -479,56 +485,20 @@ namespace nksrv.StaticInfo
internal ClearedTutorialData GetTutorialDataById(int TableId)
{
foreach (JObject item in tutorialTable)
{
var id = item["id"];
if (id == null)
{
throw new Exception("expected id field in reward data");
}
int idValue = id.ToObject<int>();
if (idValue == TableId)
{
ClearedTutorialData? data = item.ToObject<ClearedTutorialData>();
if (data == null) throw new Exception("failed to deserialize reward data");
return data;
}
}
throw new Exception("tutorial not found: " + TableId);
return tutorialTable[TableId];
}
public string? GetItemSubType(int itemType)
{
foreach (JObject item in itemEquipTable)
{
var id = item["id"];
if (id == null) throw new Exception("expected id field in reward data");
int? idValue = id.ToObject<int>();
if (idValue == itemType)
{
var subtype = item["item_sub_type"];
if (subtype == null)
{
throw new Exception("expected item_sub_type field in item equip data");
}
return subtype.ToObject<string>();
}
}
return null;
return itemEquipTable[itemType].item_sub_type;
}
internal IEnumerable<int> GetStageIdsForChapter(int chapterNumber, bool normal)
{
string mod = normal ? "Normal" : "Hard";
foreach (JObject item in stageDataRecords)
foreach (var item in stageDataRecords)
{
CampaignStageRecord? data = item.ToObject<CampaignStageRecord>();
if (data == null) throw new Exception("failed to deserialize stage data");
var data = item.Value;
int chVal = data.chapter_id - 1;

View File

@@ -1,6 +1,6 @@
namespace nksrv.StaticInfo
namespace EpinelPS.StaticInfo
{
public class MainQuestCompletionData
public class MainQuestCompletionRecord
{
public int id;
public int group_id;
@@ -10,6 +10,10 @@
public int reward_id = 0;
public int target_chapter_id;
}
public class MainQuestCompletionTable
{
public List<MainQuestCompletionRecord> records;
}
public class CampaignStageRecord
{
public int id;
@@ -24,6 +28,10 @@
public string enter_scenario = "";
public string exit_scenario = "";
}
public class CampaignStageTable
{
public List<CampaignStageRecord> records;
}
public class RewardTableRecord
{
public int id;
@@ -31,6 +39,11 @@
public int character_exp;
public RewardEntry[]? rewards;
}
public class RewardTable
{
public List<RewardTableRecord> records;
}
public class RewardEntry
{
/// <summary>
@@ -53,6 +66,10 @@
public int NextId;
public bool SaveTutorial;
}
public class TutorialTable
{
public List<ClearedTutorialData> records;
}
public class CharacterLevelData
{
@@ -85,4 +102,49 @@
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;
}
}

View File

@@ -1,4 +1,4 @@
namespace nksrv.IntlServer
namespace EpinelPS.IntlServer
{
internal class AutoLoginEndpoint : IntlMsgHandler
{

View File

@@ -1,4 +1,4 @@
namespace nksrv.IntlServer
namespace EpinelPS.IntlServer
{
public class CodeStatusEndpoint : IntlMsgHandler
{

View File

@@ -1,4 +1,4 @@
namespace nksrv.IntlServer
namespace EpinelPS.IntlServer
{
public class GetNoticeContent : IntlMsgHandler
{

View File

@@ -1,8 +1,8 @@
using nksrv.Utils;
using EpinelPS.Utils;
using System.Net;
using System.Net.Http.Headers;
namespace nksrv.IntlServer
namespace EpinelPS.IntlServer
{
/// <summary>
/// redirect for /account endponts

View File

@@ -1,11 +1,11 @@
using EmbedIO;
using Newtonsoft.Json;
using nksrv.Database;
using nksrv.Utils;
using EpinelPS.Database;
using EpinelPS.Utils;
using System.Net;
using static nksrv.IntlServer.IntlLogin2Endpoint;
using static EpinelPS.IntlServer.IntlLogin2Endpoint;
namespace nksrv.IntlServer
namespace EpinelPS.IntlServer
{
public class IntlAccountRegisterEndpoint : IntlMsgHandler
{

View File

@@ -1,4 +1,4 @@
namespace nksrv.IntlServer
namespace EpinelPS.IntlServer
{
internal class IntlGetAccountInfo : IntlMsgHandler
{

View File

@@ -1,5 +1,5 @@

namespace nksrv.IntlServer
namespace EpinelPS.IntlServer
{
internal class IntlGetProfileBindInfo : IntlMsgHandler
{

View File

@@ -1,4 +1,4 @@
namespace nksrv.IntlServer
namespace EpinelPS.IntlServer
{
public class IntlGetProfileInfo : IntlMsgHandler
{

View File

@@ -1,8 +1,8 @@
using EmbedIO;
using nksrv.Database;
using nksrv.Utils;
using EpinelPS.Database;
using EpinelPS.Utils;
namespace nksrv.IntlServer
namespace EpinelPS.IntlServer
{
public static class IntlHandler
{

View File

@@ -1,10 +1,10 @@
using EmbedIO;
using Newtonsoft.Json;
using nksrv.Database;
using EpinelPS.Database;
using System.Net;
using static nksrv.IntlServer.IntlLogin2Endpoint;
using static EpinelPS.IntlServer.IntlLogin2Endpoint;
namespace nksrv.IntlServer
namespace EpinelPS.IntlServer
{
public class IntlLogin1Endpoint : IntlMsgHandler
{

View File

@@ -1,9 +1,9 @@
using EmbedIO;
using Newtonsoft.Json;
using nksrv.Database;
using EpinelPS.Database;
using System.Net;
namespace nksrv.IntlServer
namespace EpinelPS.IntlServer
{
/// <summary>
/// This handles the login endpoint.

View File

@@ -1,10 +1,10 @@
using EmbedIO;
using Newtonsoft.Json;
using nksrv.Database;
using EpinelPS.Database;
using Swan.Logging;
using System.Text;
namespace nksrv.IntlServer
namespace EpinelPS.IntlServer
{
public abstract class IntlMsgHandler
{

View File

@@ -1,4 +1,4 @@
namespace nksrv.IntlServer
namespace EpinelPS.IntlServer
{
internal class IntlQueryAccountInfo : IntlMsgHandler
{

View File

@@ -1,4 +1,4 @@
namespace nksrv.IntlServer
namespace EpinelPS.IntlServer
{
public class IntlReturnJsonHandler : IntlMsgHandler
{

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace nksrv.IntlServer
namespace EpinelPS.IntlServer
{
internal class JuniperLauncherGetRegion : IntlMsgHandler
{

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace nksrv.IntlServer
namespace EpinelPS.IntlServer
{
internal class JuniperLauncherGetRepoVersion : IntlMsgHandler
{

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace nksrv.IntlServer
namespace EpinelPS.IntlServer
{
internal class JupiterAuthLogin : IntlMsgHandler
{

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace nksrv.IntlServer
namespace EpinelPS.IntlServer
{
internal class JuniperLauncherGetGameLauncher : IntlMsgHandler
{

View File

@@ -1,10 +1,10 @@
using EmbedIO;
using Newtonsoft.Json;
using nksrv.Database;
using EpinelPS.Database;
using System.Net;
using static nksrv.IntlServer.IntlLogin2Endpoint;
using static EpinelPS.IntlServer.IntlLogin2Endpoint;
namespace nksrv.IntlServer
namespace EpinelPS.IntlServer
{
public class SendCodeEndpoint : IntlMsgHandler
{

View File

@@ -1,11 +1,11 @@
using ASodium;
using EmbedIO;
using Google.Protobuf;
using nksrv.Database;
using nksrv.Utils;
using EpinelPS.Database;
using EpinelPS.Utils;
using Swan.Logging;
namespace nksrv.LobbyServer
namespace EpinelPS.LobbyServer
{
public static class LobbyHandler
{
@@ -105,7 +105,7 @@ namespace nksrv.LobbyServer
{
NetUserData ret = new()
{
Lv = user.userPointData.UserLevel,
Level = user.userPointData.UserLevel,
Exp = user.userPointData.ExperiencePoint,
CommanderRoomJukebox = 5,
CostumeLv = 1,
@@ -133,14 +133,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;

View File

@@ -1,9 +1,9 @@
using EmbedIO;
using Google.Protobuf;
using nksrv.Database;
using nksrv.Utils;
using EpinelPS.Database;
using EpinelPS.Utils;
namespace nksrv.LobbyServer
namespace EpinelPS.LobbyServer
{
public abstract class LobbyMsgHandler
{
@@ -112,5 +112,9 @@ namespace nksrv.LobbyServer
{
return JsonDb.GetUser(UserId) ?? throw new Exception("null user");
}
public User? GetUser(ulong id)
{
return JsonDb.GetUser(id);
}
}
}

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Antibot
namespace EpinelPS.LobbyServer.Msgs.Antibot
{
[PacketPath("/antibot/battlereportdata")]
public class BattleReportData : LobbyMsgHandler

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Antibot
namespace EpinelPS.LobbyServer.Msgs.Antibot
{
[PacketPath("/antibot/recvdata")]
public class RecieveAntibotData : LobbyMsgHandler

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Archive
namespace EpinelPS.LobbyServer.Msgs.Archive
{
[PacketPath("/bookmark/scenario/exist")]
public class CheckBookmarkScenarioExists : LobbyMsgHandler

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Archive
namespace EpinelPS.LobbyServer.Msgs.Archive
{
[PacketPath("/archive/get")]
public class GetArchives : LobbyMsgHandler

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Arena
namespace EpinelPS.LobbyServer.Msgs.Arena
{
[PacketPath("/arena/getbaninfo")]
public class GetArenaBanInfo : LobbyMsgHandler

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Arena
namespace EpinelPS.LobbyServer.Msgs.Arena
{
[PacketPath("/arena/special/showreward")]
public class ShowSpecialArenaReward : LobbyMsgHandler

View File

@@ -1,7 +1,7 @@
using nksrv.Database;
using nksrv.Utils;
using EpinelPS.Database;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Auth
namespace EpinelPS.LobbyServer.Msgs.Auth
{
[PacketPath("/auth/logout")]
public class AuthLogout : LobbyMsgHandler

View File

@@ -1,17 +1,17 @@
using EmbedIO;
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using nksrv.Database;
using nksrv.Utils;
using EpinelPS.Database;
using EpinelPS.Utils;
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,7 +26,7 @@ namespace nksrv.LobbyServer.Msgs.Auth
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 };

View File

@@ -1,9 +1,9 @@
using EmbedIO;
using Google.Protobuf.WellKnownTypes;
using nksrv.Database;
using nksrv.Utils;
using EpinelPS.Database;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Auth
namespace EpinelPS.LobbyServer.Msgs.Auth
{
[PacketPath("/auth/intl")]
public class DoIntlAuth : LobbyMsgHandler
@@ -11,7 +11,7 @@ namespace nksrv.LobbyServer.Msgs.Auth
protected override async Task HandleAsync()
{
var req = await ReadData<ReqAuthIntl>();
var response = new AuthIntlResponse();
var response = new ResAuth();
UsedAuthToken = req.Token;
foreach (var item in JsonDb.Instance.LauncherAccessTokens)
@@ -23,7 +23,7 @@ namespace nksrv.LobbyServer.Msgs.Auth
}
if (UserId == 0)
{
response.AuthError = new NetAuthError() { ErrorCode = AuthErrorCode.Error };
response.AuthError = new NetAuthError() { ErrorCode = AuthErrorCode.AuthErrorCodeError };
}
else
{
@@ -44,7 +44,7 @@ namespace nksrv.LobbyServer.Msgs.Auth
}
else
{
response.AuthSuccess = new NetAuthSuccess() { AuthToken = req.Token, CentauriZoneId = "84", FirstAuth = "", PurchaseRestriction = new NetUserPurchaseRestriction() { PurchaseRestriction = PurchaseRestriction.Child, UpdatedAt = 638546758794611090 } };
response.AuthSuccess = new NetAuthSuccess() { AuthToken = req.Token, CentauriZoneId = "84", FirstAuth = false, PurchaseRestriction = new NetUserPurchaseRestriction() { PurchaseRestriction = PurchaseRestriction.PurchaseRestrictionChild, UpdatedAt = 638546758794611090 } };
}
}

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Badge
namespace EpinelPS.LobbyServer.Msgs.Badge
{
[PacketPath("/badge/delete")]
public class DeleteBadge : LobbyMsgHandler

View File

@@ -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

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Campaign
namespace EpinelPS.LobbyServer.Msgs.Campaign
{
[PacketPath("/shutdownflags/campaignpackage/getall")]
public class CampaignPackageGetAll : LobbyMsgHandler

View File

@@ -1,8 +1,8 @@
using nksrv.LobbyServer.Msgs.Stage;
using nksrv.StaticInfo;
using nksrv.Utils;
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
@@ -15,7 +15,7 @@ namespace nksrv.LobbyServer.Msgs.Campaign
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 };

View File

@@ -0,0 +1,51 @@
using EpinelPS.Database;
using EpinelPS.LobbyServer.Msgs.Stage;
using EpinelPS.StaticInfo;
using EpinelPS.Utils;
using Swan.Logging;
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)
{
Logger.Warn("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);
}
}
}

View File

@@ -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

View File

@@ -1,8 +1,8 @@
using nksrv.Database;
using nksrv.StaticInfo;
using nksrv.Utils;
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
@@ -16,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.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);

View 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);
}
}
}

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Character
namespace EpinelPS.LobbyServer.Msgs.Character
{
[PacketPath("/character/attractive/get")]
public class GetCharacterAttractiveList : LobbyMsgHandler

View File

@@ -1,7 +1,7 @@
using nksrv.StaticInfo;
using nksrv.Utils;
using EpinelPS.StaticInfo;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Character
namespace EpinelPS.LobbyServer.Msgs.Character
{
[PacketPath("/character/costume/get")]
public class GetCharacterCostume : LobbyMsgHandler
@@ -13,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);
}

View 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);
}
}
}

View 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);
}
}
}

View File

@@ -1,9 +1,9 @@
using nksrv.Database;
using nksrv.StaticInfo;
using nksrv.Utils;
using EpinelPS.Database;
using EpinelPS.StaticInfo;
using EpinelPS.Utils;
using Swan.Logging;
namespace nksrv.LobbyServer.Msgs.Character
namespace EpinelPS.LobbyServer.Msgs.Character
{
[PacketPath("/character/levelup")]
public class LevelUp : LobbyMsgHandler
@@ -13,7 +13,7 @@ namespace nksrv.LobbyServer.Msgs.Character
var req = await ReadData<ReqCharacterLevelUp>();
var user = GetUser();
var response = new ResCharacterLevelUp();
var data = StaticDataParser.Instance.GetCharacterLevelUpData();
var data = GameData.Instance.GetCharacterLevelUpData();
foreach (var item in user.Characters.ToArray())
{
@@ -50,7 +50,7 @@ namespace nksrv.LobbyServer.Msgs.Character
{
CostumeId = item.CostumeId,
Csn = item.Csn,
Lv = item.Level,
Level = item.Level,
Skill1Lv = item.Skill1Lvl,
Skill2Lv = item.Skill2Lvl,
UltiSkillLv = item.UltimateLevel,
@@ -59,11 +59,11 @@ namespace nksrv.LobbyServer.Msgs.Character
};
var highestLevelCharacters = user.Characters.OrderByDescending(x => x.Level).Take(5).ToList();
response.SynchroLv = highestLevelCharacters.Last().Level;
response.SynchroLv = user.GetSynchroLevel();
foreach (var c in highestLevelCharacters)
{
response.SynchroStandardCharacters.Add(c.Tid);
response.SynchroStandardCharacters.Add(c.Csn);
}
foreach (var currency in user.Currency)

View File

@@ -0,0 +1,54 @@
using EpinelPS.Utils;
using Swan.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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)
{
Logger.Warn("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);
}
}
}

View File

@@ -0,0 +1,87 @@
using EpinelPS.Database;
using EpinelPS.StaticInfo;
using EpinelPS.Utils;
using Swan.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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)
{
Logger.Warn("Character level is already 1 - cannot reset");
return;
}
if (item.Level == 200)
{
Logger.Warn("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);
}
}
}

View File

@@ -1,7 +1,7 @@
using nksrv.Database;
using nksrv.Utils;
using EpinelPS.Database;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Character
namespace EpinelPS.LobbyServer.Msgs.Character
{
[PacketPath("/character/costume/set")]
public class SetCharacterCostume : LobbyMsgHandler

View File

@@ -0,0 +1,60 @@
using EpinelPS.Database;
using EpinelPS.StaticInfo;
using EpinelPS.Utils;
using Swan.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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
Logger.Error("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);
}
}
}

View File

@@ -0,0 +1,70 @@
using EpinelPS.Database;
using EpinelPS.Utils;
using Swan.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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)
{
Logger.Warn("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);
}
}
}

View File

@@ -1,7 +1,7 @@
using nksrv.Database;
using nksrv.Utils;
using EpinelPS.Database;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Event
namespace EpinelPS.LobbyServer.Msgs.Event
{
[PacketPath("/event/scenario/complete")]
public class CompleteEventScenario : LobbyMsgHandler
@@ -11,16 +11,16 @@ 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();

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Event
namespace EpinelPS.LobbyServer.Msgs.Event
{
[PacketPath("/eventfield/enter")]
public class EnterEventField : LobbyMsgHandler

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Event
namespace EpinelPS.LobbyServer.Msgs.Event
{
[PacketPath("/event/mission/getclear")]
public class GetClearedMissions : LobbyMsgHandler

View File

@@ -1,7 +1,7 @@
using nksrv.Database;
using nksrv.Utils;
using EpinelPS.Database;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Event
namespace EpinelPS.LobbyServer.Msgs.Event
{
[PacketPath("/event/scenario/get")]
public class GetEventScenario : LobbyMsgHandler
@@ -12,14 +12,14 @@ 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);

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Event
namespace EpinelPS.LobbyServer.Msgs.Event
{
[PacketPath("/event/getjoinedevent")]
public class GetJoinedEvent : LobbyMsgHandler

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Event
namespace EpinelPS.LobbyServer.Msgs.Event
{
[PacketPath("/event/list")]
public class ListEvents : LobbyMsgHandler
@@ -14,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
});
@@ -27,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
});

View File

@@ -1,11 +1,11 @@
using nksrv.Utils;
using EpinelPS.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace nksrv.LobbyServer.Msgs.Event.StoryEvent
namespace EpinelPS.LobbyServer.Msgs.Event.StoryEvent
{
[PacketPath("/event/storydungeon/get")]
public class GetStoryDungeon : LobbyMsgHandler
@@ -17,7 +17,8 @@ namespace nksrv.LobbyServer.Msgs.Event.StoryEvent
var response = new ResStoryDungeonEventData()
{
TeamData = new NetUserTeamData()
TeamData = new NetUserTeamData(),
RemainTicket = 10,
};
// TOOD

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.FavoriteItem
namespace EpinelPS.LobbyServer.Msgs.FavoriteItem
{
[PacketPath("/favoriteitem/library")]
public class GetFavoriteItemLibrary : LobbyMsgHandler

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.FavoriteItem
namespace EpinelPS.LobbyServer.Msgs.FavoriteItem
{
[PacketPath("/favoriteitem/list")]
public class ListFavoriteItem : LobbyMsgHandler

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.FavoriteItem
namespace EpinelPS.LobbyServer.Msgs.FavoriteItem
{
[PacketPath("/favoriteitem/quest/list")]
public class ListFavoriteItemQuests : LobbyMsgHandler

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Friend
namespace EpinelPS.LobbyServer.Msgs.Friend
{
[PacketPath("/friend/get")]
public class GetFriends : LobbyMsgHandler

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Gacha
namespace EpinelPS.LobbyServer.Msgs.Gacha
{
[PacketPath("/gacha/event/check")]
public class CheckGachaDailyEvent : LobbyMsgHandler

View File

@@ -1,8 +1,8 @@
using nksrv.Database;
using nksrv.StaticInfo;
using nksrv.Utils;
using EpinelPS.Database;
using EpinelPS.StaticInfo;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Gacha
namespace EpinelPS.LobbyServer.Msgs.Gacha
{
[PacketPath("/gacha/execute")]
public class ExecGacha : LobbyMsgHandler
@@ -19,17 +19,23 @@ namespace nksrv.LobbyServer.Msgs.Gacha
// TODO implement reward
response.Reward = new NetRewardData();
if (user.GachaTutorialPlayCount == 0)
foreach (var c in GameData.Instance.GetAllCharacterTids())
{
foreach (var c in StaticDataParser.Instance.GetAllCharacterTids())
if (!user.HasCharacter(c))
{
response.Gacha.Add(new NetGachaEntityData() { Corporation = 1, PieceCount = 1, CurrencyValue = 5, Sn = c, Tid = c, Type = 1 });
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 = c, Grade = 0, Lv = 1, Skill1Lv = 1, Skill2Lv = 1, Tid = c, UltiSkillLv = 1 });
user.Characters.Add(new Database.Character() { CostumeId = 0, Csn = c, Grade = 0, Level = 1, Skill1Lvl = 1, Skill2Lvl = 1, Tid = c, UltimateLevel = 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++;
}
user.GachaTutorialPlayCount++;
JsonDb.Save();

View File

@@ -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

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs
namespace EpinelPS.LobbyServer.Msgs
{
[PacketPath("/Gacha/Get")]
public class GetGacha : LobbyMsgHandler

View 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);
}
}
}

View 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);
}
}
}

View 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);
}
}
}

View 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);
}
}
}

View 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);
}
}
}

View File

@@ -1,7 +1,7 @@
using nksrv.Database;
using nksrv.Utils;
using EpinelPS.Database;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Inventory
namespace EpinelPS.LobbyServer.Msgs.Inventory
{
[PacketPath("/inventory/allclearequipment")]
public class ClearAllEquipment : LobbyMsgHandler

View File

@@ -1,7 +1,7 @@
using nksrv.Database;
using nksrv.Utils;
using EpinelPS.Database;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Inventory
namespace EpinelPS.LobbyServer.Msgs.Inventory
{
[PacketPath("/inventory/clearequipment")]
public class ClearEquipment : LobbyMsgHandler

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Inventory
namespace EpinelPS.LobbyServer.Msgs.Inventory
{
[PacketPath("/inventory/get")]
public class GetInventoryData : LobbyMsgHandler
@@ -13,7 +13,7 @@ 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

View File

@@ -1,7 +1,7 @@
using nksrv.Database;
using nksrv.Utils;
using EpinelPS.Database;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Inventory
namespace EpinelPS.LobbyServer.Msgs.Inventory
{
[PacketPath("/inventory/wearequipment")]
public class WearEquipment : LobbyMsgHandler

View File

@@ -1,7 +1,7 @@
using nksrv.Database;
using nksrv.Utils;
using EpinelPS.Database;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Inventory
namespace EpinelPS.LobbyServer.Msgs.Inventory
{
[PacketPath("/inventory/wearequipmentlist")]
public class WearEquipmentList : LobbyMsgHandler

View File

@@ -1,28 +1,22 @@
using nksrv.Net;
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.Liberate
namespace EpinelPS.LobbyServer.Msgs.Liberate
{
[PacketPath("/liberate/choosecharacter")]
public class ChooseCharacter : LobbyMsgHandler
{
protected override async Task HandleAsync()
{
var req = await ReadData<ChooseLiberateCharacterRequest>();
var req = await ReadData<ReqChooseLiberateCharacter>();
var user = GetUser();
var response = new ChooseLiberateCharacterResponse();
var response = new ResChooseLiberateCharacter();
// TODO
response.Data = new NetLiberateData() { CharacterId = req.CharacterId };
response.Data.MissionData.Add(new NetLiberateMissionData() { MissionState = LiberateMissionState.Running, Id = 1 });
response.Data.MissionData.Add(new NetLiberateMissionData() { MissionState = LiberateMissionState.Running, Id = 2 });
response.Data.MissionData.Add(new NetLiberateMissionData() { MissionState = LiberateMissionState.Running, Id = 3 });
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);
}

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Liberate
namespace EpinelPS.LobbyServer.Msgs.Liberate
{
[PacketPath("/liberate/get")]
public class GetLiberateData : LobbyMsgHandler

View 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);
}
}
}

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Lostsector
namespace EpinelPS.LobbyServer.Msgs.Lostsector
{
[PacketPath("/lostsector/get")]
public class GetLostSectorData : LobbyMsgHandler

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Messenger
namespace EpinelPS.LobbyServer.Msgs.Messenger
{
[PacketPath("/messenger/daily/pick")]
public class GetDailyMessage : LobbyMsgHandler

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Messenger
namespace EpinelPS.LobbyServer.Msgs.Messenger
{
[PacketPath("/messenger/get")]
public class GetMessages : LobbyMsgHandler

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Messenger
namespace EpinelPS.LobbyServer.Msgs.Messenger
{
[PacketPath("/messenger/picked/get")]
public class GetPickedMessage : LobbyMsgHandler

View File

@@ -1,16 +1,16 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Messenger
namespace EpinelPS.LobbyServer.Msgs.Messenger
{
[PacketPath("/messenger/random/pick")]
public class GetRandomPick : LobbyMsgHandler
{
protected override async Task HandleAsync()
{
var req = await ReadData<ReqForcePickTodayRandomMessage>();
var req = await ReadData<ReqPickTodayRandomMessage>();
// TODO: get proper response
var response = new ResForcePickTodayRandomMessage();
var response = new ResPickTodayRandomMessage();
await WriteDataAsync(response);
}

View File

@@ -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

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Minigame.Dave
namespace EpinelPS.LobbyServer.Msgs.Minigame.Dave
{
[PacketPath("/event/minigame/dave/getalldavetrigger")]
public class GetAllDaveTrigger : LobbyMsgHandler

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
using EpinelPS.Utils;
namespace nksrv.LobbyServer.Msgs.Minigame
namespace EpinelPS.LobbyServer.Msgs.Minigame
{
[PacketPath("/minigame/nksv2/get")]
public class GetNksv2Minigame : LobbyMsgHandler

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
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

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
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

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
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

View File

@@ -1,6 +1,6 @@
using nksrv.Utils;
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

View File

@@ -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

View File

@@ -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

Some files were not shown because too many files have changed in this diff Show More