mirror of
https://github.com/EpinelPS/EpinelPS.git
synced 2025-12-12 23:14:34 +01:00
implement ban, add static data progress bar, allow changing server name
This commit is contained in:
@@ -79,6 +79,11 @@ namespace nksrv.Database
|
||||
public bool ProfileIconIsPrism = false;
|
||||
public bool IsAdmin = false;
|
||||
|
||||
public bool IsBanned = false;
|
||||
public DateTime BanStart;
|
||||
public DateTime BanEnd;
|
||||
public int BanId = 0;
|
||||
|
||||
// Game data
|
||||
public List<string> CompletedScenarios = [];
|
||||
public Dictionary<string, FieldInfo> FieldInfo = []; // here for backwards compatibility
|
||||
@@ -202,6 +207,7 @@ namespace nksrv.Database
|
||||
public List<AccessToken> LauncherAccessTokens = [];
|
||||
|
||||
public Dictionary<string, GameClientInfo> GameClientTokens = [];
|
||||
public string ServerName = "<color=\"green\">Private Server</color>";
|
||||
}
|
||||
internal class JsonDb
|
||||
{
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using nksrv.Utils;
|
||||
using EmbedIO;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using nksrv.Database;
|
||||
using nksrv.Utils;
|
||||
|
||||
namespace nksrv.LobbyServer.Msgs.Auth
|
||||
{
|
||||
@@ -8,10 +11,42 @@ namespace nksrv.LobbyServer.Msgs.Auth
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqAuthIntl>();
|
||||
|
||||
var response = new AuthIntlResponse();
|
||||
//response.BanInfo = new NetBanInfo() { BanId = 123, Description = "The server admin is sad today because the hinge on his HP laptop broke which happened to be an HP Elitebook 8470p, and the RAM controller exploded and then fixed itself, please contact him", StartAt = Timestamp.FromDateTime(DateTime.UtcNow), EndAt = Timestamp.FromDateTime(DateTime.UtcNow.AddDays(256)) };
|
||||
response.AuthSuccess = new NetAuthSuccess() { AuthToken = req.Token, CentauriZoneId = "84", FirstAuth = "", PurchaseRestriction = new NetUserPurchaseRestriction() { PurchaseRestriction = PurchaseRestriction.Unknown2, UpdatedAt = 638546758794611090 } };
|
||||
|
||||
UsedAuthToken = req.Token;
|
||||
foreach (var item in JsonDb.Instance.LauncherAccessTokens)
|
||||
{
|
||||
if (item.Token == UsedAuthToken)
|
||||
{
|
||||
UserId = item.UserID;
|
||||
}
|
||||
}
|
||||
if (UserId == 0)
|
||||
{
|
||||
response.AuthError = new NetAuthError() { ErrorCode = AuthErrorCode.Error };
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = GetUser();
|
||||
|
||||
if (user.IsBanned && user.BanEnd < DateTime.UtcNow)
|
||||
{
|
||||
user.IsBanned = false;
|
||||
user.BanId = 0;
|
||||
user.BanStart = DateTime.MinValue;
|
||||
user.BanEnd = DateTime.MinValue;
|
||||
JsonDb.Save();
|
||||
}
|
||||
|
||||
if (user.IsBanned)
|
||||
{
|
||||
response.BanInfo = new NetBanInfo() { BanId = user.BanId, Description = "The server admin is sad today because the hinge on his HP laptop broke which happened to be an HP Elitebook 8470p, and the RAM controller exploded and then fixed itself, please contact him", StartAt = Timestamp.FromDateTime(DateTime.SpecifyKind(user.BanStart, DateTimeKind.Utc)), EndAt = Timestamp.FromDateTime(DateTime.SpecifyKind(user.BanEnd, DateTimeKind.Utc)) };
|
||||
}
|
||||
else
|
||||
{
|
||||
response.AuthSuccess = new NetAuthSuccess() { AuthToken = req.Token, CentauriZoneId = "84", FirstAuth = "", PurchaseRestriction = new NetUserPurchaseRestriction() { PurchaseRestriction = PurchaseRestriction.Child, UpdatedAt = 638546758794611090 } };
|
||||
}
|
||||
}
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using EmbedIO;
|
||||
using EmbedIO.Actions;
|
||||
using EmbedIO.WebApi;
|
||||
using Newtonsoft.Json;
|
||||
using nksrv.Database;
|
||||
using nksrv.IntlServer;
|
||||
using nksrv.LobbyServer;
|
||||
@@ -450,7 +451,7 @@ namespace nksrv
|
||||
""WorldId"": 1001,
|
||||
""Name"": ""pub:priv"",
|
||||
""Url"": ""https://global-lobby.nikke-kr.com/"",
|
||||
""Description"": ""Private Server"",
|
||||
""Description"": {ServerName},
|
||||
""Tags"": []
|
||||
}
|
||||
]
|
||||
@@ -466,7 +467,7 @@ namespace nksrv
|
||||
""WorldId"": 1001,
|
||||
""Name"": ""pub:priv"",
|
||||
""Url"": ""https://global-lobby.nikke-kr.com/"",
|
||||
""Description"": ""Private Server"",
|
||||
""Description"": {ServerName},
|
||||
""Tags"": []
|
||||
}
|
||||
]
|
||||
@@ -475,6 +476,7 @@ namespace nksrv
|
||||
}";
|
||||
response = response.Replace("{GameMinVer}", GameConfig.Root.GameMinVer);
|
||||
response = response.Replace("{GameMaxVer}", GameConfig.Root.GameMaxVer);
|
||||
response = response.Replace("{ServerName}", JsonConvert.ToString(JsonDb.Instance.ServerName));
|
||||
await ctx.SendStringAsync(response, "application/json", Encoding.Default);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -56,10 +56,10 @@ namespace nksrv.StaticInfo
|
||||
|
||||
static async Task<StaticDataParser> BuildAsync()
|
||||
{
|
||||
Logger.Info("Loading static data");
|
||||
Logger.Info("Decrypting static data");
|
||||
await Load();
|
||||
|
||||
Logger.Info("Parsing static data");
|
||||
Logger.Info("Loading static data");
|
||||
await Instance.Parse();
|
||||
|
||||
return Instance;
|
||||
@@ -212,7 +212,7 @@ namespace nksrv.StaticInfo
|
||||
}
|
||||
#endregion
|
||||
|
||||
private async Task<JArray> LoadZip(string entry)
|
||||
private async Task<JArray> LoadZip(string entry, ProgressBar bar)
|
||||
{
|
||||
var mainQuestData = MainZip.GetEntry(entry);
|
||||
if (mainQuestData == null) throw new Exception(entry + " does not exist in static data");
|
||||
@@ -227,20 +227,29 @@ namespace nksrv.StaticInfo
|
||||
var records = (JArray?)questdata["records"];
|
||||
if (records == null) throw new Exception(entry + " is missing records element");
|
||||
|
||||
currentFile++;
|
||||
bar.Report((double)currentFile / totalFiles);
|
||||
|
||||
return records;
|
||||
}
|
||||
int totalFiles = 12;
|
||||
int currentFile = 0;
|
||||
public async Task Parse()
|
||||
{
|
||||
questDataRecords = await LoadZip("MainQuestTable.json");
|
||||
stageDataRecords = await LoadZip("CampaignStageTable.json");
|
||||
rewardDataRecords = await LoadZip("RewardTable.json");
|
||||
userExpDataRecords = await LoadZip("UserExpTable.json");
|
||||
chapterCampaignData = await LoadZip("CampaignChapterTable.json");
|
||||
characterCostumeTable = await LoadZip("CharacterCostumeTable.json");
|
||||
characterTable = await LoadZip("CharacterTable.json");
|
||||
tutorialTable = await LoadZip("ContentsTutorialTable.json");
|
||||
itemEquipTable = await LoadZip("ItemEquipTable.json");
|
||||
var characterLevelTable = await LoadZip("CharacterLevelTable.json");
|
||||
using var progress = new ProgressBar();
|
||||
|
||||
|
||||
|
||||
questDataRecords = await LoadZip("MainQuestTable.json", progress);
|
||||
stageDataRecords = await LoadZip("CampaignStageTable.json", progress);
|
||||
rewardDataRecords = await LoadZip("RewardTable.json", progress);
|
||||
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 characterLevelTable = await LoadZip("CharacterLevelTable.json", progress);
|
||||
|
||||
foreach (JToken item in characterLevelTable)
|
||||
{
|
||||
@@ -251,7 +260,7 @@ namespace nksrv.StaticInfo
|
||||
Logger.Warn("failed to read character level table entry");
|
||||
}
|
||||
|
||||
var tacticLessonTable = await LoadZip("TacticAcademyFunctionTable.json");
|
||||
var tacticLessonTable = await LoadZip("TacticAcademyFunctionTable.json", progress);
|
||||
|
||||
foreach (JToken item in tacticLessonTable)
|
||||
{
|
||||
@@ -274,7 +283,7 @@ namespace nksrv.StaticInfo
|
||||
TacticAcademyLessons.Add(id, new TacticAcademyLessonRecord() { CurrencyId = (CurrencyType)currencyId, CurrencyValue = currencyValue, GroupId = groupid, Id = id });
|
||||
}
|
||||
|
||||
var sideStoryTable = await LoadZip("SideStoryStageTable.json");
|
||||
var sideStoryTable = await LoadZip("SideStoryStageTable.json", progress);
|
||||
|
||||
foreach (JToken item in sideStoryTable)
|
||||
{
|
||||
|
||||
105
nksrv/Utils/ProgressBar.cs
Normal file
105
nksrv/Utils/ProgressBar.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
// Source code is from: https://gist.github.com/DanielSWolf/0ab6a96899cc5377bf54
|
||||
// Licensed under MIT License
|
||||
|
||||
using System.Text;
|
||||
|
||||
namespace nksrv.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// An ASCII progress bar
|
||||
/// </summary>
|
||||
public class ProgressBar : IDisposable, IProgress<double>
|
||||
{
|
||||
private const int blockCount = 10;
|
||||
private readonly TimeSpan animationInterval = TimeSpan.FromSeconds(1.0 / 8);
|
||||
private const string animation = @"|/-\";
|
||||
|
||||
private readonly Timer timer;
|
||||
|
||||
private double currentProgress = 0;
|
||||
private string currentText = string.Empty;
|
||||
private bool disposed = false;
|
||||
private int animationIndex = 0;
|
||||
|
||||
public ProgressBar()
|
||||
{
|
||||
timer = new Timer(TimerHandler);
|
||||
|
||||
// A progress bar is only for temporary display in a console window.
|
||||
// If the console output is redirected to a file, draw nothing.
|
||||
// Otherwise, we'll end up with a lot of garbage in the target file.
|
||||
if (!Console.IsOutputRedirected)
|
||||
{
|
||||
ResetTimer();
|
||||
}
|
||||
}
|
||||
|
||||
public void Report(double value)
|
||||
{
|
||||
// Make sure value is in [0..1] range
|
||||
value = Math.Max(0, Math.Min(1, value));
|
||||
Interlocked.Exchange(ref currentProgress, value);
|
||||
}
|
||||
|
||||
private void TimerHandler(object state)
|
||||
{
|
||||
lock (timer)
|
||||
{
|
||||
if (disposed) return;
|
||||
|
||||
int progressBlockCount = (int)(currentProgress * blockCount);
|
||||
int percent = (int)(currentProgress * 100);
|
||||
string text = string.Format("[{0}{1}] {2,3}% {3}",
|
||||
new string('#', progressBlockCount), new string('-', blockCount - progressBlockCount),
|
||||
percent,
|
||||
animation[animationIndex++ % animation.Length]);
|
||||
UpdateText(text);
|
||||
|
||||
ResetTimer();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateText(string text)
|
||||
{
|
||||
// Get length of common portion
|
||||
int commonPrefixLength = 0;
|
||||
int commonLength = Math.Min(currentText.Length, text.Length);
|
||||
while (commonPrefixLength < commonLength && text[commonPrefixLength] == currentText[commonPrefixLength])
|
||||
{
|
||||
commonPrefixLength++;
|
||||
}
|
||||
|
||||
// Backtrack to the first differing character
|
||||
StringBuilder outputBuilder = new StringBuilder();
|
||||
outputBuilder.Append('\b', currentText.Length - commonPrefixLength);
|
||||
|
||||
// Output new suffix
|
||||
outputBuilder.Append(text.Substring(commonPrefixLength));
|
||||
|
||||
// If the new text is shorter than the old one: delete overlapping characters
|
||||
int overlapCount = currentText.Length - text.Length;
|
||||
if (overlapCount > 0)
|
||||
{
|
||||
outputBuilder.Append(' ', overlapCount);
|
||||
outputBuilder.Append('\b', overlapCount);
|
||||
}
|
||||
|
||||
Console.Write(outputBuilder);
|
||||
currentText = text;
|
||||
}
|
||||
|
||||
private void ResetTimer()
|
||||
{
|
||||
timer.Change(animationInterval, TimeSpan.FromMilliseconds(-1));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
lock (timer)
|
||||
{
|
||||
disposed = true;
|
||||
UpdateText(string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user