implement ban, add static data progress bar, allow changing server name

This commit is contained in:
Mikhail
2024-07-26 12:49:11 -04:00
parent 8ba6d69ade
commit cce8179e8d
5 changed files with 178 additions and 21 deletions

View File

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

View File

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

View File

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

View File

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