mirror of
https://github.com/EpinelPS/EpinelPS.git
synced 2025-12-13 07:24:52 +01:00
785 lines
26 KiB
C#
785 lines
26 KiB
C#
using EpinelPS.Data;
|
|
using EpinelPS.Utils;
|
|
using Newtonsoft.Json;
|
|
using Paseto.Builder;
|
|
using Paseto;
|
|
using Google.Protobuf;
|
|
|
|
namespace EpinelPS.Database
|
|
{
|
|
public class AccessToken
|
|
{
|
|
public string Token = "";
|
|
public long ExpirationTime;
|
|
public ulong UserID;
|
|
}
|
|
public class FieldInfo
|
|
{
|
|
public List<NetFieldStageData> CompletedStages = [];
|
|
public List<NetFieldObject> CompletedObjects = [];
|
|
}
|
|
|
|
public class FieldInfoNew
|
|
{
|
|
public List<int> CompletedStages = [];
|
|
public List<NetFieldObject> CompletedObjects = [];
|
|
public bool BossEntered = false;
|
|
}
|
|
|
|
public class Character
|
|
{
|
|
public int Csn = 0;
|
|
public int Tid = 0;
|
|
public int CostumeId = 0;
|
|
public int Level = 1;
|
|
public int UltimateLevel = 1;
|
|
public int Skill1Lvl = 1;
|
|
public int Skill2Lvl = 1;
|
|
public int Grade = 0;
|
|
}
|
|
public class MainQuestData
|
|
{
|
|
public int TableId = 0;
|
|
public bool IsReceieved = false;
|
|
}
|
|
|
|
public class UserPointData
|
|
{
|
|
public int UserLevel = 1;
|
|
public int ExperiencePoint = 0;
|
|
}
|
|
|
|
public class ItemData
|
|
{
|
|
public int ItemType;
|
|
public long Csn;
|
|
public int Count;
|
|
public int Level;
|
|
public int Exp;
|
|
public int Position;
|
|
public int Corp;
|
|
public long Isn;
|
|
}
|
|
public class EventData
|
|
{
|
|
public List<string> CompletedScenarios = new();
|
|
public int Diff = 0; // Default value for Diff
|
|
public int LastStage = 0; // Default value for LastStage
|
|
}
|
|
|
|
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 SimroomData
|
|
{
|
|
public int CurrentDifficulty;
|
|
public int CurrentChapter;
|
|
public bool Entered = false;
|
|
}
|
|
public class ResetableData
|
|
{
|
|
public int WipeoutCount = 0;
|
|
public bool ClearedSimulationRoom = false;
|
|
public int InterceptionTickets = 3;
|
|
public List<int> CompletedDailyMissions = [];
|
|
public int DailyMissionPoints;
|
|
public SimroomData SimRoomData = new();
|
|
}
|
|
public class WeeklyResetableData
|
|
{
|
|
public List<int> CompletedWeeklyMissions = [];
|
|
public int WeeklyMissionPoints;
|
|
}
|
|
public class OutpostBuffs
|
|
{
|
|
public List<int> CreditPercentages = new List<int>();
|
|
public List<int> CoreDustPercentages = new List<int>();
|
|
public List<int> BattleDataPercentages = new List<int>();
|
|
public List<int> UserExpPercentages = new List<int>();
|
|
|
|
public List<int> GetPercentages(CurrencyType currency)
|
|
{
|
|
if (currency == CurrencyType.Gold)
|
|
return CreditPercentages;
|
|
else if (currency == CurrencyType.UserExp)
|
|
return UserExpPercentages;
|
|
else if (currency == CurrencyType.CharacterExp)
|
|
return BattleDataPercentages;
|
|
else if (currency == CurrencyType.CharacterExp2)
|
|
return CoreDustPercentages;
|
|
|
|
throw new InvalidOperationException();
|
|
}
|
|
public int GetTotalPercentages(CurrencyType currency)
|
|
{
|
|
int result = 0;
|
|
var numbs = GetPercentages(currency);
|
|
foreach (var item in numbs)
|
|
{
|
|
result += item;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
public class JukeBoxSetting
|
|
{
|
|
public NetJukeboxLocation Location;
|
|
public NetJukeboxBgmType Type;
|
|
public int TableId;
|
|
}
|
|
|
|
public class UnlockData
|
|
{
|
|
public bool ButtonAnimationPlayed = false;
|
|
public bool PopupAnimationPlayed = false;
|
|
|
|
public UnlockData() { }
|
|
public UnlockData(bool button, bool popup)
|
|
{
|
|
ButtonAnimationPlayed = button;
|
|
PopupAnimationPlayed = popup;
|
|
}
|
|
}
|
|
|
|
public class MogMinigameInfo
|
|
{
|
|
public List<string> CompletedScenarios = [];
|
|
}
|
|
public class Badge
|
|
{
|
|
public string Location = "";
|
|
public long Seq;
|
|
public BadgeContents BadgeContent;
|
|
public string BadgeGuid = "";
|
|
|
|
public Badge() { }
|
|
public Badge(NetBadge badge)
|
|
{
|
|
Location = badge.Location;
|
|
Seq = badge.Seq;
|
|
BadgeContent = badge.BadgeContent;
|
|
BadgeGuid = new Guid(badge.BadgeGuid.ToArray()).ToString();
|
|
}
|
|
|
|
public NetBadge ToNet()
|
|
{
|
|
return new NetBadge()
|
|
{
|
|
BadgeContent = BadgeContent,
|
|
BadgeGuid = ByteString.CopyFrom(new Guid(BadgeGuid).ToByteArray()),
|
|
Location = Location,
|
|
Seq = Seq
|
|
};
|
|
}
|
|
}
|
|
|
|
public class Trigger
|
|
{
|
|
public TriggerType Type;
|
|
public long Id;
|
|
public long CreatedAt;
|
|
public int ConditionId;
|
|
public int Value;
|
|
|
|
public NetTrigger ToNet()
|
|
{
|
|
return new()
|
|
{
|
|
ConditionId = ConditionId,
|
|
CreatedAt = CreatedAt,
|
|
Seq = Id,
|
|
Trigger = (int)Type,
|
|
UserValue = Value
|
|
};
|
|
}
|
|
}
|
|
public class ConversationChoice
|
|
{
|
|
|
|
}
|
|
public class ConversationMessage
|
|
{
|
|
public string ConversationId { get; set; } = "";
|
|
public long CreatedAt { get; set; }
|
|
public ulong Seq { get; set; }
|
|
public string Id { get; set; } = "";
|
|
public int State { get; set; }
|
|
}
|
|
public class User
|
|
{
|
|
// User info
|
|
public string Username = "";
|
|
public string Password = "";
|
|
public string PlayerName = "";
|
|
public ulong ID;
|
|
public long RegisterTime;
|
|
public int LastNormalStageCleared;
|
|
public int LastHardStageCleared;
|
|
public string Nickname = "SomePlayer";
|
|
public int ProfileIconId = 39900;
|
|
public bool ProfileIconIsPrism = false;
|
|
public int ProfileFrame = 25;
|
|
public bool IsAdmin = false;
|
|
public bool sickpulls = false;
|
|
public bool IsBanned = false;
|
|
public int TitleId = 1;
|
|
public DateTime BanStart;
|
|
public DateTime BanEnd;
|
|
public int BanId = 0;
|
|
|
|
// Game data
|
|
public List<string> CompletedScenarios = [];
|
|
public Dictionary<string, FieldInfo> FieldInfo = []; // here for backwards compatibility
|
|
|
|
public Dictionary<string, FieldInfoNew> FieldInfoNew = [];
|
|
public Dictionary<string, string> MapJson = [];
|
|
public Dictionary<CurrencyType, long> Currency = new() {
|
|
{ CurrencyType.ContentStamina, 2 }
|
|
};
|
|
public List<SynchroSlot> SynchroSlots = new List<SynchroSlot>();
|
|
public bool SynchroDeviceUpgraded = false;
|
|
public int SynchroDeviceLevel = 200;
|
|
|
|
public ResetableData ResetableData = new();
|
|
public WeeklyResetableData WeeklyResetableData = new();
|
|
public List<ItemData> Items = new();
|
|
public List<Character> Characters = [];
|
|
public NetWholeUserTeamData RepresentationTeamData = new();
|
|
public Dictionary<int, ClearedTutorialData> ClearedTutorialData = [];
|
|
|
|
public NetWallpaperData[] WallpaperList = [];
|
|
public NetWallpaperBackground[] WallpaperBackground = [];
|
|
public NetWallpaperJukeboxFavorite[] WallpaperFavoriteList = [];
|
|
public NetWallpaperPlaylist[] WallpaperPlaylistList = [];
|
|
public NetWallpaperJukebox[] WallpaperJukeboxList = [];
|
|
public List<int> LobbyDecoBackgroundList = [];
|
|
|
|
|
|
public Dictionary<int, NetUserTeamData> UserTeams = new Dictionary<int, NetUserTeamData>();
|
|
public Dictionary<int, bool> MainQuestData = new();
|
|
public Dictionary<int, bool> SubQuestData = new();
|
|
public int InfraCoreExp = 0;
|
|
public int InfraCoreLvl = 1;
|
|
public UserPointData userPointData = new();
|
|
public DateTime LastLogin = DateTime.UtcNow;
|
|
public DateTime BattleTime = DateTime.UtcNow;
|
|
|
|
public NetOutpostBattleLevel OutpostBattleLevel = new() { Level = 1 };
|
|
public int GachaTutorialPlayCount = 0;
|
|
public List<int> CompletedTacticAcademyLessons = [];
|
|
public List<int> CompletedSideStoryStages = new();
|
|
|
|
public List<int> Memorial = new();
|
|
public List<int> JukeboxBgm = new List<int>();
|
|
|
|
public Dictionary<int, int> TowerProgress = new Dictionary<int, int>();
|
|
|
|
public JukeBoxSetting LobbyMusic = new() { Location = NetJukeboxLocation.NetJukeboxLocationLobby, TableId = 2, Type = NetJukeboxBgmType.NetJukeboxBgmTypeJukeboxTableId };
|
|
public JukeBoxSetting CommanderMusic = new() { Location = NetJukeboxLocation.NetJukeboxLocationCommanderRoom, TableId = 5, Type = NetJukeboxBgmType.NetJukeboxBgmTypeJukeboxTableId };
|
|
public OutpostBuffs OutpostBuffs = new();
|
|
public Dictionary<int, UnlockData> ContentsOpenUnlocked = new();
|
|
|
|
public List<NetStageClearInfo> StageClearHistorys = [];
|
|
|
|
public List<Badge> Badges = [];
|
|
|
|
public List<NetUserAttractiveData> BondInfo = [];
|
|
public List<Trigger> Triggers = [];
|
|
public int LastTriggerId = 1;
|
|
public List<int> CompletedAchievements = [];
|
|
public List<NetMessage> MessengerData = [];
|
|
public ulong LastMessageId = 1;
|
|
public long LastBadgeSeq = 1;
|
|
|
|
// Event data
|
|
public Dictionary<int, EventData> EventInfo = new();
|
|
public MogMinigameInfo MogInfo = new();
|
|
|
|
public Trigger AddTrigger(TriggerType type, int value, int conditionId = 0)
|
|
{
|
|
Trigger t = new()
|
|
{
|
|
Id = LastTriggerId++,
|
|
Type = type,
|
|
ConditionId = conditionId,
|
|
CreatedAt = DateTime.UtcNow.AddHours(9).Ticks,
|
|
Value = value
|
|
};
|
|
|
|
Triggers.Add(t);
|
|
|
|
return t;
|
|
}
|
|
|
|
public Badge AddBadge(BadgeContents type, string location)
|
|
{
|
|
// generate unique badge SEQ
|
|
|
|
var badge = new Badge()
|
|
{
|
|
BadgeContent = type,
|
|
Location = location,
|
|
BadgeGuid = Guid.NewGuid().ToString(),
|
|
Seq = LastBadgeSeq++
|
|
};
|
|
|
|
Badges.Add(badge);
|
|
|
|
return badge;
|
|
}
|
|
|
|
|
|
public void SetQuest(int tid, bool recievedReward)
|
|
{
|
|
if (!MainQuestData.TryAdd(tid, recievedReward))
|
|
{
|
|
MainQuestData[tid] = recievedReward;
|
|
return;
|
|
}
|
|
}
|
|
|
|
public void SetSubQuest(int tid, bool recievedReward)
|
|
{
|
|
if (!SubQuestData.TryAdd(tid, recievedReward))
|
|
{
|
|
SubQuestData[tid] = recievedReward;
|
|
return;
|
|
}
|
|
}
|
|
|
|
public int GenerateUniqueItemId()
|
|
{
|
|
var num = Rng.RandomId();
|
|
|
|
while (Items.Any(x => x.Isn == num))
|
|
{
|
|
num = Rng.RandomId();
|
|
}
|
|
|
|
return num;
|
|
}
|
|
public int GenerateUniqueCharacterId()
|
|
{
|
|
var num = Rng.RandomId();
|
|
|
|
while (Characters.Any(x => x.Csn == num))
|
|
{
|
|
num = Rng.RandomId();
|
|
}
|
|
|
|
return num;
|
|
}
|
|
public bool IsStageCompleted(int id, bool isNorm)
|
|
{
|
|
foreach (var item in FieldInfoNew)
|
|
{
|
|
if (item.Key.Contains("hard") && isNorm) continue;
|
|
if (item.Key.Contains("normal") && !isNorm) continue;
|
|
if (item.Value.CompletedStages.Contains(id))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public long GetCurrencyVal(CurrencyType type)
|
|
{
|
|
if (Currency.ContainsKey(type))
|
|
return Currency[type];
|
|
else
|
|
{
|
|
Currency.Add(type, 0);
|
|
return 0;
|
|
}
|
|
}
|
|
public void AddCurrency(CurrencyType type, long val)
|
|
{
|
|
if (Currency.ContainsKey(type)) Currency[type] += val;
|
|
else Currency.Add(type, val);
|
|
}
|
|
public bool SubtractCurrency(CurrencyType type, long val)
|
|
{
|
|
if (Currency.ContainsKey(type)) Currency[type] -= val;
|
|
else return false;
|
|
|
|
if (Currency[type] < 0)
|
|
{
|
|
Currency[type] += val;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
public bool CanSubtractCurrency(CurrencyType type, long val)
|
|
{
|
|
if (Currency.ContainsKey(type))
|
|
{
|
|
if (Currency[type] >= val) return true;
|
|
else return false;
|
|
}
|
|
else
|
|
{
|
|
if (val == 0) return true;
|
|
else return false;
|
|
}
|
|
}
|
|
|
|
public bool HasCharacter(int c)
|
|
{
|
|
// Step 1: Get the 'name_code' of the input character with Tid 'c'
|
|
if (GameData.Instance.CharacterTable.TryGetValue(c, out var inputCharacterRecord))
|
|
{
|
|
int targetNameCode = inputCharacterRecord.name_code;
|
|
// Step 2: Find all character IDs in 'characterTable' that have the same 'name_code'
|
|
var matchingCharacterIds = GameData.Instance.CharacterTable.Where(kvp => kvp.Value.name_code == targetNameCode).Select(kvp => kvp.Key).ToHashSet();
|
|
|
|
// Step 3: Check if any of your owned characters have a 'Tid' in the set of matching IDs
|
|
return Characters.Any(ownedCharacter => matchingCharacterIds.Contains(ownedCharacter.Tid));
|
|
|
|
}
|
|
else
|
|
{ // The character with Tid 'c' does not exist in 'characterTable'
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public Character? GetCharacter(int c)
|
|
{
|
|
// Step 1: Get the 'name_code' of the input character with Tid 'c'
|
|
if (GameData.Instance.CharacterTable.TryGetValue(c, out var inputCharacterRecord))
|
|
{
|
|
int targetNameCode = inputCharacterRecord.name_code;
|
|
// Step 2: Find all character IDs in 'characterTable' that have the same 'name_code'
|
|
var matchingCharacterIds = GameData.Instance.CharacterTable.Where(kvp => kvp.Value.name_code == targetNameCode).Select(kvp => kvp.Key).ToHashSet();
|
|
|
|
// Step 3: Check if any of your owned characters have a 'Tid' in the set of matching IDs
|
|
return Characters.Where(ownedCharacter => matchingCharacterIds.Contains(ownedCharacter.Tid)).First();
|
|
|
|
}
|
|
else
|
|
{ // The character with Tid 'c' does not exist in 'characterTable'
|
|
return null;
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes the specified amount of items by their ID. Returns the amount of items removed.
|
|
/// </summary>
|
|
/// <param name="isn"></param>
|
|
/// <param name="count"></param>
|
|
/// <returns></returns>
|
|
public int RemoveItemBySerialNumber(long isn, int count)
|
|
{
|
|
int removed = 0;
|
|
foreach (var item in Items.ToList())
|
|
{
|
|
if (count == 0)
|
|
break;
|
|
|
|
if (item.Isn == isn)
|
|
{
|
|
removed++;
|
|
item.Count -= count;
|
|
|
|
if (item.Count < 0)
|
|
{
|
|
item.Count = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return removed;
|
|
}
|
|
|
|
public NetMessage CreateMessage(MessengerDialogRecord r, int state = 0)
|
|
{
|
|
var msg = new NetMessage()
|
|
{
|
|
ConversationId = r.conversation_id,
|
|
CreatedAt = DateTime.UtcNow.Ticks,
|
|
MessageId = r.id,
|
|
Seq = (long)LastMessageId++,
|
|
State = state
|
|
};
|
|
MessengerData.Add(msg);
|
|
return msg;
|
|
}
|
|
|
|
public NetMessage CreateMessage(string conversationId, string messageId, int state = 0)
|
|
{
|
|
var msg = new NetMessage()
|
|
{
|
|
ConversationId = conversationId,
|
|
CreatedAt = DateTime.UtcNow.Ticks,
|
|
MessageId = messageId,
|
|
Seq = (long)LastMessageId++,
|
|
State = state
|
|
};
|
|
MessengerData.Add(msg);
|
|
return msg;
|
|
}
|
|
}
|
|
public class CoreInfo
|
|
{
|
|
public int DbVersion = 3;
|
|
public List<User> Users = [];
|
|
|
|
public List<AccessToken> LauncherAccessTokens = [];
|
|
public Dictionary<string, ulong> AdminAuthTokens = new();
|
|
|
|
public string ServerName = "<color=\"green\">Private Server</color>";
|
|
public byte[] LauncherTokenKey = [];
|
|
public byte[] EncryptionTokenKey = [];
|
|
public LogType LogLevel = LogType.Debug;
|
|
}
|
|
internal class JsonDb
|
|
{
|
|
public static CoreInfo Instance { get; internal set; }
|
|
|
|
// Note: change this in sodium
|
|
public static byte[] ServerPrivateKey = Convert.FromBase64String("FSUY8Ohd942n5LWAfxn6slK3YGwc8OqmyJoJup9nNos=");
|
|
public static byte[] ServerPublicKey = Convert.FromBase64String("04hFDd1e/BOEF2h4b0MdkX2h6W5REeqyW+0r9+eSeh0=");
|
|
|
|
static JsonDb()
|
|
{
|
|
if (!File.Exists(AppDomain.CurrentDomain.BaseDirectory + "/db.json"))
|
|
{
|
|
Console.WriteLine("users: warning: configuration not found, writing default data");
|
|
Instance = new CoreInfo();
|
|
Save();
|
|
}
|
|
|
|
var j = JsonConvert.DeserializeObject<CoreInfo>(File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + "/db.json"));
|
|
if (j != null)
|
|
{
|
|
Instance = j;
|
|
|
|
if (Instance.DbVersion == 0)
|
|
{
|
|
Instance.DbVersion = 1;
|
|
// In older versions, field info key used chapter number, but now difficultly is appened.
|
|
Console.WriteLine("Starting database update...");
|
|
|
|
foreach (var user in Instance.Users)
|
|
{
|
|
foreach (var f in user.FieldInfoNew.ToList())
|
|
{
|
|
var isNumeric = int.TryParse(f.Key, out int n);
|
|
if (isNumeric)
|
|
{
|
|
var val = f.Value;
|
|
user.FieldInfoNew.Remove(f.Key);
|
|
user.FieldInfoNew.Add(n + "_Normal", val);
|
|
}
|
|
}
|
|
}
|
|
Console.WriteLine("Database update completed");
|
|
}
|
|
else if (Instance.DbVersion == 1)
|
|
{
|
|
Console.WriteLine("Starting database update...");
|
|
// there was a bug where equipment position was not saved, so remove all items from each characters
|
|
Instance.DbVersion = 2;
|
|
foreach (var user in Instance.Users)
|
|
{
|
|
foreach (var f in user.Items.ToList())
|
|
{
|
|
f.Csn = 0;
|
|
}
|
|
}
|
|
Console.WriteLine("Database update completed");
|
|
}
|
|
else if (Instance.DbVersion == 2)
|
|
{
|
|
Console.WriteLine("Starting database update...");
|
|
// I used to use a class for FieldInfo cleared stages, but now int list is used
|
|
Instance.DbVersion = 3;
|
|
foreach (var user in Instance.Users)
|
|
{
|
|
foreach (var f in user.FieldInfo)
|
|
{
|
|
var newField = new FieldInfoNew();
|
|
foreach (var stage in f.Value.CompletedStages)
|
|
{
|
|
newField.CompletedStages.Add(stage.StageId);
|
|
}
|
|
user.FieldInfoNew.Add(f.Key, newField);
|
|
}
|
|
user.FieldInfo.Clear();
|
|
}
|
|
Console.WriteLine("Database update completed");
|
|
}
|
|
|
|
if (Instance.LauncherTokenKey.Length == 0)
|
|
{
|
|
Console.WriteLine("Launcher token key is null, generating new key");
|
|
|
|
var pasetoKey = new PasetoBuilder().Use(ProtocolVersion.V4, Purpose.Local)
|
|
.GenerateSymmetricKey();
|
|
Instance.LauncherTokenKey = pasetoKey.Key.ToArray();
|
|
}
|
|
if (Instance.EncryptionTokenKey.Length == 0)
|
|
{
|
|
Console.WriteLine("EncryptionTokenKey is null, generating new key");
|
|
|
|
var pasetoKey = new PasetoBuilder().Use(ProtocolVersion.V4, Purpose.Local)
|
|
.GenerateSymmetricKey();
|
|
Instance.EncryptionTokenKey = pasetoKey.Key.ToArray();
|
|
}
|
|
|
|
Save();
|
|
|
|
ValidateDb();
|
|
Console.WriteLine("JsonDb: Loaded");
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Failed to read configuration json file");
|
|
}
|
|
}
|
|
|
|
public static void Reload()
|
|
{
|
|
if (!File.Exists(AppDomain.CurrentDomain.BaseDirectory + "/db.json"))
|
|
{
|
|
Console.WriteLine("users: warning: configuration not found, writing default data");
|
|
Instance = new CoreInfo();
|
|
Save();
|
|
}
|
|
|
|
var j = JsonConvert.DeserializeObject<CoreInfo>(File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + "/db.json"));
|
|
if (j != null)
|
|
{
|
|
Instance = j;
|
|
Console.WriteLine("Database reload complete.");
|
|
}
|
|
}
|
|
|
|
private static void ValidateDb()
|
|
{
|
|
// check if character level is valid
|
|
foreach (var user in Instance.Users)
|
|
{
|
|
foreach (var c in user.Characters)
|
|
{
|
|
if (c.Level > 1000)
|
|
{
|
|
Console.WriteLine($"Warning: Character level for character {c.Tid} cannot be above 1000, setting to 1000");
|
|
c.Level = 1000;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static User? GetUser(ulong id)
|
|
{
|
|
return Instance.Users.Where(x => x.ID == id).FirstOrDefault();
|
|
}
|
|
public static void Save()
|
|
{
|
|
if (Instance != null)
|
|
{
|
|
File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + "/db.json", JsonConvert.SerializeObject(Instance, Formatting.Indented));
|
|
}
|
|
}
|
|
public static int CurrentJukeboxBgm(int position)
|
|
{
|
|
var activeJukeboxBgm = new List<int>();
|
|
//important first position holds lobby bgm id and second commanders room bgm id
|
|
foreach (var user in Instance.Users)
|
|
{
|
|
if (user.JukeboxBgm == null || user.JukeboxBgm.Count == 0)
|
|
{
|
|
// this if statemet only exists becaus some weird black magic copies default value over and over
|
|
//in the file when its set in public List<int> JukeboxBgm = new List<int>();
|
|
//delete when or if it gets fixed
|
|
|
|
user.JukeboxBgm = new List<int> { 2, 5 };
|
|
}
|
|
|
|
activeJukeboxBgm.AddRange(user.JukeboxBgm);
|
|
}
|
|
|
|
if (activeJukeboxBgm.Count == 0)
|
|
{
|
|
return 8995001;
|
|
}
|
|
|
|
position = (position == 2 && activeJukeboxBgm.Count > 1) ? 2 : 1;
|
|
return activeJukeboxBgm[position - 1];
|
|
}
|
|
|
|
public static bool IsSickPulls(User selectedUser)
|
|
{
|
|
if (selectedUser != null)
|
|
{
|
|
return selectedUser.sickpulls;
|
|
}
|
|
else
|
|
{
|
|
throw new Exception($"User not found");
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|