mirror of
https://github.com/EpinelPS/EpinelPS.git
synced 2025-12-12 15:04:36 +01:00
fix character counsel, server reset
This commit is contained in:
@@ -450,10 +450,16 @@ namespace EpinelPS.Data
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// sanity checks
|
||||
if (QuestDataRecords.Count == 0) throw new Exception("QuestDataRecords should not be empty");
|
||||
}
|
||||
|
||||
public MainQuestCompletionRecord? GetMainQuestForStageClearCondition(int stage)
|
||||
{
|
||||
if (QuestDataRecords.Count == 0) throw new Exception("QuestDataRecords should not be empty");
|
||||
foreach (var item in QuestDataRecords)
|
||||
{
|
||||
if (item.Value.condition_id == stage)
|
||||
@@ -581,7 +587,7 @@ namespace EpinelPS.Data
|
||||
|
||||
int chVal = data.chapter_id - 1;
|
||||
|
||||
if (chapterNumber == chVal && data.mod == mod && data.stage_type == StageType.Main)
|
||||
if (chapterNumber == chVal && data.chapter_mod == mod && data.stage_type == StageType.Main)
|
||||
{
|
||||
yield return data.id;
|
||||
}
|
||||
|
||||
@@ -107,22 +107,22 @@ namespace EpinelPS.Data
|
||||
{
|
||||
public int id;
|
||||
public int chapter_id;
|
||||
public ChapterMod mod;
|
||||
public ChapterMod chapter_mod;
|
||||
public int parent_id;
|
||||
public int group_id;
|
||||
public string name = "";
|
||||
public string name_localkey = "";
|
||||
public StageCategory stage_category;
|
||||
public StageType stage_type;
|
||||
public bool allow_autobattle;
|
||||
public bool spot_autocontrol;
|
||||
public int enter_condition;
|
||||
public int monster_stage_level;
|
||||
public int dynobj_stage_level;
|
||||
public int monster_stage_lv;
|
||||
public int dynamic_object_stage_lv;
|
||||
public int standard_battle_power;
|
||||
public int statinc_groupid;
|
||||
public bool allow_quickbattle;
|
||||
public int fieldmonster_id;
|
||||
public int spotid;
|
||||
public int reward_id = 0;
|
||||
public int stage_stat_increase_group_id;
|
||||
public bool is_use_quick_battle;
|
||||
public int field_monster_id;
|
||||
public int spot_id;
|
||||
public int reward_id;
|
||||
public ScenarioType enter_scenario_type;
|
||||
public string enter_scenario = "";
|
||||
public ScenarioType exit_scenario_type;
|
||||
|
||||
@@ -261,6 +261,7 @@ namespace EpinelPS.Database
|
||||
public DateTime BanStart;
|
||||
public DateTime BanEnd;
|
||||
public int BanId = 0;
|
||||
public DateTime LastReset = DateTime.MinValue;
|
||||
|
||||
// Game data
|
||||
public List<string> CompletedScenarios = [];
|
||||
@@ -411,7 +412,6 @@ namespace EpinelPS.Database
|
||||
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;
|
||||
@@ -601,6 +601,38 @@ namespace EpinelPS.Database
|
||||
MessengerData.Add(msg);
|
||||
return msg;
|
||||
}
|
||||
|
||||
private bool ShouldResetUser()
|
||||
{
|
||||
var nowLocal = DateTime.Now;
|
||||
|
||||
// Compute the last reset threshold (most recent 2 PM before or at nowLocal)
|
||||
DateTime todayResetTime = new(
|
||||
nowLocal.Year,
|
||||
nowLocal.Month,
|
||||
nowLocal.Day,
|
||||
JsonDb.Instance.ResetHourLocalTime, 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.Now;
|
||||
ResetableData = new();
|
||||
JsonDb.Save();
|
||||
}
|
||||
}
|
||||
public class CoreInfo
|
||||
{
|
||||
@@ -615,6 +647,7 @@ namespace EpinelPS.Database
|
||||
public LogType LogLevel = LogType.Debug;
|
||||
|
||||
public int MaxInterceptionCount = 3;
|
||||
public int ResetHourLocalTime = 14;
|
||||
}
|
||||
internal class JsonDb
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<SelfContained>true</SelfContained>
|
||||
<IncludeNativeLibrariesForSelfExtract>True</IncludeNativeLibrariesForSelfExtract>
|
||||
<NoWarn>$(NoWarn);SYSLIB0057</NoWarn>
|
||||
<Version>0.134.4.3</Version>
|
||||
<Version>0.135.4.3</Version>
|
||||
<CETCompat>false</CETCompat>
|
||||
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
|
||||
|
||||
|
||||
@@ -45,14 +45,18 @@ namespace EpinelPS.LobbyServer.Auth
|
||||
.Encode();
|
||||
|
||||
|
||||
ResEnterServer response = new();
|
||||
|
||||
response.GameClientToken = token;
|
||||
response.FeatureDataInfo = new NetFeatureDataInfo() { }; // TODO
|
||||
response.Identifier = new NetLegacyUserIdentifier() { Server = 1000, Usn = (long)user.ID };
|
||||
response.ShouldRestartAfter = Duration.FromTimeSpan(TimeSpan.FromSeconds(86400));
|
||||
ResEnterServer response = new()
|
||||
{
|
||||
GameClientToken = token,
|
||||
FeatureDataInfo = new NetFeatureDataInfo() { }, // TODO
|
||||
Identifier = new NetLegacyUserIdentifier() { Server = 1000, Usn = (long)user.ID },
|
||||
ShouldRestartAfter = Duration.FromTimeSpan(TimeSpan.FromSeconds(86400)),
|
||||
|
||||
EncryptionToken = ByteString.CopyFromUtf8(encryptionToken)
|
||||
};
|
||||
|
||||
user.ResetDataIfNeeded();
|
||||
|
||||
response.EncryptionToken = ByteString.CopyFromUtf8(encryptionToken);
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Character
|
||||
{
|
||||
[PacketPath("/character/attractive/counsel")]
|
||||
public class Counsel : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqCharacterCounsel>();
|
||||
var user = GetUser();
|
||||
|
||||
ResCharacterCounsel response = new();
|
||||
response.Attractive = new();
|
||||
response.Exp = new();
|
||||
|
||||
// TODO
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
18
EpinelPS/LobbyServer/Character/Counsel/Check.cs
Normal file
18
EpinelPS/LobbyServer/Character/Counsel/Check.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Character.Counsel;
|
||||
|
||||
[PacketPath("/character/attractive/check")]
|
||||
public class CheckCharacterCounsel : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqCounseledBefore>();
|
||||
var user = GetUser();
|
||||
|
||||
ResCounseledBefore response = new();
|
||||
|
||||
// TODO: Validate response from real server and pull info from user info
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
49
EpinelPS/LobbyServer/Character/Counsel/DoCounsel.cs
Normal file
49
EpinelPS/LobbyServer/Character/Counsel/DoCounsel.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Character.Counsel;
|
||||
|
||||
[PacketPath("/character/attractive/counsel")]
|
||||
public class DoCounsel : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqCharacterCounsel>();
|
||||
var user = GetUser();
|
||||
|
||||
ResCharacterCounsel response = new();
|
||||
|
||||
foreach (var currency in user.Currency)
|
||||
{
|
||||
response.Currencies.Add(new NetUserCurrencyData() { Type = (int)currency.Key, Value = currency.Value });
|
||||
}
|
||||
|
||||
var currentBondInfo = user.BondInfo.Where(x => x.NameCode == req.NameCode);
|
||||
|
||||
NetUserAttractiveData data;
|
||||
|
||||
if (currentBondInfo.Any())
|
||||
{
|
||||
data = currentBondInfo.First();
|
||||
|
||||
// TODO update
|
||||
response.Attractive = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = new()
|
||||
{
|
||||
NameCode = req.NameCode,
|
||||
// TODO
|
||||
};
|
||||
|
||||
response.Attractive = data;
|
||||
user.BondInfo.Add(data);
|
||||
}
|
||||
|
||||
JsonDb.Save();
|
||||
|
||||
// TODO: Validate response from real server and pull info from user info
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,8 @@ namespace EpinelPS.LobbyServer.Event
|
||||
Json = "{}"
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Retrieve collected objects
|
||||
|
||||
if (!user.FieldInfoNew.TryGetValue(req.MapId, out FieldInfoNew? field))
|
||||
|
||||
24
EpinelPS/LobbyServer/Event/Shop/ListProductList.cs
Normal file
24
EpinelPS/LobbyServer/Event/Shop/ListProductList.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Event.Shop
|
||||
{
|
||||
[PacketPath("/event/shopproductlist")]
|
||||
public class ListProductList : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqShopProductList>();
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResShopProductList();
|
||||
response.Shops.Add(new NetShopProductData()
|
||||
{
|
||||
|
||||
});
|
||||
|
||||
// TODO implement properly
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,8 @@ namespace EpinelPS.LobbyServer.Mission
|
||||
{
|
||||
if (user.ResetableData.CompletedDailyMissions.Contains(item))
|
||||
{
|
||||
Console.WriteLine("already completed daily mission");
|
||||
continue;
|
||||
Logging.WriteLine("already completed daily mission", LogType.Warning);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!GameData.Instance.TriggerTable.TryGetValue(item, out TriggerRecord? key)) throw new Exception("unknown TID");
|
||||
|
||||
@@ -10,6 +10,8 @@ namespace EpinelPS.LobbyServer.Mission.Rewards
|
||||
await ReadData<ReqGetDailyRewardedData>();
|
||||
var user = GetUser();
|
||||
|
||||
user.ResetDataIfNeeded();
|
||||
|
||||
var response = new ResGetDailyRewardedData();
|
||||
response.Ids.Add(user.ResetableData.CompletedDailyMissions);
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ namespace EpinelPS.LobbyServer.Mission.Rewards
|
||||
await ReadData<ReqGetWeeklyRewardedData>();
|
||||
var user = GetUser();
|
||||
|
||||
user.ResetDataIfNeeded();
|
||||
|
||||
var response = new ResGetWeeklyRewardedData();
|
||||
response.Ids.Add(user.WeeklyResetableData.CompletedWeeklyMissions);
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace EpinelPS.LobbyServer.Outpost
|
||||
{
|
||||
var req = await ReadData<ReqGetOutpostData>();
|
||||
var user = GetUser();
|
||||
user.ResetDataIfNeeded();
|
||||
|
||||
var battleTime = DateTime.UtcNow - user.BattleTime;
|
||||
var battleTimeMs = (long)(battleTime.TotalNanoseconds / 100);
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace EpinelPS.LobbyServer.Stage
|
||||
var response = new ResClearStage();
|
||||
var clearedStage = GameData.Instance.GetStageData(StageId) ?? throw new Exception("cleared stage cannot be null");
|
||||
|
||||
var stageMapId = GameData.Instance.GetMapIdFromChapter(clearedStage.chapter_id, clearedStage.mod);
|
||||
var stageMapId = GameData.Instance.GetMapIdFromChapter(clearedStage.chapter_id, clearedStage.chapter_mod);
|
||||
|
||||
if (user.FieldInfoNew.Count == 0)
|
||||
{
|
||||
@@ -91,7 +91,7 @@ namespace EpinelPS.LobbyServer.Stage
|
||||
|
||||
if (clearedStage.stage_category == StageCategory.Normal || clearedStage.stage_category == StageCategory.Boss || clearedStage.stage_category == StageCategory.Hard)
|
||||
{
|
||||
if (clearedStage.mod == ChapterMod.Hard)
|
||||
if (clearedStage.chapter_mod == ChapterMod.Hard)
|
||||
{
|
||||
if (StageId > user.LastHardStageCleared)
|
||||
user.LastHardStageCleared = StageId;
|
||||
@@ -135,7 +135,7 @@ namespace EpinelPS.LobbyServer.Stage
|
||||
// Mark chapter as completed if boss stage was completed
|
||||
if (clearedStage.stage_category == StageCategory.Boss && clearedStage.stage_type == StageType.Main)
|
||||
{
|
||||
if (clearedStage.mod == ChapterMod.Hard)
|
||||
if (clearedStage.chapter_mod == ChapterMod.Hard)
|
||||
user.AddTrigger(TriggerType.HardChapterClear, 1, clearedStage.chapter_id);
|
||||
else
|
||||
user.AddTrigger(TriggerType.ChapterClear, 1, clearedStage.chapter_id);
|
||||
@@ -152,10 +152,11 @@ namespace EpinelPS.LobbyServer.Stage
|
||||
private static void DoQuestSpecificUserOperations(User user, int clearedStageId)
|
||||
{
|
||||
var quest = GameData.Instance.GetMainQuestForStageClearCondition(clearedStageId);
|
||||
|
||||
user.AddTrigger(TriggerType.CampaignClear, 1, clearedStageId);
|
||||
if (quest != null)
|
||||
{
|
||||
user.SetQuest(quest.id, false);
|
||||
user.AddTrigger(TriggerType.CampaignClear, 1, clearedStageId);
|
||||
user.AddTrigger(TriggerType.MainQuestClear, 1, quest.id);
|
||||
}
|
||||
|
||||
@@ -181,7 +182,7 @@ namespace EpinelPS.LobbyServer.Stage
|
||||
|
||||
user.BondInfo.Add(new() { NameCode = 3001, Lv = 1 });
|
||||
user.BondInfo.Add(new() { NameCode = 3005, Lv = 1 });
|
||||
|
||||
|
||||
user.AddTrigger(TriggerType.ObtainCharacter, 1, 3001);
|
||||
user.AddTrigger(TriggerType.ObtainCharacter, 1, 1018);
|
||||
user.AddTrigger(TriggerType.ObtainCharacter, 1, 1015);
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace EpinelPS.LobbyServer.Stage
|
||||
var response = new ResEnterStage();
|
||||
|
||||
var clearedStage = GameData.Instance.GetStageData(req.StageId) ?? throw new Exception("cleared stage cannot be null");
|
||||
var map = GameData.Instance.GetMapIdFromChapter(clearedStage.chapter_id, clearedStage.mod);
|
||||
var map = GameData.Instance.GetMapIdFromChapter(clearedStage.chapter_id, clearedStage.chapter_mod);
|
||||
|
||||
if (clearedStage.stage_category == StageCategory.Boss)
|
||||
{
|
||||
@@ -27,7 +27,7 @@ namespace EpinelPS.LobbyServer.Stage
|
||||
info.BossEntered = true;
|
||||
}
|
||||
|
||||
user.AddTrigger(TriggerType.CampaignStart, 1);
|
||||
user.AddTrigger(TriggerType.CampaignStart, 1, req.StageId);
|
||||
|
||||
JsonDb.Save();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user