diff --git a/src/Attributes/VikingSession.cs b/src/Attributes/VikingSession.cs index e93eb2b..8cdb829 100644 --- a/src/Attributes/VikingSession.cs +++ b/src/Attributes/VikingSession.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; using sodoff.Model; namespace sodoff.Attributes; @@ -12,6 +13,9 @@ public class VikingSession : Attribute, IAsyncActionFilter { public Modes Mode { get; set; } = Modes.VIKING; public bool UseLock = false; + private static Dictionary semaphores = new(); + private static SemaphoreSlim dictSemaphore = new(1, 1); + public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { DBContext ctx = context.HttpContext.RequestServices.GetService(typeof(DBContext)) as DBContext; @@ -44,15 +48,16 @@ public class VikingSession : Attribute, IAsyncActionFilter { // NOTE: we can't refer to session.User / session.Viking here, // because it may cause to ignore modifications from the threads we are waiting for // we can use its only after vikingMutex.WaitOne() - - Mutex vikingMutex = new Mutex(false, "SoDOffViking:" + userVikingId); + string semKey = "SoDOffViking:" + userVikingId; + SemaphoreSlim semaphore = await GetSemaphore(semKey); try { - vikingMutex.WaitOne(); + await semaphore.WaitAsync(); context.ActionArguments["user"] = session.User; context.ActionArguments["viking"] = session.Viking; await next(); } finally { - vikingMutex.ReleaseMutex(); + semaphore.Release(); + await RemoveSemaphore(semKey, semaphore); } } else { context.ActionArguments["user"] = session.User; @@ -60,4 +65,22 @@ public class VikingSession : Attribute, IAsyncActionFilter { await next(); } } + + private static async Task GetSemaphore(string key) { + await dictSemaphore.WaitAsync(); + if (!semaphores.TryGetValue(key, out SemaphoreSlim semaphore)) { + semaphore = new SemaphoreSlim(1, 1); + semaphores.Add(key, semaphore); + } + dictSemaphore.Release(); + return semaphore; + } + + private static async Task RemoveSemaphore(string key, SemaphoreSlim sem) { + await dictSemaphore.WaitAsync(); + if (sem.CurrentCount == 1) { + semaphores.Remove(key); + } + dictSemaphore.Release(); + } } diff --git a/src/Controllers/Common/AuthenticationController.cs b/src/Controllers/Common/AuthenticationController.cs index 3fc5548..96e1065 100644 --- a/src/Controllers/Common/AuthenticationController.cs +++ b/src/Controllers/Common/AuthenticationController.cs @@ -49,10 +49,19 @@ public class AuthenticationController : Controller { user = ctx.Users.FirstOrDefault(e => e.Username == data.UserName); } - if (user is null || new PasswordHasher().VerifyHashedPassword(null, user.Password, data.Password) != PasswordVerificationResult.Success) { + if (user is null) { + return Ok(new ParentLoginInfo { Status = MembershipUserStatus.InvalidUserName }); + } + + PasswordVerificationResult result = new PasswordHasher().VerifyHashedPassword(null, user.Password, data.Password); + if (result == PasswordVerificationResult.Failed) { return Ok(new ParentLoginInfo { Status = MembershipUserStatus.InvalidPassword }); } + if (result == PasswordVerificationResult.SuccessRehashNeeded) { + user.Password = new PasswordHasher().HashPassword(null, data.Password); + } + // Create session Session session = new Session { User = user, diff --git a/src/Controllers/Common/ContentController.cs b/src/Controllers/Common/ContentController.cs index 0031135..071541d 100644 --- a/src/Controllers/Common/ContentController.cs +++ b/src/Controllers/Common/ContentController.cs @@ -570,7 +570,7 @@ public class ContentController : Controller { [HttpPost] [Produces("application/xml")] [Route("V2/ContentWebService.asmx/CreatePet")] - [VikingSession] + [VikingSession(UseLock = true)] public IActionResult CreatePet(Viking viking, [FromForm] string request) { RaisedPetRequest raisedPetRequest = XmlUtil.DeserializeXml(request); // TODO: Investigate SetAsSelectedPet and UnSelectOtherPets - they don't seem to do anything @@ -602,7 +602,6 @@ public class ContentController : Controller { if (raisedPetRequest.SetAsSelectedPet == true) { viking.SelectedDragon = dragon; - ctx.Update(viking); } ctx.Dragons.Add(dragon); ctx.Images.Add(image); @@ -905,7 +904,7 @@ public class ContentController : Controller { [HttpPost] [Produces("application/xml")] [Route("ContentWebService.asmx/SetImage")] - [VikingSession] + [VikingSession(UseLock = true)] public bool SetImage(Viking viking, [FromForm] string ImageType, [FromForm] int ImageSlot, [FromForm] string contentXML, [FromForm] string imageFile) { // TODO: the other properties of contentXML ImageData data = XmlUtil.DeserializeXml(contentXML); @@ -925,11 +924,8 @@ public class ContentController : Controller { image.ImageData = imageFile; image.TemplateName = data.TemplateName; - if (newImage) { + if (newImage) ctx.Images.Add(image); - } else { - ctx.Images.Update(image); - } ctx.SaveChanges(); return true; @@ -1113,14 +1109,17 @@ public class ContentController : Controller { foreach (var m in filterV2.MissionPair) if (m.MissionID != null) 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 } else { if (filterV2.GetCompletedMission ?? false) { foreach (var mission in viking.MissionStates.Where(x => x.MissionStatus == MissionStatus.Completed)) result.Missions.Add(missionService.GetMissionWithProgress(mission.MissionId, viking.Id, gameVersion)); } else { - foreach (var mission in viking.MissionStates.Where(x => x.MissionStatus != MissionStatus.Completed)) - result.Missions.Add(missionService.GetMissionWithProgress(mission.MissionId, viking.Id, gameVersion)); + var missionStatesById = viking.MissionStates.Where(x => x.MissionStatus != MissionStatus.Completed).ToDictionary(ms => ms.MissionId); + HashSet upcomingMissionIds = new(missionStore.GetUpcomingMissions(gameVersion)); + var combinedMissionIds = new HashSet(missionStatesById.Keys); + combinedMissionIds.UnionWith(upcomingMissionIds); + foreach (var missionId in combinedMissionIds) + result.Missions.Add(missionService.GetMissionWithProgress(missionId, viking.Id, gameVersion)); } } diff --git a/src/Controllers/Common/ImportExportController.cs b/src/Controllers/Common/ImportExportController.cs new file mode 100644 index 0000000..92dfea9 --- /dev/null +++ b/src/Controllers/Common/ImportExportController.cs @@ -0,0 +1,203 @@ +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Text.Encodings.Web; +using sodoff.Model; +using sodoff.Schema; +using sodoff.Util; + +namespace sodoff.Controllers.Common; +public class ExportController : ControllerBase { + private readonly DBContext ctx; + + public ExportController(DBContext ctx) { + this.ctx = ctx; + } + + [HttpPost] + [Route("Export")] + public IActionResult Export([FromForm] string username, [FromForm] string password) { + // Authenticate user by Username + User? user = ctx.Users.FirstOrDefault(e => e.Username == username); + if (user is null || new PasswordHasher().VerifyHashedPassword(null, user.Password, password) == PasswordVerificationResult.Failed) { + return Unauthorized("Invalid username or password."); + } + + // Serialize to JSON + var options = new JsonSerializerOptions + { + ReferenceHandler = ReferenceHandler.IgnoreCycles, + Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping, + WriteIndented = true + }; + string jsonData = JsonSerializer.Serialize(user, options); + + return Ok(jsonData); + } + + [HttpPost] + [Route("Import")] + public IActionResult Import([FromForm] string username, [FromForm] string password, [FromForm] string vikingName, [FromForm] IFormFile dataFile, [FromForm] string? newVikingName) { + User? user = ctx.Users.FirstOrDefault(e => e.Username == username); + if (user is null || new PasswordHasher().VerifyHashedPassword(null, user.Password, password) == PasswordVerificationResult.Failed) { + return Unauthorized("Invalid username or password."); + } + + User user_data; + using (var reader = new StreamReader(dataFile.OpenReadStream())) { + user_data = System.Text.Json.JsonSerializer.Deserialize(reader.ReadToEnd()); + } + + foreach (var v in user_data.Vikings) { + if (v.Name == vikingName) { + if (String.IsNullOrEmpty(newVikingName)) + newVikingName = vikingName; + + if (ctx.Vikings.Count(e => e.Name == newVikingName) > 0) { + return Conflict("Viking name already in use"); + } + + if (newVikingName != vikingName) { + AvatarData avatarData = XmlUtil.DeserializeXml(v.AvatarSerialized); + avatarData.DisplayName = newVikingName; + v.AvatarSerialized = XmlUtil.SerializeXml(avatarData); + } + + Viking viking = new Viking { + Uid = Guid.NewGuid(), + Name = newVikingName, + User = user, + AvatarSerialized = v.AvatarSerialized, + CreationDate = DateTime.UtcNow, + BirthDate = v.BirthDate, + Gender = v.Gender, + GameVersion = v.GameVersion + }; + user.Vikings.Add(viking); + + Dictionary dragonIds = new(); + foreach (var x in v.Dragons) { + x.Viking = viking; + x.EntityId = Guid.NewGuid(); + dragonIds.Add(x.Id, x.EntityId); + x.Id = 0; + ctx.Dragons.Add(x); + } + Dictionary itemIds = new(); + foreach (var x in v.InventoryItems) { + itemIds.Add(x.Id, x.ItemId); + x.Id = 0; + x.Viking = viking; + ctx.InventoryItems.Add(x); + } + + ctx.SaveChanges(); // need for get new ids of dragons and items + + HashSet usedItemIds = new(); + foreach (var x in v.Rooms) { + x.Viking = viking; + if (int.TryParse(x.RoomId, out int roomID)) { + // numeric room name is inventory item id + // remap old value to new value based on item id value + roomID = viking.InventoryItems.FirstOrDefault(e => e.ItemId == itemIds[roomID] && !usedItemIds.Contains(e.Id)).Id; + usedItemIds.Add(roomID); + x.RoomId = roomID.ToString(); + } + ctx.Rooms.Add(x); + } + foreach (var x in v.PairData) { + x.Viking = viking; + if (x.PairId == 2014) { // stables data + foreach (var p in x.Pairs.Where(e => e.Key.StartsWith("Stable"))) { + StableData stableData = XmlUtil.DeserializeXml(p.Value); + stableData.InventoryID = viking.InventoryItems.FirstOrDefault(e => e.ItemId == stableData.ItemID).Id; + usedItemIds.Add(stableData.InventoryID); + foreach (var n in stableData.NestList) { + if (n.PetID != 0) + n.PetID = viking.Dragons.FirstOrDefault(d => d.EntityId == dragonIds[n.PetID]).Id; + } + p.Value = XmlUtil.SerializeXml(stableData); + } + } + ctx.PairData.Add(x); + } + + foreach (var x in v.Images) { + x.Viking = viking; + ctx.Images.Add(x); + } + foreach (var x in v.MissionStates) { + x.Viking = viking; + ctx.MissionStates.Add(x); + } + foreach (var x in v.TaskStatuses) { + x.Viking = viking; + ctx.TaskStatuses.Add(x); + } + foreach (var x in v.AchievementTaskStates) { + x.Viking = viking; + ctx.AchievementTaskState.Add(x); + } + foreach (var x in v.AchievementPoints) { + x.Viking = viking; + ctx.AchievementPoints.Add(x); + } + foreach (var x in v.ProfileAnswers) { + x.Viking = viking; + ctx.ProfileAnswers.Add(x); + } + foreach (var x in v.GameData) { + x.Viking = viking; + ctx.GameData.Add(x); + } + foreach (var x in v.SavedData) { + x.Viking = viking; + ctx.SavedData.Add(x); + } + foreach (var x in v.Parties) { + x.Viking = viking; + ctx.Parties.Add(x); + } + foreach (var x in v.UserMissions) { + x.Viking = viking; + ctx.UserMissions.Add(x); + } + foreach (var x in v.UserBadgesCompleted) { + x.Viking = viking; + ctx.UserBadgesCompleted.Add(x); + } + if (v.Ratings.Count > 0) { + viking.Ratings = new List(); + foreach (var x in v.Ratings) { + // TODO (non-SoD) add rating via SetRating(viking, x.Rank.CategoryID, x.Rank.RatedEntityID, x.Rank.RatedUserID, x.Value); + } + } + if (v.Neighborhood != null) { + v.Neighborhood.Viking = viking; + ctx.Neighborhoods.Add(v.Neighborhood); + } + + if (v.SelectedDragon != null) + viking.SelectedDragon = viking.Dragons.FirstOrDefault(d => d.EntityId == dragonIds[v.SelectedDragon.Id]); + + ctx.SaveChanges(); + return Ok("OK"); + } + } + return Ok("Viking Not Found"); + } + + [HttpGet] + [Route("Export")] + public IActionResult Export() { + return Content(XmlUtil.ReadResourceXmlString("html.export"), "application/xhtml+xml"); + } + + [HttpGet] + [Route("Import")] + public IActionResult Import() { + return Content(XmlUtil.ReadResourceXmlString("html.import"), "application/xhtml+xml"); + } +} diff --git a/src/Dockerfile b/src/Dockerfile index e4fc8a9..8c3d2e5 100644 --- a/src/Dockerfile +++ b/src/Dockerfile @@ -1,5 +1,5 @@ # Use the official .NET SDK image for building the application -FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build WORKDIR /src # Copy the source code @@ -13,7 +13,7 @@ RUN mv src/mods /app && ln -s /app/mods src/ RUN mv src/assets /app && ln -s /app/assets src/ # Create clean run environment (without source and sdk) -# FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base +# FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base # WORKDIR /app # COPY --from=build /app . diff --git a/src/Model/AchievementPoints.cs b/src/Model/AchievementPoints.cs index 6cfc402..94c5b2b 100644 --- a/src/Model/AchievementPoints.cs +++ b/src/Model/AchievementPoints.cs @@ -1,12 +1,15 @@ using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; namespace sodoff.Model; public class AchievementPoints { + [JsonIgnore] public int VikingId { get; set; } public int Type { get; set; } public int Value { get; set; } + [JsonIgnore] public virtual Viking? Viking { get; set; } } diff --git a/src/Model/AchievementTaskState.cs b/src/Model/AchievementTaskState.cs index ef2edb6..27f4f03 100644 --- a/src/Model/AchievementTaskState.cs +++ b/src/Model/AchievementTaskState.cs @@ -1,15 +1,18 @@ using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; using Microsoft.EntityFrameworkCore; namespace sodoff.Model; [PrimaryKey(nameof(TaskId), nameof(VikingId))] public class AchievementTaskState { + [JsonIgnore] public int VikingId { get; set; } public int TaskId { get; set; } public int Points { get; set; } + [JsonIgnore] public virtual Viking? Viking { get; set; } } diff --git a/src/Model/DBContext.cs b/src/Model/DBContext.cs index 1832763..02b01a9 100644 --- a/src/Model/DBContext.cs +++ b/src/Model/DBContext.cs @@ -23,6 +23,9 @@ public class DBContext : DbContext { public DbSet ProfileAnswers { get; set; } = null!; public DbSet MMORoles { get; set; } = null!; public DbSet Parties { get; set; } = null!; + public DbSet AchievementTaskState { get; set; } = null!; + public DbSet SavedData { get; set; } = null!; + public DbSet UserMissions { get; set; } = null!; public DbSet Neighborhoods { get; set; } = null!; // we had a brief debate on whether it's neighborhoods or neighborheed public DbSet Groups { get; set; } = null!; diff --git a/src/Model/Dragon.cs b/src/Model/Dragon.cs index f8f636a..cdfd831 100644 --- a/src/Model/Dragon.cs +++ b/src/Model/Dragon.cs @@ -1,22 +1,29 @@ -using System.ComponentModel.DataAnnotations; +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using System.Text.Json.Serialization; namespace sodoff.Model; +[Index(nameof(EntityId), IsUnique = true)] public class Dragon { [Key] + // [JsonIgnore] used in serialised xml (stables) [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } [Required] public Guid EntityId { get; set; } + [Required] + [JsonIgnore] public int VikingId { get; set; } public string? RaisedPetData { get; set; } public int? PetXP { get; set; } - + + [JsonIgnore] public virtual Viking Viking { get; set; } = null!; public virtual ICollection PairData { get; set; } = null!; } diff --git a/src/Model/GameData.cs b/src/Model/GameData.cs index 56f801c..7db40d3 100644 --- a/src/Model/GameData.cs +++ b/src/Model/GameData.cs @@ -1,10 +1,13 @@ using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; namespace sodoff.Model; public class GameData { [Key] + [JsonIgnore] public int Id { get; set; } + [JsonIgnore] public int VikingId { get; set; } public int GameId { get; set; } @@ -15,6 +18,6 @@ public class GameData { public bool Win { get; set; } public bool Loss { get; set; } public virtual ICollection GameDataPairs { get; set; } = null!; + [JsonIgnore] public virtual Viking Viking { get; set; } = null!; - } diff --git a/src/Model/GameDataPair.cs b/src/Model/GameDataPair.cs index 3135b20..4b9d9c8 100644 --- a/src/Model/GameDataPair.cs +++ b/src/Model/GameDataPair.cs @@ -1,9 +1,12 @@ using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; namespace sodoff.Model; public class GameDataPair { [Key] + [JsonIgnore] public int Id { get; set; } + [JsonIgnore] public int GameDataId { get; set; } public string Name { get; set; } = null!; public int Value { get; set; } diff --git a/src/Model/Image.cs b/src/Model/Image.cs index f12727c..f671c4d 100644 --- a/src/Model/Image.cs +++ b/src/Model/Image.cs @@ -1,4 +1,5 @@ using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; using Microsoft.EntityFrameworkCore; namespace sodoff.Model; @@ -12,11 +13,13 @@ public class Image { public int ImageSlot { get; set; } [Required] + [JsonIgnore] public int VikingId { get; set; } public string? ImageData { get; set; } public string? TemplateName { get; set; } + [JsonIgnore] public virtual Viking Viking { get; set; } = null!; } diff --git a/src/Model/InventoryItem.cs b/src/Model/InventoryItem.cs index ea6c5d1..563fba9 100644 --- a/src/Model/InventoryItem.cs +++ b/src/Model/InventoryItem.cs @@ -1,18 +1,22 @@ using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; namespace sodoff.Model { public class InventoryItem { [Key] + // [JsonIgnore] used as room id, used in serialised xml (pairs, ...) public int Id { get; set; } public int ItemId { get; set; } + [JsonIgnore] public int VikingId { get; set; } public string? StatsSerialized { get; set; } public string? AttributesSerialized { get; set; } + [JsonIgnore] public virtual Viking Viking { get; set; } = null!; public int Quantity { get; set; } diff --git a/src/Model/MMORole.cs b/src/Model/MMORole.cs index 8f97762..4a72c1a 100644 --- a/src/Model/MMORole.cs +++ b/src/Model/MMORole.cs @@ -1,15 +1,18 @@ using sodoff.Schema; using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; namespace sodoff.Model; public class MMORole { [Key] + [JsonIgnore] public int Id { get; set; } public int VikingId { get; set; } public Role Role { get; set; } + [JsonIgnore] public virtual Viking? Viking { get; set; } } diff --git a/src/Model/MissionState.cs b/src/Model/MissionState.cs index b82f1b0..c99d738 100644 --- a/src/Model/MissionState.cs +++ b/src/Model/MissionState.cs @@ -1,15 +1,19 @@ using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; namespace sodoff.Model; public class MissionState { [Key] + [JsonIgnore] public int Id { get; set; } public int MissionId { get; set; } + [JsonIgnore] public int VikingId { get; set; } + [JsonIgnore] public virtual Viking? Viking { get; set; } public MissionStatus MissionStatus { get; set; } @@ -19,4 +23,4 @@ public class MissionState { public enum MissionStatus { Upcoming,Active,Completed -} \ No newline at end of file +} diff --git a/src/Model/Neighborhood.cs b/src/Model/Neighborhood.cs index a748c76..67b363c 100644 --- a/src/Model/Neighborhood.cs +++ b/src/Model/Neighborhood.cs @@ -1,18 +1,20 @@ using sodoff.Schema; using System.ComponentModel.DataAnnotations; -using System.Data; -using System.Diagnostics.CodeAnalysis; +using System.Text.Json.Serialization; namespace sodoff.Model { public class Neighborhood { + [JsonIgnore] public virtual Viking? Viking { get; set; } [Key] + [JsonIgnore] public int Id { get; set; } [Required] + [JsonIgnore] public int VikingId { get; set; } [Required] diff --git a/src/Model/Pair.cs b/src/Model/Pair.cs index 5c6aca6..abc55cc 100644 --- a/src/Model/Pair.cs +++ b/src/Model/Pair.cs @@ -1,18 +1,22 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using System.Text.Json.Serialization; namespace sodoff.Model; public class Pair { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + [JsonIgnore] public int Id { get; set; } public string Key { get; set; } = null!; public string Value { get; set; } = null!; + [JsonIgnore] public int MasterId { get; set; } + [JsonIgnore] public virtual PairData PairData { get; set; } = null!; } diff --git a/src/Model/PairData.cs b/src/Model/PairData.cs index 9f11ce5..9db929a 100644 --- a/src/Model/PairData.cs +++ b/src/Model/PairData.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using System.Text.Json.Serialization; namespace sodoff.Model; @@ -9,21 +10,28 @@ namespace sodoff.Model; public class PairData { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + [JsonIgnore] public int Id { get; set; } public int PairId { get; set; } + [JsonIgnore] public Guid? UserId { get; set; } + [JsonIgnore] public int? VikingId { get; set; } + [JsonIgnore] public int? DragonId { get; set; } public virtual ICollection Pairs { get; set; } + [JsonIgnore] public virtual User? User { get; set; } + [JsonIgnore] public virtual Viking? Viking { get; set; } + [JsonIgnore] public virtual Dragon? Dragon { get; set; } } diff --git a/src/Model/Party.cs b/src/Model/Party.cs index 9667da5..dd4b5ab 100644 --- a/src/Model/Party.cs +++ b/src/Model/Party.cs @@ -1,18 +1,21 @@ using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; +using System.Text.Json.Serialization; namespace sodoff.Model { public class Party { [Key] + [JsonIgnore] public int Id { get; set; } public string Location { get; set; } = null!; + [JsonIgnore] public int VikingId { get; set; } public DateTime ExpirationDate { get; set; } = DateTime.UtcNow; public bool? PrivateParty { get; set; } public string LocationIconAsset { get; set; } = null!; public string AssetBundle { get; set; } = null!; + [JsonIgnore] public virtual Viking? Viking { get; set; } } } diff --git a/src/Model/ProfileAnswer.cs b/src/Model/ProfileAnswer.cs index 4aae801..ff4982b 100644 --- a/src/Model/ProfileAnswer.cs +++ b/src/Model/ProfileAnswer.cs @@ -1,15 +1,19 @@ using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; namespace sodoff.Model { public class ProfileAnswer { [Key] + [JsonIgnore] public int Id { get; set; } + [JsonIgnore] public int VikingId { get; set; } public int QuestionID { get; set; } public int AnswerID { get; set; } + [JsonIgnore] public virtual Viking Viking { get; set; } = null!; } } diff --git a/src/Model/Rating.cs b/src/Model/Rating.cs index 565e736..a195a54 100644 --- a/src/Model/Rating.cs +++ b/src/Model/Rating.cs @@ -1,17 +1,21 @@ using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; namespace sodoff.Model; public class Rating { [Key] + [JsonIgnore] public int Id { get; set; } + [JsonIgnore] public int VikingId { get; set; } public int RankId { get; set; } public int Value { get; set; } public DateTime Date { get; set; } + [JsonIgnore] public virtual Viking Viking { get; set; } public virtual RatingRank Rank { get; set; } } diff --git a/src/Model/RatingRank.cs b/src/Model/RatingRank.cs index 1eebec1..359f9b3 100644 --- a/src/Model/RatingRank.cs +++ b/src/Model/RatingRank.cs @@ -1,9 +1,11 @@ using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; namespace sodoff.Model; public class RatingRank { [Key] + [JsonIgnore] public int Id { get; set; } public int CategoryID { get; set; } @@ -14,5 +16,6 @@ public class RatingRank { public float RatingAverage { get; set; } // On a scale of 1-5 public DateTime UpdateDate { get; set; } + [JsonIgnore] public virtual ICollection Ratings { get; set; } = null!; } diff --git a/src/Model/Room.cs b/src/Model/Room.cs index 6089e1f..6f8fe48 100644 --- a/src/Model/Room.cs +++ b/src/Model/Room.cs @@ -1,18 +1,22 @@ using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; namespace sodoff.Model; public class Room { [Key] + [JsonIgnore] public int Id { get; set; } public string RoomId { get; set; } + [JsonIgnore] public int VikingId { get; set; } public string? Name { get; set; } + [JsonIgnore] public virtual Viking? Viking { get; set; } public virtual ICollection Items { get; set; } = null!; -} \ No newline at end of file +} diff --git a/src/Model/RoomItem.cs b/src/Model/RoomItem.cs index 329b0bd..8701dd9 100644 --- a/src/Model/RoomItem.cs +++ b/src/Model/RoomItem.cs @@ -1,12 +1,16 @@ using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; namespace sodoff.Model; public class RoomItem { [Key] + [JsonIgnore] public int Id { get; set; } + [JsonIgnore] public int RoomId { get; set; } + [JsonIgnore] public virtual Room Room { get; set; } public string RoomItemData { get; set; } diff --git a/src/Model/SaveData.cs b/src/Model/SaveData.cs index 0d411cf..f455241 100644 --- a/src/Model/SaveData.cs +++ b/src/Model/SaveData.cs @@ -1,8 +1,12 @@ -namespace sodoff.Model; +using System.Text.Json.Serialization; + +namespace sodoff.Model; public class SavedData { + [JsonIgnore] public int VikingId { get; set; } public uint SaveId { get; set; } public string? SerializedData { get; set; } + [JsonIgnore] public virtual Viking Viking { get; set; } = null!; } diff --git a/src/Model/SceneData.cs b/src/Model/SceneData.cs index 5e17821..6a39cfc 100644 --- a/src/Model/SceneData.cs +++ b/src/Model/SceneData.cs @@ -1,14 +1,18 @@ using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; namespace sodoff.Model { public class SceneData { [Key] + [JsonIgnore] public int Id { get; set; } public int VikingId { get; set; } public string SceneName { get; set; } = null!; public string XmlData { get; set; } = null!; + + [JsonIgnore] public virtual Viking Viking { get; set; } = null!; } } diff --git a/src/Model/TaskStatus.cs b/src/Model/TaskStatus.cs index 9e19f2b..a83857c 100644 --- a/src/Model/TaskStatus.cs +++ b/src/Model/TaskStatus.cs @@ -1,11 +1,15 @@ -namespace sodoff.Model { +using System.Text.Json.Serialization; + +namespace sodoff.Model { public class TaskStatus { public int Id { get; set; } public int MissionId { get; set; } + [JsonIgnore] public int VikingId { get; set; } + [JsonIgnore] public virtual Viking? Viking { get; set; } public string? Payload { get; set; } diff --git a/src/Model/User.cs b/src/Model/User.cs index 358feb1..de4beb3 100644 --- a/src/Model/User.cs +++ b/src/Model/User.cs @@ -1,6 +1,10 @@ -using System.ComponentModel.DataAnnotations; +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; namespace sodoff.Model; + +[Index(nameof(Username), IsUnique = true)] public class User { [Key] public Guid Id { get; set; } @@ -14,6 +18,7 @@ public class User { [Required] public string Password { get; set; } = null!; + [JsonIgnore] public virtual ICollection Sessions { get; set; } = null!; public virtual ICollection Vikings { get; set; } = null!; public virtual ICollection PairData { get; set; } = null!; diff --git a/src/Model/UserBadgeCompleteData.cs b/src/Model/UserBadgeCompleteData.cs index efab4c9..d96eafd 100644 --- a/src/Model/UserBadgeCompleteData.cs +++ b/src/Model/UserBadgeCompleteData.cs @@ -1,11 +1,16 @@ -namespace sodoff.Model +using System.Text.Json.Serialization; + +namespace sodoff.Model { public class UserBadgeCompleteData { + [JsonIgnore] public int Id { get; set; } + [JsonIgnore] public int VikingId { get; set; } public int BadgeId { get; set; } + [JsonIgnore] public virtual Viking? Viking { get; set; } } } diff --git a/src/Model/UserMissionData.cs b/src/Model/UserMissionData.cs index 1a971b9..16a5cf8 100644 --- a/src/Model/UserMissionData.cs +++ b/src/Model/UserMissionData.cs @@ -1,4 +1,5 @@ using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; using Microsoft.EntityFrameworkCore; namespace sodoff.Model @@ -6,6 +7,7 @@ namespace sodoff.Model [PrimaryKey(nameof(VikingId), nameof(WorldId), nameof(MissionId))] public class UserMissionData { + [JsonIgnore] public int VikingId { get; set; } public int WorldId { get; set; } public int MissionId { get; set; } @@ -13,6 +15,7 @@ namespace sodoff.Model public int TaskId { get; set; } public bool IsCompleted { get; set; } = false; + [JsonIgnore] public virtual Viking? Viking { get; set; } } } diff --git a/src/Model/Viking.cs b/src/Model/Viking.cs index a787107..86a86e9 100644 --- a/src/Model/Viking.cs +++ b/src/Model/Viking.cs @@ -1,12 +1,14 @@ using Microsoft.EntityFrameworkCore; using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; using sodoff.Schema; namespace sodoff.Model; -[Index(nameof(Uid))] +[Index(nameof(Uid), IsUnique = true)] public class Viking { [Key] + [JsonIgnore] public int Id { get; set; } public Guid Uid { get; set; } @@ -15,13 +17,17 @@ public class Viking { public string Name { get; set; } = null!; [Required] + [JsonIgnore] public Guid UserId { get; set; } public string? AvatarSerialized { get; set; } + [JsonIgnore] public int? SelectedDragonId { get; set; } + [JsonIgnore] public virtual ICollection Sessions { get; set; } = null!; + [JsonIgnore] public virtual User User { get; set; } = null!; public virtual ICollection Dragons { get; set; } = null!; public virtual ICollection Images { get; set; } = null!; @@ -37,8 +43,10 @@ public class Viking { public virtual ICollection ProfileAnswers { get; set; } = null!; public virtual ICollection SavedData { get; set; } = null!; public virtual ICollection Parties { get; set; } = null!; + [JsonIgnore] public virtual ICollection MMORoles { get; set; } = null!; public virtual Neighborhood? Neighborhood { get; set; } = null!; + [JsonIgnore] public virtual ICollection Groups { get; set; } = null!; public virtual ICollection Ratings { get; set; } = null!; public virtual Dragon? SelectedDragon { get; set; } diff --git a/src/Resources/html/export.xml b/src/Resources/html/export.xml new file mode 100644 index 0000000..d93c359 --- /dev/null +++ b/src/Resources/html/export.xml @@ -0,0 +1,16 @@ + + + + + Export SoDOff account + + +
+
+
+
+

+ +
+ + diff --git a/src/Resources/html/import.xml b/src/Resources/html/import.xml new file mode 100644 index 0000000..3ed291c --- /dev/null +++ b/src/Resources/html/import.xml @@ -0,0 +1,24 @@ + + + + + Import SoDOff account + + +
+
+
+
+

+ +
+
+
+
+
+

+ + +
+ + diff --git a/src/Resources/missions/missions_sod.xml b/src/Resources/missions/missions_sod.xml index c9f1525..28a10dc 100644 --- a/src/Resources/missions/missions_sod.xml +++ b/src/Resources/missions/missions_sod.xml @@ -49061,7 +49061,7 @@ 2897 Dreadfall2020Q01 10 - <Data><Repeat>0</Repeat><Hidden>0</Hidden><Reward><Asset>PfUiMissionRewardDBDO</Asset></Reward><Random>0</Random><Title><Text>Boneknapper, Kidnapped? [2020]</Text></Title><Icon>RS_DATA/SquadTacticsDreadfallDO.unity3d/IcoDWDragonsHUDDazeReward</Icon></Data> + <Data><Repeat>0</Repeat><Hidden>0</Hidden><Reward><Asset>PfUiMissionRewardDBDO</Asset></Reward><Random>0</Random><Title><Text>Boneknapper, Kidnapped? [2020]</Text></Title><Icon>RS_DATA/SquadTacticsDreadfallDO.unity3d/IcoDWDragonsHUDDazeReward</Icon><Setup><Scene>HubDragonsEdgeDO</Scene><Asset>RS_DATA/PfDWArchaeologist.unity3d/PfDWArchaeologist</Asset><Location>PfMarker_Archaeologist</Location><Recursive>false</Recursive><Persistent>false</Persistent></Setup></Data> false 0 diff --git a/src/Schema/AchievementReward.cs b/src/Schema/AchievementReward.cs index 821e5c3..b6f4f48 100644 --- a/src/Schema/AchievementReward.cs +++ b/src/Schema/AchievementReward.cs @@ -4,48 +4,67 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "AR", Namespace = "")] [Serializable] -public class AchievementReward -{ - [XmlElement(ElementName = "ui", IsNullable = true)] - public UserItemData UserItem { get; set; } +public class AchievementReward { + public AchievementReward() { } - [XmlElement(ElementName = "a")] - public int? Amount; + public AchievementReward(AchievementReward other) { + if (other.UserItem != null) + UserItem = new UserItemData(other.UserItem); - [XmlElement(ElementName = "p", IsNullable = true)] - public AchievementPointTypes? PointTypeID; + Amount = other.Amount; + PointTypeID = other.PointTypeID; + ItemID = other.ItemID; + EntityID = other.EntityID; + EntityTypeID = other.EntityTypeID; + RewardID = other.RewardID; + AchievementID = other.AchievementID; + AllowMultiple = other.AllowMultiple; + MinAmount = other.MinAmount; + MaxAmount = other.MaxAmount; + Date = other.Date; + CommonInventoryID = other.CommonInventoryID; + } - [XmlElement(ElementName = "ii")] - public int ItemID; + [XmlElement(ElementName = "ui", IsNullable = true)] + public UserItemData UserItem { get; set; } - [XmlElement(ElementName = "i", IsNullable = true)] - public Guid? EntityID; + [XmlElement(ElementName = "a")] + public int? Amount; - [XmlElement(ElementName = "t")] - public int EntityTypeID; + [XmlElement(ElementName = "p", IsNullable = true)] + public AchievementPointTypes? PointTypeID; - [XmlElement(ElementName = "r")] - public int RewardID; + [XmlElement(ElementName = "ii")] + public int ItemID; - [XmlElement(ElementName = "ai")] - public int AchievementID; + [XmlElement(ElementName = "i", IsNullable = true)] + public Guid? EntityID; - [XmlElement(ElementName = "amulti")] - public bool AllowMultiple; + [XmlElement(ElementName = "t")] + public int EntityTypeID; - [XmlElement(ElementName = "mina", IsNullable = true)] - public int? MinAmount; + [XmlElement(ElementName = "r")] + public int RewardID; - [XmlElement(ElementName = "maxa", IsNullable = true)] - public int? MaxAmount; + [XmlElement(ElementName = "ai")] + public int AchievementID; - [XmlElement(ElementName = "d", IsNullable = true)] - public DateTime? Date; + [XmlElement(ElementName = "amulti")] + public bool AllowMultiple; - [XmlElement(ElementName = "cid")] - public int CommonInventoryID; + [XmlElement(ElementName = "mina", IsNullable = true)] + public int? MinAmount; - public AchievementReward Clone() { - return (AchievementReward) this.MemberwiseClone(); - } + [XmlElement(ElementName = "maxa", IsNullable = true)] + public int? MaxAmount; + + [XmlElement(ElementName = "d", IsNullable = true)] + public DateTime? Date; + + [XmlElement(ElementName = "cid")] + public int CommonInventoryID; + + public AchievementReward Clone() { + return (AchievementReward)this.MemberwiseClone(); + } } diff --git a/src/Schema/BluePrint.cs b/src/Schema/BluePrint.cs index 3c5aeda..47b48d9 100644 --- a/src/Schema/BluePrint.cs +++ b/src/Schema/BluePrint.cs @@ -5,14 +5,21 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "BP", Namespace = "", IsNullable = true)] [Serializable] -public class BluePrint -{ - [XmlElement(ElementName = "BPDC", IsNullable = true)] - public List Deductibles { get; set; } +public class BluePrint { + public BluePrint() { } - [XmlElement(ElementName = "ING", IsNullable = false)] - public List Ingredients { get; set; } + public BluePrint(BluePrint other) { + Deductibles = other.Deductibles.Select(d => new BluePrintDeductibleConfig(d)).ToList(); + Ingredients = other.Ingredients.Select(i => new BluePrintSpecification(i)).ToList(); + Outputs = other.Outputs.Select(o => new BluePrintSpecification(o)).ToList(); + } - [XmlElement(ElementName = "OUT", IsNullable = false)] - public List Outputs { get; set; } + [XmlElement(ElementName = "BPDC", IsNullable = true)] + public List Deductibles { get; set; } + + [XmlElement(ElementName = "ING", IsNullable = false)] + public List Ingredients { get; set; } + + [XmlElement(ElementName = "OUT", IsNullable = false)] + public List Outputs { get; set; } } diff --git a/src/Schema/BluePrintDeductibleConfig.cs b/src/Schema/BluePrintDeductibleConfig.cs index e42025d..e6ceb8c 100644 --- a/src/Schema/BluePrintDeductibleConfig.cs +++ b/src/Schema/BluePrintDeductibleConfig.cs @@ -4,17 +4,25 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "BPDC", Namespace = "", IsNullable = true)] [Serializable] -public class BluePrintDeductibleConfig -{ - [XmlElement(ElementName = "BPIID", IsNullable = false)] - public int BluePrintItemID { get; set; } +public class BluePrintDeductibleConfig { + public BluePrintDeductibleConfig() {} - [XmlElement(ElementName = "DT", IsNullable = false)] - public DeductibleType DeductibleType { get; set; } + public BluePrintDeductibleConfig(BluePrintDeductibleConfig other) { + BluePrintItemID = other.BluePrintItemID; + DeductibleType = other.DeductibleType; + ItemID = other.ItemID; + Quantity = other.Quantity; + } - [XmlElement(ElementName = "IID", IsNullable = true)] - public int? ItemID { get; set; } + [XmlElement(ElementName = "BPIID", IsNullable = false)] + public int BluePrintItemID { get; set; } - [XmlElement(ElementName = "QTY", IsNullable = false)] - public int Quantity { get; set; } + [XmlElement(ElementName = "DT", IsNullable = false)] + public DeductibleType DeductibleType { get; set; } + + [XmlElement(ElementName = "IID", IsNullable = true)] + public int? ItemID { get; set; } + + [XmlElement(ElementName = "QTY", IsNullable = false)] + public int Quantity { get; set; } } diff --git a/src/Schema/BluePrintSpecification.cs b/src/Schema/BluePrintSpecification.cs index 6f235b7..6146f1d 100644 --- a/src/Schema/BluePrintSpecification.cs +++ b/src/Schema/BluePrintSpecification.cs @@ -2,33 +2,45 @@ using System.Xml.Serialization; namespace sodoff.Schema; -public class BluePrintSpecification -{ - [XmlElement(ElementName = "BPSID", IsNullable = false)] - public int BluePrintSpecID { get; set; } +public class BluePrintSpecification { + public BluePrintSpecification() { } - [XmlElement(ElementName = "BPIID", IsNullable = false)] - public int BluePrintItemID { get; set; } + public BluePrintSpecification(BluePrintSpecification other) { + BluePrintSpecID = other.BluePrintSpecID; + BluePrintItemID = other.BluePrintItemID; + ItemID = other.ItemID; + CategoryID = other.CategoryID; + ItemRarity = other.ItemRarity; + Tier = other.Tier; + Quantity = other.Quantity; + SpecificationType = other.SpecificationType; + } - public bool ShouldSerializeBluePrintItemID() { return BluePrintItemID != 0; } + [XmlElement(ElementName = "BPSID", IsNullable = false)] + public int BluePrintSpecID { get; set; } - [XmlElement(ElementName = "IID", IsNullable = true)] - public int? ItemID { get; set; } + [XmlElement(ElementName = "BPIID", IsNullable = false)] + public int BluePrintItemID { get; set; } - [XmlElement(ElementName = "CID", IsNullable = true)] - public int? CategoryID { get; set; } + public bool ShouldSerializeBluePrintItemID() { return BluePrintItemID != 0; } - [XmlElement(ElementName = "IR", IsNullable = true)] - public ItemRarity? ItemRarity { get; set; } + [XmlElement(ElementName = "IID", IsNullable = true)] + public int? ItemID { get; set; } - [XmlElement(ElementName = "T", IsNullable = true)] - public ItemTier? Tier { get; set; } + [XmlElement(ElementName = "CID", IsNullable = true)] + public int? CategoryID { get; set; } - [XmlElement(ElementName = "QTY", IsNullable = false)] - public int Quantity { get; set; } + [XmlElement(ElementName = "IR", IsNullable = true)] + public ItemRarity? ItemRarity { get; set; } - [XmlElement(ElementName = "ST", IsNullable = true)] - public SpecificationType? SpecificationType { get; set; } + [XmlElement(ElementName = "T", IsNullable = true)] + public ItemTier? Tier { get; set; } - public bool ShouldSerializeSpecificationType() { return SpecificationType != null; } + [XmlElement(ElementName = "QTY", IsNullable = false)] + public int Quantity { get; set; } + + [XmlElement(ElementName = "ST", IsNullable = true)] + public SpecificationType? SpecificationType { get; set; } + + public bool ShouldSerializeSpecificationType() { return SpecificationType != null; } } diff --git a/src/Schema/CompletionAction.cs b/src/Schema/CompletionAction.cs index b318f64..5d49da3 100644 --- a/src/Schema/CompletionAction.cs +++ b/src/Schema/CompletionAction.cs @@ -3,8 +3,13 @@ using System.Xml.Serialization; namespace sodoff.Schema; [Serializable] -public class CompletionAction -{ - [XmlElement(ElementName = "Transition")] - public StateTransition Transition; +public class CompletionAction { + public CompletionAction() { } + + public CompletionAction(CompletionAction other) { + Transition = other.Transition; + } + + [XmlElement(ElementName = "Transition")] + public StateTransition Transition; } diff --git a/src/Schema/ItemAttribute.cs b/src/Schema/ItemAttribute.cs index e62801a..bfa76d8 100644 --- a/src/Schema/ItemAttribute.cs +++ b/src/Schema/ItemAttribute.cs @@ -4,11 +4,17 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "AT", Namespace = "")] [Serializable] -public class ItemAttribute -{ - [XmlElement(ElementName = "k")] - public string Key; +public class ItemAttribute { + public ItemAttribute() { } - [XmlElement(ElementName = "v")] - public string Value; + public ItemAttribute(ItemAttribute other) { + Key = other.Key; + Value = other.Value; + } + + [XmlElement(ElementName = "k")] + public string Key; + + [XmlElement(ElementName = "v")] + public string Value; } diff --git a/src/Schema/ItemAvailability.cs b/src/Schema/ItemAvailability.cs index 9b10bab..3b79bc6 100644 --- a/src/Schema/ItemAvailability.cs +++ b/src/Schema/ItemAvailability.cs @@ -4,11 +4,17 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "Availability", Namespace = "")] [Serializable] -public class ItemAvailability -{ - [XmlElement(ElementName = "sdate", IsNullable = true)] - public DateTime? StartDate; +public class ItemAvailability { + public ItemAvailability() { } - [XmlElement(ElementName = "edate", IsNullable = true)] - public DateTime? EndDate; + public ItemAvailability(ItemAvailability other) { + StartDate = other.StartDate; + EndDate = other.EndDate; + } + + [XmlElement(ElementName = "sdate", IsNullable = true)] + public DateTime? StartDate; + + [XmlElement(ElementName = "edate", IsNullable = true)] + public DateTime? EndDate; } diff --git a/src/Schema/ItemData.cs b/src/Schema/ItemData.cs index fc18947..73c5762 100644 --- a/src/Schema/ItemData.cs +++ b/src/Schema/ItemData.cs @@ -3,111 +3,148 @@ using System.Xml.Serialization; namespace sodoff.Schema; [XmlRoot(ElementName = "I", Namespace = "", IsNullable = true)] -public class ItemData -{ - [XmlElement(ElementName = "is")] - public List ItemStates { get; set; } +public class ItemData { + public ItemData() { } - [XmlElement(ElementName = "ir", IsNullable = true)] - public ItemRarity? ItemRarity { get; set; } + public ItemData(ItemData other) { + ItemStates = other.ItemStates.Select(s => new ItemState(s)).ToList(); + ItemRarity = other.ItemRarity; + PossibleStatsMap = new ItemPossibleStatsMap(other.PossibleStatsMap); + ItemStatsMap = new ItemStatsMap(other.ItemStatsMap); + ItemSaleConfigs = other.ItemSaleConfigs.Select(cfg => new ItemSaleConfig(cfg)).ToArray(); + BluePrint = new BluePrint(other.BluePrint); + AssetName = other.AssetName; + Attribute = other.Attribute.Select(attr => new ItemAttribute(attr)).ToArray(); + Category = other.Category.Select(cat => new ItemDataCategory(cat)).ToArray(); + Cost = other.Cost; + CashCost = other.CashCost; + CreativePoints = other.CreativePoints; + Description = other.Description; + IconName = other.IconName; + InventoryMax = other.InventoryMax; + ItemID = other.ItemID; + ItemName = other.ItemName; + ItemNamePlural = other.ItemNamePlural; + Locked = other.Locked; + Geometry2 = other.Geometry2; + Rollover = new ItemDataRollover(other.Rollover); + RankId = other.RankId; + Relationship = other.Relationship.Select(r => new ItemDataRelationship(r)).ToArray(); + Stackable = other.Stackable; + AllowStacking = other.AllowStacking; + SaleFactor = other.SaleFactor; + Texture = other.Texture.Select(t => new ItemDataTexture(t)).ToArray(); + Uses = other.Uses; + Availability = other.Availability.Select(a => new ItemAvailability(a)).ToArray(); + RewardTypeID = other.RewardTypeID; + Points = other.Points; + NormalDiscoutModifier = other.NormalDiscoutModifier; + MemberDiscountModifier = other.MemberDiscountModifier; + } - [XmlElement(ElementName = "ipsm", IsNullable = true)] - public ItemPossibleStatsMap PossibleStatsMap { get; set; } + [XmlElement(ElementName = "is")] + public List ItemStates { get; set; } - [XmlElement(ElementName = "ism", IsNullable = true)] - public ItemStatsMap ItemStatsMap { get; set; } + [XmlElement(ElementName = "ir", IsNullable = true)] + public ItemRarity? ItemRarity { get; set; } - [XmlElement(ElementName = "iscs", IsNullable = true)] - public ItemSaleConfig[] ItemSaleConfigs { get; set; } + [XmlElement(ElementName = "ipsm", IsNullable = true)] + public ItemPossibleStatsMap PossibleStatsMap { get; set; } - [XmlElement(ElementName = "bp", IsNullable = true)] - public BluePrint BluePrint { get; set; } + [XmlElement(ElementName = "ism", IsNullable = true)] + public ItemStatsMap ItemStatsMap { get; set; } - [XmlElement(ElementName = "an")] - public string AssetName; + [XmlElement(ElementName = "iscs", IsNullable = true)] + public ItemSaleConfig[] ItemSaleConfigs { get; set; } - [XmlElement(ElementName = "at", IsNullable = true)] - public ItemAttribute[] Attribute; + [XmlElement(ElementName = "bp", IsNullable = true)] + public BluePrint BluePrint { get; set; } - [XmlElement(ElementName = "c")] - public ItemDataCategory[] Category; + [XmlElement(ElementName = "an")] + public string AssetName; - [XmlElement(ElementName = "ct")] - public int Cost; + [XmlElement(ElementName = "at", IsNullable = true)] + public ItemAttribute[] Attribute; - [XmlElement(ElementName = "ct2")] - public int CashCost; + [XmlElement(ElementName = "c")] + public ItemDataCategory[] Category; - [XmlElement(ElementName = "cp")] - public int CreativePoints; + [XmlElement(ElementName = "ct")] + public int Cost; - [XmlElement(ElementName = "d")] - public string Description; + [XmlElement(ElementName = "ct2")] + public int CashCost; - [XmlElement(ElementName = "icn")] - public string IconName; + [XmlElement(ElementName = "cp")] + public int CreativePoints; - [XmlElement(ElementName = "im")] - public int InventoryMax; + [XmlElement(ElementName = "d")] + public string Description; - [XmlElement(ElementName = "id")] - public int ItemID; + [XmlElement(ElementName = "icn")] + public string IconName; - [XmlElement(ElementName = "itn")] - public string ItemName; + [XmlElement(ElementName = "im")] + public int InventoryMax; - [XmlElement(ElementName = "itnp")] - public string ItemNamePlural; + [XmlElement(ElementName = "id")] + public int ItemID; - [XmlElement(ElementName = "l")] - public bool Locked; + [XmlElement(ElementName = "itn")] + public string ItemName; - [XmlElement(ElementName = "g", IsNullable = true)] - public string Geometry2; + [XmlElement(ElementName = "itnp")] + public string ItemNamePlural; - [XmlElement(ElementName = "ro", IsNullable = true)] - public ItemDataRollover Rollover; + [XmlElement(ElementName = "l")] + public bool Locked; - [XmlElement(ElementName = "rid", IsNullable = true)] - public int? RankId; + [XmlElement(ElementName = "g", IsNullable = true)] + public string Geometry2; - [XmlElement(ElementName = "r")] - public ItemDataRelationship[] Relationship; + [XmlElement(ElementName = "ro", IsNullable = true)] + public ItemDataRollover Rollover; - [XmlElement(ElementName = "s")] - public bool Stackable; + [XmlElement(ElementName = "rid", IsNullable = true)] + public int? RankId; - [XmlElement(ElementName = "as")] - public bool AllowStacking; + [XmlElement(ElementName = "r")] + public ItemDataRelationship[] Relationship; - [XmlElement(ElementName = "sf")] - public int SaleFactor; + [XmlElement(ElementName = "s")] + public bool Stackable; - [XmlElement(ElementName = "t")] - public ItemDataTexture[] Texture; + [XmlElement(ElementName = "as")] + public bool AllowStacking; - [XmlElement(ElementName = "u")] - public int Uses; + [XmlElement(ElementName = "sf")] + public int SaleFactor; - [XmlElement(ElementName = "av")] - public ItemAvailability[] Availability; + [XmlElement(ElementName = "t")] + public ItemDataTexture[] Texture; - [XmlElement(ElementName = "rtid")] - public int RewardTypeID; + [XmlElement(ElementName = "u")] + public int Uses; - [XmlElement(ElementName = "p", IsNullable = true)] - public int? Points; + [XmlElement(ElementName = "av")] + public ItemAvailability[] Availability; - [XmlIgnore] - public float NormalDiscoutModifier; + [XmlElement(ElementName = "rtid")] + public int RewardTypeID; - [XmlIgnore] - public float MemberDiscountModifier; + [XmlElement(ElementName = "p", IsNullable = true)] + public int? Points; - [XmlIgnore] - public float FinalDiscoutModifier { - get { - return Math.Min(1f, (1f - NormalDiscoutModifier) * (1f - MemberDiscountModifier)); + [XmlIgnore] + public float NormalDiscoutModifier; + + [XmlIgnore] + public float MemberDiscountModifier; + + [XmlIgnore] + public float FinalDiscoutModifier { + get { + return Math.Min(1f, (1f - NormalDiscoutModifier) * (1f - MemberDiscountModifier)); } - } + } } diff --git a/src/Schema/ItemDataCategory.cs b/src/Schema/ItemDataCategory.cs index de91e1d..d9b31b6 100644 --- a/src/Schema/ItemDataCategory.cs +++ b/src/Schema/ItemDataCategory.cs @@ -4,14 +4,21 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "IC", Namespace = "")] [Serializable] -public class ItemDataCategory -{ - [XmlElement(ElementName = "cid")] - public int CategoryId; +public class ItemDataCategory { + public ItemDataCategory() { } - [XmlElement(ElementName = "cn")] - public string CategoryName; + public ItemDataCategory(ItemDataCategory other) { + CategoryId = other.CategoryId; + CategoryName = other.CategoryName; + IconName = other.IconName; + } - [XmlElement(ElementName = "i", IsNullable = true)] - public string IconName; + [XmlElement(ElementName = "cid")] + public int CategoryId; + + [XmlElement(ElementName = "cn")] + public string CategoryName; + + [XmlElement(ElementName = "i", IsNullable = true)] + public string IconName; } diff --git a/src/Schema/ItemDataRelationship.cs b/src/Schema/ItemDataRelationship.cs index c15424b..58c0817 100644 --- a/src/Schema/ItemDataRelationship.cs +++ b/src/Schema/ItemDataRelationship.cs @@ -4,20 +4,29 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "IRE", Namespace = "")] [Serializable] -public class ItemDataRelationship -{ - [XmlElement(ElementName = "t")] - public string Type; +public class ItemDataRelationship { + public ItemDataRelationship() { } - [XmlElement(ElementName = "id")] - public int ItemId; + public ItemDataRelationship(ItemDataRelationship other) { + Type = other.Type; + ItemId = other.ItemId; + Weight = other.Weight; + Quantity = other.Quantity; + MaxQuantity = other.MaxQuantity; + } - [XmlElement(ElementName = "wt")] - public int Weight; + [XmlElement(ElementName = "t")] + public string Type; - [XmlElement(ElementName = "q")] - public int Quantity; + [XmlElement(ElementName = "id")] + public int ItemId; - [XmlElement(ElementName = "mxq")] - public int? MaxQuantity; + [XmlElement(ElementName = "wt")] + public int Weight; + + [XmlElement(ElementName = "q")] + public int Quantity; + + [XmlElement(ElementName = "mxq")] + public int? MaxQuantity; } diff --git a/src/Schema/ItemDataRollover.cs b/src/Schema/ItemDataRollover.cs index e4b1e33..7e03179 100644 --- a/src/Schema/ItemDataRollover.cs +++ b/src/Schema/ItemDataRollover.cs @@ -4,11 +4,17 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "IRO", Namespace = "")] [Serializable] -public class ItemDataRollover -{ - [XmlElement(ElementName = "d")] - public string DialogName; +public class ItemDataRollover { + public ItemDataRollover() { } - [XmlElement(ElementName = "b")] - public string Bundle; + public ItemDataRollover(ItemDataRollover other) { + DialogName = other.DialogName; + Bundle = other.Bundle; + } + + [XmlElement(ElementName = "d")] + public string DialogName; + + [XmlElement(ElementName = "b")] + public string Bundle; } diff --git a/src/Schema/ItemDataTexture.cs b/src/Schema/ItemDataTexture.cs index 35e155e..053d109 100644 --- a/src/Schema/ItemDataTexture.cs +++ b/src/Schema/ItemDataTexture.cs @@ -4,17 +4,25 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "IT", Namespace = "")] [Serializable] -public class ItemDataTexture -{ - [XmlElement(ElementName = "n")] - public string TextureName; +public class ItemDataTexture { + public ItemDataTexture() { } - [XmlElement(ElementName = "t")] - public string TextureTypeName; + public ItemDataTexture(ItemDataTexture other) { + TextureName = other.TextureName; + TextureTypeName = other.TextureTypeName; + OffsetX = other.OffsetX; + OffsetY = other.OffsetY; + } - [XmlElement(ElementName = "x", IsNullable = true)] - public float? OffsetX; + [XmlElement(ElementName = "n")] + public string TextureName; - [XmlElement(ElementName = "y", IsNullable = true)] - public float? OffsetY; + [XmlElement(ElementName = "t")] + public string TextureTypeName; + + [XmlElement(ElementName = "x", IsNullable = true)] + public float? OffsetX; + + [XmlElement(ElementName = "y", IsNullable = true)] + public float? OffsetY; } diff --git a/src/Schema/ItemPossibleStatsMap.cs b/src/Schema/ItemPossibleStatsMap.cs index 6087d5a..4070725 100644 --- a/src/Schema/ItemPossibleStatsMap.cs +++ b/src/Schema/ItemPossibleStatsMap.cs @@ -4,17 +4,25 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "IPSM", Namespace = "", IsNullable = false)] [Serializable] -public class ItemPossibleStatsMap -{ - [XmlElement(ElementName = "IID", IsNullable = false)] - public int ItemID { get; set; } +public class ItemPossibleStatsMap { + public ItemPossibleStatsMap() { } - [XmlElement(ElementName = "SC", IsNullable = false)] - public int ItemStatsCount { get; set; } + public ItemPossibleStatsMap(ItemPossibleStatsMap other) { + ItemID = other.ItemID; + ItemStatsCount = other.ItemStatsCount; + SetID = other.SetID; + Stats = other.Stats.Select(s => new Stat(s)).ToList(); + } - [XmlElement(ElementName = "SID", IsNullable = false)] - public int SetID { get; set; } + [XmlElement(ElementName = "IID", IsNullable = false)] + public int ItemID { get; set; } - [XmlElement(ElementName = "SS", IsNullable = false)] - public List Stats { get; set; } + [XmlElement(ElementName = "SC", IsNullable = false)] + public int ItemStatsCount { get; set; } + + [XmlElement(ElementName = "SID", IsNullable = false)] + public int SetID { get; set; } + + [XmlElement(ElementName = "SS", IsNullable = false)] + public List Stats { get; set; } } diff --git a/src/Schema/ItemSaleConfig.cs b/src/Schema/ItemSaleConfig.cs index 0495ed7..c7644e6 100644 --- a/src/Schema/ItemSaleConfig.cs +++ b/src/Schema/ItemSaleConfig.cs @@ -4,20 +4,29 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "ISC", Namespace = "", IsNullable = true)] [Serializable] -public class ItemSaleConfig -{ - [XmlElement(ElementName = "IID", IsNullable = true)] - public int? ItemID { get; set; } +public class ItemSaleConfig { + public ItemSaleConfig() { } - [XmlElement(ElementName = "CID", IsNullable = true)] - public int? CategoryID { get; set; } + public ItemSaleConfig(ItemSaleConfig other) { + ItemID = other.ItemID; + CategoryID = other.CategoryID; + RarityID = other.RarityID; + Quantity = other.Quantity; + RewardItemID = other.RewardItemID; + } - [XmlElement(ElementName = "RID", IsNullable = true)] - public int? RarityID { get; set; } + [XmlElement(ElementName = "IID", IsNullable = true)] + public int? ItemID { get; set; } - [XmlElement(ElementName = "QTY", IsNullable = false)] - public int Quantity { get; set; } + [XmlElement(ElementName = "CID", IsNullable = true)] + public int? CategoryID { get; set; } - [XmlElement(ElementName = "RIID", IsNullable = false)] - public int RewardItemID { get; set; } + [XmlElement(ElementName = "RID", IsNullable = true)] + public int? RarityID { get; set; } + + [XmlElement(ElementName = "QTY", IsNullable = false)] + public int Quantity { get; set; } + + [XmlElement(ElementName = "RIID", IsNullable = false)] + public int RewardItemID { get; set; } } diff --git a/src/Schema/ItemStat.cs b/src/Schema/ItemStat.cs index e7431e2..3782a33 100644 --- a/src/Schema/ItemStat.cs +++ b/src/Schema/ItemStat.cs @@ -4,17 +4,25 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "IS", Namespace = "")] [Serializable] -public class ItemStat -{ - [XmlElement(ElementName = "ID")] - public int ItemStatID { get; set; } +public class ItemStat { + public ItemStat() { } - [XmlElement(ElementName = "N")] - public string Name { get; set; } + public ItemStat(ItemStat other) { + ItemStatID = other.ItemStatID; + Name = other.Name; + Value = other.Value; + DataType = other.DataType; + } - [XmlElement(ElementName = "V")] - public string Value { get; set; } + [XmlElement(ElementName = "ID")] + public int ItemStatID { get; set; } - [XmlElement(ElementName = "DTI")] - public DataTypeInfo DataType { get; set; } + [XmlElement(ElementName = "N")] + public string Name { get; set; } + + [XmlElement(ElementName = "V")] + public string Value { get; set; } + + [XmlElement(ElementName = "DTI")] + public DataTypeInfo DataType { get; set; } } diff --git a/src/Schema/ItemState.cs b/src/Schema/ItemState.cs index a8d1351..3d90ab4 100644 --- a/src/Schema/ItemState.cs +++ b/src/Schema/ItemState.cs @@ -4,23 +4,33 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "ItemState", Namespace = "")] [Serializable] -public class ItemState -{ - [XmlElement(ElementName = "ItemStateID")] - public int ItemStateID; +public class ItemState { + public ItemState() { } - [XmlElement(ElementName = "Name")] - public string Name; + public ItemState(ItemState other) { + ItemStateID = other.ItemStateID; + Name = other.Name; + Rule = new ItemStateRule(other.Rule); + Order = other.Order; + AchievementID = other.AchievementID; + Rewards = other.Rewards.Select(r => new AchievementReward(r)).ToArray(); + } - [XmlElement(ElementName = "Rule")] - public ItemStateRule Rule; + [XmlElement(ElementName = "ItemStateID")] + public int ItemStateID; - [XmlElement(ElementName = "Order")] - public int Order; + [XmlElement(ElementName = "Name")] + public string Name; - [XmlElement(ElementName = "AchievementID", IsNullable = true)] - public int? AchievementID; + [XmlElement(ElementName = "Rule")] + public ItemStateRule Rule; - [XmlElement(ElementName = "Rewards")] - public AchievementReward[] Rewards; + [XmlElement(ElementName = "Order")] + public int Order; + + [XmlElement(ElementName = "AchievementID", IsNullable = true)] + public int? AchievementID; + + [XmlElement(ElementName = "Rewards")] + public AchievementReward[] Rewards; } diff --git a/src/Schema/ItemStateCriteria.cs b/src/Schema/ItemStateCriteria.cs index 9510796..5a482c4 100644 --- a/src/Schema/ItemStateCriteria.cs +++ b/src/Schema/ItemStateCriteria.cs @@ -10,8 +10,13 @@ namespace sodoff.Schema; [XmlInclude(typeof(ItemStateCriteriaSpeedUpItem))] [XmlInclude(typeof(ItemStateCriteriaExpiry))] [Serializable] -public class ItemStateCriteria -{ - [XmlElement(ElementName = "Type")] - public ItemStateCriteriaType Type; +public class ItemStateCriteria { + public ItemStateCriteria() { } + + public ItemStateCriteria(ItemStateCriteria other) { + Type = other.Type; + } + + [XmlElement(ElementName = "Type")] + public ItemStateCriteriaType Type; } diff --git a/src/Schema/ItemStateRule.cs b/src/Schema/ItemStateRule.cs index 2685c40..e8eac05 100644 --- a/src/Schema/ItemStateRule.cs +++ b/src/Schema/ItemStateRule.cs @@ -4,11 +4,17 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "ItemStateRule", Namespace = "")] [Serializable] -public class ItemStateRule -{ - [XmlElement(ElementName = "Criterias")] - public List Criterias; +public class ItemStateRule { + public ItemStateRule() { } - [XmlElement(ElementName = "CompletionAction")] - public CompletionAction CompletionAction; + public ItemStateRule(ItemStateRule other) { + Criterias = other.Criterias.Select(c => new ItemStateCriteria(c)).ToList(); + CompletionAction = new CompletionAction(other.CompletionAction); + } + + [XmlElement(ElementName = "Criterias")] + public List Criterias; + + [XmlElement(ElementName = "CompletionAction")] + public CompletionAction CompletionAction; } diff --git a/src/Schema/ItemStatsMap.cs b/src/Schema/ItemStatsMap.cs index 0c090bc..f694446 100644 --- a/src/Schema/ItemStatsMap.cs +++ b/src/Schema/ItemStatsMap.cs @@ -4,14 +4,21 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "ISM", Namespace = "", IsNullable = false)] [Serializable] -public class ItemStatsMap -{ - [XmlElement(ElementName = "IID", IsNullable = false)] - public int ItemID { get; set; } +public class ItemStatsMap { + public ItemStatsMap() { } - [XmlElement(ElementName = "IT", IsNullable = false)] - public ItemTier ItemTier { get; set; } + public ItemStatsMap(ItemStatsMap other) { + ItemID = other.ItemID; + ItemTier = other.ItemTier; + ItemStats = other.ItemStats.Select(s => new ItemStat(s)).ToArray(); + } - [XmlElement(ElementName = "ISS", IsNullable = false)] - public ItemStat[] ItemStats { get; set; } + [XmlElement(ElementName = "IID", IsNullable = false)] + public int ItemID { get; set; } + + [XmlElement(ElementName = "IT", IsNullable = false)] + public ItemTier ItemTier { get; set; } + + [XmlElement(ElementName = "ISS", IsNullable = false)] + public ItemStat[] ItemStats { get; set; } } diff --git a/src/Schema/Mission.cs b/src/Schema/Mission.cs index 43ecb21..278e4ce 100644 --- a/src/Schema/Mission.cs +++ b/src/Schema/Mission.cs @@ -3,8 +3,32 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "Mission", Namespace = "")] -[Serializable] // FIXME: Remove serializable once we have a different way of deep copying than BinaryFormatter +[Serializable] public class Mission { + public Mission() { } + + public Mission(Mission other) { + if (other == null) throw new ArgumentNullException(nameof(other)); + MissionID = other.MissionID; + Name = other.Name; + GroupID = other.GroupID; + ParentID = other.ParentID; + Static = other.Static; + Accepted = other.Accepted; + Completed = other.Completed; + Rule = other.Rule; + VersionID = other.VersionID; + AchievementID = other.AchievementID; + AcceptanceAchievementID = other.AcceptanceAchievementID; + Repeatable = other.Repeatable; + MissionRule = new MissionRule(other.MissionRule); + + Missions = other.Missions.Select(m => new Mission(m)).ToList(); + Tasks = other.Tasks.Select(t => new Task(t)).ToList(); + Rewards = other.Rewards.Select(r => new AchievementReward(r)).ToList(); + AcceptanceRewards = other.AcceptanceRewards.Select(a => new AchievementReward(a)).ToList(); + } + [XmlElement(ElementName = "I")] public int MissionID; diff --git a/src/Schema/MissionCriteria.cs b/src/Schema/MissionCriteria.cs index 5ff9d2d..154a6ee 100644 --- a/src/Schema/MissionCriteria.cs +++ b/src/Schema/MissionCriteria.cs @@ -5,6 +5,16 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "MissionCriteria", Namespace = "")] [Serializable] public class MissionCriteria { + public MissionCriteria() { } + + public MissionCriteria(MissionCriteria other) { + Type = other.Type; + Ordered = other.Ordered; + Min = other.Min; + Repeat = other.Repeat; + RuleItems = other.RuleItems.Select(r => new RuleItem(r)).ToList(); + } + [XmlElement(ElementName = "Type")] public string Type; diff --git a/src/Schema/MissionRule.cs b/src/Schema/MissionRule.cs index 2a1877f..d34905b 100644 --- a/src/Schema/MissionRule.cs +++ b/src/Schema/MissionRule.cs @@ -5,6 +5,13 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "MissionRule", Namespace = "")] [Serializable] public class MissionRule { + public MissionRule() { } + + public MissionRule(MissionRule other) { + Prerequisites = other.Prerequisites.Select(p => new PrerequisiteItem(p)).ToList(); + Criteria = new MissionCriteria(other.Criteria); + } + [XmlElement(ElementName = "Prerequisites")] public List Prerequisites; diff --git a/src/Schema/NestData.cs b/src/Schema/NestData.cs new file mode 100644 index 0000000..c115c54 --- /dev/null +++ b/src/Schema/NestData.cs @@ -0,0 +1,13 @@ +using System.Xml.Serialization; + +namespace sodoff.Schema; + +[XmlRoot(ElementName = "NestData", Namespace = "")] +[Serializable] +public class NestData { + [XmlElement(ElementName = "PetID")] + public int PetID; + + [XmlElement(ElementName = "ID")] + public int ID; +} diff --git a/src/Schema/Pair.cs b/src/Schema/Pair.cs index c14b803..c100b2f 100644 --- a/src/Schema/Pair.cs +++ b/src/Schema/Pair.cs @@ -4,14 +4,21 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "Pair", Namespace = "")] [Serializable] -public class Pair -{ - [XmlElement(ElementName = "PairKey")] - public string PairKey; - - [XmlElement(ElementName = "PairValue")] - public string PairValue; - - [XmlElement(ElementName = "UpdateDate")] - public DateTime UpdateDate; +public class Pair { + public Pair() { } + + public Pair(Pair other) { + PairKey = other.PairKey; + PairValue = other.PairValue; + UpdateDate = other.UpdateDate; + } + + [XmlElement(ElementName = "PairKey")] + public string PairKey; + + [XmlElement(ElementName = "PairValue")] + public string PairValue; + + [XmlElement(ElementName = "UpdateDate")] + public DateTime UpdateDate; } \ No newline at end of file diff --git a/src/Schema/PairData.cs b/src/Schema/PairData.cs index ffb862f..8b7d995 100644 --- a/src/Schema/PairData.cs +++ b/src/Schema/PairData.cs @@ -5,6 +5,12 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "Pairs", Namespace = "", IsNullable = true)] [Serializable] public class PairData { + public PairData() { } + + public PairData(PairData other) { + Pairs = other.Pairs.Select(p => new Pair(p)).ToArray(); + } + [XmlElement("Pair", IsNullable = true)] public Pair[] Pairs { get; set; } } \ No newline at end of file diff --git a/src/Schema/PrerequisiteItem.cs b/src/Schema/PrerequisiteItem.cs index 69cb33d..11fb74f 100644 --- a/src/Schema/PrerequisiteItem.cs +++ b/src/Schema/PrerequisiteItem.cs @@ -5,6 +5,15 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "PrerequisiteItem", Namespace = "")] [Serializable] public class PrerequisiteItem { + public PrerequisiteItem() { } + + public PrerequisiteItem(PrerequisiteItem other) { + Type = other.Type; + Value = other.Value; + Quantity = other.Quantity; + ClientRule = other.ClientRule; + } + [XmlElement(ElementName = "Type")] public PrerequisiteRequiredType Type; diff --git a/src/Schema/RuleItem.cs b/src/Schema/RuleItem.cs index 5c106d9..ac4fcd1 100644 --- a/src/Schema/RuleItem.cs +++ b/src/Schema/RuleItem.cs @@ -5,6 +5,15 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "RuleItem", Namespace = "")] [Serializable] public class RuleItem { + public RuleItem() { } + + public RuleItem(RuleItem other) { + Type = other.Type; + MissionID = other.MissionID; + ID = other.ID; + Complete = other.Complete; + } + [XmlElement(ElementName = "Type")] public RuleItemType Type; diff --git a/src/Schema/StableData.cs b/src/Schema/StableData.cs new file mode 100644 index 0000000..dff5268 --- /dev/null +++ b/src/Schema/StableData.cs @@ -0,0 +1,22 @@ +using System.Xml.Serialization; + +namespace sodoff.Schema; + +[XmlRoot(ElementName = "StableData", Namespace = "")] +[Serializable] +public class StableData { + [XmlElement(ElementName = "Name")] + public string Name; + + [XmlElement(ElementName = "ID")] + public int ID; + + [XmlElement(ElementName = "ItemID")] + public int ItemID; + + [XmlElement(ElementName = "InventoryID")] + public int InventoryID; + + [XmlElement(ElementName = "Nests")] + public List NestList; +} diff --git a/src/Schema/Stat.cs b/src/Schema/Stat.cs index f85fd4b..23fd6f0 100644 --- a/src/Schema/Stat.cs +++ b/src/Schema/Stat.cs @@ -4,20 +4,29 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "STAT", Namespace = "", IsNullable = false)] [Serializable] -public class Stat -{ - [XmlElement(ElementName = "IID", IsNullable = false)] - public int ItemID { get; set; } +public class Stat { + public Stat() { } - [XmlElement(ElementName = "ISID", IsNullable = false)] - public int ItemStatsID { get; set; } + public Stat(Stat other) { + ItemID = other.ItemID; + ItemStatsID = other.ItemStatsID; + SetID = other.SetID; + Probability = other.Probability; + ItemStatsRangeMaps = other.ItemStatsRangeMaps.Select(s => new StatRangeMap(s)).ToList(); + } - [XmlElement(ElementName = "SID", IsNullable = false)] - public int SetID { get; set; } + [XmlElement(ElementName = "IID", IsNullable = false)] + public int ItemID { get; set; } - [XmlElement(ElementName = "PROB", IsNullable = false)] - public int Probability { get; set; } + [XmlElement(ElementName = "ISID", IsNullable = false)] + public int ItemStatsID { get; set; } - [XmlElement(ElementName = "ISRM", IsNullable = false)] - public List ItemStatsRangeMaps { get; set; } + [XmlElement(ElementName = "SID", IsNullable = false)] + public int SetID { get; set; } + + [XmlElement(ElementName = "PROB", IsNullable = false)] + public int Probability { get; set; } + + [XmlElement(ElementName = "ISRM", IsNullable = false)] + public List ItemStatsRangeMaps { get; set; } } diff --git a/src/Schema/StatRangeMap.cs b/src/Schema/StatRangeMap.cs index 7c74a6b..0f27ce9 100644 --- a/src/Schema/StatRangeMap.cs +++ b/src/Schema/StatRangeMap.cs @@ -4,20 +4,29 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "SRM", Namespace = "", IsNullable = false)] [Serializable] -public class StatRangeMap -{ - [XmlElement(ElementName = "ISID", IsNullable = false)] - public int ItemStatsID { get; set; } +public class StatRangeMap { + public StatRangeMap() { } - [XmlElement(ElementName = "ISN", IsNullable = false)] - public string ItemStatsName { get; set; } + public StatRangeMap(StatRangeMap other) { + ItemStatsID = other.ItemStatsID; + ItemStatsName = other.ItemStatsName; + ItemTierID = other.ItemTierID; + StartRange = other.StartRange; + EndRange = other.EndRange; + } - [XmlElement(ElementName = "ITID", IsNullable = false)] - public int ItemTierID { get; set; } + [XmlElement(ElementName = "ISID", IsNullable = false)] + public int ItemStatsID { get; set; } - [XmlElement(ElementName = "SR", IsNullable = false)] - public int StartRange { get; set; } + [XmlElement(ElementName = "ISN", IsNullable = false)] + public string ItemStatsName { get; set; } - [XmlElement(ElementName = "ER", IsNullable = false)] - public int EndRange { get; set; } + [XmlElement(ElementName = "ITID", IsNullable = false)] + public int ItemTierID { get; set; } + + [XmlElement(ElementName = "SR", IsNullable = false)] + public int StartRange { get; set; } + + [XmlElement(ElementName = "ER", IsNullable = false)] + public int EndRange { get; set; } } diff --git a/src/Schema/Task.cs b/src/Schema/Task.cs index 1f66a0b..e909f21 100644 --- a/src/Schema/Task.cs +++ b/src/Schema/Task.cs @@ -8,6 +8,17 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "Task", Namespace = "")] [Serializable] public class Task { + public Task() { } + + public Task(Task other) { + TaskID = other.TaskID; + Name = other.Name; + Static = other.Static; + Completed = other.Completed; + Failed = other.Failed; + Payload = other.Payload; + } + [XmlElement(ElementName = "I")] public int TaskID; diff --git a/src/Schema/UserItemData.cs b/src/Schema/UserItemData.cs index 4c908e7..4974e42 100644 --- a/src/Schema/UserItemData.cs +++ b/src/Schema/UserItemData.cs @@ -4,35 +4,49 @@ namespace sodoff.Schema; [XmlRoot(ElementName = "UserItem", Namespace = "")] [Serializable] -public class UserItemData -{ - [XmlElement(ElementName = "iid")] - public int ItemID { get; set; } +public class UserItemData { + public UserItemData() { } - [XmlElement(ElementName = "md", IsNullable = true)] - public DateTime? ModifiedDate { get; set; } + public UserItemData(UserItemData other) { + ItemID = other.ItemID; + ModifiedDate = other.ModifiedDate; + UserItemAttributes = new PairData(other.UserItemAttributes); + ItemStats = other.ItemStats.Select(stat => new ItemStat(stat)).ToArray(); + ItemTier = other.ItemTier; + CreatedDate = other.CreatedDate; + UserInventoryID = other.UserInventoryID; + Quantity = other.Quantity; + Uses = other.Uses; + Item = new ItemData(other.Item); + } - [XmlElement(ElementName = "uia", IsNullable = true)] - public PairData UserItemAttributes { get; set; } + [XmlElement(ElementName = "iid")] + public int ItemID { get; set; } - [XmlElement(ElementName = "iss", IsNullable = true)] - public ItemStat[] ItemStats { get; set; } + [XmlElement(ElementName = "md", IsNullable = true)] + public DateTime? ModifiedDate { get; set; } - [XmlElement(ElementName = "IT", IsNullable = true)] - public ItemTier? ItemTier { get; set; } + [XmlElement(ElementName = "uia", IsNullable = true)] + public PairData UserItemAttributes { get; set; } - [XmlElement(ElementName = "cd", IsNullable = true)] - public DateTime? CreatedDate { get; set; } + [XmlElement(ElementName = "iss", IsNullable = true)] + public ItemStat[] ItemStats { get; set; } - [XmlElement(ElementName = "uiid")] - public int UserInventoryID; + [XmlElement(ElementName = "IT", IsNullable = true)] + public ItemTier? ItemTier { get; set; } - [XmlElement(ElementName = "q")] - public int Quantity; + [XmlElement(ElementName = "cd", IsNullable = true)] + public DateTime? CreatedDate { get; set; } - [XmlElement(ElementName = "u")] - public int Uses; + [XmlElement(ElementName = "uiid")] + public int UserInventoryID; - [XmlElement(ElementName = "i")] - public ItemData Item; + [XmlElement(ElementName = "q")] + public int Quantity; + + [XmlElement(ElementName = "u")] + public int Uses; + + [XmlElement(ElementName = "i")] + public ItemData Item; } diff --git a/src/Schema/UserRankData.cs b/src/Schema/UserRankData.cs new file mode 100644 index 0000000..fa9fc48 --- /dev/null +++ b/src/Schema/UserRankData.cs @@ -0,0 +1,23 @@ +using System.Diagnostics; +using System.Xml.Serialization; + +namespace sodoff.Schema; + +[XmlRoot(ElementName = "UserRankData", Namespace = "")] +[Serializable] +public class UserRankData { + [XmlElement(ElementName = "UserID")] + public Guid UserID; + + [XmlElement(ElementName = "Points")] + public int Points; + + [XmlElement(ElementName = "CurrentRank")] + public UserRank CurrentRank; + + [XmlElement(ElementName = "MemberRank")] + public UserRank MemberRank; + + [XmlElement(ElementName = "NextRank")] + public UserRank NextRank; +} diff --git a/src/Services/KeyValueService.cs b/src/Services/KeyValueService.cs index 1144108..9eb85c7 100644 --- a/src/Services/KeyValueService.cs +++ b/src/Services/KeyValueService.cs @@ -50,9 +50,7 @@ public class KeyValueService { } } - if (exists) - ctx.PairData.Update(pair); - else + if (!exists) ctx.PairData.Add(pair); ctx.SaveChanges(); diff --git a/src/Services/MissionStoreSingleton.cs b/src/Services/MissionStoreSingleton.cs index 09da06f..f25532e 100644 --- a/src/Services/MissionStoreSingleton.cs +++ b/src/Services/MissionStoreSingleton.cs @@ -119,20 +119,8 @@ public class MissionStoreSingleton { } } - // FIXME: Don't use BinaryFormatter for deep copying - // FIXME: Remove flag from the project file once we have a different way of deep copying public static Mission DeepCopy(Mission original) { - using (MemoryStream memoryStream = new MemoryStream()) { - BinaryFormatter formatter = new BinaryFormatter(); - - formatter.Serialize(memoryStream, original); - - memoryStream.Position = 0; - - Mission clone = (Mission)formatter.Deserialize(memoryStream); - - return clone; - } + return new Mission(original); } } diff --git a/src/appsettings.json b/src/appsettings.json index de5849a..32c1f6c 100644 --- a/src/appsettings.json +++ b/src/appsettings.json @@ -74,7 +74,7 @@ "Logging": { "LogLevel": { "Default": "Information", - "Microsoft.AspNetCore": "Warning" + "Microsoft.AspNetCore": "Information" } }, "AllowedHosts": "*" diff --git a/src/sodoff.csproj b/src/sodoff.csproj index b8fe201..4e30ed9 100644 --- a/src/sodoff.csproj +++ b/src/sodoff.csproj @@ -1,37 +1,38 @@  - net6.0 + net9.0 enable enable - true USE_SQLITE;$(DefineConstants) USE_POSTGRESQL;$(DefineConstants) USE_MYSQL;$(DefineConstants) + + 8600,8601,8602,8603,8604,8618,8625,8629 - + - + - + - + @@ -154,5 +155,11 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest +