mirror of
https://github.com/EpinelPS/EpinelPS.git
synced 2025-12-14 16:04:36 +01:00
Implement stage skipping
This commit is contained in:
@@ -10,8 +10,8 @@ namespace ProtobufViewUtil
|
||||
{
|
||||
Console.WriteLine("Hello, World!");
|
||||
|
||||
ResGetOutpostData s = new ResGetOutpostData();
|
||||
var inn = File.ReadAllBytes(@"C:\Users\Misha\Downloads\getoutpostdatach2done");
|
||||
StaticDataPackResponse s = new StaticDataPackResponse();
|
||||
var inn = File.ReadAllBytes(@"C:\Users\Misha\Desktop\response");
|
||||
s.MergeFrom(inn);
|
||||
Console.WriteLine(s.ToString());
|
||||
var outt = s.ToByteArray();
|
||||
|
||||
@@ -25,6 +25,10 @@ If the game does not get past the title screen, open an issue and send %appdata%
|
||||
|
||||
Note that this was tested with the latest version (122.8.20c)
|
||||
|
||||
To access the admin panel, go to https://127.0.0.1/admin/ and sign in. Note that IsAdmin needs to be true for the user account. Note that this interface does not have anything yet.
|
||||
|
||||
To skip stages, a basic command line interface is implemented.
|
||||
|
||||
## Progress
|
||||
Stage, character, outpost and story information is saved and works, as well as player nickname.
|
||||
|
||||
|
||||
22
nksrv/LobbyServer/Msgs/Arena/ShowSpecialArenaReward.cs
Normal file
22
nksrv/LobbyServer/Msgs/Arena/ShowSpecialArenaReward.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace nksrv.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace nksrv.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
23
nksrv/LobbyServer/Msgs/FavoriteItem/ListFavoriteItem.cs
Normal file
23
nksrv/LobbyServer/Msgs/FavoriteItem/ListFavoriteItem.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace nksrv.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,23 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace nksrv.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
25
nksrv/LobbyServer/Msgs/Liberate/GetLiberateData.cs
Normal file
25
nksrv/LobbyServer/Msgs/Liberate/GetLiberateData.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace nksrv.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
25
nksrv/LobbyServer/Msgs/Lostsector/GetLostSectorData.cs
Normal file
25
nksrv/LobbyServer/Msgs/Lostsector/GetLostSectorData.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace nksrv.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
25
nksrv/LobbyServer/Msgs/Sidestory/ListSideStory.cs
Normal file
25
nksrv/LobbyServer/Msgs/Sidestory/ListSideStory.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using nksrv.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Sidestory
|
||||
{
|
||||
[PacketPath("/sidestory/list")]
|
||||
public class ListSideStory : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqListSideStory>();
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResListSideStory();
|
||||
|
||||
// TODO
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,17 @@ namespace nksrv.LobbyServer.Msgs.Stage
|
||||
// TODO: check if user has already cleared this stage
|
||||
if (req.BattleResult == 1)
|
||||
{
|
||||
var clearedStage = StaticDataParser.Instance.GetStageData(req.StageId);
|
||||
response = CompleteStage(user, req.StageId);
|
||||
}
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
|
||||
|
||||
public static ResClearStage CompleteStage(Utils.User user, int StageId)
|
||||
{
|
||||
var response = new ResClearStage();
|
||||
var clearedStage = StaticDataParser.Instance.GetStageData(StageId);
|
||||
if (clearedStage == null) throw new Exception("cleared stage cannot be null");
|
||||
|
||||
|
||||
@@ -33,24 +43,24 @@ namespace nksrv.LobbyServer.Msgs.Stage
|
||||
user.FieldInfo.Add("0_" + clearedStage.chapter_mod, new FieldInfo() { });
|
||||
}
|
||||
|
||||
DoQuestSpecificUserOperations(user, req.StageId);
|
||||
DoQuestSpecificUserOperations(user, StageId);
|
||||
var rewardData = StaticDataParser.Instance.GetRewardTableEntry(clearedStage.reward_id);
|
||||
|
||||
if (rewardData != null)
|
||||
response.StageClearReward = RegisterRewardsForUser(user, rewardData);
|
||||
else
|
||||
Logger.Warn("rewardId is null for stage " + req.StageId);
|
||||
Logger.Warn("rewardId is null for stage " + StageId);
|
||||
|
||||
|
||||
if (clearedStage.stage_category == "Normal" || clearedStage.stage_category == "Boss" || clearedStage.stage_category == "Hard")
|
||||
{
|
||||
if (clearedStage.chapter_mod == "Hard")
|
||||
{
|
||||
user.LastHardStageCleared = req.StageId;
|
||||
user.LastHardStageCleared = StageId;
|
||||
}
|
||||
else if (clearedStage.chapter_mod == "Normal")
|
||||
{
|
||||
user.LastNormalStageCleared = req.StageId;
|
||||
user.LastNormalStageCleared = StageId;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -66,14 +76,16 @@ namespace nksrv.LobbyServer.Msgs.Stage
|
||||
Logger.Warn("Unknown stage category " + clearedStage.stage_category);
|
||||
}
|
||||
|
||||
user.FieldInfo[(clearedStage.chapter_id - 1) + "_" + clearedStage.chapter_mod].CompletedStages.Add(new NetFieldStageData() { StageId = req.StageId });
|
||||
var key = (clearedStage.chapter_id - 1) + "_" + clearedStage.chapter_mod;
|
||||
if (!user.FieldInfo.ContainsKey(key))
|
||||
user.FieldInfo.Add(key, new FieldInfo());
|
||||
|
||||
user.FieldInfo[key].CompletedStages.Add(new NetFieldStageData() { StageId = StageId });
|
||||
JsonDb.Save();
|
||||
return response;
|
||||
}
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
|
||||
private NetRewardData RegisterRewardsForUser(Utils.User user, RewardTableRecord rewardData)
|
||||
private static NetRewardData RegisterRewardsForUser(Utils.User user, RewardTableRecord rewardData)
|
||||
{
|
||||
NetRewardData ret = new();
|
||||
if (rewardData.rewards == null) return ret;
|
||||
|
||||
191
nksrv/Program.cs
191
nksrv/Program.cs
@@ -21,6 +21,7 @@ using Swan;
|
||||
using Google.Api;
|
||||
using nksrv.StaticInfo;
|
||||
using EmbedIO.WebApi;
|
||||
using nksrv.LobbyServer.Msgs.Stage;
|
||||
|
||||
namespace nksrv
|
||||
{
|
||||
@@ -39,9 +40,195 @@ namespace nksrv
|
||||
LobbyHandler.Init();
|
||||
|
||||
Logger.Info("Starting server");
|
||||
new Thread(() =>
|
||||
{
|
||||
var server = CreateWebServer();
|
||||
server.RunAsync();
|
||||
}).Start();
|
||||
|
||||
using var server = CreateWebServer();
|
||||
await server.RunAsync();
|
||||
// cli interface
|
||||
|
||||
ulong selectedUser = 0;
|
||||
string prompt = "# ";
|
||||
while (true)
|
||||
{
|
||||
Console.Write(prompt);
|
||||
|
||||
var input = Console.ReadLine();
|
||||
var args = input.Split(' ');
|
||||
if (string.IsNullOrEmpty(input) || string.IsNullOrWhiteSpace(input))
|
||||
{
|
||||
|
||||
}
|
||||
else if (input == "?" || input == "help")
|
||||
{
|
||||
Console.WriteLine("Nikke Private Server CLI interface");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Commands:");
|
||||
Console.WriteLine(" help - show this help");
|
||||
Console.WriteLine(" ls /users - show all users");
|
||||
Console.WriteLine(" cd (user id) - select user by id");
|
||||
Console.WriteLine(" rmuser - delete selected user");
|
||||
Console.WriteLine(" ban - ban selected user from game");
|
||||
Console.WriteLine(" unban - unban selected user from game");
|
||||
Console.WriteLine(" exit - exit server application");
|
||||
Console.WriteLine(" completestage (chapter num)-(stage number) - complete selected stage and get rewards (and all previous ones). Example completestage 15-1. Note that the exact stage number cleared may not be exact.");
|
||||
}
|
||||
else if (input == "ls /users")
|
||||
{
|
||||
Console.WriteLine("Id,Username,Nickname");
|
||||
foreach (var item in JsonDb.Instance.Users)
|
||||
{
|
||||
Console.WriteLine($"{item.ID},{item.Username},{item.Nickname}");
|
||||
}
|
||||
}
|
||||
else if (input.StartsWith("cd"))
|
||||
{
|
||||
if (args.Length == 2)
|
||||
{
|
||||
if (ulong.TryParse(args[1], out ulong id))
|
||||
{
|
||||
// check if user id exists
|
||||
var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == id);
|
||||
if (user != null)
|
||||
{
|
||||
selectedUser = user.ID;
|
||||
Console.WriteLine("Selected user: " + user.Username);
|
||||
prompt = "/users/" + user.Username + "# ";
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("User not found");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Argument #1 should be a number");
|
||||
Console.WriteLine("Usage: chroot (user id)");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Incorrect number of arguments for chroot");
|
||||
Console.WriteLine("Usage: chroot (user id)");
|
||||
}
|
||||
}
|
||||
else if (input.StartsWith("rmuser"))
|
||||
{
|
||||
if (selectedUser == 0)
|
||||
{
|
||||
Console.WriteLine("No user selected");
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser);
|
||||
if (user == null)
|
||||
{
|
||||
Console.WriteLine("Selected user does not exist");
|
||||
selectedUser = 0;
|
||||
prompt = "# ";
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Write("Are you sure you want to delete user " + user.Username + "? (y/n) ");
|
||||
var confirm = Console.ReadLine();
|
||||
if (confirm == "y")
|
||||
{
|
||||
JsonDb.Instance.Users.Remove(user);
|
||||
JsonDb.Save();
|
||||
Console.WriteLine("User deleted");
|
||||
selectedUser = 0;
|
||||
prompt = "# ";
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("User not deleted");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (input.StartsWith("completestage"))
|
||||
{
|
||||
if (selectedUser == 0)
|
||||
{
|
||||
Console.WriteLine("No user selected");
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser);
|
||||
if (user == null)
|
||||
{
|
||||
Console.WriteLine("Selected user does not exist");
|
||||
selectedUser = 0;
|
||||
prompt = "# ";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (args.Length == 2)
|
||||
{
|
||||
var input2 = args[1];
|
||||
try
|
||||
{
|
||||
var chapter = int.TryParse(input2.Split('-')[0], out int chapterNumber);
|
||||
var stage = int.TryParse(input2.Split('-')[1], out int stageNumber);
|
||||
|
||||
if (chapter && stage)
|
||||
{
|
||||
for (int i = 0; i < chapterNumber + 1; i++)
|
||||
{
|
||||
var stages = StaticDataParser.Instance.GetStageIdsForChapter(i, true);
|
||||
int target = 1;
|
||||
foreach (var item in stages)
|
||||
{
|
||||
if (!user.IsStageCompleted(item, true))
|
||||
{
|
||||
Console.WriteLine("Completing stage " + item);
|
||||
ClearStage.CompleteStage(user, item);
|
||||
}
|
||||
|
||||
if (i == chapterNumber && target == stageNumber)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
target++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("chapter and stage number must be a 32 bit integer");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("exception:" + ex.ToString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("invalid argument length, must be 1");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (input == "exit")
|
||||
{
|
||||
Environment.Exit(0);
|
||||
}
|
||||
else if (input == "ban")
|
||||
{
|
||||
Console.WriteLine("Not implemented");
|
||||
}
|
||||
else if (input == "unban")
|
||||
{
|
||||
Console.WriteLine("Not implemented");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Unknown command");
|
||||
}
|
||||
}
|
||||
}
|
||||
private static WebServer CreateWebServer()
|
||||
{
|
||||
|
||||
@@ -2196,3 +2196,105 @@ message ResAllClearEquipment {
|
||||
int64 Csn = 2;
|
||||
repeated NetUserItemData Items = 3;
|
||||
}
|
||||
|
||||
message NetFavoriteItemLibraryElement {
|
||||
int32 Tid = 1;
|
||||
int64 ReceivedAt = 2;
|
||||
}
|
||||
|
||||
message ReqGetFavoriteItemLibrary {
|
||||
|
||||
}
|
||||
message ResGetFavoriteItemLibrary {
|
||||
repeated NetFavoriteItemLibraryElement FavoriteItemLibrary = 1;
|
||||
}
|
||||
|
||||
|
||||
message ReqListFavoriteItem {
|
||||
|
||||
}
|
||||
message ResListFavoriteItem {
|
||||
repeated NetUserFavoriteItemData FavoriteItems = 1;
|
||||
}
|
||||
|
||||
message NetUserFavoriteItemQuestData {
|
||||
int32 QuestId = 1;
|
||||
bool Clear = 2;
|
||||
bool Received = 3;
|
||||
}
|
||||
message ReqListFavoriteItemQuest {
|
||||
|
||||
}
|
||||
message ResListFavoriteItemQuest {
|
||||
repeated NetUserFavoriteItemQuestData FavoriteItemQuests = 1;
|
||||
}
|
||||
|
||||
message NetUserLostSectorData {
|
||||
int32 SectorId = 1;
|
||||
int32 RewardCount = 2;
|
||||
bool IsFinalReward = 3;
|
||||
bool IsPlaying = 4;
|
||||
bool IsOpen = 5;
|
||||
int32 CurrentClearStageCount = 6;
|
||||
int32 MaxClearStageCount = 7;
|
||||
bool IsPerfectReward = 8;
|
||||
}
|
||||
message ReqGetLostSectorData {
|
||||
|
||||
}
|
||||
message ResGetLostSectorData {
|
||||
repeated NetUserLostSectorData LostSector = 2;
|
||||
int32 LastEnterSectorId = 3;
|
||||
repeated NetFieldStageData ClearedStages = 4;
|
||||
}
|
||||
|
||||
message NetSideStoryStageData {
|
||||
int32 SideStoryStageId = 1;
|
||||
google.protobuf.Timestamp ClearedAt = 2;
|
||||
}
|
||||
|
||||
message ReqListSideStory {}
|
||||
message ResListSideStory {
|
||||
repeated NetSideStoryStageData SideStoryStageDataList = 1;
|
||||
}
|
||||
|
||||
enum LiberateMissionState {
|
||||
LiberateMissionState_Running = 0;
|
||||
LiberateMissionState_Rewarded = 1;
|
||||
LiberateMissionState_Closed = 2;
|
||||
}
|
||||
|
||||
message NetLiberateMissionData {
|
||||
int64 Id = 1;
|
||||
int32 MissionTid = 2;
|
||||
int32 LiberateCharacterId = 3;
|
||||
LiberateMissionState MissionState = 4;
|
||||
int64 CreatedAt = 6;
|
||||
int64 TriggerStartAt = 7;
|
||||
int64 TriggerEndAt = 8;
|
||||
optional int64 ReceivedAt = 9;
|
||||
}
|
||||
|
||||
message NetLiberateData {
|
||||
int32 CharacterId = 2;
|
||||
int32 StepId = 3;
|
||||
int32 ProgressPoint = 4;
|
||||
repeated NetLiberateMissionData MissionData = 5;
|
||||
int32 RewardedCount = 6;
|
||||
bool IsCompleted = 7;
|
||||
}
|
||||
|
||||
message ReqGetLiberateData {}
|
||||
message ResGetLiberateData {
|
||||
repeated int32 OpenLiberateTypeIdList = 2;
|
||||
NetLiberateData LiberateData = 3;
|
||||
}
|
||||
|
||||
message ReqShowSpecialArenaReward {}
|
||||
message ResShowSpecialArenaReward {
|
||||
NetRewardData reward = 4;
|
||||
/*SpecialArenaContentsState SpecialArenaContentsState = 5;
|
||||
NetSpecialArenaRewardHistory History = 6;*/
|
||||
bool IsBan = 7;
|
||||
NetArenaBanInfo BanInfo = 8;
|
||||
}
|
||||
@@ -26,6 +26,7 @@ namespace nksrv.StaticInfo
|
||||
/// Can be Normal or Hard
|
||||
/// </summary>
|
||||
public string chapter_mod = "";
|
||||
public string stage_type = "";
|
||||
}
|
||||
public class RewardTableRecord
|
||||
{
|
||||
|
||||
@@ -448,5 +448,22 @@ namespace nksrv.StaticInfo
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
internal IEnumerable<int> GetStageIdsForChapter(int chapterNumber, bool normal)
|
||||
{
|
||||
string mod = normal ? "Normal" : "Hard";
|
||||
foreach (JObject item in stageDataRecords)
|
||||
{
|
||||
CampaignStageRecord? data = JsonConvert.DeserializeObject<CampaignStageRecord>(item.ToString());
|
||||
if (data == null) throw new Exception("failed to deserialize stage data");
|
||||
|
||||
int chVal = data.chapter_id - 1;
|
||||
|
||||
if (chapterNumber == chVal && data.chapter_mod == mod && data.stage_type == "Main")
|
||||
{
|
||||
yield return data.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using ASodium;
|
||||
using Newtonsoft.Json;
|
||||
using nksrv.LobbyServer;
|
||||
using nksrv.LobbyServer.Msgs.Stage;
|
||||
using nksrv.StaticInfo;
|
||||
using Swan.Logging;
|
||||
using System;
|
||||
@@ -135,6 +136,24 @@ namespace nksrv.Utils
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
public bool IsStageCompleted(int id, bool isNorm)
|
||||
{
|
||||
foreach (var item in FieldInfo)
|
||||
{
|
||||
if (item.Key.Contains("hard") && isNorm) continue;
|
||||
if (item.Key.Contains("normal") && !isNorm) continue;
|
||||
foreach (var s in item.Value.CompletedStages)
|
||||
{
|
||||
if (s.StageId == id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public class CoreInfo
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user