mirror of
https://github.com/EpinelPS/EpinelPS.git
synced 2025-12-12 15:04:36 +01:00
begin trigger implementation
This commit is contained in:
@@ -172,6 +172,27 @@ namespace EpinelPS.Database
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
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 User
|
||||
{
|
||||
// User info
|
||||
@@ -249,11 +270,29 @@ namespace EpinelPS.Database
|
||||
public List<Badge> Badges = [];
|
||||
|
||||
public List<NetUserAttractiveData> BondInfo = [];
|
||||
public List<Trigger> Triggers = [];
|
||||
public int LastTriggerId = 1;
|
||||
|
||||
// Event data
|
||||
public Dictionary<int, EventData> EventInfo = new();
|
||||
public MogMinigameInfo MogInfo = new();
|
||||
|
||||
public Trigger AddTrigger(TriggerType type, int value, int conditionId = 0)
|
||||
{
|
||||
Trigger t = new()
|
||||
{
|
||||
Id = LastTriggerId++,
|
||||
Type = type,
|
||||
ConditionId = conditionId,
|
||||
CreatedAt = DateTime.Now.Ticks,
|
||||
Value = value
|
||||
};
|
||||
|
||||
Triggers.Add(t);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
public Badge AddBadge(BadgeContents type, string location)
|
||||
{
|
||||
// generate unique badge SEQ
|
||||
|
||||
@@ -50,12 +50,12 @@ namespace EpinelPS.StaticInfo
|
||||
public Dictionary<int, EventManager> eventManagers = new Dictionary<int, EventManager>();
|
||||
public Dictionary<int, LiveWallpaperRecord> lwptablemgrs = new Dictionary<int, LiveWallpaperRecord>(); // Fixed initialization
|
||||
public Dictionary<int, AlbumResourceRecord> albumResourceRecords = new Dictionary<int, AlbumResourceRecord>();
|
||||
public Dictionary<int, UserFrameTableRecord> userFrameTable = new Dictionary<int, UserFrameTableRecord>();
|
||||
public Dictionary<int, ArchiveRecordManagerRecord> archiveRecordManagerTable = new Dictionary<int, ArchiveRecordManagerRecord>();
|
||||
public Dictionary<int, ArchiveEventStoryRecord> archiveEventStoryRecords = new Dictionary<int, ArchiveEventStoryRecord>();
|
||||
public Dictionary<int, ArchiveEventQuestRecord> archiveEventQuestRecords = new Dictionary<int, ArchiveEventQuestRecord>();
|
||||
public Dictionary<int, ArchiveEventDungeonStageRecord> archiveEventDungeonStageRecords = new Dictionary<int, ArchiveEventDungeonStageRecord>();
|
||||
public Dictionary<int, UserTitleRecord> userTitleRecords = new Dictionary<int, UserTitleRecord>();
|
||||
public Dictionary<int, UserFrameTableRecord> userFrameTable = new Dictionary<int, UserFrameTableRecord>();
|
||||
public Dictionary<int, ArchiveRecordManagerRecord> archiveRecordManagerTable = new Dictionary<int, ArchiveRecordManagerRecord>();
|
||||
public Dictionary<int, ArchiveEventStoryRecord> archiveEventStoryRecords = new Dictionary<int, ArchiveEventStoryRecord>();
|
||||
public Dictionary<int, ArchiveEventQuestRecord> archiveEventQuestRecords = new Dictionary<int, ArchiveEventQuestRecord>();
|
||||
public Dictionary<int, ArchiveEventDungeonStageRecord> archiveEventDungeonStageRecords = new Dictionary<int, ArchiveEventDungeonStageRecord>();
|
||||
public Dictionary<int, UserTitleRecord> userTitleRecords = new Dictionary<int, UserTitleRecord>();
|
||||
public Dictionary<int, ArchiveMessengerConditionRecord> archiveMessengerConditionRecords = [];
|
||||
public Dictionary<int, CharacterStatRecord> characterStatTable = [];
|
||||
public Dictionary<int, SkillInfoRecord> skillInfoTable = [];
|
||||
@@ -107,7 +107,7 @@ namespace EpinelPS.StaticInfo
|
||||
// Initialize Jukebox data dictionaries
|
||||
jukeboxListDataRecords = [];
|
||||
jukeboxThemeDataRecords = [];
|
||||
archiveMessengerConditionRecords = [];
|
||||
archiveMessengerConditionRecords = [];
|
||||
|
||||
var rawBytes = File.ReadAllBytes(filePath);
|
||||
Sha256Hash = SHA256.HashData(rawBytes);
|
||||
@@ -409,12 +409,12 @@ namespace EpinelPS.StaticInfo
|
||||
{
|
||||
OutpostBattle.Add(obj.id, obj);
|
||||
}
|
||||
|
||||
var archiveRecordManagerTableData = await LoadZip<ArchiveRecordManagerTable>("ArchiveRecordManagerTable.json", progress);
|
||||
foreach (var obj in archiveRecordManagerTableData.records)
|
||||
{
|
||||
archiveRecordManagerTable.Add(obj.id, obj);
|
||||
}
|
||||
|
||||
var archiveRecordManagerTableData = await LoadZip<ArchiveRecordManagerTable>("ArchiveRecordManagerTable.json", progress);
|
||||
foreach (var obj in archiveRecordManagerTableData.records)
|
||||
{
|
||||
archiveRecordManagerTable.Add(obj.id, obj);
|
||||
}
|
||||
|
||||
var gachaTypeTable = await LoadZip<GachaTypeTable>("GachaTypeTable.json", progress);
|
||||
|
||||
@@ -439,38 +439,38 @@ namespace EpinelPS.StaticInfo
|
||||
{
|
||||
lwptablemgrs.Add(obj.id, obj); // Use obj.id as the key and obj (the LiveWallpaperRecord) as the value
|
||||
}
|
||||
|
||||
var userFrameData = await LoadZip<UserFrameTable>("UserFrameTable.json", progress);
|
||||
foreach (var record in userFrameData.records)
|
||||
{
|
||||
userFrameTable[record.id] = record;
|
||||
}
|
||||
// Load and parse ArchiveEventDungeonStageTable.json
|
||||
var archiveEventDungeonStageData = await LoadZip<ArchiveEventDungeonStageTable>("ArchiveEventDungeonStageTable.json", progress);
|
||||
foreach (var obj in archiveEventDungeonStageData.records)
|
||||
{
|
||||
archiveEventDungeonStageRecords.Add(obj.id, obj);
|
||||
}
|
||||
|
||||
var userTitleTable = await LoadZip<UserTitleTable>("UserTitleTable.json", progress);
|
||||
foreach (var obj in userTitleTable.records)
|
||||
{
|
||||
userTitleRecords.Add(obj.id, obj);
|
||||
}
|
||||
|
||||
// Load and parse ArchiveEventStoryTable.json
|
||||
var archiveEventStoryTable = await LoadZip<ArchiveEventStoryTable>("ArchiveEventStoryTable.json", progress);
|
||||
foreach (var obj in archiveEventStoryTable.records)
|
||||
{
|
||||
archiveEventStoryRecords.Add(obj.id, obj);
|
||||
}
|
||||
var userFrameData = await LoadZip<UserFrameTable>("UserFrameTable.json", progress);
|
||||
foreach (var record in userFrameData.records)
|
||||
{
|
||||
userFrameTable[record.id] = record;
|
||||
}
|
||||
// Load and parse ArchiveEventDungeonStageTable.json
|
||||
var archiveEventDungeonStageData = await LoadZip<ArchiveEventDungeonStageTable>("ArchiveEventDungeonStageTable.json", progress);
|
||||
foreach (var obj in archiveEventDungeonStageData.records)
|
||||
{
|
||||
archiveEventDungeonStageRecords.Add(obj.id, obj);
|
||||
}
|
||||
|
||||
// Load and parse ArchiveEventQuestTable.json
|
||||
var archiveEventQuestTable = await LoadZip<ArchiveEventQuestTable>("ArchiveEventQuestTable.json", progress);
|
||||
foreach (var obj in archiveEventQuestTable.records)
|
||||
{
|
||||
archiveEventQuestRecords.Add(obj.id, obj);
|
||||
}
|
||||
var userTitleTable = await LoadZip<UserTitleTable>("UserTitleTable.json", progress);
|
||||
foreach (var obj in userTitleTable.records)
|
||||
{
|
||||
userTitleRecords.Add(obj.id, obj);
|
||||
}
|
||||
|
||||
// Load and parse ArchiveEventStoryTable.json
|
||||
var archiveEventStoryTable = await LoadZip<ArchiveEventStoryTable>("ArchiveEventStoryTable.json", progress);
|
||||
foreach (var obj in archiveEventStoryTable.records)
|
||||
{
|
||||
archiveEventStoryRecords.Add(obj.id, obj);
|
||||
}
|
||||
|
||||
// Load and parse ArchiveEventQuestTable.json
|
||||
var archiveEventQuestTable = await LoadZip<ArchiveEventQuestTable>("ArchiveEventQuestTable.json", progress);
|
||||
foreach (var obj in archiveEventQuestTable.records)
|
||||
{
|
||||
archiveEventQuestRecords.Add(obj.id, obj);
|
||||
}
|
||||
// LOAD ARCHIVE MESSENGER CONDITION TABLE
|
||||
var archiveMessengerConditionTable = await LoadZip<ArchiveMessengerConditionTable>("ArchiveMessengerConditionTable.json", progress);
|
||||
foreach (var obj in archiveMessengerConditionTable.records)
|
||||
@@ -763,4 +763,151 @@ namespace EpinelPS.StaticInfo
|
||||
|
||||
|
||||
}
|
||||
|
||||
public enum TriggerType
|
||||
{
|
||||
None = 0,
|
||||
UserLevel = 1,
|
||||
CampaignClear = 2,
|
||||
ChapterClear = 3,
|
||||
CampaignStart = 4,
|
||||
TowerAllStart = 5,
|
||||
TowerBasicClear = 6,
|
||||
CharacterLevel = 7,
|
||||
CharacterGrade = 8,
|
||||
CharacterCore = 9,
|
||||
CharacterAttractiveLevel = 10,
|
||||
MainShopBuy = 11,
|
||||
ShopGuildBuy = 12,
|
||||
GachaCharacter = 13,
|
||||
OutpostBattleReward = 14,
|
||||
OutpostFastBattleReward = 15,
|
||||
PointRewardDaily = 16,
|
||||
PointRewardWeekly = 17,
|
||||
ObtainCharacter = 18,
|
||||
OutpostBuilding = 19,
|
||||
SendFriendShipPoint = 20,
|
||||
SendDispatch = 21,
|
||||
MainQuestClear = 22,
|
||||
ObtainJukeboxTheme = 23,
|
||||
SubQuestClear = 24,
|
||||
CampaignGroupClear = 25,
|
||||
NpcTalk = 26,
|
||||
TowerElysionClear = 27,
|
||||
TowerMissilisClear = 28,
|
||||
TowerTetraClear = 29,
|
||||
TowerOverspecClear = 30,
|
||||
AchieveRanking1st = 31,
|
||||
AchieveRanking5th = 32,
|
||||
AchieveRanking10th = 33,
|
||||
EventPoint = 34,
|
||||
HardChapterClear = 35,
|
||||
ObtainCharacterSSR = 36,
|
||||
GachaCompany = 37,
|
||||
ObtainCharacterNew = 38,
|
||||
WinArena = 39,
|
||||
SpecialArenaTier = 40,
|
||||
PointRewardAchievement = 41,
|
||||
ObtainCharacterPilgrim = 42,
|
||||
ShopDisassembleBuy = 43,
|
||||
CharacterCounsel = 44,
|
||||
CharacterAttractivePresent = 45,
|
||||
ObtainEquipItemT3T4 = 46,
|
||||
ObtainEquipItemT5T6 = 47,
|
||||
ObtainEquipItemT7T8 = 48,
|
||||
ObtainEquipItemT9 = 49,
|
||||
PointRewardEvent = 50,
|
||||
MissionClearEvent = 51,
|
||||
ObtainMemorialItem = 52,
|
||||
LostSectorClear = 53,
|
||||
ObtainHarmonyCube = 54,
|
||||
HarmonyCubeLevel = 55,
|
||||
CooperationEventClear = 56,
|
||||
SynchroDeviceSlot = 57,
|
||||
ObtainEquipItemALL = 58,
|
||||
EquipItemLevel = 59,
|
||||
CharacterSkillLevel = 60,
|
||||
PickupGachaCharacter = 61,
|
||||
ObtainSilverMileage = 62,
|
||||
ObtainGoldMileage = 63,
|
||||
SendDispatchGrade = 64,
|
||||
OutpostBattleBoxLevel = 65,
|
||||
GetFriendShipPoint = 66,
|
||||
MessageClear = 67,
|
||||
RecycleResearchLevel = 68,
|
||||
GachaPremium = 69,
|
||||
CharacterLevelUpCount = 70,
|
||||
CharacterGradeUpCount = 71,
|
||||
CharacterLevelMax = 72,
|
||||
CharacterGradeMax = 73,
|
||||
HarmonyCubeLevelMax = 74,
|
||||
CharacterSkillLevelMax = 75,
|
||||
CharacterAttractiveLevelMax = 76,
|
||||
EquipItemLevelMax = 77,
|
||||
ObtainEquipItemT2 = 78,
|
||||
FieldObjectCollection = 79,
|
||||
SimulationRoomStart = 80,
|
||||
InterceptStart = 81,
|
||||
EquipItemLevelCount = 82,
|
||||
SimulationRoomClear = 83,
|
||||
InterceptClear = 84,
|
||||
DailyEventClear = 85,
|
||||
EventStageClear = 86,
|
||||
ObtainEventCurrencyMaterialMiraclesnow = 87,
|
||||
EventDungeonStageClear = 88,
|
||||
EventSortOutClear = 89,
|
||||
EventSortOutPointMax = 90,
|
||||
EquipItemLevelUpCount = 91,
|
||||
CharacterSkillLevelUpCount = 92,
|
||||
FirstPaidGacha_Legecy = 93,
|
||||
ObtainCharacterCostume = 94,
|
||||
SyncroDeviceLevelMax = 95,
|
||||
ObtainEventCurrencyMaterial = 96,
|
||||
SimulationRoomClearWithoutCondition = 97,
|
||||
EventTextAdventureClear = 98,
|
||||
RookieArenaPlayCount = 99,
|
||||
EventDicePlayCount = 100,
|
||||
EventBBQTycoonDailyRewardCheck = 101,
|
||||
EventBBQTycoonHighScore = 102,
|
||||
ChampionArenaGambleWinAll = 103,
|
||||
ChampionArenaGambleLoseAll = 104,
|
||||
EventMiniGameCe002PlayCheck = 105,
|
||||
EventMiniGameNKSPlayCheck = 106,
|
||||
EventSnowfallOasisDailyRewardCheck = 107,
|
||||
EventMiniGameCe003RewardCheck = 108,
|
||||
EventTowerDefensePlayCheck = 109,
|
||||
EventPlaySodaPlayCheck = 110,
|
||||
EventIslandAdventureFishingPlayCheck = 111,
|
||||
MiniGameDDCompleteDive = 112,
|
||||
MiniGameDDCompleteSushi = 113,
|
||||
MiniGameDDTotalGold = 114,
|
||||
MiniGameDDSushiPreTurnover = 115,
|
||||
MiniGameDDTotalFish = 116,
|
||||
MiniGameDDPerUnderwaterEncounter = 117,
|
||||
MiniGameDDUnlockEmployeeCount = 118,
|
||||
MiniGameDDUnlockNikkeCount = 119,
|
||||
MiniGameDDGunLevel = 120,
|
||||
MiniGameDDIDiverLevel = 121,
|
||||
MiniGameDDUnlockSushiCount = 122,
|
||||
MiniGameDDSushiLevel = 123,
|
||||
MiniGameDDSushiCookScore = 124,
|
||||
MiniGameDDSushiPreTurnoverTotalMax = 125,
|
||||
MiniGameDDSushiLevelTotalMax = 126,
|
||||
MiniGameDDAllAchievement = 127,
|
||||
ComebackPollComplete = 128,
|
||||
AliceAccessAttractiveScenario = 129,
|
||||
AliceEquipCollectionItemLevel = 130,
|
||||
AliceEquipCollectionItemSR = 131,
|
||||
AliceEquipItemOverload = 132,
|
||||
AliceSkill1Level = 133,
|
||||
AliceSkillBurstLevel = 134,
|
||||
InterceptNormalClearWithCondition = 135,
|
||||
InterceptSpecialClearWithCondition = 136,
|
||||
SimulationRoomClearCount1Only = 137,
|
||||
TacticAcademyFinish9_4 = 138,
|
||||
EventMiniGameCe004RewardCheck = 139,
|
||||
EventMVGPlayCheck = 140,
|
||||
EventDDRRewardCheck = 141
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -107,13 +107,13 @@ namespace EpinelPS.LobbyServer
|
||||
}
|
||||
else
|
||||
{
|
||||
var bin = await PacketDecryption.DecryptOrReturnContentAsync(ctx);
|
||||
|
||||
// return grpc IMessage from byte array with type T
|
||||
T msg = new();
|
||||
Console.WriteLine("Reading " + msg.GetType().Name);
|
||||
|
||||
var bin = await PacketDecryption.DecryptOrReturnContentAsync(ctx);
|
||||
msg.MergeFrom(bin.Contents);
|
||||
|
||||
Console.WriteLine("Reading " + msg.GetType().Name);
|
||||
PrintMessage(msg);
|
||||
Console.WriteLine();
|
||||
|
||||
|
||||
18
EpinelPS/LobbyServer/Mission/ObtainDaily.cs
Normal file
18
EpinelPS/LobbyServer/Mission/ObtainDaily.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Mission
|
||||
{
|
||||
[PacketPath("/mission/obtain/daily")]
|
||||
public class ObtainDaily : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqObtainDailyMissionReward>();
|
||||
|
||||
var response = new ResObtainDailyMissionReward();
|
||||
|
||||
// TODO
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace EpinelPS.LobbyServer.Mission.Rewards
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = ReadData<ReqGetWeeklyRewardedData>();
|
||||
var req = await ReadData<ReqGetWeeklyRewardedData>();
|
||||
|
||||
// TODO: implement
|
||||
var response = new ResGetWeeklyRewardedData();
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace EpinelPS.LobbyServer.Jukebox
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = ReadData<ReqRecordJukeboxPlayHistory>();
|
||||
var req = await ReadData<ReqRecordJukeboxPlayHistory>();
|
||||
|
||||
var response = new ResRecordJukeboxPlayHistory();
|
||||
await WriteDataAsync(response);
|
||||
|
||||
@@ -147,9 +147,11 @@ namespace EpinelPS.LobbyServer.Stage
|
||||
|
||||
private static void DoQuestSpecificUserOperations(Database.User user, int clearedStageId)
|
||||
{
|
||||
var quest = GameData.Instance.GetMainQuestForStageClearCondition(clearedStageId);
|
||||
if (quest != null)
|
||||
user.SetQuest(quest.id, false);
|
||||
var quest = GameData.Instance.GetMainQuestForStageClearCondition(clearedStageId) ?? throw new Exception("cannot find quest from cleared stage id");
|
||||
|
||||
user.SetQuest(quest.id, false);
|
||||
user.AddTrigger(TriggerType.CampaignClear, 1, clearedStageId);
|
||||
user.AddTrigger(TriggerType.MainQuestClear, 1, quest.id);
|
||||
|
||||
// TODO: Is this the right place to add default characters?
|
||||
// Stage 1-4 BOSS
|
||||
|
||||
@@ -8,8 +8,11 @@ namespace EpinelPS.LobbyServer.Stage
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqEnterStage>();
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResEnterStage();
|
||||
|
||||
user.AddTrigger(StaticInfo.TriggerType.CampaignStart, 1);
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
|
||||
@@ -14,8 +14,10 @@ namespace EpinelPS.LobbyServer.Trigger
|
||||
Console.WriteLine("Complete quest: " + req.Tid);
|
||||
user.SetQuest(req.Tid, false);
|
||||
|
||||
var completedQuest = GameData.Instance.GetMainQuestByTableId(req.Tid);
|
||||
if (completedQuest == null) throw new Exception("Quest not found");
|
||||
var completedQuest = GameData.Instance.GetMainQuestByTableId(req.Tid) ?? throw new Exception("Quest not found");
|
||||
|
||||
user.AddTrigger(TriggerType.CampaignClear, 1, completedQuest.condition_id);
|
||||
user.AddTrigger(TriggerType.MainQuestClear, 1, completedQuest.id);
|
||||
|
||||
JsonDb.Save();
|
||||
var response = new ResFinMainQuest();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using EpinelPS.Utils;
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Trigger
|
||||
{
|
||||
@@ -7,9 +8,39 @@ namespace EpinelPS.LobbyServer.Trigger
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = ReadData<ReqSyncTrigger>();
|
||||
var req = await ReadData<ReqSyncTrigger>();
|
||||
var user = GetUser();
|
||||
|
||||
// This request is responsible for fetching a log for
|
||||
// daily, weekly, challenge mission completion.
|
||||
// This endpoint also returns the entire "history" for the account when
|
||||
// Seq = 0, which the client does when it is started for the first time, or when
|
||||
// the "Clear Cache" option is invoked.
|
||||
// When Seq = 0, the server limits the responses to 2000 items,
|
||||
// and HasRemainData is set to true.
|
||||
// TODO: Is it necessary to store the entire account history each time a stage
|
||||
// is cleared, why does the official server do this?
|
||||
|
||||
var response = new ResSyncTrigger();
|
||||
Console.WriteLine("needs " + req.Seq);
|
||||
|
||||
// Look for triggers past that amount
|
||||
var newTriggers = user.Triggers.Where(x => x.Id > req.Seq).ToArray();
|
||||
|
||||
// Return all triggers
|
||||
int triggerCount = 0;
|
||||
foreach (var item in newTriggers)
|
||||
{
|
||||
triggerCount++;
|
||||
|
||||
response.Triggers.Add(item.ToNet());
|
||||
|
||||
if (triggerCount >= 2000)
|
||||
{
|
||||
response.HasRemainData = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user