Compare commits

...

3 Commits

Author SHA1 Message Date
Spirtix
8e141ab43d better upcoming mission filtering 2025-04-18 15:18:13 +02:00
Spirtix
d9d35c47a8 autofill common payload instead of saving to db 2025-04-14 12:06:37 +02:00
Spirtix
60cc00dc66 don't create upcoming missions upfront 2025-04-14 11:29:41 +02:00
2 changed files with 60 additions and 21 deletions

View File

@ -967,8 +967,25 @@ public class ContentController : Controller {
uint gameVersion = ClientVersion.GetVersion(apiKey); uint gameVersion = ClientVersion.GetVersion(apiKey);
UserMissionStateResult result = new UserMissionStateResult { Missions = new List<Mission>() }; UserMissionStateResult result = new UserMissionStateResult { Missions = new List<Mission>() };
foreach (var mission in viking.MissionStates.Where(x => x.MissionStatus == MissionStatus.Upcoming))
result.Missions.Add(missionService.GetMissionWithProgress(mission.MissionId, viking.Id, gameVersion)); HashSet<int> upcomingMissionsSet = new(missionStore.GetUpcomingMissions(gameVersion));
var toDiscardIds = new HashSet<int>(
viking.MissionStates
.Where(x => x.MissionStatus != MissionStatus.Upcoming)
.Select(x => x.MissionId)
);
var toAddIds = new HashSet<int>(
viking.MissionStates
.Where(x => x.MissionStatus == MissionStatus.Upcoming)
.Select(x => x.MissionId)
);
upcomingMissionsSet.UnionWith(toAddIds);
upcomingMissionsSet.ExceptWith(toDiscardIds);
foreach (var missionId in upcomingMissionsSet)
result.Missions.Add(missionService.GetMissionWithProgress(missionId, viking.Id, gameVersion));
result.UserID = viking.Uid; result.UserID = viking.Uid;
return Ok(result); return Ok(result);
@ -1016,16 +1033,27 @@ public class ContentController : Controller {
[Produces("application/xml")] [Produces("application/xml")]
[Route("ContentWebService.asmx/AcceptMission")] [Route("ContentWebService.asmx/AcceptMission")]
[VikingSession] [VikingSession]
public IActionResult AcceptMission(Viking viking, [FromForm] Guid userId, [FromForm] int missionId) { public IActionResult AcceptMission(Viking viking, [FromForm] Guid userId, [FromForm] int missionId, [FromForm] string apiKey) {
if (viking.Uid != userId) if (viking.Uid != userId)
return Unauthorized("Can't accept not owned mission"); return Unauthorized("Can't accept not owned mission");
uint gameVersion = ClientVersion.GetVersion(apiKey);
int[] upcomingMissions = missionStore.GetUpcomingMissions(gameVersion);
MissionState? missionState = viking.MissionStates.FirstOrDefault(x => x.MissionId == missionId); MissionState? missionState = viking.MissionStates.FirstOrDefault(x => x.MissionId == missionId);
if (missionState is null || missionState.MissionStatus != MissionStatus.Upcoming) if (!upcomingMissions.Contains(missionId) || (missionState is not null && missionState.MissionStatus != MissionStatus.Upcoming))
return Ok(false); return Ok(false);
missionState.MissionStatus = MissionStatus.Active; if (missionState is null) {
missionState.UserAccepted = true; viking.MissionStates.Add(new MissionState {
MissionId = missionId,
MissionStatus = MissionStatus.Active,
UserAccepted = true
});
} else {
missionState.MissionStatus = MissionStatus.Active;
missionState.UserAccepted = true;
}
ctx.SaveChanges(); ctx.SaveChanges();
return Ok(true); return Ok(true);
} }
@ -1040,10 +1068,19 @@ public class ContentController : Controller {
uint gameVersion = ClientVersion.GetVersion(apiKey); uint gameVersion = ClientVersion.GetVersion(apiKey);
UserMissionStateResult result = new UserMissionStateResult { Missions = new List<Mission>() }; UserMissionStateResult result = new UserMissionStateResult { Missions = new List<Mission>() };
foreach (var mission in viking.MissionStates) {
Mission updatedMission = missionService.GetMissionWithProgress(mission.MissionId, viking.Id, gameVersion);
if (mission.MissionStatus == MissionStatus.Upcoming) { var missionStatesById = viking.MissionStates.ToDictionary(ms => ms.MissionId);
HashSet<int> upcomingMissionIds = new(missionStore.GetUpcomingMissions(gameVersion));
var combinedMissionIds = new HashSet<int>(missionStatesById.Keys);
combinedMissionIds.UnionWith(upcomingMissionIds);
foreach (var missionId in combinedMissionIds) {
MissionState? missionState = missionStatesById.TryGetValue(missionId, out var ms) ? ms : null;
Mission updatedMission = missionService.GetMissionWithProgress(missionId, viking.Id, gameVersion);
// Only upcoming missions are missing in the database, so if db is null, mission must be upcoming
MissionStatus status = missionState != null ? missionState.MissionStatus : MissionStatus.Upcoming;
if (status == MissionStatus.Upcoming) {
// NOTE: in old SoD job board mission must be send as non active and required accept // NOTE: in old SoD job board mission must be send as non active and required accept
// (to avoid show all job board in journal and quest arrow pointing to job board) // (to avoid show all job board in journal and quest arrow pointing to job board)
// do this in this place (instead of update missions.xml) to avoid conflict with newer versions of SoD // do this in this place (instead of update missions.xml) to avoid conflict with newer versions of SoD
@ -1052,8 +1089,8 @@ public class ContentController : Controller {
prerequisite.Value = "true"; prerequisite.Value = "true";
} }
if (mission.UserAccepted != null) if (missionState != null && missionState.UserAccepted != null)
updatedMission.Accepted = (bool)mission.UserAccepted; updatedMission.Accepted = (bool)missionState.UserAccepted;
result.Missions.Add(updatedMission); result.Missions.Add(updatedMission);
} }

View File

@ -219,8 +219,12 @@ public class MissionService {
Schema.Task? t = mission.Tasks.Find(x => x.TaskID == task.Id); Schema.Task? t = mission.Tasks.Find(x => x.TaskID == task.Id);
if (t != null) { if (t != null) {
if (task.Completed) t.Completed = 1; if (task.Completed) {
t.Payload = task.Payload; t.Completed = 1;
t.Payload = task.Payload ?? "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Data>\r\n <S>true</S>\r\n</Data>";
} else {
t.Payload = task.Payload;
}
} }
} }
@ -247,18 +251,16 @@ public class MissionService {
MissionStatus = MissionStatus.Active MissionStatus = MissionStatus.Active
}); });
} }
foreach (int m in missionStore.GetUpcomingMissions(gameVersion)) {
viking.MissionStates.Add(new MissionState {
MissionId = m,
MissionStatus = MissionStatus.Upcoming
});
}
} }
private void SetTaskProgressDB(int missionId, int taskId, int userId, bool completed, string xmlPayload) { private void SetTaskProgressDB(int missionId, int taskId, int userId, bool completed, string? xmlPayload) {
Model.TaskStatus? status = ctx.TaskStatuses.FirstOrDefault(task => task.Id == taskId && task.MissionId == missionId && task.VikingId == userId); Model.TaskStatus? status = ctx.TaskStatuses.FirstOrDefault(task => task.Id == taskId && task.MissionId == missionId && task.VikingId == userId);
// Based on the observation that no payloads on completed missions are null
// This is the most common task payload, so if the mission is completed with this payload we can set the payload to null and let the server autofill
if (completed && xmlPayload == "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Data>\r\n <S>true</S>\r\n</Data>")
xmlPayload = null;
if (status is null) { if (status is null) {
status = new Model.TaskStatus { status = new Model.TaskStatus {
Id = taskId, Id = taskId,