Adventureland Part 1

Adds most of the stuff related to AL. Part 2 will have the mission data itself.
This commit is contained in:
YoshiCraft64 2025-02-09 21:28:44 -06:00 committed by GitHub
parent 13df822608
commit 995bcd6307
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
38 changed files with 939 additions and 16 deletions

View File

@ -22,6 +22,7 @@ public class ContentController : Controller {
private GameDataService gameDataService;
private DisplayNamesService displayNamesService;
private NeighborhoodService neighborhoodService;
private WorldIdService worldIdService;
private Random random = new Random();
private readonly IOptions<ApiServerConfig> config;
@ -36,6 +37,7 @@ public class ContentController : Controller {
GameDataService gameDataService,
DisplayNamesService displayNamesService,
NeighborhoodService neighborhoodService,
WorldIdService worldIdService,
IOptions<ApiServerConfig> config
) {
this.ctx = ctx;
@ -48,6 +50,7 @@ public class ContentController : Controller {
this.gameDataService = gameDataService;
this.displayNamesService = displayNamesService;
this.neighborhoodService = neighborhoodService;
this.worldIdService = worldIdService;
this.config = config;
}
@ -2119,12 +2122,103 @@ public class ContentController : Controller {
return Ok(new TreasureChestData());
}
//Oh boy it's the AL code stuff you guys ready for p a i n
[HttpPost]
[Produces("application/xml")]
[Route("MissionWebService.asmx/GetWorldId")] // used by Math Blaster
public IActionResult GetWorldId() {
// TODO: This is a placeholder
return Ok(0);
[Route("MissionWebService.asmx/GetWorldId")] // used by Math Blaster and WoJS Adventureland
public IActionResult GetWorldId([FromForm] int gameId, [FromForm] string sceneName, [FromForm] string apiKey)
{
var result = worldIdService.GetWorldID(sceneName);
return Ok(result);
}
[HttpPost]
//[Produces("application/xml")]
[Route("MissionWebService.asmx/GetBadge")]
public IActionResult GetBadge([FromForm] int gameId)
{
if (gameId == 1) return Ok(System.IO.File.ReadAllText("./Resources/missions/badge_wojs_al.xml"));
return Ok(); // if it doesn't work/causes errors then: return Ok(XmlUtil.SerializeXml(new BadgeData()));
}
[HttpPost]
[Produces("application/xml")]
[Route("MissionWebService.asmx/GetMission")]
public IActionResult GetMission([FromForm] int gameId, [FromForm] int type, [FromForm] string apiKey)
{
MissionData mission = missionService.GetMissionDataFromFile(ClientVersion.GetVersion(apiKey), gameId, type);
if (mission != null) return Ok(mission);
else return Ok(new MissionData());
}
[HttpPost]
[Produces("application/xml")]
[Route("ContentWebService.asmx/GetUserMission")]
[VikingSession]
public IActionResult GetUserMission(Viking viking, [FromForm] int worldId, [FromForm] string apiKey)
{
//if (ClientVersion.GetVersion(apiKey) <= ClientVersion.WoJS_AdvLand)
//{
return Ok(missionService.GetUserMissionData(viking, worldId));
//}
return Ok(new Schema.UserMissionData());
}
[HttpPost]
[Produces("application/xml")]
[Route("ContentWebService.asmx/SetUserMission")]
[VikingSession]
public IActionResult SetUserMission(Viking viking, [FromForm] int worldId, [FromForm] int missionId, [FromForm] int stepId, [FromForm] int taskId, [FromForm] string apiKey)
{
//if (ClientVersion.GetVersion(apiKey) <= ClientVersion.WoJS_AdvLand)
//{
missionService.SetOrUpdateUserMissionData(viking, worldId, missionId, stepId, taskId);
return Ok(true); // assuming true or false response here
//}
return Ok(false);
}
[HttpPost]
[Produces("application/xml")]
[Route("ContentWebService.asmx/SetUserMissionComplete")]
[VikingSession]
public IActionResult SetUserMissionComplete(Viking viking, [FromForm] int worldId, [FromForm] int missionId, [FromForm] string apiKey)
{
//if (ClientVersion.GetVersion(apiKey) <= ClientVersion.WoJS_AdvLand)
//{
return Ok(missionService.SetUserMissionCompleted(viking, worldId, missionId, true));
//}
return Ok(false);
}
[HttpPost]
[Produces("application/xml")]
[Route("ContentWebService.asmx/SetUserBadgeComplete")]
[VikingSession]
public IActionResult SetUserBadgeComplete(Viking viking, [FromForm] int badgeId)
{
return Ok(missionService.SetUserBadgeComplete(viking, badgeId));
}
[HttpPost]
[Produces("application/xml")]
[Route("ContentWebService.asmx/GetUserBadgeComplete")]
[VikingSession]
public IActionResult GetUserBadgeComplete(Viking viking)
{
return Ok(missionService.GetUserBadgesCompleted(viking));
}
[HttpPost]
[Produces("application/xml")]
[Route("MissionWebService.asmx/GetStep")]
public IActionResult GetMissionStep([FromForm] int stepId, [FromForm] string apiKey)
{
return Ok(missionService.GetMissionStepFromFile(ClientVersion.GetVersion(apiKey), stepId));
}
[HttpPost]

View File

@ -3,7 +3,8 @@ using Microsoft.Extensions.Options;
using sodoff.Configuration;
namespace sodoff.Model;
public class DBContext : DbContext {
public class DBContext : DbContext
{
public DbSet<User> Users { get; set; } = null!;
public DbSet<Viking> Vikings { get; set; } = null!;
public DbSet<Dragon> Dragons { get; set; } = null!;
@ -28,27 +29,31 @@ public class DBContext : DbContext {
public DbSet<Group> Groups { get; set; } = null!;
public DbSet<Rating> Ratings { get; set; } = null!;
public DbSet<RatingRank> RatingRanks { get; set; } = null!;
public DbSet<UserMissionData> UserMissionData { get; set; } = null!;
public DbSet<UserBadgeCompleteData> UserBadgesCompleted { get; set; } = null!;
private readonly IOptions<ApiServerConfig> config;
public DBContext(IOptions<ApiServerConfig> config) {
public DBContext(IOptions<ApiServerConfig> config)
{
this.config = config;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
#if USE_POSTGRESQL
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
#if USE_POSTGRESQL
if (config.Value.DbProvider == DbProviders.PostgreSQL) {
optionsBuilder.UseNpgsql(config.Value.DbConnection).UseLazyLoadingProxies();
return;
}
#endif
#if USE_MYSQL
#endif
#if USE_MYSQL
if (config.Value.DbProvider == DbProviders.MySQL) {
optionsBuilder.UseMySQL(config.Value.DbConnection).UseLazyLoadingProxies();
return;
}
#endif
#if USE_SQLITE
#endif
#if USE_SQLITE
if (config.Value.DbProvider == DbProviders.SQLite) {
string DbPath;
if (String.IsNullOrEmpty(config.Value.DbPath)) {
@ -59,11 +64,12 @@ public class DBContext : DbContext {
optionsBuilder.UseSqlite($"Data Source={DbPath}").UseLazyLoadingProxies();
return;
}
#endif
#endif
throw new Exception($"Unsupported DbProvider {config.Value.DbProvider}");
}
protected override void OnModelCreating(ModelBuilder builder) {
protected override void OnModelCreating(ModelBuilder builder)
{
// Sessions
builder.Entity<Session>().HasOne(s => s.User)
.WithMany(e => e.Sessions)

View File

@ -0,0 +1,11 @@
namespace sodoff.Model
{
public class UserBadgeCompleteData
{
public int Id { get; set; }
public int VikingId { get; set; }
public int BadgeId { get; set; }
public virtual Viking? Viking { get; set; }
}
}

View File

@ -0,0 +1,18 @@
using System.ComponentModel.DataAnnotations;
namespace sodoff.Model
{
public class UserMissionData
{
[Key]
public int Id { get; set; }
public int VikingId { get; set; }
public int WorldId { get; set; }
public int MissionId { get; set; }
public int StepId { get; set; }
public int TaskId { get; set; }
public bool IsCompleted { get; set; } = false;
public virtual Viking? Viking { get; set; }
}
}

View File

@ -5,7 +5,8 @@ using sodoff.Schema;
namespace sodoff.Model;
[Index(nameof(Uid))]
public class Viking {
public class Viking
{
[Key]
public int Id { get; set; }
@ -42,6 +43,8 @@ public class Viking {
public virtual ICollection<Group> Groups { get; set; } = null!;
public virtual ICollection<Rating> Ratings { get; set; } = null!;
public virtual Dragon? SelectedDragon { get; set; }
public virtual ICollection<UserMissionData> UserMissions { get; set; } = null!;
public virtual ICollection<UserBadgeCompleteData> UserBadgesCompleted { get; set; } = null!;
public DateTime? CreationDate { get; set; }
public DateTime? BirthDate { get; set; }

View File

@ -30,6 +30,7 @@ builder.Services.AddSingleton<ItemService>();
builder.Services.AddSingleton<StoreService>();
builder.Services.AddSingleton<DisplayNamesService>();
builder.Services.AddSingleton<MMOConfigService>();
builder.Services.AddSingleton<WorldIdService>();
builder.Services.AddScoped<KeyValueService>();
builder.Services.AddScoped<MissionService>();
@ -40,6 +41,7 @@ builder.Services.AddScoped<GameDataService>();
builder.Services.AddScoped<ProfileService>();
builder.Services.AddScoped<NeighborhoodService>();
bool assetServer = builder.Configuration.GetSection("AssetServer").GetValue<bool>("Enabled");
string assetIP = builder.Configuration.GetSection("AssetServer").GetValue<string>("ListenIP");
int assetPort = builder.Configuration.GetSection("AssetServer").GetValue<int>("Port");

12
src/Schema/BadgeData.cs Normal file
View File

@ -0,0 +1,12 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "BadgeData", Namespace = "", IsNullable = true)]
[Serializable]
public class BadgeData
{
[XmlElement(ElementName = "Badge")]
public BadgeDataBadge[] Badge;
}
}

View File

@ -0,0 +1,39 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "BadgeDataBadge", Namespace = "")]
[Serializable]
public class BadgeDataBadge
{
[XmlElement(ElementName = "BadgeId")]
public int BadgeId;
[XmlElement(ElementName = "Name")]
public string Name;
[XmlElement(ElementName = "Description")]
public string Description;
[XmlElement(ElementName = "Experience")]
public int Experience;
[XmlElement(ElementName = "Pieces")]
public int Pieces;
[XmlElement(ElementName = "Mask")]
public string Mask;
[XmlElement(ElementName = "Color")]
public string Color;
[XmlElement(ElementName = "Grey")]
public string Grey;
[XmlElement(ElementName = "PieceDialog", IsNullable = true)]
public BadgeDataBadgePieceDialog PieceDialog;
[XmlElement(ElementName = "CompleteDialog", IsNullable = true)]
public BadgeDataBadgeCompleteDialog CompleteDialog;
}
}

View File

@ -0,0 +1,18 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "BadgeDataBadgeCompleteDialog", Namespace = "")]
[Serializable]
public class BadgeDataBadgeCompleteDialog
{
[XmlElement(ElementName = "FileName")]
public string FileName;
[XmlElement(ElementName = "NPC")]
public string NPC;
[XmlElement(ElementName = "Bundle")]
public string Bundle;
}
}

View File

@ -0,0 +1,18 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "BadgeDataBadgePieceDialog", Namespace = "")]
[Serializable]
public class BadgeDataBadgePieceDialog
{
[XmlElement(ElementName = "FileName")]
public string FileName;
[XmlElement(ElementName = "NPC")]
public string NPC;
[XmlElement(ElementName = "Bundle")]
public string Bundle;
}
}

12
src/Schema/MissionData.cs Normal file
View File

@ -0,0 +1,12 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "MissionData", Namespace = "", IsNullable = false)]
[Serializable]
public class MissionData
{
[XmlElement(ElementName = "Mission")]
public MissionDataMission[] Mission;
}
}

View File

@ -0,0 +1,36 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "MissionDataMission", Namespace = "")]
[Serializable]
public class MissionDataMission
{
[XmlElement(ElementName = "MissionID")]
public int MissionID;
[XmlElement(ElementName = "Name")]
public string Name;
[XmlElement(ElementName = "DisplayName", IsNullable = true)]
public string DisplayName;
[XmlElement(ElementName = "IconName", IsNullable = true)]
public string IconName;
[XmlElement(ElementName = "Description", IsNullable = true)]
public string Description;
[XmlElement(ElementName = "Experience")]
public int Experience;
[XmlElement(ElementName = "RewardDialog", IsNullable = true)]
public MissionDataMissionRewardDialog RewardDialog;
[XmlElement(ElementName = "UnlockMission")]
public int[] UnlockMission;
[XmlElement(ElementName = "Step", IsNullable = true)]
public MissionDataMissionStep[] Step;
}
}

View File

@ -0,0 +1,18 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "MissionDataMissionRewardDialog", Namespace = "")]
[Serializable]
public class MissionDataMissionRewardDialog
{
[XmlElement(ElementName = "FileName")]
public string FileName;
[XmlElement(ElementName = "NPC")]
public string NPC;
[XmlElement(ElementName = "Bundle")]
public string Bundle;
}
}

View File

@ -0,0 +1,15 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "MissionDataMissionStep", Namespace = "")]
[Serializable]
public class MissionDataMissionStep
{
[XmlElement(ElementName = "StepID")]
public int StepID;
[XmlElement(ElementName = "TaskID")]
public int[] TaskID;
}
}

36
src/Schema/Step.cs Normal file
View File

@ -0,0 +1,36 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "Step", Namespace = "", IsNullable = false)]
[Serializable]
public class Step
{
[XmlElement(ElementName = "StepID")]
public StepStepID StepID;
[XmlElement(ElementName = "OfferSpeech", IsNullable = true)]
public StepOfferSpeech OfferSpeech;
[XmlElement(ElementName = "EndSpeech", IsNullable = true)]
public StepEndSpeech EndSpeech;
[XmlElement(ElementName = "TasksNeeded")]
public int TasksNeeded;
[XmlElement(ElementName = "Task")]
public StepTask[] Task;
[XmlElement(ElementName = "Message")]
public StepMessage[] Message;
[XmlElement(ElementName = "NPCData")]
public StepNPCData[] NPCData;
[XmlElement(ElementName = "StoreItem")]
public StepStoreItem[] StoreItem;
[XmlElement(ElementName = "StartPlayerItem")]
public StepStartPlayerItem[] StartPlayerItem;
}
}

View File

@ -0,0 +1,18 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "StepEndSpeech", Namespace = "")]
[Serializable]
public class StepEndSpeech
{
[XmlElement(ElementName = "FileName")]
public string FileName;
[XmlElement(ElementName = "NPC")]
public string NPC;
[XmlElement(ElementName = "Bundle")]
public string Bundle;
}
}

18
src/Schema/StepMessage.cs Normal file
View File

@ -0,0 +1,18 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "StepMessage", Namespace = "")]
[Serializable]
public class StepMessage
{
[XmlElement(ElementName = "Text", IsNullable = true)]
public string Text;
[XmlElement(ElementName = "ItemID", IsNullable = true)]
public int? ItemID;
[XmlElement(ElementName = "Scale", IsNullable = true)]
public float? Scale;
}
}

21
src/Schema/StepNPCData.cs Normal file
View File

@ -0,0 +1,21 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "StepNPCData", Namespace = "")]
[Serializable]
public class StepNPCData
{
[XmlElement(ElementName = "NPC")]
public string NPC;
[XmlElement(ElementName = "Marker")]
public string Marker;
[XmlElement(ElementName = "Scene")]
public string Scene;
[XmlElement(ElementName = "Animation", IsNullable = true)]
public string Animation;
}
}

View File

@ -0,0 +1,18 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "StepOfferSpeech", Namespace = "")]
[Serializable]
public class StepOfferSpeech
{
[XmlElement(ElementName = "FileName")]
public string FileName;
[XmlElement(ElementName = "NPC")]
public string NPC;
[XmlElement(ElementName = "Bundle")]
public string Bundle;
}
}

View File

@ -0,0 +1,15 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "StepStartPlayerItem", Namespace = "")]
[Serializable]
public class StepStartPlayerItem
{
[XmlElement(ElementName = "ItemID")]
public int ItemID;
[XmlElement(ElementName = "Quantity")]
public int Quantity;
}
}

12
src/Schema/StepStepID.cs Normal file
View File

@ -0,0 +1,12 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "StepStepID", Namespace = "")]
[Serializable]
public class StepStepID
{
[XmlText]
public int Value;
}
}

View File

@ -0,0 +1,15 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "StepStoreItem", Namespace = "")]
[Serializable]
public class StepStoreItem
{
[XmlElement(ElementName = "StoreID")]
public int StoreID;
[XmlElement(ElementName = "ItemID")]
public int ItemID;
}
}

52
src/Schema/StepTask.cs Normal file
View File

@ -0,0 +1,52 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "StepTask", Namespace = "")]
[Serializable]
public class StepTask
{
[XmlElement(ElementName = "TaskID")]
public int TaskID;
// Token: 0x0400043C RID: 1084
[XmlElement(ElementName = "Type")]
public string Type;
// Token: 0x0400043D RID: 1085
[XmlElement(ElementName = "Dialog", IsNullable = true)]
public StepTaskDialog Dialog;
// Token: 0x0400043E RID: 1086
[XmlElement(ElementName = "Message")]
public StepTaskMessage[] Message;
// Token: 0x0400043F RID: 1087
[XmlElement(ElementName = "SetupGroup", IsNullable = true)]
public string SetupGroup;
// Token: 0x04000440 RID: 1088
[XmlElement(ElementName = "SetupScene", IsNullable = true)]
public string SetupScene;
// Token: 0x04000441 RID: 1089
[XmlElement(ElementName = "Help")]
public StepTaskHelp[] Help;
// Token: 0x04000442 RID: 1090
[XmlElement(ElementName = "RewardPlayerItem")]
public StepTaskRewardPlayerItem[] RewardPlayerItem;
// Token: 0x04000443 RID: 1091
[XmlElement(ElementName = "Experience")]
public int Experience;
// Token: 0x04000444 RID: 1092
[XmlElement(ElementName = "Time", IsNullable = true)]
public int? Time;
// Token: 0x04000445 RID: 1093
[XmlElement(ElementName = "Objective")]
public StepTaskObjective Objective;
}
}

View File

@ -0,0 +1,18 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "StepTaskDialog", Namespace = "")]
[Serializable]
public class StepTaskDialog
{
[XmlElement(ElementName = "FileName")]
public string FileName;
[XmlElement(ElementName = "NPC")]
public string NPC;
[XmlElement(ElementName = "Bundle")]
public string Bundle;
}
}

View File

@ -0,0 +1,18 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "StepTaskHelp", Namespace = "")]
[Serializable]
public class StepTaskHelp
{
[XmlElement(ElementName = "FileName")]
public string FileName;
[XmlElement(ElementName = "NPC")]
public string NPC;
[XmlElement(ElementName = "Bundle")]
public string Bundle;
}
}

View File

@ -0,0 +1,18 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "StepTaskMessage", Namespace = "")]
[Serializable]
public class StepTaskMessage
{
[XmlElement(ElementName = "Text", IsNullable = true)]
public string Text;
[XmlElement(ElementName = "ItemID", IsNullable = true)]
public int? ItemID;
[XmlElement(ElementName = "Scale", IsNullable = true)]
public float? Scale;
}
}

View File

@ -0,0 +1,72 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "StepTaskObjective", Namespace = "")]
[Serializable]
public class StepTaskObjective
{
[XmlElement(ElementName = "Beacon", IsNullable = true)]
public bool? Beacon;
// Token: 0x0400045B RID: 1115
[XmlElement(ElementName = "NPC", IsNullable = true)]
public string NPC;
// Token: 0x0400045C RID: 1116
[XmlElement(ElementName = "Marker", IsNullable = true)]
public string Marker;
// Token: 0x0400045D RID: 1117
[XmlElement(ElementName = "Scene", IsNullable = true)]
public string Scene;
// Token: 0x0400045E RID: 1118
[XmlElement(ElementName = "Range", IsNullable = true)]
public float? Range;
// Token: 0x0400045F RID: 1119
[XmlElement(ElementName = "Module", IsNullable = true)]
public string Module;
// Token: 0x04000460 RID: 1120
[XmlElement(ElementName = "Group", IsNullable = true)]
public string Group;
// Token: 0x04000461 RID: 1121
[XmlElement(ElementName = "Object", IsNullable = true)]
public string Object;
// Token: 0x04000462 RID: 1122
[XmlElement(ElementName = "StoreID", IsNullable = true)]
public int? StoreID;
// Token: 0x04000463 RID: 1123
[XmlElement(ElementName = "ItemID", IsNullable = true)]
public int? ItemID;
// Token: 0x04000464 RID: 1124
[XmlElement(ElementName = "ItemName", IsNullable = true)]
public string ItemName;
// Token: 0x04000465 RID: 1125
[XmlElement(ElementName = "CategoryID", IsNullable = true)]
public int? CategoryID;
// Token: 0x04000466 RID: 1126
[XmlElement(ElementName = "AttributeID")]
public int[] AttributeID;
// Token: 0x04000467 RID: 1127
[XmlElement(ElementName = "Quantity", IsNullable = true)]
public int? Quantity;
// Token: 0x04000468 RID: 1128
[XmlElement(ElementName = "Photo", IsNullable = true)]
public StepTaskObjectivePhoto Photo;
// Token: 0x04000469 RID: 1129
[XmlElement(ElementName = "Creative", IsNullable = true)]
public StepTaskObjectiveCreative Creative;
}
}

View File

@ -0,0 +1,15 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "StepTaskObjectiveCreative", Namespace = "")]
[Serializable]
public class StepTaskObjectiveCreative
{
[XmlElement(ElementName = "Type")]
public int Type;
[XmlElement(ElementName = "AttributeID")]
public int[] AttributeID;
}
}

View File

@ -0,0 +1,24 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "StepTaskObjectivePhoto", Namespace = "")]
[Serializable]
public class StepTaskObjectivePhoto
{
[XmlElement(ElementName = "ItemName")]
public string[] ItemName;
[XmlElement(ElementName = "NPC")]
public string[] NPC;
[XmlElement(ElementName = "CategoryID")]
public int[] CategoryID;
[XmlElement(ElementName = "AttributeID")]
public int[] AttributeID;
[XmlElement(ElementName = "Quantity")]
public int Quantity;
}
}

View File

@ -0,0 +1,15 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "StepTaskRewardPlayerItem", Namespace = "")]
[Serializable]
public class StepTaskRewardPlayerItem
{
[XmlElement(ElementName = "ItemID")]
public int ItemID;
[XmlElement(ElementName = "Quantity")]
public int Quantity;
}
}

12
src/Schema/UserBadge.cs Normal file
View File

@ -0,0 +1,12 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "UserBadge", Namespace = "", IsNullable = false)]
[Serializable]
public class UserBadge
{
[XmlElement(ElementName = "BadgeId")]
public int[] BadgeId;
}
}

View File

@ -0,0 +1,15 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "UserMissionData", Namespace = "")]
[Serializable]
public class UserMissionData
{
[XmlElement(ElementName = "Mission")]
public UserMissionDataMission[] Mission;
[XmlElement(ElementName = "MissionComplete")]
public int[] MissionComplete;
}
}

View File

@ -0,0 +1,15 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "UserMissionDataMission", Namespace = "")]
[Serializable]
public class UserMissionDataMission
{
[XmlElement(ElementName = "MissionId")]
public int MissionId;
[XmlElement(ElementName = "Step")]
public UserMissionDataMissionStep[] Step;
}
}

View File

@ -0,0 +1,15 @@
using System.Xml.Serialization;
namespace sodoff.Schema
{
[XmlRoot(ElementName = "UserMissionDataMissionStep", Namespace = "")]
[Serializable]
public class UserMissionDataMissionStep
{
[XmlElement(ElementName = "StepId")]
public int StepId;
[XmlElement(ElementName = "TaskId")]
public int[] TaskId;
}
}

12
src/Schema/World.cs Normal file
View File

@ -0,0 +1,12 @@
using System.Xml.Serialization;
[XmlRoot(ElementName = "World", Namespace = "")]
[Serializable]
public class World
{
[XmlElement(ElementName = "Scene")]
public string Scene;
[XmlElement(ElementName = "ID")]
public int ID;
}

View File

@ -54,6 +54,141 @@ public class MissionService {
return mission;
}
public MissionData GetMissionDataFromFile(uint gameVersion, int gameId, int type)
{
//if (gameVersion <= ClientVersion.WoJS_AdvLand)
//{
return XmlUtil.DeserializeXml<MissionData>(File.ReadAllText($"./Resources/missions/stepsmissions_{gameId}_{type}.xml"));
//}
return new MissionData();
}
public Step GetMissionStepFromFile(uint gameVersion, int id)
{
//if (gameVersion <= ClientVersion.WoJS_AdvLand)
//{
return XmlUtil.DeserializeXml<Step>(File.ReadAllText($"./Resources/missions/steps/{id}.xml"));
//}
return new Step();
}
public Schema.UserMissionData GetUserMissionData(Viking viking, int worldId)
{
Schema.UserMissionData umdRes = new Schema.UserMissionData();
// 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>();
// 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() });
}
// add completed mission id's to usermissionscompletedids
List<Model.UserMissionData> vikingCompletedUmds = vikingUmds.Where(e => e.IsCompleted == true).ToList();
foreach (Model.UserMissionData mission in vikingCompletedUmds)
{
userMissionsCompletedIds.Add(mission.MissionId);
}
// construct response
umdRes.Mission = missions.ToArray();
umdRes.MissionComplete = userMissionsCompletedIds.ToArray();
// return
return umdRes;
}
public UserBadge GetUserBadgesCompleted(Viking viking)
{
// get badges
List<UserBadgeCompleteData> userBadgesCompleted = viking.UserBadgesCompleted.ToList();
List<int> completedBadgeIds = new List<int>();
foreach (var userBadge in userBadgesCompleted)
{
completedBadgeIds.Add(userBadge.BadgeId);
}
return new UserBadge { BadgeId = completedBadgeIds.ToArray() };
}
public Model.UserMissionData 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)
.Where(e => e.MissionId == missionId)
.FirstOrDefault();
if (existingMission != null)
{
// update taskid and stepid
existingMission.StepId = stepId;
existingMission.TaskId = taskId;
ctx.SaveChanges();
return existingMission;
}
// 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)
{
Model.UserMissionData? mission = viking.UserMissions.Where(e => e.WorldId == worldId)
.Where(e => e.MissionId == missionId)
.FirstOrDefault();
if (mission != null)
{
// set mission complete
mission.IsCompleted = isCompleted;
// add jumpstars for completing the mission
if (isCompleted) achievementService.AddAchievementPoints(viking, AchievementPointTypes.PlayerXP, 25); // hardcoding earning 25 for now
ctx.SaveChanges();
return true;
}
return false;
}
public bool SetUserBadgeComplete(Viking viking, int gameId)
{
// add completed badge to database
UserBadgeCompleteData userBadgeCompleteData = new() { BadgeId = gameId };
viking.UserBadgesCompleted.Add(userBadgeCompleteData);
ctx.SaveChanges();
return true;
}
public List<MissionCompletedResult> UpdateTaskProgress(int missionId, int taskId, int userId, bool completed, string xmlPayload, uint gameVersion) {
SetTaskProgressDB(missionId, taskId, userId, completed, xmlPayload);

View File

@ -0,0 +1,29 @@
using sodoff.Schema;
using sodoff.Util;
namespace sodoff.Services;
public class WorldIdService {
Dictionary<string, int> worlds_id = new();
public WorldIdService()
{
var worlds = XmlUtil.DeserializeXml<World[]>(XmlUtil.ReadResourceXmlString("worlds"));
//Console.WriteLine("We are confirming this thing works");
foreach (var w in worlds)
{
worlds_id[w.Scene] = w.ID;
}
}
public int GetWorldID(string mapName)
{
//Console.WriteLine(worlds_id[mapName]);
if (worlds_id.ContainsKey(mapName))
return worlds_id[mapName];
else
return 0;
}
}

View File

@ -141,6 +141,9 @@
</EmbeddedResource>
<EmbeddedResource Include="Resources\defaulthouse.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="Resources\worlds.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
</Project>