fixes to PR

- use multicolumn primary key on UserMissionData
- simplification of GetUserMissionData and SetOrUpdateUserMissionData

also:
- AuthenticateUser endpoint compatible with games that use e-mail as login
- using option to disable loading non SoD data also for achievements
This commit is contained in:
Robert Paciorek 2025-02-11 19:51:14 +00:00
parent df979ca476
commit 3a66ffd864
5 changed files with 42 additions and 48 deletions

View File

@ -87,12 +87,14 @@ public class AuthenticationController : Controller {
[Route("v3/AuthenticationWebService.asmx/AuthenticateUser")]
[DecryptRequest("username")]
[DecryptRequest("password")]
public bool AuthenticateUser() {
public bool AuthenticateUser([FromForm] string apiKey) {
String username = Request.Form["username"];
String password = Request.Form["password"];
// Authenticate the user
User? user = ctx.Users.FirstOrDefault(e => e.Username == username);
User? user = (ClientVersion.GetVersion(apiKey) <= ClientVersion.Max_OldJS)
? ctx.Users.FirstOrDefault(e => e.Email == username)
: ctx.Users.FirstOrDefault(e => e.Username == username);
if (user is null || new PasswordHasher<object>().VerifyHashedPassword(null, user.Password, password) != PasswordVerificationResult.Success) {
return false;
}

View File

@ -2135,7 +2135,7 @@ public class ContentController : Controller {
[HttpPost]
// [Produces("application/xml")]
[Route("MissionWebService.asmx/GetMission")] // old ("step") missions - used by MB and WoJS lands
public IActionResult GetMission([FromForm] int gameId, [FromForm] int type) {
public IActionResult GetMission([FromForm] int gameId, [FromForm] string name) {
if (gameId == 1) return Ok(XmlUtil.ReadResourceXmlString("missions.step_missions_wojs_al"));
if (gameId == 5) return Ok(XmlUtil.ReadResourceXmlString("missions.step_missions_mb"));
return Ok();

View File

@ -1,11 +1,11 @@
using System.ComponentModel.DataAnnotations;
using Microsoft.EntityFrameworkCore;
namespace sodoff.Model
{
[PrimaryKey(nameof(VikingId), nameof(WorldId), nameof(MissionId))]
public class UserMissionData
{
[Key]
public int Id { get; set; }
public int VikingId { get; set; }
public int WorldId { get; set; }
public int MissionId { get; set; }

View File

@ -1,10 +1,12 @@
using sodoff.Schema;
using sodoff.Model;
using sodoff.Util;
using sodoff.Configuration;
using System.Reflection;
using System.Xml;
using System.Xml.Linq;
using System.Collections.ObjectModel;
using Microsoft.Extensions.Options;
namespace sodoff.Services {
public class AchievementStoreSingleton {
@ -34,7 +36,7 @@ namespace sodoff.Services {
int dragonAdultMinXP;
int dragonTitanMinXP;
public AchievementStoreSingleton() {
public AchievementStoreSingleton(IOptions<ApiServerConfig> config) {
ArrayOfUserRank allranks = XmlUtil.DeserializeXml<ArrayOfUserRank>(XmlUtil.ReadResourceXmlString("ranks.allranks_sod"));
foreach (var pointType in Enum.GetValues<AchievementPointTypes>()) {
ranks[pointType] = allranks.UserRank.Where(r => r.PointTypeID == pointType).ToArray();
@ -46,11 +48,13 @@ namespace sodoff.Services {
}
achievementsTasks[ClientVersion.Min_SoD] = new AchievementTasks("achievements.achievementtaskinfo_sod");
achievementsTasks[ClientVersion.MaM] = new AchievementTasks("achievements.achievementtaskinfo_mam");
achievementsTasks[ClientVersion.MB] = new AchievementTasks("achievements.achievementtaskinfo_mb");
achievementsTasks[ClientVersion.EMD] = new AchievementTasks("achievements.achievementtaskinfo_emd");
achievementsTasks[ClientVersion.SS] = new AchievementTasks("achievements.achievementtaskinfo_ss");
achievementsTasks[ClientVersion.WoJS] = new AchievementTasks("achievements.achievementtaskinfo_wojs");
if (config.Value.LoadNonSoDData) {
achievementsTasks[ClientVersion.MaM] = new AchievementTasks("achievements.achievementtaskinfo_mam");
achievementsTasks[ClientVersion.MB] = new AchievementTasks("achievements.achievementtaskinfo_mb");
achievementsTasks[ClientVersion.EMD] = new AchievementTasks("achievements.achievementtaskinfo_emd");
achievementsTasks[ClientVersion.SS] = new AchievementTasks("achievements.achievementtaskinfo_ss");
achievementsTasks[ClientVersion.WoJS] = new AchievementTasks("achievements.achievementtaskinfo_wojs");
}
dragonAdultMinXP = ranks[AchievementPointTypes.DragonXP][10].Value;
dragonTitanMinXP = ranks[AchievementPointTypes.DragonXP][20].Value;

View File

@ -54,24 +54,25 @@ public class MissionService {
return mission;
}
public Schema.UserMissionData GetUserMissionData(Viking viking, int worldId)
{
Schema.UserMissionData umdRes = new Schema.UserMissionData();
public Schema.UserMissionData GetUserMissionData(Viking viking, int worldId) {
Schema.UserMissionData umdRes = new();
// instantiate schema lists and int lists
List<int> userMissionsCompletedIds = new List<int>();
List<UserMissionDataMission> missions = new List<UserMissionDataMission>();
List<UserMissionDataMissionStep> steps = new List<UserMissionDataMissionStep>();
List<int> tasks = new List<int>();
List<int> userMissionsCompletedIds = new();
List<UserMissionDataMission> missions = new();
// get all initiated missions
List<Model.UserMissionData> vikingUmds = viking.UserMissions.Where(e => e.WorldId == worldId).ToList();
foreach (Model.UserMissionData mission in vikingUmds)
{
tasks.Add(mission.TaskId);
steps.Add(new UserMissionDataMissionStep { StepId = mission.StepId, TaskId = tasks.ToArray() });
missions.Add(new UserMissionDataMission { MissionId = mission.MissionId, Step = steps.ToArray() });
foreach (Model.UserMissionData mission in vikingUmds) {
missions.Add(new UserMissionDataMission {
MissionId = mission.MissionId,
Step = new UserMissionDataMissionStep[] { new UserMissionDataMissionStep {
// NOTE: we store in database only last StepId and TaskId this is different behavior than og
StepId = mission.StepId,
TaskId = new int[] {mission.TaskId}
}}
});
}
// add completed mission id's to usermissionscompletedids
@ -104,37 +105,24 @@ public class MissionService {
return new UserBadge { BadgeId = completedBadgeIds.ToArray() };
}
public Model.UserMissionData SetOrUpdateUserMissionData(Viking viking, int worldId, int missionId, int stepId, int taskId)
{
public void SetOrUpdateUserMissionData(Viking viking, int worldId, int missionId, int stepId, int taskId) {
// find any existing records of this mission
Model.UserMissionData? existingMission = viking.UserMissions.Where(e => e.WorldId == worldId)
Model.UserMissionData? missionData = viking.UserMissions.Where(e => e.WorldId == worldId)
.Where(e => e.MissionId == missionId)
.FirstOrDefault();
if (existingMission != null)
{
// update taskid and stepid
existingMission.StepId = stepId;
existingMission.TaskId = taskId;
ctx.SaveChanges();
return existingMission;
if (missionData != null) {
missionData.StepId = stepId;
missionData.TaskId = taskId;
} else {
viking.UserMissions.Add(new Model.UserMissionData() {
WorldId = worldId,
MissionId = missionId,
StepId = stepId,
TaskId = taskId
});
}
// add mission data to db
Model.UserMissionData missionData = new Model.UserMissionData()
{
WorldId = worldId,
MissionId = missionId,
StepId = stepId,
TaskId = taskId
};
viking.UserMissions.Add(missionData);
ctx.SaveChanges();
return missionData;
}
public bool SetUserMissionCompleted(Viking viking, int worldId, int missionId, bool isCompleted)