From 2c195832f50720c8e0124dc31b19cfab0f401826 Mon Sep 17 00:00:00 2001 From: Spirtix Date: Tue, 20 Jun 2023 17:15:08 +0200 Subject: [PATCH] mockup for the tutorial mission --- mitm-redirect.py | 2 +- src/Attributes/SignResponse.cs | 2 +- .../Common/AchievementController.cs | 10 +- src/Controllers/Common/ContentController.cs | 51 ++ src/Resources/tutorialmission.xml | 479 ++++++++++++++++++ src/Schema/Mission.cs | 57 +++ src/Schema/MissionCompletedResult.cs | 13 + src/Schema/MissionCriteria.cs | 22 + src/Schema/MissionGroup.cs | 25 + src/Schema/MissionRule.cs | 13 + src/Schema/PrerequisiteItem.cs | 19 + src/Schema/PrerequisiteRequiredType.cs | 20 + src/Schema/RuleItem.cs | 19 + src/Schema/RuleItemType.cs | 10 + src/Schema/SetTaskStateResult.cs | 23 + src/Schema/SetTaskStateStatus.cs | 38 ++ src/Schema/Task.cs | 28 + src/Schema/UserMissionStateResult.cs | 23 + src/Schema/UserTimedAchievement.cs | 40 ++ src/Util/XmlUtil.cs | 14 +- src/sodoff.csproj | 7 + 21 files changed, 904 insertions(+), 11 deletions(-) create mode 100644 src/Resources/tutorialmission.xml create mode 100644 src/Schema/Mission.cs create mode 100644 src/Schema/MissionCompletedResult.cs create mode 100644 src/Schema/MissionCriteria.cs create mode 100644 src/Schema/MissionGroup.cs create mode 100644 src/Schema/MissionRule.cs create mode 100644 src/Schema/PrerequisiteItem.cs create mode 100644 src/Schema/PrerequisiteRequiredType.cs create mode 100644 src/Schema/RuleItem.cs create mode 100644 src/Schema/RuleItemType.cs create mode 100644 src/Schema/SetTaskStateResult.cs create mode 100644 src/Schema/SetTaskStateStatus.cs create mode 100644 src/Schema/Task.cs create mode 100644 src/Schema/UserMissionStateResult.cs create mode 100644 src/Schema/UserTimedAchievement.cs diff --git a/mitm-redirect.py b/mitm-redirect.py index c7a4c22..509c2fd 100644 --- a/mitm-redirect.py +++ b/mitm-redirect.py @@ -4,7 +4,7 @@ import mitmproxy.http def routable(path): methods = ['GetRules', 'LoginParent', 'RegisterParent', 'GetSubscriptionInfo', 'GetUserInfoByApiToken', 'IsValidApiToken_V2', 'ValidateName', 'GetDefaultNameSuggestion', 'RegisterChild', 'GetProfileByUserId', 'LoginChild', 'GetUserProfileByUserID', 'GetKeyValuePair', 'SetKeyValuePair', 'GetKeyValuePairByUserID', 'SetKeyValuePairByUserID', 'GetUserProfile', 'GetQuestions', 'GetCommonInventory', -'GetAuthoritativeTime', 'SetAvatar', 'GetAllActivePetsByuserId', 'GetPetAchievementsByUserID', 'GetDetailedChildList', 'GetStore', 'GetAllRanks'] +'GetAuthoritativeTime', 'SetAvatar', 'GetAllActivePetsByuserId', 'GetPetAchievementsByUserID', 'GetDetailedChildList', 'GetStore', 'GetAllRanks', 'GetUserUpcomingMissionState', 'GetUserActiveMissionState', 'GetUserCompletedMissionState', 'SetTaskState'] for method in methods: if method in path: return True diff --git a/src/Attributes/SignResponse.cs b/src/Attributes/SignResponse.cs index 4533240..2d9a69a 100644 --- a/src/Attributes/SignResponse.cs +++ b/src/Attributes/SignResponse.cs @@ -8,7 +8,7 @@ using System.Text; namespace sodoff.Attributes; public class SignResponse : Attribute, IAsyncResultFilter { const string key = "11A0CC5A-C4DF-4A0E-931C-09A44C9966AE"; - public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next) { + public async System.Threading.Tasks.Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next) { var originalBodyStream = context.HttpContext.Response.Body; try { diff --git a/src/Controllers/Common/AchievementController.cs b/src/Controllers/Common/AchievementController.cs index 28968dd..9018cc2 100644 --- a/src/Controllers/Common/AchievementController.cs +++ b/src/Controllers/Common/AchievementController.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Mvc; using sodoff.Model; +using sodoff.Util; namespace sodoff.Controllers.Common; public class AchievementController : Controller { @@ -24,13 +25,6 @@ public class AchievementController : Controller { [Route("AchievementWebService.asmx/GetAllRanks")] public IActionResult GetAllRanks() { // TODO, this is a placeholder - var assembly = Assembly.GetExecutingAssembly(); - string resourceName = assembly.GetManifestResourceNames().Single(str => str.EndsWith("allranks.xml")); - - using (Stream stream = assembly.GetManifestResourceStream(resourceName)) - using (StreamReader reader = new StreamReader(stream)) { - string result = reader.ReadToEnd(); - return Ok(result); - } + return Ok(XmlUtil.ReadResourceXmlString("allranks")); } } diff --git a/src/Controllers/Common/ContentController.cs b/src/Controllers/Common/ContentController.cs index be98711..4227481 100644 --- a/src/Controllers/Common/ContentController.cs +++ b/src/Controllers/Common/ContentController.cs @@ -202,4 +202,55 @@ public class ContentController : Controller { // TODO, this is a placeholder return Ok("\n"); } + + [HttpPost] + [Produces("application/xml")] + [Route("V2/ContentWebService.asmx/GetUserUpcomingMissionState")] + public IActionResult GetUserUpcomingMissionState([FromForm] string apiToken, [FromForm] string userId) { + Session? session = ctx.Sessions.FirstOrDefault(s => s.ApiToken == apiToken); + UserMissionStateResult result = new UserMissionStateResult(); + + if (session is null) + return Ok(result); + + result.UserID = Guid.Parse(session.VikingId); + return Ok(result); // TODO: placeholder, returns no upcoming missions + } + + [HttpPost] + [Produces("application/xml")] + [Route("V2/ContentWebService.asmx/GetUserActiveMissionState")] + public IActionResult GetUserActiveMissionState([FromForm] string apiToken, [FromForm] string userId) { + Session? session = ctx.Sessions.FirstOrDefault(s => s.ApiToken == apiToken); + UserMissionStateResult result = new UserMissionStateResult { Missions = new List() }; + result.Missions.Add(XmlUtil.DeserializeXml(XmlUtil.ReadResourceXmlString("tutorialmission"))); + + if (session is null) + return Ok("error"); + + result.UserID = Guid.Parse(session.VikingId); + return Ok(result); // TODO: placeholder, returns the tutorial + } + + [HttpPost] + [Produces("application/xml")] + [Route("V2/ContentWebService.asmx/GetUserCompletedMissionState")] + public IActionResult GetUserCompletedMissionState([FromForm] string apiToken, [FromForm] string userId) { + Session? session = ctx.Sessions.FirstOrDefault(s => s.ApiToken == apiToken); + UserMissionStateResult result = new UserMissionStateResult(); + + if (session is null) + return Ok(result); + + result.UserID = Guid.Parse(session.VikingId); + return Ok(result); // TODO: placeholder, returns no completed missions + } + + [HttpPost] + [Produces("application/xml")] + [Route("V2/ContentWebService.asmx/SetTaskState")] + public IActionResult SetTaskState([FromForm] string apiToken, [FromForm] int missionId, [FromForm] int taskId, [FromForm] bool completed) { + // TODO + return Ok(new SetTaskStateResult { Success = true, Status = SetTaskStateStatus.TaskCanBeDone }); + } } diff --git a/src/Resources/tutorialmission.xml b/src/Resources/tutorialmission.xml new file mode 100644 index 0000000..9dae3aa --- /dev/null +++ b/src/Resources/tutorialmission.xml @@ -0,0 +1,479 @@ + + + false + 999 + Quest 1 + 51 + 3 +

+ <Data><Setup><Scene>HubFTUEDO</Scene><Asset>RS_DATA/PfGrpQMMO_Off.unity3d/PfGrpQMMO_Off</Asset><Recursive>false</Recursive><Persistent>false</Persistent></Setup><Setup><Scene>HubSchoolDO</Scene><Asset>RS_DATA/PfGrpFTUE2020T15.unity3d/PfGrpFTUE2020T15</Asset><Recursive>false</Recursive><Persistent>true</Persistent></Setup><Repeat>0</Repeat><Hidden>0</Hidden><Reward><Asset>PfUiMissionRewardDBDO</Asset></Reward><Random>0</Random><Title><Text>New Student</Text><ID>922059</ID></Title></Data> + false + 0 + + + 2 + False + false + + + 1 + False + false + + + all + true + 4 + 1 + + 1 + 999 + 5930 + 0 + + + 1 + 999 + 5931 + 0 + + + 1 + 999 + 5932 + 0 + + + 2 + 999 + 2880 + 0 + + + 2 + 999 + 2881 + 0 + + + 1 + 999 + 5935 + 0 + + + 1 + 999 + 5936 + 0 + + + 1 + 999 + 5937 + 0 + + + 1 + 999 + 5938 + 0 + + + 2 + 999 + 2882 + 0 + + + 1 + 999 + 5940 + 0 + + + 1 + 999 + 5941 + 0 + + + 1 + 999 + 5942 + 0 + + + 2 + 999 + 2883 + 0 + + + 1 + 999 + 5944 + 0 + + + 1 + 999 + 6619 + 0 + + + + 8 + 201320 + 0 + + false + 2880 + FTUE2020-04 + 51 + 3 +

999

+ <Data><Repeat>0</Repeat><Hidden>0</Hidden><Reward><Asset /></Reward><Random>0</Random><Title><Text>{{Input}} on cage</Text><ID>939800</ID></Title></Data> + false + 0 + + + 2 + False + false + + + 1 + False + false + + + all + true + 4 + 1 + + 1 + 2880 + 5933 + 0 + + + + 8 + 0 + 0 + + 5933 + FTUE2020-04: Click cage + <Data><Offer><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>Be careful. Even baby dragons can be dangerous when frightened. Step forward and {{input}} on the cage door to open it. After that, just trust your instincts!@@Hey, don't worry, you got this.</Text><ID>939805</ID><ItemID>0</ItemID><Priority>0</Priority></Offer><End><Type>CutScene</Type><Asset>RS_DATA/PfGrpFTUE2020T04CS.unity3d/PfGrpFTUE2020T04CS</Asset><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Scene</Key><Value>HubFTUEDO</Value></Pair><Pair><Key>Type</Key><Value>DragonSelect</Value></Pair><Pair><Key>NPC</Key><Value>PfDWFTUECage</Value></Pair><Pair><Key>Asset</Key><Value>RS_DATA/PfUiFTUEDragonSelection.unity3d/PfUiFTUEDragonSelection</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Meet</Type><Title><Text>{{Input}} on the Dragon Cage</Text><ID>939804</ID></Title><Desc><Text>{{Input}} on the Dragon Cage</Text><ID>939804</ID></Desc><AutoComplete><Pair><Key>RaisedPetStage</Key><Value>BABY</Value></Pair></AutoComplete></Data> + 0 + + + + false + 2881 + FTUE2020-05 + 51 + 3 +

999

+ <Data><Repeat>0</Repeat><Hidden>0</Hidden><Reward><Asset>PfUiMissionRewardDBDO</Asset></Reward><Random>0</Random><Title><Text>Look for a way out of the cave</Text><ID>939801</ID></Title></Data> + false + 0 + + + 2 + False + false + + + 1 + False + false + + + all + true + 4 + 1 + + 1 + 2881 + 5934 + 0 + + + + 8 + 206555 + 0 + + 5934 + FTUE2020-05: Look for a way out + <Data><Offer><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>Whoa, that was unexpected. Who would have thought you two would bond so quickly?@@You’re a natural at this! Well, mission accomplished!@@Now, what do you say we find a way out of here?</Text><ID>939807</ID><ItemID>0</ItemID><Priority>0</Priority></Offer><End><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>This must be the heaviest part of the cave-in. With all these boulders piled up, this might be a dead end for us.@@{{dragon name}} is only a Tiny Tooth, so their dragon fire isn't quite enough to shatter that rock. But they are very close, and we can help them to grow.</Text><ID>939808</ID><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Scene</Key><Value>HubFTUEDO</Value></Pair><Pair><Key>Name</Key><Value>PfMarker_CaveIn</Value></Pair><Pair><Key>Range</Key><Value>8</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Visit</Type><Title><Text>Look for a way out of the Cave</Text><ID>939801</ID></Title><Desc><Text>Look for a way out of the Cave</Text><ID>939801</ID></Desc></Data> + 0 + + + 1 +

6

+ + 1 + 8399 + 10996 + 206555 + true + 1 + 1 + + 0 + + 0 + 0 +
+
+ + false + 2882 + FTUE2020-10 + 51 + 3 +

999

+ <Data><Repeat>0</Repeat><Hidden>0</Hidden><Reward><Asset /></Reward><Random>0</Random><Title><Text>Light fire</Text><ID>939802</ID></Title></Data> + false + 0 + + + 2 + False + false + + + 1 + False + false + + + all + true + 4 + 1 + + 1 + 2882 + 5939 + 0 + + + + 8 + 206242 + 0 + + 5939 + FTUE2020-10: Light fire + <Data><Setup><Scene>HubFTUEDO</Scene><Asset>PfDWHiccup</Asset><Location>PfMarker_HiccupFire</Location><Recursive>false</Recursive><Persistent>false</Persistent></Setup><Offer><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>There’s a good spot for a signal fire. Would you ask {{dragon name}} to shoot it?</Text><ID>939810</ID><ItemID>0</ItemID><Priority>0</Priority></Offer><End><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>That’s not going to be enough; the fire is just too small...</Text><ID>939811</ID><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Scene</Key><Value>HubFTUEDO</Value></Pair><Pair><Key>Location</Key><Value>PfMarker_FireSpot</Value></Pair><Pair><Key>Name</Key><Value>LightFire</Value></Pair><Pair><Key>ItemName</Key><Value>PfDragonLitFirePit</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Action</Type><Title><Text>{{Input}} on the Fire Pit to Light a Signal Fire</Text><ID>942392</ID></Title><Desc><Text>{{Input}} on the Fire Pit to Light a Signal Fire</Text><ID>942392</ID></Desc></Data> + 0 + +
+ + false + 2883 + FTUE2020-14 + 51 + 3 +

999

+ <Data><Repeat>0</Repeat><Hidden>0</Hidden><Reward><Asset>PfUiMissionRewardDBDO</Asset></Reward><Random>0</Random><Title><Text>Follow Hiccup</Text><ID>939803</ID></Title></Data> + false + 0 + + + 2 + False + false + + + 1 + False + false + + + all + true + 4 + 1 + + 1 + 2883 + 5943 + 0 + + + + 8 + 207960 + 0 + + 5943 + FTUE2020-14: Follow Hiccup + <Data><Setup><Scene>HubFTUEDO</Scene><Asset>PfDWToothlessAlphaHiccupRiderPortal</Asset><Location>PfMarker_HiccupAndToothless</Location><Recursive>false</Recursive><Persistent>false</Persistent></Setup><Offer><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>Now that you've got the hang of this, follow me and Toothless! Come on, I want to show you something cool!</Text><ID>939813</ID><ItemID>0</ItemID><Priority>0</Priority></Offer><Objective><Pair><Key>Scene</Key><Value>HubSchoolDO</Value></Pair><Pair><Key>Location</Key><Value>PfMarker_LoadSchool</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Visit</Type><Title><Text>Follow Hiccup and Toothless</Text><ID>942393</ID></Title><Desc><Text>Follow Hiccup and Toothless</Text><ID>942393</ID></Desc></Data> + 0 + + + 1 +

6

+ + 1 + 10897 + 20882 + 207960 + true + 1 + 1 + + 0 + + 0 + 0 +
+
+ + 5930 + FTUE2020-01: Talk to Hiccup + <Data><Offer><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>Hey, are you all right, {{Name}}? That cave collapse was no joke. Give me a hand, will you? Use the movement controls to walk here and {{input}} on me.</Text><ID>939815</ID><ItemID>0</ItemID><Priority>0</Priority></Offer><End><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>I'm glad you're okay. I guess our investigation about potential Dragon Hunters lurking in these caves paid off, it seems they had a camp right under our feet this entire time.</Text><ID>939816</ID><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Scene</Key><Value>HubFTUEDO</Value></Pair><Pair><Key>NPC</Key><Value>PfDWHiccup</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Meet</Type><Title><Text>Walk forward and {{input}} on Hiccup</Text><ID>929442</ID></Title></Data> + 0 + + + 5931 + FTUE2020-02: Find axe + <Data><Offer><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>I’d like to meet up with Toothless again, but there are a few cages here that might have dragons in them.@@We can’t just leave them. I’ll start opening this other one, do you think you could handle the one on your right?@@That lock looks rusted, though... Maybe there’s an axe somewhere around here...</Text><ID>939818</ID><ItemID>0</ItemID><Priority>0</Priority></Offer><Objective><Pair><Key>Scene</Key><Value>HubFTUEDO</Value></Pair><Pair><Key>Name</Key><Value>PfCollectDWAxe</Value></Pair><Pair><Key>Quantity</Key><Value>1</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Collect</Type><Title><Text>Find the Axe in the Cave</Text><ID>939817</ID></Title><Desc><Text>Find the Axe in the Cave</Text><ID>939817</ID></Desc></Data> + 0 + + + 5932 + FTUE2020-03: Chop padlock + <Data><Offer><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>Perfect! That axe looks strong enough. I'm sure it can chop the padlock off the dragon cage without a problem!</Text><ID>939820</ID><ItemID>0</ItemID><Priority>0</Priority></Offer><End><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>All right, that did the trick!</Text><ID>939821</ID><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Scene</Key><Value>HubFTUEDO</Value></Pair><Pair><Key>Location</Key><Value>ChoppableCage</Value></Pair><Pair><Key>Name</Key><Value>Chop</Value></Pair><Pair><Key>ItemName</Key><Value>PfDragonCageChop</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Action</Type><Title><Text>Chop the Padlock on the Dragon Cage</Text><ID>939819</ID></Title><Desc><Text>Chop the Padlock on the Dragon Cage</Text><ID>939819</ID></Desc></Data> + 0 + + + 5935 + FTUE2020-06: Age Up + <Data><Setup><Scene>HubFTUEDO</Scene><Asset>PfDWHiccup</Asset><Location>PfMarker_HiccupCaveIn</Location><Recursive>false</Recursive><Persistent>false</Persistent></Setup><Offer><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>This will allow us to take a dragon straight to Broad Wing Stage! I'll show you how.</Text><ID>939823</ID><ItemID>0</ItemID><Priority>0</Priority></Offer><Objective><Pair><Key>Scene</Key><Value>HubFTUEDO</Value></Pair><Pair><Key>Name</Key><Value>AgeUp</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Action</Type><Title><Text>Age Up {{dragon name}}</Text><ID>942394</ID></Title><Desc><Text>Age Up {{dragon name}}</Text><ID>942394</ID></Desc><AutoComplete><Pair><Key>RaisedPetStage</Key><Value>ADULT</Value></Pair></AutoComplete></Data> + 0 + + + 5936 + FTUE2020-07: Shoot + <Data><Setup><Scene>HubFTUEDO</Scene><Asset>PfDWHiccup</Asset><Location>PfMarker_HiccupCaveIn</Location><Recursive>false</Recursive><Persistent>false</Persistent></Setup><Offer><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>All right, let's try this now! Look for a weak spot in the rocks, then have {{dragon name}} shoot some fireballs!@@{{Input}} on the cave-in and select the [c][3eebff]Fire[/c][ffffff] button.</Text><ID>939825</ID><ItemID>0</ItemID><Priority>0</Priority></Offer><Objective><Pair><Key>Scene</Key><Value>HubFTUEDO</Value></Pair><Pair><Key>Location</Key><Value>PfCaveInTarget</Value></Pair><Pair><Key>Name</Key><Value>LightFire</Value></Pair><Pair><Key>ItemName</Key><Value>PfCaveInTarget</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Action</Type><Title><Text>{{Input}} on the Cave-In</Text><ID>942395</ID></Title><Desc><Text>{{Input}} on the Cave-In</Text><ID>942395</ID></Desc></Data> + 0 + + + 5937 + FTUE2020-08: Collect Box + <Data><Setup><Scene>HubFTUEDO</Scene><Asset>PfDWHiccup</Asset><Location>PfMarker_HiccupCaveIn</Location><Recursive>false</Recursive><Persistent>false</Persistent></Setup><Offer><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>That was perfect!</Text><ID>939828</ID><ItemID>0</ItemID><Priority>0</Priority></Offer><Offer><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>Wait... What's that? Is that a chest?</Text><ID>939829</ID><ItemID>0</ItemID><Priority>1</Priority></Offer><End><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>A box of dragon eggs...@@Those Dragon Hunters are getting bolder than we expected.</Text><ID>941113</ID><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Scene</Key><Value>HubFTUEDO</Value></Pair><Pair><Key>Location</Key><Value>PfCollectDWOpenArcticChest</Value></Pair><Pair><Key>Name</Key><Value>PfCollectDWOpenArcticChest</Value></Pair><Pair><Key>Quantity</Key><Value>1</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Collect</Type><Title><Text>Pick up the Chest</Text><ID>939827</ID></Title><Desc><Text>Pick up the Chest</Text><ID>939827</ID></Desc></Data> + 0 + + + 5938 + FTUE2020-09: Exit cave + <Data><Setup><Scene>HubFTUEDO</Scene><Asset>PfDWHiccup</Asset><Location>PfMarker_HiccupChest</Location><Recursive>false</Recursive><Persistent>false</Persistent></Setup><Offer><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>Well, one problem at a time. {{Name}}, can you follow the path of the cave and figure out a way to set up a signal? @@My friends should be nearby, they'll be able to help us out!</Text><ID>939831</ID><ItemID>0</ItemID><Priority>0</Priority></Offer><Objective><Pair><Key>Scene</Key><Value>HubFTUEDO</Value></Pair><Pair><Key>Name</Key><Value>PfMarker_CaveExit</Value></Pair><Pair><Key>Range</Key><Value>3</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Visit</Type><Title><Text>Leave the Cave</Text><ID>939830</ID></Title><Desc><Text>Leave the Cave</Text><ID>939830</ID></Desc></Data> + 0 + + + 5940 + FTUE2020-11: Collect Leaves + <Data><Setup><Scene>HubFTUEDO</Scene><Asset>PfDWHiccup</Asset><Location>PfMarker_HiccupFire</Location><Recursive>false</Recursive><Persistent>false</Persistent></Setup><Offer><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>I’ll get some more wood stacked; can you grab some green leaves to help make this fire more smokey?</Text><ID>939833</ID><ItemID>0</ItemID><Priority>0</Priority></Offer><End><Type>CutScene</Type><Asset>RS_DATA/PfGrpFTUE2020T11CS.unity3d/PfGrpFTUE2020T11CS</Asset><ItemID>0</ItemID><Priority>0</Priority></End><End><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWAstrid</NPC><Text>There you are! Glad to see you're safe. @@Oh? I don’t think we’ve met, have we?@@{{Name}}? It's great to meet you, I’m Astrid. Seems that Hiccup's gotten himself in over his head again, huh? @@He's lucky he has good people like you around to help him out. And that’s one incredible dragon you’ve found, wow!</Text><ID>941114</ID><ItemID>0</ItemID><Priority>1</Priority></End><Objective><Pair><Key>Scene</Key><Value>HubFTUEDO</Value></Pair><Pair><Key>Name</Key><Value>PfCollectFTUELeaf</Value></Pair><Pair><Key>Quantity</Key><Value>5</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Collect</Type><Title><Text>Collect Green Leaves</Text><ID>942396</ID></Title><Desc><Text>Collect Green Leaves</Text><ID>942396</ID></Desc></Data> + 0 + + + 5941 + FTUE2020-12: Mount + <Data><Offer><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>{{Name}} bonded with {{dragon name}} right away, you should’ve seen it, Astrid. I bet they’ll be flying together in no time. Speaking of which...@@{{Name}} let’s do a quick flying lesson. I’ll show you the ropes!@@First, {{input}} on the [c][3eebff]Mount[/c][ffffff] button to climb aboard your dragon.</Text><ID>939835</ID><ItemID>0</ItemID><Priority>0</Priority></Offer><Objective><Pair><Key>Name</Key><Value>MountDragon</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Action</Type><Title><Text>Mount {{dragon name}}</Text><ID>939834</ID></Title><Desc><Text>Mount {{dragon name}}</Text><ID>939834</ID></Desc><AutoComplete><Pair><Key>Mounted</Key><Value>true</Value></Pair></AutoComplete></Data> + 0 + + + 5942 + FTUE2020-13: Fly through rings + <Data><Offer><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>Alright! {{dragon name}} is ready to go. Now, you just have to learn how to fly! Why don't you get used to the controls and soar through these rings?@@{{Input}} on the [c][3eebff]Jump[/c][ffffff] button [c][3eebff]twice[/c][ffffff] to get up into the air and we can go from there.</Text><ID>939837</ID><ItemID>0</ItemID><Priority>0</Priority></Offer><End><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>You're a natural!</Text><ID>905008</ID><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Scene</Key><Value>HubFTUEDO</Value></Pair><Pair><Key>Location</Key><Value>PfDWToothlessAlphaGuide</Value></Pair><Pair><Key>Name</Key><Value>PfCollectRing</Value></Pair><Pair><Key>Quantity</Key><Value>5</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Collect</Type><Title><Text>Fly through the Rings</Text><ID>938870</ID></Title><Desc><Text>Fly through the Rings</Text><ID>938870</ID></Desc></Data> + 0 + + + 5944 + FTUE2020-15: Deliver Headmaster + <Data><Offer><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>Welcome to the School of Dragons! I have a feeling you'll fit right in.@@Can you give the box of dragon eggs that you found to the Headmaster of the School? You can't miss him – he's the stout one with all the hair!</Text><ID>939840</ID><ItemID>0</ItemID><Priority>1</Priority></Offer><Offer><Type>CutScene</Type><Asset>RS_DATA/PfGrpFTUE2020T14CS.unity3d/PfGrpFTUE2020T14CS</Asset><ItemID>0</ItemID><Priority>0</Priority></Offer><End><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHeadmaster</NPC><Text>You come highly recommended from the Chieftain of Berk himself. Welcome, {{Name}}. So, are you ready to learn how to become the Ultimate Dragon Trainer?</Text><ID>939841</ID><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Scene</Key><Value>HubSchoolDO</Value></Pair><Pair><Key>NPC</Key><Value>PfDWHeadmaster</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Meet</Type><Title><Text>Deliver the Dragon Eggs to the Headmaster</Text><ID>942397</ID></Title><Desc><Text>Deliver the Dragon Eggs to the Headmaster</Text><ID>942397</ID></Desc></Data> + 0 + + + 6619 + FTUE2020-16: Explain Branch Quest + <Data><Offer><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHeadmaster</NPC><Text>Now {{Name}}, you can learn about the many things we have to offer here at the School through our [c][3eebff]Branch Quests[/c][ffffff]</Text><ID>941799</ID><ItemID>0</ItemID><Priority>0</Priority></Offer><End><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHeadmaster</NPC><Text>Feel free to also explore the campus, you might even encounter other students. @@We are happy to have you here with us!</Text><ID>941800</ID><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Scene</Key><Value>HubSchoolDO</Value></Pair><Pair><Key>Name</Key><Value>CompleteTutorial</Value></Pair><Pair><Key>ItemName</Key><Value>BranchUiTutorial</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Action</Type><Title><Text>Check out the Branch Quests</Text><ID>941798</ID></Title><Desc><Text>Check out the Branch Quests</Text><ID>941798</ID></Desc></Data> + 0 + + + 5 +

1

+ + 1 + 3 + 0 + 201320 + true + 5 + 5 + + 0 + + 0 + 0 +
+ + 100 +

2

+ + 1 + 23 + 0 + 201320 + true + 100 + 100 + + 0 + + 0 + 0 +
+ + 50 +

8

+ + 1 + 609 + 0 + 201320 + true + 50 + 50 + + 0 + + 0 + 0 +
+ + 50 +

12

+ + 1 + 913 + 0 + 201320 + true + 50 + 50 + + 0 + + 0 + 0 +
+
\ No newline at end of file diff --git a/src/Schema/Mission.cs b/src/Schema/Mission.cs new file mode 100644 index 0000000..66c5969 --- /dev/null +++ b/src/Schema/Mission.cs @@ -0,0 +1,57 @@ +using System.Xml.Serialization; + +namespace sodoff.Schema; + +[XmlRoot(ElementName = "Mission", Namespace = "")] +public class Mission { + [XmlElement(ElementName = "I")] + public int MissionID; + + [XmlElement(ElementName = "N")] + public string Name; + + [XmlElement(ElementName = "G")] + public int GroupID; + + [XmlElement(ElementName = "P", IsNullable = true)] + public int? ParentID; + + [XmlElement(ElementName = "S")] + public string Static; + + [XmlElement(ElementName = "A")] + public bool Accepted; + + [XmlElement(ElementName = "C")] + public int Completed; + + [XmlElement(ElementName = "R")] + public string Rule; + + [XmlElement(ElementName = "MR")] + public MissionRule MissionRule; + + [XmlElement(ElementName = "V")] + public int VersionID; + + [XmlElement(ElementName = "AID")] + public int AchievementID; + + [XmlElement(ElementName = "AAID")] + public int AcceptanceAchievementID; + + [XmlElement(ElementName = "M")] + public List Missions; + + [XmlElement(ElementName = "Task")] + public List Tasks; + + [XmlElement(ElementName = "AR")] + public List Rewards; + + [XmlElement(ElementName = "AAR")] + public List AcceptanceRewards; + + [XmlElement(ElementName = "RPT")] + public bool Repeatable; +} diff --git a/src/Schema/MissionCompletedResult.cs b/src/Schema/MissionCompletedResult.cs new file mode 100644 index 0000000..56fbd72 --- /dev/null +++ b/src/Schema/MissionCompletedResult.cs @@ -0,0 +1,13 @@ +using System.Xml.Serialization; + +namespace sodoff.Schema; + +[XmlRoot(ElementName = "MissionCompletedResult", Namespace = "")] +[Serializable] +public class MissionCompletedResult { + [XmlElement(ElementName = "M")] + public int MissionID; + + [XmlElement(ElementName = "A")] + public AchievementReward[] Rewards; +} diff --git a/src/Schema/MissionCriteria.cs b/src/Schema/MissionCriteria.cs new file mode 100644 index 0000000..5ff9d2d --- /dev/null +++ b/src/Schema/MissionCriteria.cs @@ -0,0 +1,22 @@ +using System.Xml.Serialization; + +namespace sodoff.Schema; + +[XmlRoot(ElementName = "MissionCriteria", Namespace = "")] +[Serializable] +public class MissionCriteria { + [XmlElement(ElementName = "Type")] + public string Type; + + [XmlElement(ElementName = "Ordered")] + public bool Ordered; + + [XmlElement(ElementName = "Min")] + public int Min; + + [XmlElement(ElementName = "Repeat")] + public int Repeat; + + [XmlElement(ElementName = "RuleItems")] + public List RuleItems; +} diff --git a/src/Schema/MissionGroup.cs b/src/Schema/MissionGroup.cs new file mode 100644 index 0000000..f2728c3 --- /dev/null +++ b/src/Schema/MissionGroup.cs @@ -0,0 +1,25 @@ +using System.Xml.Serialization; + +namespace sodoff.Schema; + +[XmlRoot(ElementName = "MGF", Namespace = "")] +[Serializable] +public class MissionGroup { + [XmlElement(ElementName = "P")] + public int ProductID; + + [XmlElement(ElementName = "MG")] + public int MissionGroupID; + + [XmlElement(ElementName = "DMC")] + public int DailyMissionCount; + + [XmlElement(ElementName = "CC")] + public int CompletionCount; + + [XmlElement(ElementName = "D")] + public int Day; + + [XmlElement(ElementName = "RC")] + public int RewardCycle; +} diff --git a/src/Schema/MissionRule.cs b/src/Schema/MissionRule.cs new file mode 100644 index 0000000..2a1877f --- /dev/null +++ b/src/Schema/MissionRule.cs @@ -0,0 +1,13 @@ +using System.Xml.Serialization; + +namespace sodoff.Schema; + +[XmlRoot(ElementName = "MissionRule", Namespace = "")] +[Serializable] +public class MissionRule { + [XmlElement(ElementName = "Prerequisites")] + public List Prerequisites; + + [XmlElement(ElementName = "Criteria")] + public MissionCriteria Criteria; +} diff --git a/src/Schema/PrerequisiteItem.cs b/src/Schema/PrerequisiteItem.cs new file mode 100644 index 0000000..69cb33d --- /dev/null +++ b/src/Schema/PrerequisiteItem.cs @@ -0,0 +1,19 @@ +using System.Xml.Serialization; + +namespace sodoff.Schema; + +[XmlRoot(ElementName = "PrerequisiteItem", Namespace = "")] +[Serializable] +public class PrerequisiteItem { + [XmlElement(ElementName = "Type")] + public PrerequisiteRequiredType Type; + + [XmlElement(ElementName = "Value")] + public string Value; + + [XmlElement(ElementName = "Quantity")] + public short Quantity; + + [XmlElement(ElementName = "ClientRule")] + public bool ClientRule; +} diff --git a/src/Schema/PrerequisiteRequiredType.cs b/src/Schema/PrerequisiteRequiredType.cs new file mode 100644 index 0000000..73fe6fb --- /dev/null +++ b/src/Schema/PrerequisiteRequiredType.cs @@ -0,0 +1,20 @@ +using System.Xml.Serialization; + +namespace sodoff.Schema; + +public enum PrerequisiteRequiredType { + [XmlEnum("1")] + Member = 1, + [XmlEnum("2")] + Accept, + [XmlEnum("3")] + Mission, + [XmlEnum("4")] + Rank, + [XmlEnum("5")] + DateRange, + [XmlEnum("7")] + Item = 7, + [XmlEnum("8")] + Event +} diff --git a/src/Schema/RuleItem.cs b/src/Schema/RuleItem.cs new file mode 100644 index 0000000..5c106d9 --- /dev/null +++ b/src/Schema/RuleItem.cs @@ -0,0 +1,19 @@ +using System.Xml.Serialization; + +namespace sodoff.Schema; + +[XmlRoot(ElementName = "RuleItem", Namespace = "")] +[Serializable] +public class RuleItem { + [XmlElement(ElementName = "Type")] + public RuleItemType Type; + + [XmlElement(ElementName = "MissionID")] + public int MissionID; + + [XmlElement(ElementName = "ID")] + public int ID; + + [XmlElement(ElementName = "Complete")] + public int Complete; +} diff --git a/src/Schema/RuleItemType.cs b/src/Schema/RuleItemType.cs new file mode 100644 index 0000000..45e9722 --- /dev/null +++ b/src/Schema/RuleItemType.cs @@ -0,0 +1,10 @@ +using System.Xml.Serialization; + +namespace sodoff.Schema; + +public enum RuleItemType { + [XmlEnum("1")] + Task = 1, + [XmlEnum("2")] + Mission +} diff --git a/src/Schema/SetTaskStateResult.cs b/src/Schema/SetTaskStateResult.cs new file mode 100644 index 0000000..df7e993 --- /dev/null +++ b/src/Schema/SetTaskStateResult.cs @@ -0,0 +1,23 @@ +using System.Xml.Serialization; + +namespace sodoff.Schema; + +[XmlRoot(ElementName = "SetTaskStateResult", Namespace = "")] +[Serializable] +public class SetTaskStateResult { + [XmlElement(ElementName = "S")] + public bool Success; + + [XmlElement(ElementName = "T")] + public SetTaskStateStatus Status; + + [XmlElement(ElementName = "A")] + public string AdditionalStatusParams; + + [XmlElement(ElementName = "R")] + public MissionCompletedResult[] MissionsCompleted; + + // TODO: Not needed now (requires many additional schemas) + // [XmlElement(ElementName = "C")] + // public CommonInventoryResponse CommonInvRes; +} diff --git a/src/Schema/SetTaskStateStatus.cs b/src/Schema/SetTaskStateStatus.cs new file mode 100644 index 0000000..f4d5f47 --- /dev/null +++ b/src/Schema/SetTaskStateStatus.cs @@ -0,0 +1,38 @@ +using System.Xml.Serialization; + +namespace sodoff.Schema; + +public enum SetTaskStateStatus { + [XmlEnum("1")] + RequiresMembership = 1, + [XmlEnum("2")] + RequiresAcceptance, + [XmlEnum("3")] + NotWithinDateRange, + [XmlEnum("4")] + PreRequisiteMissionIncomplete, + [XmlEnum("5")] + UserRankLessThanMinRank, + [XmlEnum("6")] + UserRankGreaterThanMaxRank, + [XmlEnum("7")] + UserHasNoRankData, + [XmlEnum("8")] + MissionStateNotFound, + [XmlEnum("9")] + RequiredPriorTaskIncomplete, + [XmlEnum("10")] + ParentsTaskIncomplete, + [XmlEnum("11")] + ParentsSubMissionIncomplete, + [XmlEnum("12")] + TaskCanBeDone, + [XmlEnum("13")] + OneOrMoreMissionsHaveNoRewardsAttached, + [XmlEnum("14")] + PayLoadUpdated, + [XmlEnum("15")] + NonRepeatableMission, + [XmlEnum("255")] + Unknown = 255 +} diff --git a/src/Schema/Task.cs b/src/Schema/Task.cs new file mode 100644 index 0000000..1f66a0b --- /dev/null +++ b/src/Schema/Task.cs @@ -0,0 +1,28 @@ +using System.Diagnostics; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Serialization; + +namespace sodoff.Schema; + +[XmlRoot(ElementName = "Task", Namespace = "")] +[Serializable] +public class Task { + [XmlElement(ElementName = "I")] + public int TaskID; + + [XmlElement(ElementName = "N")] + public string Name; + + [XmlElement(ElementName = "S")] + public string Static; + + [XmlElement(ElementName = "C")] + public int Completed; + + [XmlElement(ElementName = "F")] + public bool Failed; + + [XmlElement(ElementName = "P")] + public string Payload; +} diff --git a/src/Schema/UserMissionStateResult.cs b/src/Schema/UserMissionStateResult.cs new file mode 100644 index 0000000..13392ce --- /dev/null +++ b/src/Schema/UserMissionStateResult.cs @@ -0,0 +1,23 @@ +using System.Xml.Serialization; + +namespace sodoff.Schema; + +[XmlRoot(ElementName = "UserMissionStateResult", Namespace = "")] +[Serializable] +public class UserMissionStateResult { + [XmlElement(ElementName = "UID")] + public Guid UserID; + + [XmlElement(ElementName = "Mission")] + public List Missions; + + [XmlElement(ElementName = "UTA")] + public List UserTimedAchievement; + + // NOTE: It appears that the server doesn't send this + // [XmlElement(ElementName = "D")] + // public int Day; + + [XmlElement(ElementName = "MG")] + public List MissionGroup; +} diff --git a/src/Schema/UserTimedAchievement.cs b/src/Schema/UserTimedAchievement.cs new file mode 100644 index 0000000..cf742e3 --- /dev/null +++ b/src/Schema/UserTimedAchievement.cs @@ -0,0 +1,40 @@ +using System.Xml.Serialization; + +namespace sodoff.Schema; + +[XmlRoot(ElementName = "UTA", Namespace = "")] +[Serializable] +public class UserTimedAchievement { + [XmlElement(ElementName = "uid")] + public Guid? UserID; + + [XmlElement(ElementName = "uta")] + public int UserTimedAchievementMapID; + + [XmlElement(ElementName = "a")] + public int AchievementID; + + [XmlElement(ElementName = "s")] + public int Sequence; + + [XmlElement(ElementName = "st")] + public int StatusID; + + [XmlElement(ElementName = "c")] + public DateTime CreatedDate; + + [XmlElement(ElementName = "u", IsNullable = true)] + public DateTime? UpdatedDate; + + [XmlElement(ElementName = "isdel")] + public bool IsDeleted; + + [XmlElement(ElementName = "gid")] + public int GroupID; + + [XmlElement(ElementName = "ar")] + public List AchievementReward; + + [XmlElement(ElementName = "sid")] + public int SetID; +} diff --git a/src/Util/XmlUtil.cs b/src/Util/XmlUtil.cs index e54ea73..ec31f93 100644 --- a/src/Util/XmlUtil.cs +++ b/src/Util/XmlUtil.cs @@ -1,4 +1,5 @@ -using System.Xml.Serialization; +using System.Reflection; +using System.Xml.Serialization; namespace sodoff.Util; public class XmlUtil { @@ -15,4 +16,15 @@ public class XmlUtil { return writer.ToString(); } } + + public static string ReadResourceXmlString(string name) { + string result = ""; + var assembly = Assembly.GetExecutingAssembly(); + string resourceName = assembly.GetManifestResourceNames().Single(str => str.EndsWith($"{name}.xml")); + + using (Stream stream = assembly.GetManifestResourceStream(resourceName)) + using (StreamReader reader = new StreamReader(stream)) + result = reader.ReadToEnd(); + return result; + } } diff --git a/src/sodoff.csproj b/src/sodoff.csproj index 670ef0b..472717a 100644 --- a/src/sodoff.csproj +++ b/src/sodoff.csproj @@ -14,6 +14,7 @@ + @@ -22,6 +23,9 @@ PreserveNewest + + PreserveNewest + @@ -30,5 +34,8 @@ PreserveNewest + + PreserveNewest +