rework game version managment

now we use game and SoD version encoded in uint (instead of compare raw apiKey values),
this allows for easy support for more versions ...
This commit is contained in:
Robert Paciorek 2024-02-24 18:47:04 +00:00
parent 2dfb5fd1b8
commit 97503cc389
7 changed files with 77 additions and 65 deletions

View File

@ -95,7 +95,7 @@ public class AuthenticationController : Controller {
Username = user.Username, Username = user.Username,
MembershipID = "ef84db9-59c6-4950-b8ea-bbc1521f899b", // placeholder MembershipID = "ef84db9-59c6-4950-b8ea-bbc1521f899b", // placeholder
FacebookUserID = 0, FacebookUserID = 0,
MultiplayerEnabled = !ClientVersion.IsOldSoD(apiKey), MultiplayerEnabled = ClientVersion.IsMultiplayerSupported(apiKey),
IsApproved = true, IsApproved = true,
Age = 24, Age = 24,
OpenChatEnabled = true OpenChatEnabled = true
@ -110,7 +110,7 @@ public class AuthenticationController : Controller {
UserID = viking.Uid.ToString(), UserID = viking.Uid.ToString(),
Username = viking.Name, Username = viking.Name,
FacebookUserID = 0, FacebookUserID = 0,
MultiplayerEnabled = !ClientVersion.IsOldSoD(apiKey), MultiplayerEnabled = ClientVersion.IsMultiplayerSupported(apiKey),
IsApproved = true, IsApproved = true,
Age = 24, Age = 24,
OpenChatEnabled = true OpenChatEnabled = true

View File

@ -646,9 +646,10 @@ public class ContentController : Controller {
if (viking is null) if (viking is null)
return Ok("error"); return Ok("error");
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)) foreach (var mission in viking.MissionStates.Where(x => x.MissionStatus == MissionStatus.Upcoming))
result.Missions.Add(missionService.GetMissionWithProgress(mission.MissionId, viking.Id, apiKey)); result.Missions.Add(missionService.GetMissionWithProgress(mission.MissionId, viking.Id, gameVersion));
result.UserID = viking.Uid; result.UserID = viking.Uid;
return Ok(result); return Ok(result);
@ -662,9 +663,10 @@ public class ContentController : Controller {
if (viking is null) if (viking is null)
return Ok("error"); return Ok("error");
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.Active)) { foreach (var mission in viking.MissionStates.Where(x => x.MissionStatus == MissionStatus.Active)) {
Mission updatedMission = missionService.GetMissionWithProgress(mission.MissionId, viking.Id, apiKey); Mission updatedMission = missionService.GetMissionWithProgress(mission.MissionId, viking.Id, gameVersion);
if (mission.UserAccepted != null) if (mission.UserAccepted != null)
updatedMission.Accepted = (bool)mission.UserAccepted; updatedMission.Accepted = (bool)mission.UserAccepted;
result.Missions.Add(updatedMission); result.Missions.Add(updatedMission);
@ -682,9 +684,10 @@ public class ContentController : Controller {
if (viking is null) if (viking is null)
return Ok("error"); return Ok("error");
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.Completed)) foreach (var mission in viking.MissionStates.Where(x => x.MissionStatus == MissionStatus.Completed))
result.Missions.Add(missionService.GetMissionWithProgress(mission.MissionId, viking.Id, apiKey)); result.Missions.Add(missionService.GetMissionWithProgress(mission.MissionId, viking.Id, gameVersion));
result.UserID = viking.Uid; result.UserID = viking.Uid;
return Ok(result); return Ok(result);
@ -716,9 +719,10 @@ public class ContentController : Controller {
if (viking is null) if (viking is null)
return Ok("error"); return Ok("error");
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.Completed)) { foreach (var mission in viking.MissionStates.Where(x => x.MissionStatus != MissionStatus.Completed)) {
Mission updatedMission = missionService.GetMissionWithProgress(mission.MissionId, viking.Id, apiKey); Mission updatedMission = missionService.GetMissionWithProgress(mission.MissionId, viking.Id, gameVersion);
if (mission.MissionStatus == MissionStatus.Upcoming) { if (mission.MissionStatus == 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
@ -748,19 +752,20 @@ public class ContentController : Controller {
if (viking is null) if (viking is null)
return Ok("error"); return Ok("error");
uint gameVersion = ClientVersion.GetVersion(apiKey);
UserMissionStateResult result = new UserMissionStateResult { Missions = new List<Mission>() }; UserMissionStateResult result = new UserMissionStateResult { Missions = new List<Mission>() };
if (filterV2.MissionPair.Count > 0) { if (filterV2.MissionPair.Count > 0) {
foreach (var m in filterV2.MissionPair) foreach (var m in filterV2.MissionPair)
if (m.MissionID != null) if (m.MissionID != null)
result.Missions.Add(missionService.GetMissionWithProgress((int)m.MissionID, viking.Id, apiKey)); result.Missions.Add(missionService.GetMissionWithProgress((int)m.MissionID, viking.Id, gameVersion));
// TODO: probably should also check for mission based on filterV2.ProductGroupID vs mission.GroupID // TODO: probably should also check for mission based on filterV2.ProductGroupID vs mission.GroupID
} else { } else {
if (filterV2.GetCompletedMission ?? false) { if (filterV2.GetCompletedMission ?? false) {
foreach (var mission in viking.MissionStates.Where(x => x.MissionStatus == MissionStatus.Completed)) foreach (var mission in viking.MissionStates.Where(x => x.MissionStatus == MissionStatus.Completed))
result.Missions.Add(missionService.GetMissionWithProgress(mission.MissionId, viking.Id, apiKey)); result.Missions.Add(missionService.GetMissionWithProgress(mission.MissionId, viking.Id, gameVersion));
} else { } else {
foreach (var mission in viking.MissionStates.Where(x => x.MissionStatus != MissionStatus.Completed)) foreach (var mission in viking.MissionStates.Where(x => x.MissionStatus != MissionStatus.Completed))
result.Missions.Add(missionService.GetMissionWithProgress(mission.MissionId, viking.Id, apiKey)); result.Missions.Add(missionService.GetMissionWithProgress(mission.MissionId, viking.Id, gameVersion));
} }
} }
@ -776,7 +781,8 @@ public class ContentController : Controller {
if (viking.Uid != userId) if (viking.Uid != userId)
return Unauthorized("Can't set not owned task"); return Unauthorized("Can't set not owned task");
List<MissionCompletedResult> results = missionService.UpdateTaskProgress(missionId, taskId, viking.Id, completed, xmlPayload, apiKey); uint gameVersion = ClientVersion.GetVersion(apiKey);
List<MissionCompletedResult> results = missionService.UpdateTaskProgress(missionId, taskId, viking.Id, completed, xmlPayload, gameVersion);
SetTaskStateResult taskResult = new SetTaskStateResult { SetTaskStateResult taskResult = new SetTaskStateResult {
Success = true, Success = true,
@ -797,7 +803,8 @@ public class ContentController : Controller {
if (viking.Uid != userId) if (viking.Uid != userId)
return Unauthorized("Can't set not owned task"); return Unauthorized("Can't set not owned task");
List<MissionCompletedResult> results = missionService.UpdateTaskProgress(missionId, taskId, viking.Id, completed, xmlPayload, apiKey); uint gameVersion = ClientVersion.GetVersion(apiKey);
List<MissionCompletedResult> results = missionService.UpdateTaskProgress(missionId, taskId, viking.Id, completed, xmlPayload, gameVersion);
SetTaskStateResult taskResult = new SetTaskStateResult { SetTaskStateResult taskResult = new SetTaskStateResult {
Success = true, Success = true,

View File

@ -116,7 +116,7 @@ public class ProfileController : Controller {
avatarData.Id = viking.Id; avatarData.Id = viking.Id;
} }
if (avatarData != null && ClientVersion.Use2019SoDTutorial(apiKey)) { if (avatarData != null && ClientVersion.GetVersion(apiKey) == 0xa3a12a0a) { // TODO adjust version number: we don't know for which versions it is required (for 3.12 it is, for 3.19 and 3.0 it's not)
if (avatarData.Part.FirstOrDefault(e => e.PartType == "Sword") is null) { if (avatarData.Part.FirstOrDefault(e => e.PartType == "Sword") is null) {
var extraParts = new AvatarDataPart[] { var extraParts = new AvatarDataPart[] {
new AvatarDataPart { new AvatarDataPart {
@ -139,7 +139,7 @@ public class ProfileController : Controller {
ParentUserID = viking.UserId.ToString(), ParentUserID = viking.UserId.ToString(),
Username = viking.Name, Username = viking.Name,
FirstName = viking.Name, FirstName = viking.Name,
MultiplayerEnabled = !ClientVersion.IsOldSoD(apiKey), MultiplayerEnabled = ClientVersion.IsMultiplayerSupported(apiKey),
Locale = "en-US", // placeholder Locale = "en-US", // placeholder
GenderID = Gender.Male, // placeholder GenderID = Gender.Male, // placeholder
OpenChatEnabled = true, OpenChatEnabled = true,

View File

@ -126,12 +126,13 @@ public class RegistrationController : Controller {
Rooms = new List<Room>() Rooms = new List<Room>()
}; };
missionService.SetUpMissions(v, apiKey); uint gameVersion = ClientVersion.GetVersion(apiKey);
missionService.SetUpMissions(v, gameVersion);
ctx.Vikings.Add(v); ctx.Vikings.Add(v);
ctx.SaveChanges(); ctx.SaveChanges();
if (ClientVersion.Use2013SoDTutorial(apiKey)) { if (gameVersion < 0xa2a09a0a) {
keyValueService.SetPairData(null, v, null, 2017, new Schema.PairData { keyValueService.SetPairData(null, v, null, 2017, new Schema.PairData {
Pairs = new Schema.Pair[]{ Pairs = new Schema.Pair[]{
new Schema.Pair { new Schema.Pair {

View File

@ -17,20 +17,20 @@ public class MissionService {
this.achievementService = achievementService; this.achievementService = achievementService;
} }
public Mission GetMissionWithProgress(int missionId, int userId, string apiKey) { public Mission GetMissionWithProgress(int missionId, int userId, uint gameVersion) {
Mission mission = null; Mission mission = null;
if (missionId == 999) { // TODO This is not a pretty solution with hard-coded values. if (missionId == 999) { // TODO This is not a pretty solution with hard-coded values.
if (ClientVersion.Use2013SoDTutorial(apiKey)) { if (gameVersion < 0xa2a03a0a) {
mission = missionStore.GetMission(30999); mission = missionStore.GetMission(30999);
} else if (ClientVersion.Use2016SoDTutorial(apiKey)) { } else if (gameVersion < 0xa3a03a0a) {
mission = missionStore.GetMission(20999); mission = missionStore.GetMission(20999);
} else if (ClientVersion.Use2019SoDTutorial(apiKey)) { } else if (gameVersion <= 0xa3a23a0a) {
mission = missionStore.GetMission(10999); mission = missionStore.GetMission(10999);
} }
} else if (missionId == 1044 && ClientVersion.IsMaM(apiKey)) { } else if (missionId == 1044 && gameVersion == ClientVersion.MaM) {
mission = missionStore.GetMission(11044); mission = missionStore.GetMission(11044);
} else if (missionId == 1074 && ClientVersion.IsMaM(apiKey)) { } else if (missionId == 1074 && gameVersion == ClientVersion.MaM) {
mission = missionStore.GetMission(11074); mission = missionStore.GetMission(11074);
} }
@ -45,7 +45,7 @@ public class MissionService {
return mission; return mission;
} }
public List<MissionCompletedResult> UpdateTaskProgress(int missionId, int taskId, int userId, bool completed, string xmlPayload, string apiKey) { public List<MissionCompletedResult> UpdateTaskProgress(int missionId, int taskId, int userId, bool completed, string xmlPayload, uint gameVersion) {
SetTaskProgressDB(missionId, taskId, userId, completed, xmlPayload); SetTaskProgressDB(missionId, taskId, userId, completed, xmlPayload);
// NOTE: This won't work if a mission can be completed by completing an inner mission // NOTE: This won't work if a mission can be completed by completing an inner mission
@ -59,7 +59,7 @@ public class MissionService {
// I do know that outer missions have inner missions as RuleItems, and if the RuleItem is supposed to be "complete" and it isn't, the quest breaks when the player quits the game and loads the quest again // I do know that outer missions have inner missions as RuleItems, and if the RuleItem is supposed to be "complete" and it isn't, the quest breaks when the player quits the game and loads the quest again
List<MissionCompletedResult> result = new(); List<MissionCompletedResult> result = new();
if (completed) { if (completed) {
Mission mission = GetMissionWithProgress(missionId, userId, apiKey); Mission mission = GetMissionWithProgress(missionId, userId, gameVersion);
if (MissionCompleted(mission)) { if (MissionCompleted(mission)) {
// Update mission from active to completed // Update mission from active to completed
Viking viking = ctx.Vikings.FirstOrDefault(x => x.Id == userId)!; Viking viking = ctx.Vikings.FirstOrDefault(x => x.Id == userId)!;
@ -74,7 +74,7 @@ public class MissionService {
task.Payload = null; task.Payload = null;
task.Completed = false; task.Completed = false;
} }
if (missionStore.GetActiveMissions(apiKey).Contains(missionId)) if (missionStore.GetActiveMissions(gameVersion).Contains(missionId))
missionState.MissionStatus = MissionStatus.Active; missionState.MissionStatus = MissionStatus.Active;
else else
missionState.MissionStatus = MissionStatus.Upcoming; missionState.MissionStatus = MissionStatus.Upcoming;
@ -126,17 +126,17 @@ public class MissionService {
mission.Completed = 1; mission.Completed = 1;
} }
public void SetUpMissions(Viking viking, string apiKey) { public void SetUpMissions(Viking viking, uint gameVersion) {
viking.MissionStates = new List<MissionState>(); viking.MissionStates = new List<MissionState>();
foreach (int m in missionStore.GetActiveMissions(apiKey)) { foreach (int m in missionStore.GetActiveMissions(gameVersion)) {
viking.MissionStates.Add(new MissionState { viking.MissionStates.Add(new MissionState {
MissionId = m, MissionId = m,
MissionStatus = MissionStatus.Active MissionStatus = MissionStatus.Active
}); });
} }
foreach (int m in missionStore.GetUpcomingMissions(apiKey)) { foreach (int m in missionStore.GetUpcomingMissions(gameVersion)) {
viking.MissionStates.Add(new MissionState { viking.MissionStates.Add(new MissionState {
MissionId = m, MissionId = m,
MissionStatus = MissionStatus.Upcoming MissionStatus = MissionStatus.Upcoming

View File

@ -35,23 +35,23 @@ public class MissionStoreSingleton {
return DeepCopy(missions[missionID]); return DeepCopy(missions[missionID]);
} }
public int[] GetActiveMissions(string apiKey) { public int[] GetActiveMissions(uint gameVersion) {
if (ClientVersion.Use2013SoDTutorial(apiKey)) { if (gameVersion == ClientVersion.MaM) {
return activeMissionsV1;
}
if (ClientVersion.IsMaM(apiKey)) {
return activeMissionsMaM; return activeMissionsMaM;
} }
if (gameVersion < 0xa2a00a0a) {
return activeMissionsV1;
}
return activeMissions; return activeMissions;
} }
public int[] GetUpcomingMissions(string apiKey) { public int[] GetUpcomingMissions(uint gameVersion) {
if (ClientVersion.Use2013SoDTutorial(apiKey)) { if (gameVersion == ClientVersion.MaM) {
return upcomingMissionsV1;
}
if (ClientVersion.IsMaM(apiKey)) {
return upcomingMissionsMaM; return upcomingMissionsMaM;
} }
if (gameVersion < 0xa2a00a0a) {
return upcomingMissionsV1;
}
return upcomingMissions; return upcomingMissions;
} }

View File

@ -1,34 +1,38 @@
namespace sodoff.Util; namespace sodoff.Util;
public class ClientVersion { public class ClientVersion {
public static bool IsOldSoD(string apiKey) { public const uint Min_SoD = 0xa0000000;
return ( public const uint MaM = 0x00800000;
apiKey == "a1a06a0a-7c6e-4e9b-b0f7-22034d799013" || public const uint MB = 0x00700000;
apiKey == "a1a13a0a-7c6e-4e9b-b0f7-22034d799013" || public const uint WoJS = 0x00600000;
apiKey == "a2a09a0a-7c6e-4e9b-b0f7-22034d799013" ||
apiKey == "a3a12a0a-7c6e-4e9b-b0f7-22034d799013" public static uint GetVersion(string apiKey) {
); if (
} apiKey == "b99f695c-7c6e-4e9b-b0f7-22034d799013" || // PC / Windows
public static bool Use2013SoDTutorial(string apiKey) { apiKey == "515af675-bec7-4c42-ba64-7bfaf198d8ea" || // Android
return ( apiKey == "1e7ccc3a-4adb-4736-b843-7b3da5140a43" // iOS
apiKey == "a1a06a0a-7c6e-4e9b-b0f7-22034d799013" || ) {
apiKey == "a1a13a0a-7c6e-4e9b-b0f7-22034d799013" return 0xa3a31a0a;
); } else if (
} apiKey.EndsWith("7c6e-4e9b-b0f7-22034d799013")
public static bool Use2016SoDTutorial(string apiKey) { ) {
return ( return Convert.ToUInt32(apiKey.Substring(0, 8), 16);
apiKey == "a2a09a0a-7c6e-4e9b-b0f7-22034d799013" } else if (
); apiKey == "e20150cc-ff70-435c-90fd-341dc9161cc3"
} ) {
public static bool Use2019SoDTutorial(string apiKey) { return MaM;
return ( } else if (
apiKey == "a3a12a0a-7c6e-4e9b-b0f7-22034d799013" apiKey == "6738196d-2a2c-4ef8-9b6e-1252c6ec7325"
); ) {
} return MB;
public static bool Use2021SoDTutorial(string apiKey) { } else if (
return !IsOldSoD(apiKey); apiKey == "1552008f-4a95-46f5-80e2-58574da65875"
) {
return WoJS;
}
return 0;
} }
public static bool IsMaM(string apiKey) { public static bool IsMultiplayerSupported(string apiKey) {
return apiKey == "e20150cc-ff70-435c-90fd-341dc9161cc3"; return GetVersion(apiKey) >= 0xa3a19a0a;
} }
} }