mirror of
https://github.com/SoDOff-Project/sodoff.git
synced 2025-10-11 08:18:49 -07:00
Merge branch 'WorldOfJumpStart'
add support for World of JumpStart, MathBlaster and some other JS online games
This commit is contained in:
commit
a420c774d1
@ -90,6 +90,20 @@ public class AchievementController : Controller {
|
||||
return Ok("OK");
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("AchievementWebService.asmx/GetUserAchievementInfo")] // used by World Of Jumpstart
|
||||
public IActionResult GetUserAchievementInfo([FromForm] Guid apiToken) {
|
||||
Viking? viking = ctx.Sessions.FirstOrDefault(x => x.ApiToken == apiToken).Viking;
|
||||
|
||||
if (viking != null) {
|
||||
return Ok(
|
||||
achievementService.CreateUserAchievementInfo(viking, AchievementPointTypes.PlayerXP)
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("AchievementWebService.asmx/GetAchievementsByUserID")]
|
||||
|
@ -33,11 +33,18 @@ public class AuthenticationController : Controller {
|
||||
[Route("v3/AuthenticationWebService.asmx/LoginParent")]
|
||||
[DecryptRequest("parentLoginData")]
|
||||
[EncryptResponse]
|
||||
public IActionResult LoginParent() {
|
||||
public IActionResult LoginParent([FromForm] string apiKey) {
|
||||
ParentLoginData data = XmlUtil.DeserializeXml<ParentLoginData>(Request.Form["parentLoginData"]);
|
||||
|
||||
// Authenticate the user
|
||||
User? user = ctx.Users.FirstOrDefault(e => e.Username == data.UserName);
|
||||
User? user = null;
|
||||
uint gameVersion = ClientVersion.GetVersion(apiKey);
|
||||
if (gameVersion == ClientVersion.WoJS || gameVersion == ClientVersion.MB) {
|
||||
user = ctx.Users.FirstOrDefault(e => e.Email == data.UserName);
|
||||
} else {
|
||||
user = ctx.Users.FirstOrDefault(e => e.Username == data.UserName);
|
||||
}
|
||||
|
||||
if (user is null || new PasswordHasher<object>().VerifyHashedPassword(null, user.Password, data.Password) != PasswordVerificationResult.Success) {
|
||||
return Ok(new ParentLoginInfo { Status = MembershipUserStatus.InvalidPassword });
|
||||
}
|
||||
@ -52,6 +59,11 @@ public class AuthenticationController : Controller {
|
||||
ctx.Sessions.Add(session);
|
||||
ctx.SaveChanges();
|
||||
|
||||
var childList = new List<sodoff.Schema.UserLoginInfo>();
|
||||
foreach (var viking in user.Vikings) {
|
||||
childList.Add(new sodoff.Schema.UserLoginInfo{UserName = viking.Name, UserID = viking.Uid.ToString()});
|
||||
}
|
||||
|
||||
var response = new ParentLoginInfo {
|
||||
UserName = user.Username,
|
||||
//Email = user.Email, /* disabled to avoid put email in client debug logs */
|
||||
@ -59,7 +71,8 @@ public class AuthenticationController : Controller {
|
||||
UserID = user.Id.ToString(),
|
||||
Status = MembershipUserStatus.Success,
|
||||
SendActivationReminder = false,
|
||||
UnAuthorized = false
|
||||
UnAuthorized = false,
|
||||
ChildList = childList.ToArray()
|
||||
};
|
||||
|
||||
return Ok(response);
|
||||
@ -121,10 +134,25 @@ public class AuthenticationController : Controller {
|
||||
return Ok(new UserInfo {});
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("AuthenticationWebService.asmx/IsValidApiToken")] // used by World Of Jumpstart (FutureLand)
|
||||
public IActionResult IsValidApiToken_V1([FromForm] Guid? apiToken) {
|
||||
if (apiToken is null)
|
||||
return Ok(false);
|
||||
User? user = ctx.Sessions.FirstOrDefault(e => e.ApiToken == apiToken)?.User;
|
||||
Viking? viking = ctx.Sessions.FirstOrDefault(e => e.ApiToken == apiToken)?.Viking;
|
||||
if (user is null && viking is null)
|
||||
return Ok(false);
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("AuthenticationWebService.asmx/IsValidApiToken_V2")]
|
||||
public IActionResult IsValidApiToken([FromForm] Guid apiToken) {
|
||||
public IActionResult IsValidApiToken([FromForm] Guid? apiToken) {
|
||||
if (apiToken is null)
|
||||
return Ok(ApiTokenStatus.TokenNotFound);
|
||||
User? user = ctx.Sessions.FirstOrDefault(e => e.ApiToken == apiToken)?.User;
|
||||
Viking? viking = ctx.Sessions.FirstOrDefault(e => e.ApiToken == apiToken)?.Viking;
|
||||
if (user is null && viking is null)
|
||||
|
@ -20,10 +20,11 @@ public class ContentController : Controller {
|
||||
private AchievementService achievementService;
|
||||
private InventoryService inventoryService;
|
||||
private GameDataService gameDataService;
|
||||
private DisplayNamesService displayNamesService;
|
||||
private Random random = new Random();
|
||||
private readonly IOptions<ApiServerConfig> config;
|
||||
|
||||
public ContentController(DBContext ctx, KeyValueService keyValueService, ItemService itemService, MissionService missionService, RoomService roomService, AchievementService achievementService, InventoryService inventoryService, GameDataService gameDataService, IOptions<ApiServerConfig> config) {
|
||||
public ContentController(DBContext ctx, KeyValueService keyValueService, ItemService itemService, MissionService missionService, RoomService roomService, AchievementService achievementService, InventoryService inventoryService, GameDataService gameDataService, DisplayNamesService displayNamesService, IOptions<ApiServerConfig> config) {
|
||||
this.ctx = ctx;
|
||||
this.keyValueService = keyValueService;
|
||||
this.itemService = itemService;
|
||||
@ -32,9 +33,98 @@ public class ContentController : Controller {
|
||||
this.achievementService = achievementService;
|
||||
this.inventoryService = inventoryService;
|
||||
this.gameDataService = gameDataService;
|
||||
this.displayNamesService = displayNamesService;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/GetRaisedPetGrowthStates")] // used by World Of Jumpstart 1.1
|
||||
public RaisedPetGrowthState[] GetRaisedPetGrowthStates()
|
||||
{
|
||||
return new RaisedPetGrowthState[] {
|
||||
new RaisedPetGrowthState {GrowthStateID = 0, Name = "none"},
|
||||
new RaisedPetGrowthState {GrowthStateID = 1, Name = "powerup"},
|
||||
new RaisedPetGrowthState {GrowthStateID = 2, Name = "find"},
|
||||
new RaisedPetGrowthState {GrowthStateID = 3, Name = "eggInHand"},
|
||||
new RaisedPetGrowthState {GrowthStateID = 4, Name = "hatching"},
|
||||
new RaisedPetGrowthState {GrowthStateID = 5, Name = "baby"},
|
||||
new RaisedPetGrowthState {GrowthStateID = 6, Name = "child"},
|
||||
new RaisedPetGrowthState {GrowthStateID = 7, Name = "teen"},
|
||||
new RaisedPetGrowthState {GrowthStateID = 8, Name = "adult"},
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
//[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/GetProduct")] // used by World Of Jumpstart
|
||||
[VikingSession(UseLock=false)]
|
||||
public string? GetProduct(Viking viking, [FromForm] string apiKey) {
|
||||
return Util.SavedData.Get(
|
||||
viking,
|
||||
ClientVersion.GetVersion(apiKey)
|
||||
);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
//[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/SetProduct")] // used by World Of Jumpstart
|
||||
[VikingSession]
|
||||
public bool SetProduct(Viking viking, [FromForm] string contentXml, [FromForm] string apiKey) {
|
||||
Util.SavedData.Set(
|
||||
viking,
|
||||
ClientVersion.GetVersion(apiKey),
|
||||
contentXml
|
||||
);
|
||||
ctx.SaveChanges();
|
||||
return true;
|
||||
}
|
||||
|
||||
// NOTE: "Pet" (Petz) system (GetCurrentPetByUserID, GetCurrentPet, SetCurrentPet, DelCurrentPet) is a totally different system than "RaisedPet" (Dragons)
|
||||
|
||||
[HttpPost]
|
||||
//[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/GetCurrentPetByUserID")] // used by World Of Jumpstart
|
||||
public string GetCurrentPetByUserID([FromForm] Guid userId) {
|
||||
return GetCurrentPet(ctx.Vikings.FirstOrDefault(e => e.Uid == userId));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
//[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/GetCurrentPet")] // used by World Of Jumpstart
|
||||
[VikingSession]
|
||||
public string GetCurrentPet(Viking viking) {
|
||||
string? ret = Util.SavedData.Get(
|
||||
viking,
|
||||
ClientVersion.WoJS + 1
|
||||
);
|
||||
if (ret is null)
|
||||
return XmlUtil.SerializeXml<PetData>(null);
|
||||
return ret;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/SetCurrentPet")] // used by World Of Jumpstart
|
||||
[VikingSession]
|
||||
public bool SetCurrentPet(Viking viking, [FromForm] string? contentXml) {
|
||||
Util.SavedData.Set(
|
||||
viking,
|
||||
ClientVersion.WoJS + 1,
|
||||
contentXml
|
||||
);
|
||||
ctx.SaveChanges();
|
||||
return true;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/DelCurrentPet")] // used by World Of Jumpstart
|
||||
[VikingSession]
|
||||
public bool DelCurrentPet(Viking viking) {
|
||||
return SetCurrentPet(viking, null);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/GetDefaultNameSuggestion")]
|
||||
@ -315,6 +405,40 @@ public class ContentController : Controller {
|
||||
return 0;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/GetAvatar")] // used by World Of Jumpstart
|
||||
[VikingSession(UseLock=false)]
|
||||
public IActionResult GetAvatar(Viking viking) {
|
||||
AvatarData avatarData = XmlUtil.DeserializeXml<AvatarData>(viking.AvatarSerialized);
|
||||
avatarData.Id = viking.Id;
|
||||
return Ok(avatarData);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/SetAvatar")] // used by World Of Jumpstart
|
||||
[VikingSession]
|
||||
public IActionResult SetAvatarV1(Viking viking, [FromForm] string contentXML) {
|
||||
if (viking.AvatarSerialized != null) {
|
||||
AvatarData dbAvatarData = XmlUtil.DeserializeXml<AvatarData>(viking.AvatarSerialized);
|
||||
AvatarData reqAvatarData = XmlUtil.DeserializeXml<AvatarData>(contentXML);
|
||||
|
||||
int dbAvatarVersion = GetAvatarVersion(dbAvatarData);
|
||||
int reqAvatarVersion = GetAvatarVersion(reqAvatarData);
|
||||
|
||||
if (dbAvatarVersion > reqAvatarVersion) {
|
||||
// do not allow override newer version avatar data by older version
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
|
||||
viking.AvatarSerialized = contentXML;
|
||||
ctx.SaveChanges();
|
||||
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("V2/ContentWebService.asmx/SetAvatar")]
|
||||
@ -363,7 +487,10 @@ public class ContentController : Controller {
|
||||
raisedPetData.IsSelected = false; // The api returns false, not sure why
|
||||
raisedPetData.CreateDate = new DateTime(DateTime.Now.Ticks);
|
||||
raisedPetData.UpdateDate = new DateTime(DateTime.Now.Ticks);
|
||||
if (petTypeID == 2)
|
||||
raisedPetData.GrowthState = new RaisedPetGrowthState { Name = "BABY" };
|
||||
else
|
||||
raisedPetData.GrowthState = new RaisedPetGrowthState { Name = "POWERUP" };
|
||||
int imageSlot = (viking.Images.Select(i => i.ImageSlot).DefaultIfEmpty(-1).Max() + 1);
|
||||
raisedPetData.ImagePosition = imageSlot;
|
||||
// NOTE: Placing an egg into a hatchery slot calls CreatePet, but doesn't SetImage.
|
||||
@ -454,6 +581,28 @@ public class ContentController : Controller {
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/SetRaisedPet")] // used by World Of Jumpstart
|
||||
[VikingSession]
|
||||
public IActionResult SetRaisedPetv1(Viking viking, [FromForm] string raisedPetData) {
|
||||
RaisedPetData petData = XmlUtil.DeserializeXml<RaisedPetData>(raisedPetData);
|
||||
|
||||
// Find the dragon
|
||||
Dragon? dragon = viking.Dragons.FirstOrDefault(e => e.Id == petData.RaisedPetID);
|
||||
if (dragon is null) {
|
||||
return Ok(new SetRaisedPetResponse {
|
||||
RaisedPetSetResult = RaisedPetSetResult.Invalid
|
||||
});
|
||||
}
|
||||
|
||||
dragon.RaisedPetData = XmlUtil.SerializeXml(UpdateDragon(dragon, petData));
|
||||
ctx.Update(dragon);
|
||||
ctx.SaveChanges();
|
||||
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("V2/ContentWebService.asmx/SetRaisedPet")] // used by Magic & Mythies
|
||||
@ -504,6 +653,31 @@ public class ContentController : Controller {
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/SetRaisedPetInactive")] // used by World Of Jumpstart
|
||||
[VikingSession]
|
||||
public IActionResult SetRaisedPetInactive(Viking viking, [FromForm] int raisedPetID) {
|
||||
if (raisedPetID == viking.SelectedDragonId) {
|
||||
viking.SelectedDragonId = null;
|
||||
} else {
|
||||
Dragon? dragon = viking.Dragons.FirstOrDefault(e => e.Id == raisedPetID);
|
||||
if (dragon is null) {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
// check if Minisaurs - we real delete only Minisaurs
|
||||
RaisedPetData dragonData = XmlUtil.DeserializeXml<RaisedPetData>(dragon.RaisedPetData);
|
||||
if (dragonData.PetTypeID != 2) {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
viking.Dragons.Remove(dragon);
|
||||
}
|
||||
ctx.SaveChanges();
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/SetSelectedPet")]
|
||||
@ -574,6 +748,48 @@ public class ContentController : Controller {
|
||||
return filteredDragons.ToArray();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/GetActiveRaisedPet")] // used by World Of Jumpstart
|
||||
[VikingSession(UseLock=false)]
|
||||
public RaisedPetData[] GetActiveRaisedPet(Viking viking, [FromForm] string userId, [FromForm] int petTypeID) {
|
||||
if (petTypeID == 2) {
|
||||
// player can have multiple Minisaurs at the same time ... Minisaurs should never have been selected also ... so use GetUnselectedPetByTypes in this case
|
||||
return GetUnselectedPetByTypes(viking, "2", false);
|
||||
}
|
||||
|
||||
Dragon? dragon = viking.SelectedDragon;
|
||||
if (dragon is null) {
|
||||
return new RaisedPetData[0];
|
||||
}
|
||||
|
||||
RaisedPetData dragonData = GetRaisedPetDataFromDragon(dragon);
|
||||
if (petTypeID != dragonData.PetTypeID)
|
||||
return new RaisedPetData[0];
|
||||
|
||||
// NOTE: returned dragon PetTypeID should be equal value of pair 1967 → CurrentRaisedPetType
|
||||
return new RaisedPetData[] {dragonData};
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/GetActiveRaisedPetsByTypes")] // used by Math Blaster
|
||||
[VikingSession(UseLock=false)]
|
||||
public RaisedPetData[] GetActiveRaisedPet([FromForm] Guid userId, [FromForm] string petTypeIDs) {
|
||||
Viking? viking = ctx.Vikings.FirstOrDefault(e => e.Uid == userId);
|
||||
Dragon? dragon = viking.SelectedDragon;
|
||||
if (dragon is null) {
|
||||
return new RaisedPetData[0];
|
||||
}
|
||||
|
||||
RaisedPetData dragonData = GetRaisedPetDataFromDragon(dragon);
|
||||
int[] petTypeIDsInt = Array.ConvertAll(petTypeIDs.Split(','), s => int.Parse(s));
|
||||
if (!petTypeIDsInt.Contains(dragonData.PetTypeID))
|
||||
return new RaisedPetData[0];
|
||||
|
||||
return new RaisedPetData[] {dragonData};
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/GetSelectedRaisedPet")]
|
||||
@ -589,6 +805,30 @@ public class ContentController : Controller {
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/GetInactiveRaisedPet")] // used by World Of Jumpstart 1.1
|
||||
[VikingSession(UseLock=false)]
|
||||
public RaisedPetData[] GetInactiveRaisedPet(Viking viking, [FromForm] int petTypeID) {
|
||||
RaisedPetData[] dragons = viking.Dragons
|
||||
.Where(d => d.RaisedPetData is not null && d.Id != viking.SelectedDragonId)
|
||||
.Select(d => GetRaisedPetDataFromDragon(d, viking.SelectedDragonId))
|
||||
.ToArray();
|
||||
|
||||
List<RaisedPetData> filteredDragons = new List<RaisedPetData>();
|
||||
foreach (RaisedPetData dragon in dragons) {
|
||||
if (petTypeID == dragon.PetTypeID) {
|
||||
filteredDragons.Add(dragon);
|
||||
}
|
||||
}
|
||||
|
||||
if (filteredDragons.Count == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return filteredDragons.ToArray();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/SetImage")]
|
||||
@ -1156,6 +1396,35 @@ public class ContentController : Controller {
|
||||
return Ok(roomService.NextItemState(item, request.OverrideStateCriteria));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
//[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/GetDisplayNames")] // used by World Of Jumpstart
|
||||
[Route("ContentWebService.asmx/GetDisplayNamesByCategoryID")] // used by Math Blaster
|
||||
public IActionResult GetDisplayNames() {
|
||||
// TODO: This is a placeholder
|
||||
return Ok(XmlUtil.ReadResourceXmlString("displaynames"));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
//[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/SetDisplayName")] // used by World Of Jumpstart
|
||||
[VikingSession]
|
||||
public IActionResult SetProduct(Viking viking, [FromForm] int firstNameID, [FromForm] int secondNameID, [FromForm] int thirdNameID) {
|
||||
AvatarData avatarData = XmlUtil.DeserializeXml<AvatarData>(viking.AvatarSerialized);
|
||||
avatarData.DisplayName = displayNamesService.GetName(firstNameID, secondNameID, thirdNameID);
|
||||
viking.AvatarSerialized = XmlUtil.SerializeXml(avatarData);
|
||||
ctx.SaveChanges();
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
//[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/GetScene")] // used by World Of Jumpstart
|
||||
public IActionResult GetScene() {
|
||||
// TODO: This is a placeholder
|
||||
return Ok("<?xml version=\"1.0\" encoding=\"utf-8\"?><SceneData xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:nil=\"true\" />");
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("V2/ContentWebService.asmx/GetGameData")]
|
||||
@ -1570,6 +1839,30 @@ public class ContentController : Controller {
|
||||
return Ok(gameDataService.GetGameData(viking, gameId, isMultiplayer, difficulty, gameLevel, key, count, AscendingOrder, buddyFilter, DateTime.Parse(startDate, usCulture), DateTime.Parse(endDate, usCulture)));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("ContentWebService.asmx/GetPeriodicGameDataByGame")] // used by Math Blaster
|
||||
public IActionResult GetPeriodicGameDataByGame() {
|
||||
// TODO: This is a placeholder
|
||||
return Ok(new GameDataSummary());
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("MissionWebService.asmx/GetTreasureChest")] // used by Math Blaster
|
||||
public IActionResult GetTreasureChest() {
|
||||
// TODO: This is a placeholder
|
||||
return Ok(new TreasureChestData());
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("MissionWebService.asmx/GetWorldId")] // used by Math Blaster
|
||||
public IActionResult GetWorldId() {
|
||||
// TODO: This is a placeholder
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
private static RaisedPetData GetRaisedPetDataFromDragon (Dragon dragon, int? selectedDragonId = null) {
|
||||
if (selectedDragonId is null)
|
||||
selectedDragonId = dragon.Viking.SelectedDragonId;
|
||||
|
@ -46,6 +46,13 @@ public class ItemStoreController : Controller {
|
||||
return Ok(itemService.GetItem(itemId));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("ItemStoreWebService.asmx/GetItemsInStore")] // used by World Of Jumpstart
|
||||
public IActionResult GetItemsInStore([FromForm] int storeId) {
|
||||
return Ok(storeService.GetStore(storeId));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
//[Produces("application/xml")]
|
||||
[Route("ItemStoreWebService.asmx/GetRankAttributeData")]
|
||||
|
@ -61,47 +61,6 @@ public class ProfileController : Controller {
|
||||
[Route("ProfileWebService.asmx/GetQuestions")]
|
||||
public IActionResult GetQuestions() {
|
||||
return Ok(XmlUtil.ReadResourceXmlString("questiondata"));
|
||||
|
||||
//return Ok(new ProfileQuestionData {
|
||||
// Lists = new ProfileQuestionList[] {
|
||||
// new ProfileQuestionList {
|
||||
// ID = 4,
|
||||
// Questions = new ProfileQuestion[] {
|
||||
// new ProfileQuestion {
|
||||
// CategoryID = 3,
|
||||
// IsActive = "true", // this is a string, which makes me sad
|
||||
// Locale = "en-US",
|
||||
// Ordinal = 1,
|
||||
// ID = 48,
|
||||
// DisplayText = "How Did You Hear About US ?",
|
||||
// Answers = new ProfileAnswer[] {
|
||||
// new ProfileAnswer {
|
||||
// ID = 320,
|
||||
// DisplayText = "TV Commercial",
|
||||
// Locale = "en-US",
|
||||
// Ordinal = 1,
|
||||
// QuestionID = 48
|
||||
// },
|
||||
// new ProfileAnswer {
|
||||
// ID = 324,
|
||||
// DisplayText = "I bought the RIders Of Berk DVD",
|
||||
// Locale = "en-US",
|
||||
// Ordinal = 5,
|
||||
// QuestionID = 48
|
||||
// },
|
||||
// new ProfileAnswer {
|
||||
// ID = 325,
|
||||
// DisplayText = "I bought the Defenders of Berk DVD",
|
||||
// Locale = "en-US",
|
||||
// Ordinal = 6,
|
||||
// QuestionID = 48
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
|
@ -53,7 +53,7 @@ public class RegistrationController : Controller {
|
||||
[Route("v3/RegistrationWebService.asmx/RegisterParent")]
|
||||
[DecryptRequest("parentRegistrationData")]
|
||||
[EncryptResponse]
|
||||
public IActionResult RegisterParent() {
|
||||
public IActionResult RegisterParent([FromForm] string apiKey) {
|
||||
ParentRegistrationData data = XmlUtil.DeserializeXml<ParentRegistrationData>(Request.Form["parentRegistrationData"]);
|
||||
User u = new User {
|
||||
Id = Guid.NewGuid(),
|
||||
@ -63,11 +63,30 @@ public class RegistrationController : Controller {
|
||||
};
|
||||
|
||||
// Check if user exists
|
||||
uint gameVersion = ClientVersion.GetVersion(apiKey);
|
||||
if (gameVersion == ClientVersion.WoJS || gameVersion == ClientVersion.MB) {
|
||||
if (ctx.Users.Count(e => e.Email == u.Email) > 0) {
|
||||
return Ok(new RegistrationResult { Status = MembershipUserStatus.DuplicateEmail });
|
||||
}
|
||||
}
|
||||
if (ctx.Users.Count(e => e.Username== u.Username) > 0) {
|
||||
return Ok(new RegistrationResult { Status = MembershipUserStatus.DuplicateUserName });
|
||||
}
|
||||
|
||||
ctx.Users.Add(u);
|
||||
|
||||
if(gameVersion == ClientVersion.MB) {
|
||||
Viking v = new Viking {
|
||||
Uid = Guid.NewGuid(),
|
||||
Name = data.ChildList[0].ChildName,
|
||||
User = u,
|
||||
InventoryItems = new List<InventoryItem>(),
|
||||
AchievementPoints = new List<AchievementPoints>(),
|
||||
Rooms = new List<Room>()
|
||||
};
|
||||
ctx.Vikings.Add(v);
|
||||
}
|
||||
|
||||
ctx.SaveChanges();
|
||||
|
||||
ParentLoginInfo pli = new ParentLoginInfo {
|
||||
|
@ -112,6 +112,9 @@ public class DBContext : DbContext {
|
||||
builder.Entity<Viking>().HasMany(v => v.GameData)
|
||||
.WithOne(e => e.Viking);
|
||||
|
||||
builder.Entity<Viking>().HasMany(v => v.SavedData)
|
||||
.WithOne(e => e.Viking);
|
||||
|
||||
builder.Entity<Viking>().HasMany(v => v.ProfileAnswers)
|
||||
.WithOne(e => e.Viking);
|
||||
|
||||
@ -204,6 +207,13 @@ public class DBContext : DbContext {
|
||||
.WithMany(e => e.AchievementPoints)
|
||||
.HasForeignKey(e => e.VikingId);
|
||||
|
||||
builder.Entity<SavedData>().HasKey(e => new { e.VikingId, e.SaveId });
|
||||
|
||||
builder.Entity<SavedData>()
|
||||
.HasOne(e => e.Viking)
|
||||
.WithMany(v => v.SavedData)
|
||||
.HasForeignKey(e => e.VikingId);
|
||||
|
||||
builder.Entity<ProfileAnswer>().HasOne(i => i.Viking)
|
||||
.WithMany(i => i.ProfileAnswers)
|
||||
.HasForeignKey(e => e.VikingId);
|
||||
|
8
src/Model/SaveData.cs
Normal file
8
src/Model/SaveData.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace sodoff.Model;
|
||||
public class SavedData {
|
||||
public int VikingId { get; set; }
|
||||
public uint SaveId { get; set; }
|
||||
public string? SerializedData { get; set; }
|
||||
|
||||
public virtual Viking Viking { get; set; } = null!;
|
||||
}
|
@ -32,5 +32,6 @@ public class Viking {
|
||||
public virtual ICollection<InventoryItem> InventoryItems { get; set; } = null!;
|
||||
public virtual ICollection<GameData> GameData { get; set; } = null!;
|
||||
public virtual ICollection<ProfileAnswer> ProfileAnswers { get; set; } = null!;
|
||||
public virtual ICollection<SavedData> SavedData { get; set; } = null!;
|
||||
public virtual Dragon? SelectedDragon { get; set; }
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ builder.Services.AddSingleton<MissionStoreSingleton>();
|
||||
builder.Services.AddSingleton<AchievementStoreSingleton>();
|
||||
builder.Services.AddSingleton<ItemService>();
|
||||
builder.Services.AddSingleton<StoreService>();
|
||||
builder.Services.AddSingleton<DisplayNamesService>();
|
||||
|
||||
builder.Services.AddScoped<KeyValueService>();
|
||||
builder.Services.AddScoped<MissionService>();
|
||||
|
37
src/Resources/defaultmissionlist_wojs.xml
Normal file
37
src/Resources/defaultmissionlist_wojs.xml
Normal file
@ -0,0 +1,37 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<DefaultMissions>
|
||||
<!-- list of default mission for World of Jump Start -->
|
||||
<Active>
|
||||
<id>1509</id>
|
||||
<id>1511</id>
|
||||
<id>1512</id>
|
||||
<id>1513</id>
|
||||
<id>1514</id>
|
||||
<id>1743</id>
|
||||
<id>2323</id>
|
||||
<id>2374</id>
|
||||
<id>2375</id>
|
||||
<id>2376</id>
|
||||
<id>2377</id>
|
||||
<id>2378</id>
|
||||
<id>2379</id>
|
||||
<id>2380</id>
|
||||
<id>2381</id>
|
||||
<id>2382</id>
|
||||
<id>2383</id>
|
||||
<id>2384</id>
|
||||
<id>2385</id>
|
||||
<id>2386</id>
|
||||
<id>2440</id>
|
||||
<id>2441</id>
|
||||
<id>2442</id>
|
||||
<id>2446</id>
|
||||
<id>2447</id>
|
||||
<id>2448</id>
|
||||
<id>2449</id>
|
||||
<id>2451</id>
|
||||
<id>2452</id>
|
||||
</Active>
|
||||
<Upcoming>
|
||||
</Upcoming>
|
||||
</DefaultMissions>
|
33
src/Resources/displaynames.xml
Normal file
33
src/Resources/displaynames.xml
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<DisplayNames xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<DisplayName>
|
||||
<ID>1</ID>
|
||||
<Name>Aaliyah</Name>
|
||||
<Ordinal>1</Ordinal>
|
||||
</DisplayName>
|
||||
<DisplayName>
|
||||
<ID>2</ID>
|
||||
<Name>Abby</Name>
|
||||
<Ordinal>2</Ordinal>
|
||||
</DisplayName>
|
||||
<DisplayName>
|
||||
<ID>3</ID>
|
||||
<Name>Adrian</Name>
|
||||
<Ordinal>3</Ordinal>
|
||||
</DisplayName>
|
||||
<DisplayName>
|
||||
<ID>11</ID>
|
||||
<Name>Karen</Name>
|
||||
<Ordinal>2</Ordinal>
|
||||
</DisplayName>
|
||||
<DisplayName>
|
||||
<ID>12</ID>
|
||||
<Name>Luna</Name>
|
||||
<Ordinal>2</Ordinal>
|
||||
</DisplayName>
|
||||
<DisplayName>
|
||||
<ID>13</ID>
|
||||
<Name>Tori</Name>
|
||||
<Ordinal>2</Ordinal>
|
||||
</DisplayName>
|
||||
</DisplayNames>
|
3546
src/Resources/missions_wojs.xml
Normal file
3546
src/Resources/missions_wojs.xml
Normal file
File diff suppressed because it is too large
Load Diff
@ -2303,6 +2303,42 @@
|
||||
</Answers>
|
||||
</Qs>
|
||||
</QL>
|
||||
<QL>
|
||||
<ID>4</ID>
|
||||
<Qs>
|
||||
<CID>3</CID>
|
||||
<Img xsi:nil="true" />
|
||||
<A>true</A>
|
||||
<L>en-US</L>
|
||||
<Ord>1</Ord>
|
||||
<ID>48</ID>
|
||||
<T>How Did You Hear About US ?</T>
|
||||
<Answers>
|
||||
<ID>320</ID>
|
||||
<T>TV Commercial</T>
|
||||
<Img xsi:nil="true" />
|
||||
<L>en-US</L>
|
||||
<O>1</O>
|
||||
<QID>48</QID>
|
||||
</Answers>
|
||||
<Answers>
|
||||
<ID>324</ID>
|
||||
<T>I bought the Riders Of Berk DVD</T>
|
||||
<Img xsi:nil="true" />
|
||||
<L>en-US</L>
|
||||
<O>5</O>
|
||||
<QID>48</QID>
|
||||
</Answers>
|
||||
<Answers>
|
||||
<ID>325</ID>
|
||||
<T>I bought the Defenders of Berk DVD</T>
|
||||
<Img xsi:nil="true" />
|
||||
<L>en-US</L>
|
||||
<O>6</O>
|
||||
<QID>48</QID>
|
||||
</Answers>
|
||||
</Qs>
|
||||
</QL>
|
||||
<QL>
|
||||
<ID>5</ID>
|
||||
<Qs>
|
||||
|
15
src/Schema/DisplayNames.cs
Normal file
15
src/Schema/DisplayNames.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace sodoff.Schema;
|
||||
|
||||
[Serializable]
|
||||
[XmlRoot(ElementName = "DisplayNames", Namespace = "")]
|
||||
public class DisplayNameList : List<DisplayName> {
|
||||
}
|
||||
public class DisplayName {
|
||||
[XmlElement("ID")]
|
||||
public int Id;
|
||||
|
||||
[XmlElement("Name")]
|
||||
public string Name;
|
||||
}
|
10
src/Schema/PetData.cs
Normal file
10
src/Schema/PetData.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace sodoff.Schema;
|
||||
|
||||
[XmlRoot(ElementName = "PetData", Namespace = "")]
|
||||
[Serializable]
|
||||
public class PetData {
|
||||
[XmlElement(ElementName = "Pet")]
|
||||
public PetDataPet[]? Pet;
|
||||
}
|
21
src/Schema/PetDataPet.cs
Normal file
21
src/Schema/PetDataPet.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace sodoff.Schema;
|
||||
|
||||
[XmlRoot(ElementName = "PetDataPet", Namespace = "")]
|
||||
[Serializable]
|
||||
public class PetDataPet {
|
||||
public string Geometry;
|
||||
|
||||
public string Texture;
|
||||
|
||||
public string Type;
|
||||
|
||||
public string Name;
|
||||
|
||||
public float Dirtiness;
|
||||
|
||||
public string AccessoryGeometry;
|
||||
|
||||
public string AccessoryTexture;
|
||||
}
|
33
src/Schema/TreasureChestData.cs
Normal file
33
src/Schema/TreasureChestData.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace sodoff.Schema;
|
||||
|
||||
[XmlRoot(ElementName = "TreasureChestData", Namespace = "")]
|
||||
[Serializable]
|
||||
public class TreasureChestData
|
||||
{
|
||||
public int TreasureChestId;
|
||||
|
||||
[XmlElement(ElementName = "StartDate", IsNullable = true)]
|
||||
public string StartDate;
|
||||
|
||||
[XmlElement(ElementName = "EndDate", IsNullable = true)]
|
||||
public string EndDate;
|
||||
|
||||
public string ServerTime;
|
||||
|
||||
public float RespawnTime;
|
||||
|
||||
public int ChestMin;
|
||||
|
||||
public int ChestMax;
|
||||
|
||||
[XmlElement(ElementName = "GameCurrencyMin", IsNullable = true)]
|
||||
public int? GameCurrencyMin;
|
||||
|
||||
[XmlElement(ElementName = "GameCurrencyMax", IsNullable = true)]
|
||||
public int? GameCurrencyMax;
|
||||
|
||||
[XmlElement(ElementName = "ItemId")]
|
||||
public int[] ItemId;
|
||||
}
|
20
src/Services/DisplayNamesService.cs
Normal file
20
src/Services/DisplayNamesService.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using sodoff.Schema;
|
||||
using sodoff.Util;
|
||||
|
||||
namespace sodoff.Services;
|
||||
|
||||
public class DisplayNamesService {
|
||||
Dictionary<int, string> displayNames = new();
|
||||
|
||||
public DisplayNamesService(ItemService itemService) {
|
||||
DisplayNameList displayNamesList = XmlUtil.DeserializeXml<DisplayNameList>(XmlUtil.ReadResourceXmlString("displaynames"));
|
||||
displayNames.Add(0, "");
|
||||
foreach (var n in displayNamesList) {
|
||||
displayNames.Add(n.Id, n.Name);
|
||||
}
|
||||
}
|
||||
|
||||
public string GetName(int firstNameID, int secondNameID, int thirdNameID) {
|
||||
return displayNames[firstNameID] + " " + displayNames[secondNameID] + displayNames[thirdNameID];
|
||||
}
|
||||
}
|
@ -12,6 +12,8 @@ public class MissionStoreSingleton {
|
||||
private int[] upcomingMissionsV1;
|
||||
private int[] activeMissionsMaM;
|
||||
private int[] upcomingMissionsMaM;
|
||||
private int[] activeMissionsWoJS;
|
||||
private int[] upcomingMissionsWoJS;
|
||||
|
||||
public MissionStoreSingleton() {
|
||||
ServerMissionArray missionArray = XmlUtil.DeserializeXml<ServerMissionArray>(XmlUtil.ReadResourceXmlString("missions"));
|
||||
@ -29,6 +31,14 @@ public class MissionStoreSingleton {
|
||||
defaultMissions = XmlUtil.DeserializeXml<DefaultMissions>(XmlUtil.ReadResourceXmlString("defaultmissionlistmam"));
|
||||
activeMissionsMaM = defaultMissions.Active;
|
||||
upcomingMissionsMaM = defaultMissions.Upcoming;
|
||||
|
||||
missionArray = XmlUtil.DeserializeXml<ServerMissionArray>(XmlUtil.ReadResourceXmlString("missions_wojs"));
|
||||
defaultMissions = XmlUtil.DeserializeXml<DefaultMissions>(XmlUtil.ReadResourceXmlString("defaultmissionlist_wojs"));
|
||||
foreach (var mission in missionArray.MissionDataArray) {
|
||||
SetUpRecursive(mission); // TODO: use separate missions dict for WoJS (?)
|
||||
}
|
||||
activeMissionsWoJS = defaultMissions.Active;
|
||||
upcomingMissionsWoJS = defaultMissions.Upcoming;
|
||||
}
|
||||
|
||||
public Mission GetMission(int missionID) {
|
||||
@ -39,6 +49,9 @@ public class MissionStoreSingleton {
|
||||
if (gameVersion == ClientVersion.MaM) {
|
||||
return activeMissionsMaM;
|
||||
}
|
||||
if (gameVersion == ClientVersion.WoJS) {
|
||||
return activeMissionsWoJS;
|
||||
}
|
||||
if (gameVersion < 0xa2a00a0a) {
|
||||
return activeMissionsV1;
|
||||
}
|
||||
@ -49,6 +62,9 @@ public class MissionStoreSingleton {
|
||||
if (gameVersion == ClientVersion.MaM) {
|
||||
return upcomingMissionsMaM;
|
||||
}
|
||||
if (gameVersion == ClientVersion.WoJS) {
|
||||
return upcomingMissionsWoJS;
|
||||
}
|
||||
if (gameVersion < 0xa2a00a0a) {
|
||||
return upcomingMissionsV1;
|
||||
}
|
||||
|
@ -28,6 +28,10 @@ public class ClientVersion {
|
||||
apiKey == "1552008f-4a95-46f5-80e2-58574da65875"
|
||||
) {
|
||||
return WoJS;
|
||||
} else if (
|
||||
apiKey == "b4e0f71a-1cda-462a-97b3-0b355e87e0c8"
|
||||
) {
|
||||
return WoJS+10; // WoJS--Adventureland
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
22
src/Util/SavedData.cs
Normal file
22
src/Util/SavedData.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using sodoff.Model;
|
||||
|
||||
namespace sodoff.Util;
|
||||
public class SavedData {
|
||||
public static string? Get(Viking? viking, uint saveId) {
|
||||
return viking?.SavedData.FirstOrDefault(s => s.SaveId == saveId)?.SerializedData;
|
||||
}
|
||||
|
||||
public static void Set(Viking viking, uint saveId, string? contentXml) {
|
||||
Console.WriteLine($"\n\n{saveId} {contentXml}\n");
|
||||
Model.SavedData? savedData = viking.SavedData.FirstOrDefault(s => s.SaveId == saveId);
|
||||
if (savedData is null) {
|
||||
savedData = new() {
|
||||
SaveId = saveId,
|
||||
SerializedData = contentXml
|
||||
};
|
||||
viking.SavedData.Add(savedData);
|
||||
} else {
|
||||
savedData.SerializedData = contentXml;
|
||||
}
|
||||
}
|
||||
}
|
@ -41,6 +41,7 @@
|
||||
<None Remove="Resources\items.xml" />
|
||||
<None Remove="Resources\missions.xml" />
|
||||
<None Remove="Resources\mmo.xml" />
|
||||
<None Remove="Resources\displaynames.xml" />
|
||||
<None Remove="Resources\rankattrib.xml" />
|
||||
<None Remove="Resources\rewardmultiplier.xml" />
|
||||
<None Remove="Resources\store.xml" />
|
||||
@ -50,6 +51,7 @@
|
||||
<None Remove="Resources\defaultmissionlist.xml" />
|
||||
<None Remove="Resources\defaultmissionlistv1.xml" />
|
||||
<None Remove="Resources\defaultmissionlistmam.xml" />
|
||||
<None Remove="Resources\defaultmissionlist_wojs.xml" />
|
||||
<None Remove="Resources\questiondata.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -79,6 +81,9 @@
|
||||
<EmbeddedResource Include="Resources\mmo.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Resources\displaynames.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Resources\rewardmultiplier.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
@ -109,6 +114,9 @@
|
||||
<EmbeddedResource Include="Resources\missions.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Resources\missions_wojs.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Resources\defaultmissionlist.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
@ -118,6 +126,9 @@
|
||||
<EmbeddedResource Include="Resources\defaultmissionlistmam.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Resources\defaultmissionlist_wojs.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Resources\questiondata.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
|
Loading…
x
Reference in New Issue
Block a user