diff --git a/README.md b/README.md index 8515af4..68b092f 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,7 @@ Almost everything: #### Implemented enough (probably) - GetCommonInventory (V1 - returns the viking's inventory if it is called with a viking; otherwise returns 8 viking slots) +- GetGroupsByGroupType (only useful for Eat My Dust at the moment) - GetQuestions (doesn't return all questions, probably doesn't need to) - GetRules (doesn't return any rules, probably doesn't need to) - GetSubscriptionInfo (always returns member, with end date 10 years from now) @@ -168,6 +169,7 @@ Almost everything: - GetTopAchievementPointUsers (ignores type [all, buddy, hall of fame, ...] and mode [overall, monthly, weekly] properties) - GetUserAchievements (used by Magic & Mythies) - GetUserRoomList (room categories are not implemented, but it's enough for SoD) +- JoinGroup (for Eat My Dust only) - ProcessRewardedItems (gives gems, but doesn't give gold, gold is not yet implemented) - SellItems (gives gems, but doesn't give gold, gold is not yet implemented) - SetUserAchievementTask (returns a real reward but still use task placeholder) diff --git a/src/Controllers/Common/GroupController.cs b/src/Controllers/Common/GroupController.cs new file mode 100644 index 0000000..8ee0d9c --- /dev/null +++ b/src/Controllers/Common/GroupController.cs @@ -0,0 +1,104 @@ +using Microsoft.AspNetCore.Mvc; +using sodoff.Attributes; +using sodoff.Model; +using sodoff.Schema; +using sodoff.Util; + +namespace sodoff.Controllers.Common; +public class GroupController : Controller { + public static readonly Schema.Group EMD_Dragons = new Schema.Group { + GroupID = "8e68214a-c801-4759-8461-d01f28484134", + Name = "Dragons", + Color = "234,57,23", + Logo = "RS_DATA/Content/PlayerData/EMD/IcoEMDTeamDragons.png" + }; + public static readonly Schema.Group EMD_Scorpions = new Schema.Group { + GroupID = "db0aa225-2f0e-424c-83a7-73783fe63fef", + Name = "Scorpions", + Color = "120,183,53", + Logo = "RS_DATA/Content/PlayerData/EMD/IcoEMDTeamScorpions.png" + }; + + + private readonly DBContext ctx; + + public GroupController(DBContext ctx) { + this.ctx = ctx; + } + + [HttpPost] + [Produces("application/xml")] + [Route("GroupWebService.asmx/JoinGroup")] + [VikingSession] + public IActionResult JoinGroup(Viking viking, [FromForm] string apiKey, [FromForm] string groupID) { + AddEMDGroups(); + uint version = ClientVersion.GetVersion(apiKey); + + // Only implemented for EMD so far. + if (version == ClientVersion.EMD) { + if (viking.Groups.Any(g => { + // Check for loyalty. + string id = g.GroupID.ToString(); + return id == EMD_Dragons.GroupID || id == EMD_Scorpions.GroupID; + })) { + return Ok(new JoinGroupResult { GroupStatus = GroupMembershipStatus.ALREADY_MEMBER }); + } + groupID = groupID.ToUpper(); + Model.Group? group = ctx.Groups.FirstOrDefault(g => g.GroupID.ToString() == groupID); + if (group != null) { + group.Vikings.Add(viking); + ctx.SaveChanges(); + return Ok(new JoinGroupResult { GroupStatus = GroupMembershipStatus.APPROVED }); + } + } + return Ok(new JoinGroupResult { GroupStatus = GroupMembershipStatus.REJECTED }); + } + + [HttpPost] + [Produces("application/xml")] + [Route("GroupWebService.asmx/GetGroupsByGroupType")] + [VikingSession] + public Schema.Group[] GetGroupsByGroupType([FromForm] string apiKey, [FromForm] string groupType) { + AddEMDGroups(); + List groups = new List(); + foreach (Model.Group group in ctx.Groups) { + if (group.ApiKey == apiKey && group.Type.ToString() == groupType) groups.Add(new Schema.Group { + GroupID = group.GroupID.ToString(), + Name = group.Name, + Color = group.Color, + Logo = group.Logo, + Type = group.Type + }); + } + return groups.ToArray(); + } + + private void AddEMDGroups() { + bool changed = false; + Guid DragonString = new Guid(EMD_Dragons.GroupID); + Guid ScorpionString = new Guid(EMD_Scorpions.GroupID); + if (!ctx.Groups.Any(g => g.GroupID == DragonString)) { + ctx.Groups.Add(new Model.Group { + GroupID = DragonString, + Name = EMD_Dragons.Name, + Color = EMD_Dragons.Color, + Logo = EMD_Dragons.Logo, + Type = GroupType.System, + ApiKey = "dd602cf1-cc98-4738-9a0a-56dde3026947" + }); + changed = true; + } + if (!ctx.Groups.Any(g => g.GroupID == ScorpionString)) { + ctx.Groups.Add(new Model.Group { + GroupID = ScorpionString, + Name = EMD_Scorpions.Name, + Color = EMD_Scorpions.Color, + Logo = EMD_Scorpions.Logo, + Type = GroupType.System, + ApiKey = "dd602cf1-cc98-4738-9a0a-56dde3026947" + }); + changed = true; + } + if (changed) ctx.SaveChanges(); + } +} diff --git a/src/Controllers/Common/ProfileController.cs b/src/Controllers/Common/ProfileController.cs index 5503070..c6928c2 100644 --- a/src/Controllers/Common/ProfileController.cs +++ b/src/Controllers/Common/ProfileController.cs @@ -152,6 +152,22 @@ public class ProfileController : Controller { UserGameCurrency currency = achievementService.GetUserCurrency(viking); + ICollection groups = viking.Groups; + + UserProfileGroupData[] groupData = new UserProfileGroupData[groups.Count]; + int i = 0; + foreach (Model.Group group in groups) { + groupData[i] = new UserProfileGroupData { + GroupID = group.GroupID.ToString(), + Name = group.Name, + Color = group.Color, + Logo = group.Logo, + TypeID = (int)group.Type, + RoleID = 0 + }; + i++; + } + return new UserProfileData { ID = viking.Uid.ToString(), AvatarInfo = avatar, @@ -169,7 +185,8 @@ public class ProfileController : Controller { ProfileTags = new List(), UserID = viking.Uid, UserProfileTagID = 1 - } + }, + Groups = groupData }; } } diff --git a/src/Model/DBContext.cs b/src/Model/DBContext.cs index c72f7c0..0d287df 100644 --- a/src/Model/DBContext.cs +++ b/src/Model/DBContext.cs @@ -25,6 +25,7 @@ public class DBContext : DbContext { public DbSet Parties { 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!; private readonly IOptions config; @@ -136,6 +137,9 @@ public class DBContext : DbContext { builder.Entity().HasOne(v => v.Neighborhood) .WithOne(e => e.Viking); + builder.Entity().HasMany(v => v.Groups) + .WithMany(e => e.Vikings); + // Dragons builder.Entity().HasOne(d => d.Viking) .WithMany(e => e.Dragons) @@ -252,5 +256,9 @@ public class DBContext : DbContext { builder.Entity().HasOne(r => r.Viking) .WithOne(e => e.Neighborhood) .HasForeignKey(e => e.VikingId); + + // Groups + builder.Entity().HasMany(r => r.Vikings) + .WithMany(e => e.Groups); } } diff --git a/src/Model/Group.cs b/src/Model/Group.cs new file mode 100644 index 0000000..c06d450 --- /dev/null +++ b/src/Model/Group.cs @@ -0,0 +1,25 @@ +using sodoff.Schema; +using System.ComponentModel.DataAnnotations; + +namespace sodoff.Model; + +// Implementation for EMD, add whatever else if needed +public class Group { + [Key] + public int Id { get; set; } + + [Required] + public Guid GroupID { get; set; } + + public string Name { get; set; } + + public GroupType Type { get; set; } + + public string Color { get; set; } + + public string Logo { get; set; } + + public string ApiKey { get; set; } + + public virtual ICollection Vikings { get; set; } = null!; +} diff --git a/src/Model/Viking.cs b/src/Model/Viking.cs index ff8bc93..67b188f 100644 --- a/src/Model/Viking.cs +++ b/src/Model/Viking.cs @@ -38,6 +38,7 @@ public class Viking { public virtual ICollection Parties { get; set; } = null!; public virtual ICollection MMORoles { get; set; } = null!; public virtual Neighborhood? Neighborhood { get; set; } = null!; + public virtual ICollection Groups { get; set; } = null!; public virtual Dragon? SelectedDragon { get; set; } public DateTime? CreationDate { get; set; } diff --git a/src/Resources/mmo.xml b/src/Resources/mmo.xml index 9945ec9..b2a086a 100644 --- a/src/Resources/mmo.xml +++ b/src/Resources/mmo.xml @@ -35,7 +35,14 @@ - + 0x04000000 + 0x04ffffff + BadlandsEMD RoadSideAttractionEMD JunkYardEMD PitRowEMD RacingCircuitEMD MyGarageEMDInt DragonHomeEMD ScorpionHomeEMD + + +