mirror of
https://github.com/EpinelPS/EpinelPS.git
synced 2025-12-16 08:54:47 +01:00
Move models out of JsonDb
This commit is contained in:
6
EpinelPS/Database/DatabaseConnection.cs
Normal file
6
EpinelPS/Database/DatabaseConnection.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace EpinelPS.Database;
|
||||
|
||||
public class DatabaseConnection
|
||||
{
|
||||
|
||||
}
|
||||
@@ -9,643 +9,6 @@ using Paseto.Builder;
|
||||
|
||||
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 = [];
|
||||
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 RecycleRoomResearchProgress
|
||||
{
|
||||
public int Level = 1;
|
||||
public int Exp;
|
||||
public int Attack;
|
||||
public int Defense;
|
||||
public int Hp;
|
||||
}
|
||||
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 = [];
|
||||
public List<int> CoreDustPercentages = [];
|
||||
public List<int> BattleDataPercentages = [];
|
||||
public List<int> UserExpPercentages = [];
|
||||
|
||||
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]).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 LostSectorData
|
||||
{
|
||||
public bool IsOpen { get; set; }
|
||||
public bool IsPlaying { get; set; }
|
||||
public string Json { get; set; } = "";
|
||||
public Dictionary<string, NetLostSectorFieldObject> Objects { get; set; } = [];
|
||||
public Dictionary<string, int> ClearedStages { get; set; } = [];
|
||||
public List<NetLostSectorTeamPosition> TeamPositions { get; set; } = [];
|
||||
public int ObtainedRewards { get; set; } = 0;
|
||||
public bool RecievedFinalReward { get; set; }
|
||||
public bool CompletedPerfectly { 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;
|
||||
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;
|
||||
public DateTime LastReset = DateTime.MinValue;
|
||||
|
||||
// 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 = [];
|
||||
public bool SynchroDeviceUpgraded = false;
|
||||
public int SynchroDeviceLevel = 200;
|
||||
public Dictionary<int, RecycleRoomResearchProgress> ResearchProgress = [];
|
||||
|
||||
public ResetableData ResetableData = new();
|
||||
public WeeklyResetableData WeeklyResetableData = new();
|
||||
public List<ItemData> Items = [];
|
||||
public List<Character> Characters = [];
|
||||
public long[] RepresentationTeamDataNew = [];
|
||||
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 = [];
|
||||
public Dictionary<int, bool> MainQuestData = [];
|
||||
public Dictionary<int, bool> SubQuestData = [];
|
||||
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 = [];
|
||||
|
||||
public List<int> Memorial = [];
|
||||
public List<int> JukeboxBgm = [];
|
||||
|
||||
public Dictionary<int, int> TowerProgress = [];
|
||||
|
||||
public JukeBoxSetting LobbyMusic = new() { Location = NetJukeboxLocation.Lobby, TableId = 2, Type = NetJukeboxBgmType.JukeboxTableId };
|
||||
public JukeBoxSetting CommanderMusic = new() { Location = NetJukeboxLocation.CommanderRoom, TableId = 5, Type = NetJukeboxBgmType.JukeboxTableId };
|
||||
public OutpostBuffs OutpostBuffs = new();
|
||||
public Dictionary<int, UnlockData> ContentsOpenUnlocked = [];
|
||||
|
||||
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;
|
||||
public Dictionary<int, LostSectorData> LostSectorData = [];
|
||||
|
||||
// Event data
|
||||
public Dictionary<int, EventData> EventInfo = [];
|
||||
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)
|
||||
{
|
||||
foreach (var item in FieldInfoNew)
|
||||
{
|
||||
if (item.Value.CompletedStages.Contains(id))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public long GetCurrencyVal(CurrencyType type)
|
||||
{
|
||||
if (Currency.TryGetValue(type, out long value))
|
||||
return value;
|
||||
else
|
||||
{
|
||||
Currency.Add(type, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
public void AddCurrency(CurrencyType type, long val)
|
||||
{
|
||||
if (!Currency.TryAdd(type, val)) Currency[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)).FirstOrDefault();
|
||||
|
||||
}
|
||||
else
|
||||
{ // The character with Tid 'c' does not exist in 'characterTable'
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Character? GetCharacterBySerialNumber(long value)
|
||||
{
|
||||
if (value == 0) return null;
|
||||
return Characters.Where(x => x.Csn == value).FirstOrDefault();
|
||||
}
|
||||
|
||||
internal bool GetSynchro(long csn)
|
||||
{
|
||||
return SynchroSlots.Where(x => x.CharacterSerialNumber == csn).Any();
|
||||
}
|
||||
internal int GetCharacterLevel(int csn)
|
||||
{
|
||||
var c = GetCharacterBySerialNumber(csn) ?? 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;
|
||||
}
|
||||
|
||||
private bool ShouldResetUser()
|
||||
{
|
||||
var nowLocal = DateTime.UtcNow;
|
||||
|
||||
// Compute the last reset threshold (most recent 2 PM before or at nowLocal)
|
||||
DateTime todayResetTime = new(
|
||||
nowLocal.Year,
|
||||
nowLocal.Month,
|
||||
nowLocal.Day,
|
||||
JsonDb.Instance.ResetHourUtcTime, 0, 0
|
||||
);
|
||||
|
||||
if (nowLocal < todayResetTime)
|
||||
{
|
||||
todayResetTime = todayResetTime.AddDays(-1);
|
||||
}
|
||||
|
||||
// If user's last reset was before the last scheduled 2 PM, they need reset
|
||||
return LastReset < todayResetTime;
|
||||
}
|
||||
|
||||
public void ResetDataIfNeeded()
|
||||
{
|
||||
if (!ShouldResetUser()) return;
|
||||
|
||||
Logging.WriteLine("Resetting user...", LogType.Warning);
|
||||
|
||||
LastReset = DateTime.UtcNow;
|
||||
ResetableData = new();
|
||||
JsonDb.Save();
|
||||
}
|
||||
}
|
||||
public class CoreInfo
|
||||
{
|
||||
public int DbVersion = 3;
|
||||
public List<User> Users = [];
|
||||
|
||||
public List<AccessToken> LauncherAccessTokens = [];
|
||||
public Dictionary<string, ulong> AdminAuthTokens = [];
|
||||
|
||||
public byte[] LauncherTokenKey = [];
|
||||
public byte[] EncryptionTokenKey = [];
|
||||
public LogType LogLevel = LogType.Debug;
|
||||
|
||||
public int MaxInterceptionCount = 3;
|
||||
public int ResetHourUtcTime = 20;
|
||||
}
|
||||
internal class JsonDb
|
||||
{
|
||||
public static CoreInfo Instance { get; internal set; }
|
||||
@@ -670,109 +33,11 @@ namespace EpinelPS.Database
|
||||
{
|
||||
Instance = j;
|
||||
|
||||
if (Instance.DbVersion == 0)
|
||||
if (Instance.DbVersion != 5)
|
||||
{
|
||||
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");
|
||||
}
|
||||
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");
|
||||
}
|
||||
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.DbVersion == 3)
|
||||
{
|
||||
Console.WriteLine("Starting database update...");
|
||||
Instance.DbVersion = 4;
|
||||
foreach (var user in Instance.Users)
|
||||
{
|
||||
user.RepresentationTeamDataNew = new long[5];
|
||||
}
|
||||
Console.WriteLine("Database update completed");
|
||||
}
|
||||
if (Instance.DbVersion == 4)
|
||||
{
|
||||
Console.WriteLine("Starting database update...");
|
||||
Instance.DbVersion = 5;
|
||||
// FieldInfoNew uses MapId instead of ChapterNum_ChapterDifficulty format
|
||||
foreach (var user in Instance.Users)
|
||||
{
|
||||
Dictionary<string, FieldInfoNew> info = [];
|
||||
foreach (var item in user.FieldInfoNew)
|
||||
{
|
||||
if (item.Key.EndsWith("_Normal") || item.Key.EndsWith("_Hard"))
|
||||
{
|
||||
var newKey = GameData.Instance.GetMapIdFromDBFieldName(item.Key);
|
||||
if (newKey != null)
|
||||
{
|
||||
if (!info.ContainsKey(newKey))
|
||||
{
|
||||
info.Add(newKey, item.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// overwrite old data
|
||||
info[newKey] = item.Value;
|
||||
}
|
||||
}
|
||||
else
|
||||
Console.WriteLine("Unknown chapter/difficulty: " + item.Value + ", discarding");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!info.ContainsKey(item.Key))
|
||||
info.Add(item.Key, item.Value);
|
||||
}
|
||||
}
|
||||
|
||||
user.FieldInfoNew = info;
|
||||
}
|
||||
Console.WriteLine("Database update completed");
|
||||
Logging.Warn("!!!WARNING!!!");
|
||||
Logging.Warn("Database version is extremely out of date.");
|
||||
Logging.Warn("It is recommended to delete db.json to avoid issues.");
|
||||
}
|
||||
|
||||
if (Instance.LauncherTokenKey.Length == 0)
|
||||
@@ -888,6 +153,5 @@ namespace EpinelPS.Database
|
||||
throw new Exception($"User not found");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<Version>0.135.4.3</Version>
|
||||
<CETCompat>false</CETCompat>
|
||||
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
|
||||
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
@@ -26,7 +26,6 @@
|
||||
<PackageReference Include="DnsClient" Version="1.8.0" />
|
||||
<PackageReference Include="Google.Api.CommonProtos" Version="2.17.0" />
|
||||
<PackageReference Include="Google.Protobuf.Tools" Version="3.31.1" />
|
||||
<PackageReference Include="Grpc.AspNetCore" Version="2.71.0" />
|
||||
<PackageReference Include="MemoryPack" Version="1.21.4" />
|
||||
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="6.0.0" />
|
||||
<PackageReference Include="Paseto.Core" Version="1.4.1" />
|
||||
|
||||
1
EpinelPS/Global.cs
Normal file
1
EpinelPS/Global.cs
Normal file
@@ -0,0 +1 @@
|
||||
global using EpinelPS.Models;
|
||||
@@ -1,6 +1,5 @@
|
||||
using EpinelPS.Utils;
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Data; // Ensure this namespace is included
|
||||
|
||||
namespace EpinelPS.LobbyServer.Archive
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace EpinelPS.LobbyServer.Arena
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetArena req = await ReadData<ReqGetArena>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetArena response = new()
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace EpinelPS.LobbyServer.Arena
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetSpecialArena req = await ReadData<ReqGetSpecialArena>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetSpecialArena response = new()
|
||||
{
|
||||
|
||||
@@ -9,11 +9,11 @@ namespace EpinelPS.LobbyServer.Badge
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqSyncBadge req = await ReadData<ReqSyncBadge>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResSyncBadge response = new();
|
||||
|
||||
foreach (Database.Badge item in user.Badges)
|
||||
foreach (BadgeModel item in user.Badges)
|
||||
{
|
||||
response.BadgeList.Add(item.ToNet());
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace EpinelPS.LobbyServer.Campaign
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetCampaignFieldData req = await ReadData<ReqGetCampaignFieldData>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
Console.WriteLine("Map ID: " + req.MapId);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Campaign
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqSaveCampaignField req = await ReadData<ReqSaveCampaignField>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResSaveCampaignField response = new();
|
||||
|
||||
|
||||
@@ -18,10 +18,10 @@ namespace EpinelPS.LobbyServer.Character
|
||||
|
||||
ResSynchroChange response = new();
|
||||
|
||||
List<Database.Character> highestLevelCharacters = [.. user.Characters.OrderByDescending(x => x.Level).Take(5)];
|
||||
List<CharacterModel> highestLevelCharacters = [.. user.Characters.OrderByDescending(x => x.Level).Take(5)];
|
||||
|
||||
int slot = 1;
|
||||
foreach (Database.Character? item in highestLevelCharacters)
|
||||
foreach (CharacterModel? item in highestLevelCharacters)
|
||||
{
|
||||
if (item.Level != 200)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ public class CheckCharacterCounsel : LobbyMsgHandler
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqCounseledBefore req = await ReadData<ReqCounseledBefore>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResCounseledBefore response = new();
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace EpinelPS.LobbyServer.Character
|
||||
// Get all character data from the game's character table
|
||||
List<CharacterRecord> fullchardata = [.. GameData.Instance.CharacterTable.Values];
|
||||
|
||||
Database.Character targetCharacter = user.GetCharacterBySerialNumber(req.Csn) ?? throw new NullReferenceException();
|
||||
CharacterModel targetCharacter = user.GetCharacterBySerialNumber(req.Csn) ?? throw new NullReferenceException();
|
||||
|
||||
// Find the element with the current csn from the request
|
||||
CharacterRecord currentCharacter = fullchardata.FirstOrDefault(c => c.id == targetCharacter.Tid) ?? throw new NullReferenceException();
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Character
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetAttractiveList req = await ReadData<ReqGetAttractiveList>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetAttractiveList response = new()
|
||||
{
|
||||
|
||||
@@ -8,17 +8,17 @@ namespace EpinelPS.LobbyServer.Character
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetCharacterData req = await ReadData<ReqGetCharacterData>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetCharacterData response = new();
|
||||
foreach (Database.Character item in user.Characters)
|
||||
foreach (CharacterModel item in user.Characters)
|
||||
{
|
||||
response.Character.Add(new NetUserCharacterData() { Default = new() { Csn = item.Csn, Skill1Lv = item.Skill1Lvl, Skill2Lv = item.Skill2Lvl, CostumeId = item.CostumeId, Lv = user.GetCharacterLevel(item.Csn, item.Level), Grade = item.Grade, Tid = item.Tid, UltiSkillLv = item.UltimateLevel }, IsSynchro = user.GetSynchro(item.Csn) });
|
||||
}
|
||||
|
||||
List<Database.Character> highestLevelCharacters = [.. user.Characters.OrderByDescending(x => x.Level).Take(5)];
|
||||
List<CharacterModel> highestLevelCharacters = [.. user.Characters.OrderByDescending(x => x.Level).Take(5)];
|
||||
|
||||
foreach (Database.Character? c in highestLevelCharacters)
|
||||
foreach (CharacterModel? c in highestLevelCharacters)
|
||||
{
|
||||
response.SynchroStandardCharacters.Add(c.Csn);
|
||||
}
|
||||
|
||||
@@ -23,14 +23,14 @@ namespace EpinelPS.LobbyServer.Character
|
||||
];
|
||||
}
|
||||
|
||||
List<Database.Character> highestLevelCharacters = [.. user.Characters.OrderByDescending(x => x.Level).Take(5)];
|
||||
List<CharacterModel> highestLevelCharacters = [.. user.Characters.OrderByDescending(x => x.Level).Take(5)];
|
||||
|
||||
ResGetSynchroData response = new()
|
||||
{
|
||||
Synchro = new NetUserSynchroData()
|
||||
};
|
||||
|
||||
foreach (Database.Character? item in highestLevelCharacters)
|
||||
foreach (CharacterModel? item in highestLevelCharacters)
|
||||
{
|
||||
response.Synchro.StandardCharacters.Add(new NetUserCharacterData() { Default = new() { Csn = item.Csn, Skill1Lv = item.Skill1Lvl, Skill2Lv = item.Skill2Lvl, CostumeId = item.CostumeId, Lv = item.Level, Grade = item.Grade, Tid = item.Tid, UltiSkillLv = item.UltimateLevel }, IsSynchro = user.GetSynchro(item.Csn) });
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace EpinelPS.LobbyServer.Character
|
||||
ResCharacterLevelUp response = new();
|
||||
Dictionary<int, CharacterLevelData> data = GameData.Instance.GetCharacterLevelUpData();
|
||||
|
||||
foreach (Database.Character item in user.Characters.ToArray())
|
||||
foreach (CharacterModel item in user.Characters.ToArray())
|
||||
{
|
||||
if (item.Csn == req.Csn)
|
||||
{
|
||||
@@ -55,11 +55,11 @@ namespace EpinelPS.LobbyServer.Character
|
||||
Grade = item.Grade,
|
||||
Tid = item.Tid
|
||||
};
|
||||
List<Database.Character> highestLevelCharacters = [.. user.Characters.OrderByDescending(x => x.Level).Take(5)];
|
||||
List<CharacterModel> highestLevelCharacters = [.. user.Characters.OrderByDescending(x => x.Level).Take(5)];
|
||||
|
||||
response.SynchroLv = user.GetSynchroLevel();
|
||||
|
||||
foreach (Database.Character? c in highestLevelCharacters)
|
||||
foreach (CharacterModel? c in highestLevelCharacters)
|
||||
{
|
||||
response.SynchroStandardCharacters.Add(c.Csn);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace EpinelPS.LobbyServer.Character
|
||||
{
|
||||
ReqSynchroRegister req = await ReadData<ReqSynchroRegister>();
|
||||
User user = GetUser();
|
||||
Database.Character? targetCharacter = user.GetCharacterBySerialNumber(req.Csn) ?? throw new Exception("target character does not exist");
|
||||
CharacterModel? targetCharacter = user.GetCharacterBySerialNumber(req.Csn) ?? throw new Exception("target character does not exist");
|
||||
ResSynchroRegister response = new();
|
||||
foreach (SynchroSlot item in user.SynchroSlots)
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace EpinelPS.LobbyServer.Character
|
||||
ResCharacterGrowReset response = new();
|
||||
Dictionary<int, CharacterLevelData> data = GameData.Instance.GetCharacterLevelUpData();
|
||||
|
||||
foreach (Database.Character item in user.Characters.ToArray())
|
||||
foreach (CharacterModel item in user.Characters.ToArray())
|
||||
{
|
||||
if (item.Csn == req.Csn)
|
||||
{
|
||||
@@ -56,11 +56,11 @@ namespace EpinelPS.LobbyServer.Character
|
||||
Grade = item.Grade,
|
||||
Tid = item.Tid
|
||||
};
|
||||
List<Database.Character> highestLevelCharacters = [.. user.Characters.OrderByDescending(x => x.Level).Take(5)];
|
||||
List<CharacterModel> highestLevelCharacters = [.. user.Characters.OrderByDescending(x => x.Level).Take(5)];
|
||||
|
||||
response.SynchroLv = highestLevelCharacters.Last().Level;
|
||||
|
||||
foreach (Database.Character? c in highestLevelCharacters)
|
||||
foreach (CharacterModel? c in highestLevelCharacters)
|
||||
{
|
||||
response.SynchroStandardCharacters.Add(c.Csn);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace EpinelPS.LobbyServer.Character
|
||||
ReqSetCharacterCostume req = await ReadData<ReqSetCharacterCostume>();
|
||||
User user = GetUser();
|
||||
|
||||
foreach (Database.Character item in user.Characters)
|
||||
foreach (CharacterModel item in user.Characters)
|
||||
{
|
||||
if (item.Csn == req.Csn)
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace EpinelPS.LobbyServer.Character
|
||||
User user = GetUser();
|
||||
ResCharacterSkillLevelUp response = new();
|
||||
|
||||
Database.Character character = user.Characters.FirstOrDefault(c => c.Csn == req.Csn) ?? throw new Exception("cannot find character");
|
||||
CharacterModel character = user.Characters.FirstOrDefault(c => c.Csn == req.Csn) ?? throw new Exception("cannot find character");
|
||||
|
||||
CharacterRecord charRecord = GameData.Instance.CharacterTable.Values.FirstOrDefault(c => c.id == character.Tid) ?? throw new Exception("cannot find character record");
|
||||
Dictionary<int, int> skillIdMap = new()
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace EpinelPS.LobbyServer.Character
|
||||
{
|
||||
long oldCSN = item.CharacterSerialNumber;
|
||||
item.CharacterSerialNumber = 0;
|
||||
Database.Character data = user.GetCharacterBySerialNumber(oldCSN) ?? throw new Exception("failed to lookup character");
|
||||
CharacterModel data = user.GetCharacterBySerialNumber(oldCSN) ?? throw new Exception("failed to lookup character");
|
||||
|
||||
response.Character = new NetUserCharacterDefaultData()
|
||||
{
|
||||
@@ -41,10 +41,10 @@ namespace EpinelPS.LobbyServer.Character
|
||||
response.Slot = new NetSynchroSlot() { AvailableRegisterAt = item.AvailableAt, Csn = item.CharacterSerialNumber, Slot = item.Slot };
|
||||
|
||||
response.IsSynchro = false;
|
||||
List<Database.Character> highestLevelCharacters = [.. user.Characters.OrderByDescending(x => x.Level).Take(5)];
|
||||
List<CharacterModel> highestLevelCharacters = [.. user.Characters.OrderByDescending(x => x.Level).Take(5)];
|
||||
|
||||
|
||||
foreach (Database.Character? item2 in highestLevelCharacters)
|
||||
foreach (CharacterModel? item2 in highestLevelCharacters)
|
||||
{
|
||||
response.SynchroStandardCharacters.Add(item2.Csn);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace EpinelPS.LobbyServer.Character
|
||||
// Get all character data from the game's character table
|
||||
List<CharacterRecord> fullchardata = [.. GameData.Instance.CharacterTable.Values];
|
||||
|
||||
Database.Character targetCharacter = user.GetCharacterBySerialNumber(req.Csn) ?? throw new NullReferenceException();
|
||||
CharacterModel targetCharacter = user.GetCharacterBySerialNumber(req.Csn) ?? throw new NullReferenceException();
|
||||
|
||||
// Find the element with the current csn from the request
|
||||
CharacterRecord? currentCharacter = fullchardata.FirstOrDefault(c => c.id == targetCharacter.Tid);
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Event.CollectSystem
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqListFieldEventCollectData req = await ReadData<ReqListFieldEventCollectData>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResListFieldEventCollectData response = new();
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Event.Field
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqListFieldPasswordDoorData req = await ReadData<ReqListFieldPasswordDoorData>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResListFieldPasswordDoorData response = new();
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Event
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqChallengeEventStageData req = await ReadData<ReqChallengeEventStageData>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResChallengeEventStageData response = new()
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
using EpinelPS.Utils;
|
||||
using EpinelPS.Data; // For GameData access
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Event.Minigame.CE002
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetMiniGameCe002Data req = await ReadData<ReqGetMiniGameCe002Data>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetMiniGameCe002Data response = new()
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Event.Minigame.CE006
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetStellarBladeStatistics req = await ReadData<ReqGetStellarBladeStatistics>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetStellarBladeStatistics response = new();
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Event.Shop
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqShopProductList req = await ReadData<ReqShopProductList>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResShopProductList response = new();
|
||||
response.Shops.Add(new NetShopProductData()
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using EpinelPS.Utils;
|
||||
using EpinelPS.Database;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Event.StoryEvent
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace EpinelPS.LobbyServer.FavoriteItem
|
||||
ReqGetFavoriteItemLibrary req = await ReadData<ReqGetFavoriteItemLibrary>();
|
||||
|
||||
ResGetFavoriteItemLibrary response = new();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
|
||||
await WriteDataAsync(response);
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.FavoriteItem
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqListFavoriteItem req = await ReadData<ReqListFavoriteItem>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResListFavoriteItem response = new();
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.FavoriteItem
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqListFavoriteItemQuest req = await ReadData<ReqListFavoriteItemQuest>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResListFavoriteItemQuest response = new();
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace EpinelPS.LobbyServer.Gacha
|
||||
|
||||
if (user.HasCharacter(characterData.id))
|
||||
{
|
||||
Database.Character character = user.GetCharacter(characterData.id) ?? throw new Exception("HasCharacter() returned true, however character was null");
|
||||
CharacterModel character = user.GetCharacter(characterData.id) ?? throw new Exception("HasCharacter() returned true, however character was null");
|
||||
|
||||
ItemData? existingItem = user.Items.FirstOrDefault(item => item.ItemType == characterData.piece_id);
|
||||
|
||||
@@ -200,7 +200,7 @@ namespace EpinelPS.LobbyServer.Gacha
|
||||
UltiSkillLv = 1
|
||||
});
|
||||
|
||||
user.Characters.Add(new Database.Character()
|
||||
user.Characters.Add(new CharacterModel()
|
||||
{
|
||||
CostumeId = 0,
|
||||
Csn = (int)gacha.Sn,
|
||||
|
||||
@@ -146,7 +146,7 @@ namespace EpinelPS.LobbyServer.Gacha
|
||||
UltiSkillLv = 1
|
||||
});
|
||||
|
||||
user.Characters.Add(new Database.Character()
|
||||
user.Characters.Add(new CharacterModel()
|
||||
{
|
||||
CostumeId = 0,
|
||||
Csn = id,
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace EpinelPS.LobbyServer
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetGachaData req = await ReadData<ReqGetGachaData>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetGachaData response = new();
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Intercept
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqEnterIntercept req = await ReadData<ReqEnterIntercept>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResEnterIntercept response = new();
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@ namespace EpinelPS.LobbyServer.Inventory
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetInventoryData req = await ReadData<ReqGetInventoryData>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetInventoryData response = new();
|
||||
foreach (Database.ItemData item in user.Items)
|
||||
foreach (ItemData 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 });
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace EpinelPS.LobbyServer.Inventory
|
||||
{
|
||||
ItemData? spareItem = user.Items.FirstOrDefault(i => i.ItemType == character.piece_id);
|
||||
|
||||
if (user.GetCharacter(character.id) is Database.Character ownedCharacter)
|
||||
if (user.GetCharacter(character.id) is CharacterModel ownedCharacter)
|
||||
{
|
||||
// If the character already exists, we can increase its piece count
|
||||
int maxLimitBroken = GetValueByRarity(character.original_rare, 0, 2, 11);
|
||||
@@ -104,7 +104,7 @@ namespace EpinelPS.LobbyServer.Inventory
|
||||
Csn = user.GenerateUniqueCharacterId(),
|
||||
Tid = character.id,
|
||||
});
|
||||
user.Characters.Add(new Database.Character
|
||||
user.Characters.Add(new CharacterModel
|
||||
{
|
||||
CostumeId = 0,
|
||||
Csn = csn,
|
||||
@@ -194,7 +194,7 @@ namespace EpinelPS.LobbyServer.Inventory
|
||||
_ => throw new Exception($"Unknown character rarity: {rarity}")
|
||||
};
|
||||
|
||||
private NetCharacterData GetNetCharacterData(Database.Character character, int bodyLabel = 0)
|
||||
private NetCharacterData GetNetCharacterData(CharacterModel character, int bodyLabel = 0)
|
||||
{
|
||||
return new NetCharacterData
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Liberate
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqChooseLiberateCharacter req = await ReadData<ReqChooseLiberateCharacter>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResChooseLiberateCharacter response = new()
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Liberate
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetLiberateData req = await ReadData<ReqGetLiberateData>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetLiberateData response = new() { };
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Liberate
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetLiberateProgressList req = await ReadData<ReqGetLiberateProgressList>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetLiberateProgressList response = new();
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.LobbyUser
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqAcquireUserTitle req = await ReadData<ReqAcquireUserTitle>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResAcquireUserTitle response = new();
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace EpinelPS.LobbyServer.LobbyUser
|
||||
response.Currency.Add(new NetUserCurrencyData() { Type = (int)item.Key, Value = item.Value });
|
||||
}
|
||||
|
||||
foreach (Database.Character item in user.Characters)
|
||||
foreach (CharacterModel item in user.Characters)
|
||||
{
|
||||
response.Character.Add(new NetUserCharacterData() { Default = new() { Csn = item.Csn, Skill1Lv = item.Skill1Lvl, Skill2Lv = item.Skill2Lvl, CostumeId = item.CostumeId, Lv = user.GetCharacterLevel(item.Csn, item.Level), Grade = item.Grade, Tid = item.Tid, UltiSkillLv = item.UltimateLevel}, IsSynchro = user.GetSynchro(item.Csn) });
|
||||
}
|
||||
@@ -49,10 +49,10 @@ namespace EpinelPS.LobbyServer.LobbyUser
|
||||
// Add squad data if there are characters
|
||||
if (user.Characters.Count > 0)
|
||||
{
|
||||
List<Database.Character> highestLevelCharacters = [.. user.Characters.OrderByDescending(x => x.Level).Take(5)];
|
||||
List<CharacterModel> highestLevelCharacters = [.. user.Characters.OrderByDescending(x => x.Level).Take(5)];
|
||||
response.SynchroLv = user.GetSynchroLevel();
|
||||
|
||||
foreach (Database.Character? item in highestLevelCharacters)
|
||||
foreach (CharacterModel? item in highestLevelCharacters)
|
||||
{
|
||||
response.SynchroStandardCharacters.Add(item.Csn);
|
||||
}
|
||||
|
||||
@@ -8,14 +8,14 @@ namespace EpinelPS.LobbyServer.LobbyUser
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetContentsOpenData req = await ReadData<ReqGetContentsOpenData>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
// this request returns a list of "special" stages that mark when something is unlocked, ex: the shop or interception
|
||||
|
||||
List<int> specialStages = [6003003, 6002008, 6002016, 6005003, 6003021, 6011018, 6007021, 6004018, 6005013, 6003009, 6003012, 6009017, 6016039, 6001004, 6000003, 6000001, 6002001, 6004023, 6005026, 6020050, 6006004, 6006023,6022049];
|
||||
|
||||
ResGetContentsOpenData response = new();
|
||||
foreach (Database.FieldInfoNew field in user.FieldInfoNew.Values)
|
||||
foreach (FieldInfoNew field in user.FieldInfoNew.Values)
|
||||
{
|
||||
foreach (int stage in field.CompletedStages)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.LobbyUser
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetFieldTalkList req = await ReadData<ReqGetFieldTalkList>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetFieldTalkList response = new();
|
||||
// TODO
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.LobbyUser
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetScenarioList req = await ReadData<ReqGetScenarioList>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
// todo what are bookmark scenarios?
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ namespace EpinelPS.LobbyServer.LobbyUser
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetProfileData req = await ReadData<ReqGetProfileData>();
|
||||
Database.User callingUser = GetUser();
|
||||
Database.User? user = GetUser((ulong)req.TargetUsn);
|
||||
User callingUser = GetUser();
|
||||
User? user = GetUser((ulong)req.TargetUsn);
|
||||
ResGetProfileData response = new();
|
||||
|
||||
if (user != null)
|
||||
@@ -28,7 +28,7 @@ namespace EpinelPS.LobbyServer.LobbyUser
|
||||
for (int i = 0; i < user.RepresentationTeamDataNew.Length; i++)
|
||||
{
|
||||
long csn = user.RepresentationTeamDataNew[i];
|
||||
Database.Character? c = user.GetCharacterBySerialNumber(csn);
|
||||
CharacterModel? c = user.GetCharacterBySerialNumber(csn);
|
||||
|
||||
if (c != null)
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace EpinelPS.LobbyServer.LobbyUser
|
||||
|
||||
ResExistScenario response = new();
|
||||
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
foreach (string? item in req.ScenarioGroupIds)
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace EpinelPS.LobbyServer.LobbyUser
|
||||
{
|
||||
ReqGetWallpaper req = await ReadData<ReqGetWallpaper>();
|
||||
ResGetWallpaper response = new();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
|
||||
response.WallpaperList.AddRange(user.WallpaperList);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using EpinelPS.Utils;
|
||||
using EpinelPS.Data; // For GameData access
|
||||
|
||||
namespace EpinelPS.LobbyServer.LobbyUser
|
||||
{
|
||||
@@ -10,7 +9,7 @@ namespace EpinelPS.LobbyServer.LobbyUser
|
||||
{
|
||||
ReqRecordNoticeLog req = await ReadData<ReqRecordNoticeLog>();
|
||||
ResRecordNoticeLog r = new();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
// TODO
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.LobbyUser
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqUnMarkUserTitleBadge req = await ReadData<ReqUnMarkUserTitleBadge>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResUnMarkUserTitleBadge response = new();
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ namespace EpinelPS.LobbyServer.Lostsector
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetLostSectorFieldData req = await ReadData<ReqGetLostSectorFieldData>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
Database.LostSectorData f = user.LostSectorData[req.SectorId];
|
||||
LostSectorData f = user.LostSectorData[req.SectorId];
|
||||
ResGetLostSectorFieldData response = new()
|
||||
{
|
||||
Field = new NetFieldObjectData(),
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace EpinelPS.LobbyServer.Lostsector
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetLostSectorData req = await ReadData<ReqGetLostSectorData>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetLostSectorData response = new();
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace EpinelPS.LobbyServer.Lostsector
|
||||
response.ClearStages.Add(new NetFieldStageData() { StageId = item.Value.open_condition_value });
|
||||
}
|
||||
|
||||
if (user.LostSectorData.TryGetValue(item.Key, out Database.LostSectorData? val))
|
||||
if (user.LostSectorData.TryGetValue(item.Key, out LostSectorData? val))
|
||||
{
|
||||
MapInfo map = GameData.Instance.MapData[item.Value.field_id];
|
||||
response.LostSector.Add(new NetUserLostSectorData()
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace EpinelPS.LobbyServer.Lostsector
|
||||
ResPlayLostSector response = new();
|
||||
|
||||
if (!user.LostSectorData.ContainsKey(req.SectorId))
|
||||
user.LostSectorData.Add(req.SectorId, new Database.LostSectorData()
|
||||
user.LostSectorData.Add(req.SectorId, new LostSectorData()
|
||||
{
|
||||
IsPlaying = true
|
||||
});
|
||||
|
||||
@@ -8,12 +8,12 @@ namespace EpinelPS.LobbyServer.Lostsector
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqSaveLostSectorField req = await ReadData<ReqSaveLostSectorField>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResSaveLostSectorField response = new();
|
||||
|
||||
if (!user.LostSectorData.TryGetValue(req.SectorId, out Database.LostSectorData? value))
|
||||
user.LostSectorData.Add(req.SectorId, new Database.LostSectorData()
|
||||
if (!user.LostSectorData.TryGetValue(req.SectorId, out LostSectorData? value))
|
||||
user.LostSectorData.Add(req.SectorId, new LostSectorData()
|
||||
{
|
||||
Json = req.Json
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Lostsector
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqSaveLostSectorFieldObject req = await ReadData<ReqSaveLostSectorFieldObject>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResSaveLostSectorFieldObject response = new();
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Messenger
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Minigame.nksv2
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetNKSV2Scenario req = await ReadData<ReqGetNKSV2Scenario>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetNKSV2Scenario response = new();
|
||||
response.ScenarioIdList.Add(user.MogInfo.CompletedScenarios);
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Misc
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGachaGetAllShutdownFlags req = await ReadData<ReqGachaGetAllShutdownFlags>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGachaGetAllShutdownFlags response = new();
|
||||
if (user.GachaTutorialPlayCount > 0)
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Misc
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqUserOnlineStateLog req = await ReadData<ReqUserOnlineStateLog>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResUserOnlineStateLog response = new();
|
||||
user.LastLogin = DateTime.UtcNow;
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace EpinelPS.LobbyServer.Misc
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqRetroactive req = await ReadData<ReqRetroactive>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResRetroactive response = new();
|
||||
await WriteDataAsync(response);
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Mission
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
await ReadData<ReqGetAchievementRewardedData>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetAchievementRewardedData response = new();
|
||||
response.Ids.AddRange(user.CompletedAchievements);
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Mission
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetRewardedData req = await ReadData<ReqGetRewardedData>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetRewardedData response = new();
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Mission.Rewards
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
await ReadData<ReqGetDailyRewardedData>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
user.ResetDataIfNeeded();
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Mission.Rewards
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
await ReadData<ReqGetWeeklyRewardedData>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
user.ResetDataIfNeeded();
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace EpinelPS.LobbyServer.Outpost
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
|
||||
private static void ProcessLessonReward(Database.User user, TacticAcademyLessonRecord r)
|
||||
private static void ProcessLessonReward(User user, TacticAcademyLessonRecord r)
|
||||
{
|
||||
if (r.lesson_reward == null)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using EpinelPS.Utils;
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Data;
|
||||
namespace EpinelPS.LobbyServer.Outpost
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Outpost
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Outpost
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetTacticAcademyData req = await ReadData<ReqGetTacticAcademyData>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetTacticAcademyData response = new();
|
||||
response.ClearLessons.AddRange(user.CompletedTacticAcademyLessons);
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Outpost
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetMemoryList req = await ReadData<ReqGetMemoryList>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetMemoryList response = new();
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Outpost
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqBuildingIsDone req = await ReadData<ReqBuildingIsDone>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResBuildingIsDone response = new();
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Outpost
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.PartyMatch
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqListInvitation req = await ReadData<ReqListInvitation>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResListInvitation response = new();
|
||||
// TODO
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Sidestory
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqClearSideStoryCutForBattle req = await ReadData<ReqClearSideStoryCutForBattle>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResClearSideStoryCutForBattle response = new();
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Sidestory
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqClearSideStoryCutForScenario req = await ReadData<ReqClearSideStoryCutForScenario>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResClearSideStoryCutForScenario response = new();
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Sidestory
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqEnterSideStoryCutForBattle req = await ReadData<ReqEnterSideStoryCutForBattle>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResEnterSideStoryCutForBattle response = new();
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Sidestory
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqEnterSideStoryStage req = await ReadData<ReqEnterSideStoryStage>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResEnterSideStoryStage response = new();
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace EpinelPS.LobbyServer.Sidestory
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqListSideStory req = await ReadData<ReqListSideStory>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResListSideStory response = new();
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace EpinelPS.LobbyServer.Simroom
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetSimRoom req = await ReadData<ReqGetSimRoom>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetSimRoom response = new()
|
||||
{
|
||||
|
||||
@@ -10,9 +10,9 @@ namespace EpinelPS.LobbyServer.Stage
|
||||
ReqCheckStageClear req = await ReadData<ReqCheckStageClear>();
|
||||
|
||||
ResCheckStageClear response = new();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
foreach (KeyValuePair<string, Database.FieldInfoNew> fields in user.FieldInfoNew)
|
||||
foreach (KeyValuePair<string, FieldInfoNew> fields in user.FieldInfoNew)
|
||||
{
|
||||
foreach (int stages in fields.Value.CompletedStages)
|
||||
{
|
||||
|
||||
@@ -170,11 +170,11 @@ namespace EpinelPS.LobbyServer.Stage
|
||||
LastContentsTeamNumber = 1
|
||||
};
|
||||
|
||||
user.Characters.Add(new Database.Character() { Csn = 47263455, Tid = 201001 });
|
||||
user.Characters.Add(new Database.Character() { Csn = 47273456, Tid = 330501 });
|
||||
user.Characters.Add(new Database.Character() { Csn = 47263457, Tid = 130201 });
|
||||
user.Characters.Add(new Database.Character() { Csn = 47263458, Tid = 230101 });
|
||||
user.Characters.Add(new Database.Character() { Csn = 47263459, Tid = 301201 });
|
||||
user.Characters.Add(new CharacterModel() { Csn = 47263455, Tid = 201001 });
|
||||
user.Characters.Add(new CharacterModel() { Csn = 47273456, Tid = 330501 });
|
||||
user.Characters.Add(new CharacterModel() { Csn = 47263457, Tid = 130201 });
|
||||
user.Characters.Add(new CharacterModel() { Csn = 47263458, Tid = 230101 });
|
||||
user.Characters.Add(new CharacterModel() { Csn = 47263459, Tid = 301201 });
|
||||
|
||||
user.BondInfo.Add(new() { NameCode = 3001, Lv = 1 });
|
||||
user.BondInfo.Add(new() { NameCode = 3005, Lv = 1 });
|
||||
@@ -193,7 +193,7 @@ namespace EpinelPS.LobbyServer.Stage
|
||||
|
||||
for (int i = 1; i < 6; i++)
|
||||
{
|
||||
Database.Character character = user.Characters[i - 1];
|
||||
CharacterModel character = user.Characters[i - 1];
|
||||
team1Sub.Slots.Add(new NetTeamSlot() { Slot = i, Value = character.Csn });
|
||||
}
|
||||
team1.Teams.Add(team1Sub);
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace EpinelPS.LobbyServer.Stage
|
||||
{
|
||||
ReqFastClearCampaignStage req = await ReadData<ReqFastClearCampaignStage>();
|
||||
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
Console.WriteLine($"Stage " + req.CampaignStageId + " completed using quick battle");
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace EpinelPS.LobbyServer.Stage
|
||||
{
|
||||
ReqGetStageClearInfo req = await ReadData<ReqGetStageClearInfo>();
|
||||
ResGetStageClearInfo response = new();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
response.Historys.AddRange(user.StageClearHistorys);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Subquest
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetSubQuestList req = await ReadData<ReqGetSubQuestList>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetSubQuestList response = new();
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Team
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetTeamData req = await ReadData<ReqGetTeamData>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetTeamData response = new();
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace EpinelPS.LobbyServer.Tower
|
||||
|
||||
ResGetTowerData response = new();
|
||||
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
// TODO: Load remain count for these
|
||||
NetTowerData t0 = new() { Type = 1, RemainCount = 3 };
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace EpinelPS.LobbyServer.Trigger
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetMainQuestData req = await ReadData<ReqGetMainQuestData>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetMainQuestData response = new();
|
||||
foreach (KeyValuePair<int, bool> item in user.MainQuestData)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Trigger
|
||||
{
|
||||
@@ -25,11 +24,11 @@ namespace EpinelPS.LobbyServer.Trigger
|
||||
Console.WriteLine("needs " + req.Seq);
|
||||
|
||||
// Look for triggers past that amount
|
||||
Database.Trigger[] newTriggers = [.. user.Triggers.Where(x => x.Id > req.Seq)];
|
||||
TriggerModel[] newTriggers = [.. user.Triggers.Where(x => x.Id > req.Seq)];
|
||||
|
||||
// Return all triggers
|
||||
int triggerCount = 0;
|
||||
foreach (Database.Trigger? item in newTriggers)
|
||||
foreach (TriggerModel item in newTriggers)
|
||||
{
|
||||
triggerCount++;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace EpinelPS.LobbyServer.Wallet
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqGetCurrencyData req = await ReadData<ReqGetCurrencyData>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResGetCurrencyData response = new();
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace EpinelPS.LobbyServer.Wallet
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
ReqRefreshChargeCurrencyData req = await ReadData<ReqRefreshChargeCurrencyData>();
|
||||
Database.User user = GetUser();
|
||||
User user = GetUser();
|
||||
|
||||
ResRefreshChargeCurrencyData response = new()
|
||||
{
|
||||
|
||||
18
EpinelPS/Models/CoreInfoModel.cs
Normal file
18
EpinelPS/Models/CoreInfoModel.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.Models;
|
||||
public class CoreInfo
|
||||
{
|
||||
public int DbVersion = 3;
|
||||
public List<User> Users = [];
|
||||
|
||||
public List<AccessToken> LauncherAccessTokens = [];
|
||||
public Dictionary<string, ulong> AdminAuthTokens = [];
|
||||
|
||||
public byte[] LauncherTokenKey = [];
|
||||
public byte[] EncryptionTokenKey = [];
|
||||
public LogType LogLevel = LogType.Debug;
|
||||
|
||||
public int MaxInterceptionCount = 3;
|
||||
public int ResetHourUtcTime = 20;
|
||||
}
|
||||
244
EpinelPS/Models/DbModels.cs
Normal file
244
EpinelPS/Models/DbModels.cs
Normal file
@@ -0,0 +1,244 @@
|
||||
using System.Globalization;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using EpinelPS.Data;
|
||||
using EpinelPS.Utils;
|
||||
using Google.Protobuf;
|
||||
using Paseto;
|
||||
using Paseto.Builder;
|
||||
|
||||
namespace EpinelPS.Models
|
||||
{
|
||||
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 CharacterModel
|
||||
{
|
||||
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 = [];
|
||||
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 RecycleRoomResearchProgress
|
||||
{
|
||||
public int Level = 1;
|
||||
public int Exp;
|
||||
public int Attack;
|
||||
public int Defense;
|
||||
public int Hp;
|
||||
}
|
||||
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 = [];
|
||||
public List<int> CoreDustPercentages = [];
|
||||
public List<int> BattleDataPercentages = [];
|
||||
public List<int> UserExpPercentages = [];
|
||||
|
||||
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 BadgeModel
|
||||
{
|
||||
public string Location = "";
|
||||
public long Seq;
|
||||
public BadgeContents BadgeContent;
|
||||
public string BadgeGuid = "";
|
||||
|
||||
public BadgeModel() { }
|
||||
public BadgeModel(NetBadge badge)
|
||||
{
|
||||
Location = badge.Location;
|
||||
Seq = badge.Seq;
|
||||
BadgeContent = badge.BadgeContent;
|
||||
BadgeGuid = new Guid([.. badge.BadgeGuid]).ToString();
|
||||
}
|
||||
|
||||
public NetBadge ToNet()
|
||||
{
|
||||
return new NetBadge()
|
||||
{
|
||||
BadgeContent = BadgeContent,
|
||||
BadgeGuid = ByteString.CopyFrom(new Guid(BadgeGuid).ToByteArray()),
|
||||
Location = Location,
|
||||
Seq = Seq
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class TriggerModel
|
||||
{
|
||||
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 LostSectorData
|
||||
{
|
||||
public bool IsOpen { get; set; }
|
||||
public bool IsPlaying { get; set; }
|
||||
public string Json { get; set; } = "";
|
||||
public Dictionary<string, NetLostSectorFieldObject> Objects { get; set; } = [];
|
||||
public Dictionary<string, int> ClearedStages { get; set; } = [];
|
||||
public List<NetLostSectorTeamPosition> TeamPositions { get; set; } = [];
|
||||
public int ObtainedRewards { get; set; } = 0;
|
||||
public bool RecievedFinalReward { get; set; }
|
||||
public bool CompletedPerfectly { get; set; }
|
||||
}
|
||||
}
|
||||
396
EpinelPS/Models/UserModel.cs
Normal file
396
EpinelPS/Models/UserModel.cs
Normal file
@@ -0,0 +1,396 @@
|
||||
using EpinelPS.Data;
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.Models;
|
||||
|
||||
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;
|
||||
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;
|
||||
public DateTime LastReset = DateTime.MinValue;
|
||||
|
||||
// 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 = [];
|
||||
public bool SynchroDeviceUpgraded = false;
|
||||
public int SynchroDeviceLevel = 200;
|
||||
public Dictionary<int, RecycleRoomResearchProgress> ResearchProgress = [];
|
||||
|
||||
public ResetableData ResetableData = new();
|
||||
public WeeklyResetableData WeeklyResetableData = new();
|
||||
public List<ItemData> Items = [];
|
||||
public List<CharacterModel> Characters = [];
|
||||
public long[] RepresentationTeamDataNew = [];
|
||||
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 = [];
|
||||
public Dictionary<int, bool> MainQuestData = [];
|
||||
public Dictionary<int, bool> SubQuestData = [];
|
||||
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 = [];
|
||||
|
||||
public List<int> Memorial = [];
|
||||
public List<int> JukeboxBgm = [];
|
||||
|
||||
public Dictionary<int, int> TowerProgress = [];
|
||||
|
||||
public JukeBoxSetting LobbyMusic = new() { Location = NetJukeboxLocation.Lobby, TableId = 2, Type = NetJukeboxBgmType.JukeboxTableId };
|
||||
public JukeBoxSetting CommanderMusic = new() { Location = NetJukeboxLocation.CommanderRoom, TableId = 5, Type = NetJukeboxBgmType.JukeboxTableId };
|
||||
public OutpostBuffs OutpostBuffs = new();
|
||||
public Dictionary<int, UnlockData> ContentsOpenUnlocked = [];
|
||||
|
||||
public List<NetStageClearInfo> StageClearHistorys = [];
|
||||
|
||||
public List<BadgeModel> Badges = [];
|
||||
|
||||
public List<NetUserAttractiveData> BondInfo = [];
|
||||
public List<TriggerModel> Triggers = [];
|
||||
public int LastTriggerId = 1;
|
||||
public List<int> CompletedAchievements = [];
|
||||
public List<NetMessage> MessengerData = [];
|
||||
public ulong LastMessageId = 1;
|
||||
public long LastBadgeSeq = 1;
|
||||
public Dictionary<int, LostSectorData> LostSectorData = [];
|
||||
|
||||
// Event data
|
||||
public Dictionary<int, EventData> EventInfo = [];
|
||||
public MogMinigameInfo MogInfo = new();
|
||||
|
||||
public TriggerModel AddTrigger(TriggerType type, int value, int conditionId = 0)
|
||||
{
|
||||
TriggerModel t = new()
|
||||
{
|
||||
Id = LastTriggerId++,
|
||||
Type = type,
|
||||
ConditionId = conditionId,
|
||||
CreatedAt = DateTime.UtcNow.AddHours(9).Ticks,
|
||||
Value = value
|
||||
};
|
||||
|
||||
Triggers.Add(t);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
public BadgeModel AddBadge(BadgeContents type, string location)
|
||||
{
|
||||
// generate unique badge SEQ
|
||||
|
||||
var badge = new BadgeModel()
|
||||
{
|
||||
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)
|
||||
{
|
||||
foreach (var item in FieldInfoNew)
|
||||
{
|
||||
if (item.Value.CompletedStages.Contains(id))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public long GetCurrencyVal(CurrencyType type)
|
||||
{
|
||||
if (Currency.TryGetValue(type, out long value))
|
||||
return value;
|
||||
else
|
||||
{
|
||||
Currency.Add(type, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
public void AddCurrency(CurrencyType type, long val)
|
||||
{
|
||||
if (!Currency.TryAdd(type, val)) Currency[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 CharacterModel? 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)).FirstOrDefault();
|
||||
|
||||
}
|
||||
else
|
||||
{ // The character with Tid 'c' does not exist in 'characterTable'
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public CharacterModel? GetCharacterBySerialNumber(long value)
|
||||
{
|
||||
if (value == 0) return null;
|
||||
return Characters.Where(x => x.Csn == value).FirstOrDefault();
|
||||
}
|
||||
|
||||
internal bool GetSynchro(long csn)
|
||||
{
|
||||
return SynchroSlots.Where(x => x.CharacterSerialNumber == csn).Any();
|
||||
}
|
||||
internal int GetCharacterLevel(int csn)
|
||||
{
|
||||
var c = GetCharacterBySerialNumber(csn) ?? 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;
|
||||
}
|
||||
|
||||
private bool ShouldResetUser()
|
||||
{
|
||||
var nowLocal = DateTime.UtcNow;
|
||||
|
||||
// Compute the last reset threshold (most recent 2 PM before or at nowLocal)
|
||||
DateTime todayResetTime = new(
|
||||
nowLocal.Year,
|
||||
nowLocal.Month,
|
||||
nowLocal.Day,
|
||||
JsonDb.Instance.ResetHourUtcTime, 0, 0
|
||||
);
|
||||
|
||||
if (nowLocal < todayResetTime)
|
||||
{
|
||||
todayResetTime = todayResetTime.AddDays(-1);
|
||||
}
|
||||
|
||||
// If user's last reset was before the last scheduled 2 PM, they need reset
|
||||
return LastReset < todayResetTime;
|
||||
}
|
||||
|
||||
public void ResetDataIfNeeded()
|
||||
{
|
||||
if (!ShouldResetUser()) return;
|
||||
|
||||
Logging.WriteLine("Resetting user...", LogType.Warning);
|
||||
|
||||
LastReset = DateTime.UtcNow;
|
||||
ResetableData = new();
|
||||
JsonDb.Save();
|
||||
}
|
||||
}
|
||||
@@ -162,7 +162,7 @@ namespace EpinelPS.Utils
|
||||
{
|
||||
if (!user.HasCharacter(character.id))
|
||||
{
|
||||
user.Characters.Add(new Database.Character()
|
||||
user.Characters.Add(new CharacterModel()
|
||||
{
|
||||
CostumeId = 0,
|
||||
Csn = user.GenerateUniqueCharacterId(),
|
||||
@@ -232,7 +232,7 @@ namespace EpinelPS.Utils
|
||||
{
|
||||
if (!(inputGrade >= 0 && inputGrade <= 11)) return new RunCmdResponse() { error = "core level out of range, must be between 0-12" };
|
||||
|
||||
foreach (Character character in user.Characters)
|
||||
foreach (CharacterModel character in user.Characters)
|
||||
{
|
||||
// Get current character's Tid
|
||||
int tid = character.Tid;
|
||||
@@ -310,7 +310,7 @@ namespace EpinelPS.Utils
|
||||
public static RunCmdResponse SetCharacterLevel(User user, int level)
|
||||
{
|
||||
if (level > 999 || level <= 0) return new RunCmdResponse() { error = "level must be between 1-999" };
|
||||
foreach (Character character in user.Characters)
|
||||
foreach (CharacterModel character in user.Characters)
|
||||
{
|
||||
character.Level = level;
|
||||
}
|
||||
@@ -322,7 +322,7 @@ namespace EpinelPS.Utils
|
||||
public static RunCmdResponse SetSkillLevel(User user, int skillLevel)
|
||||
{
|
||||
if (skillLevel > 10 || skillLevel < 0) return new RunCmdResponse() { error = "level must be between 1-10" };
|
||||
foreach (Character character in user.Characters)
|
||||
foreach (CharacterModel character in user.Characters)
|
||||
{
|
||||
character.UltimateLevel = skillLevel;
|
||||
character.Skill1Lvl = skillLevel;
|
||||
@@ -337,7 +337,7 @@ namespace EpinelPS.Utils
|
||||
{
|
||||
if (!user.HasCharacter(characterId))
|
||||
{
|
||||
user.Characters.Add(new Database.Character()
|
||||
user.Characters.Add(new CharacterModel()
|
||||
{
|
||||
CostumeId = 0,
|
||||
Csn = user.GenerateUniqueCharacterId(),
|
||||
|
||||
@@ -4,9 +4,9 @@ namespace EpinelPS.Utils
|
||||
{
|
||||
public class FormulaUtils
|
||||
{
|
||||
public static int CalculateCP(Database.User user, long csn)
|
||||
public static int CalculateCP(User user, long csn)
|
||||
{
|
||||
Database.Character? character = user.Characters.FirstOrDefault(c => c.Csn == csn);
|
||||
CharacterModel? character = user.Characters.FirstOrDefault(c => c.Csn == csn);
|
||||
if (character == null) return 0;
|
||||
|
||||
CharacterRecord? charRecord = GameData.Instance.CharacterTable.Values.FirstOrDefault(c => c.id == character.Tid);
|
||||
|
||||
@@ -336,7 +336,7 @@ namespace EpinelPS.Utils
|
||||
|
||||
NetWholeTeamSlot result = new();
|
||||
|
||||
Character? c = user.GetCharacterBySerialNumber(csn);
|
||||
CharacterModel? c = user.GetCharacterBySerialNumber(csn);
|
||||
if (c == null) return new() { Slot = slot };
|
||||
|
||||
return new NetWholeTeamSlot()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@model EpinelPS.Database.User
|
||||
@model EpinelPS.Models.User
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Delete user";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@model IEnumerable<EpinelPS.Database.User>
|
||||
@model IEnumerable<EpinelPS.Models.User>
|
||||
@{
|
||||
ViewData["Title"] = "用户管理";
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user