diff --git a/src/Configuration/ApiServerConfig.cs b/src/Configuration/ApiServerConfig.cs index cf638cc..58b079b 100644 --- a/src/Configuration/ApiServerConfig.cs +++ b/src/Configuration/ApiServerConfig.cs @@ -1,7 +1,11 @@ namespace sodoff.Configuration; public class ApiServerConfig { public string ResponseURL { get; set; } = string.Empty; - + + public string MMOAdress { get; set; } = "127.0.0.1"; + public int MMOPort { get; set; } = 9933; + public uint MMOSupportMinVersion { get; set; } = 0; + public DbProviders DbProvider { get; set; } = DbProviders.SQLite; public string DbPath { get; set; } = string.Empty; public string DbConnection { get; set; } = string.Empty; diff --git a/src/Controllers/Common/AuthenticationController.cs b/src/Controllers/Common/AuthenticationController.cs index 57b5187..07f678f 100644 --- a/src/Controllers/Common/AuthenticationController.cs +++ b/src/Controllers/Common/AuthenticationController.cs @@ -1,9 +1,11 @@ using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; using sodoff.Attributes; using sodoff.Model; using sodoff.Schema; using sodoff.Util; +using sodoff.Configuration; namespace sodoff.Controllers.Common; @@ -11,9 +13,11 @@ namespace sodoff.Controllers.Common; public class AuthenticationController : Controller { private readonly DBContext ctx; + private readonly IOptions config; - public AuthenticationController(DBContext ctx) { + public AuthenticationController(DBContext ctx, IOptions config) { this.ctx = ctx; + this.config = config; } [HttpPost] @@ -108,7 +112,7 @@ public class AuthenticationController : Controller { Username = user.Username, MembershipID = "ef84db9-59c6-4950-b8ea-bbc1521f899b", // placeholder FacebookUserID = 0, - MultiplayerEnabled = ClientVersion.IsMultiplayerSupported(apiKey), + MultiplayerEnabled = ClientVersion.GetVersion(apiKey) >= config.Value.MMOSupportMinVersion, IsApproved = true, Age = 24, OpenChatEnabled = true @@ -123,7 +127,7 @@ public class AuthenticationController : Controller { UserID = viking.Uid.ToString(), Username = viking.Name, FacebookUserID = 0, - MultiplayerEnabled = ClientVersion.IsMultiplayerSupported(apiKey), + MultiplayerEnabled = ClientVersion.GetVersion(apiKey) >= config.Value.MMOSupportMinVersion, IsApproved = true, Age = 24, OpenChatEnabled = true diff --git a/src/Controllers/Common/ConfigurationController.cs b/src/Controllers/Common/ConfigurationController.cs index adf03c8..1cd8f9b 100644 --- a/src/Controllers/Common/ConfigurationController.cs +++ b/src/Controllers/Common/ConfigurationController.cs @@ -1,21 +1,24 @@ using Microsoft.AspNetCore.Mvc; using sodoff.Schema; +using sodoff.Services; using sodoff.Util; namespace sodoff.Controllers.Common; public class ConfigurationController : Controller { + private MMOConfigService mmoConfigService; + + public ConfigurationController(MMOConfigService mmoConfigService) { + this.mmoConfigService = mmoConfigService; + } [HttpPost] - //[Produces("application/xml")] + [Produces("application/xml")] [Route("ConfigurationWebService.asmx/GetMMOServerInfoWithZone")] public IActionResult GetMMOServerInfoWithZone([FromForm] string apiKey) { - // TODO: this is a placeholder - if (apiKey == "A1A13A0A-7C6E-4E9B-B0F7-22034D799013" || apiKey == "A2A09A0A-7C6E-4E9B-B0F7-22034D799013" || apiKey == "A3A12A0A-7C6E-4E9B-B0F7-22034D799013") { // NOTE: in this request apiKey is send uppercase - // do not send MMO servers to old (incompatibility with MMO server) client - return Ok(XmlUtil.SerializeXml(new MMOServerInformation[0])); - } - return Ok(XmlUtil.ReadResourceXmlString("mmo")); + return Ok(mmoConfigService.GetMMOServerInformation( + ClientVersion.GetVersion(apiKey.ToLower()) // NOTE: in this request apiKey is send uppercase + )); } [HttpPost] diff --git a/src/Controllers/Common/ProfileController.cs b/src/Controllers/Common/ProfileController.cs index 58dd57f..5503070 100644 --- a/src/Controllers/Common/ProfileController.cs +++ b/src/Controllers/Common/ProfileController.cs @@ -1,10 +1,12 @@ using System.Reflection; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; using sodoff.Attributes; using sodoff.Model; using sodoff.Schema; using sodoff.Services; using sodoff.Util; +using sodoff.Configuration; namespace sodoff.Controllers.Common; public class ProfileController : Controller { @@ -12,10 +14,13 @@ public class ProfileController : Controller { private readonly DBContext ctx; private AchievementService achievementService; private ProfileService profileService; - public ProfileController(DBContext ctx, AchievementService achievementService, ProfileService profileService) { + private readonly IOptions config; + + public ProfileController(DBContext ctx, AchievementService achievementService, ProfileService profileService, IOptions config) { this.ctx = ctx; this.achievementService = achievementService; this.profileService = profileService; + this.config = config; } [HttpPost] @@ -116,7 +121,7 @@ public class ProfileController : Controller { ParentUserID = viking.UserId.ToString(), Username = viking.Name, FirstName = viking.Name, - MultiplayerEnabled = ClientVersion.IsMultiplayerSupported(apiKey), + MultiplayerEnabled = ClientVersion.GetVersion(apiKey) >= config.Value.MMOSupportMinVersion, Locale = "en-US", // placeholder GenderID = gender, OpenChatEnabled = true, diff --git a/src/Program.cs b/src/Program.cs index fb76f16..b374bb4 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -29,6 +29,7 @@ builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); +builder.Services.AddSingleton(); builder.Services.AddScoped(); builder.Services.AddScoped(); diff --git a/src/Resources/mmo.xml b/src/Resources/mmo.xml index 4d6f01c..506b79f 100644 --- a/src/Resources/mmo.xml +++ b/src/Resources/mmo.xml @@ -1,22 +1,59 @@ - - - + + + + + + 0xa0000000 + 0xa2a03a0a + ArenaFrenzyDO ArmorWingIslandDO BerkCloudsDO BerkDocksDO BerkFarmDO CreditsDO DEClubhouseINTDO DarkDeepDO DragonRacingDO FarmingDO FarmingOceanDO GauntletDO GlacierIslandDO GreatHallSchoolIntDO HatcheryINT02DO HatcheryINTDO HelheimsGateDO HobblegruntIslandDO HubArctic01DO HubArcticINTDO HubAuctionIslandDO HubBerkDO HubDeathsongIslandDO HubDragonIslandDO HubDragonIslandINTDO HubDragonsEdgeDO HubEruptodonIslandDO HubLookoutDO HubSchoolDO HubTrainingDO HubWilderness01DO MudrakerIslandDO MyRoomINTDO OpenOceanDO RacingDragon ScuttleclawIslandDO ShipGraveyardDO TargetPracticeDO TitanIslandDO ZipplebackIslandDO + + + + + 0x00700000 + 0x00700000 + DNAMorph AlienWorldJungle GauntletShooter AlienRace Spaceport ReadyRoom AlienBattleGame TrainingRoom FaceOffGame AlienWorldIce AlienAdult SnatchItMB AlienRiderGame AlienBaby AlienBattleArena SpaceRacing Academy AlienRider Hangar AlienLarvaRoom MyPodInt DNAMorph AlienWorldJungle GauntletShooter AlienRace Spaceport ReadyRoom AlienBattleGame TrainingRoom FaceOffGame AlienWorldIce AlienAdult SnatchItMB AlienRiderGame AlienBaby AlienBattleArena SpaceRacing Academy AlienRider Hangar AlienLarvaRoom MyPodInt DNAMorph AlienWorldJungle GauntletShooter AlienRace Spaceport ReadyRoom AlienBattleGame TrainingRoom FaceOffGame AlienWorldIce AlienAdult SnatchItMB AlienRiderGame AlienBaby AlienBattleArena SpaceRacing Academy AlienRider Hangar AlienLarvaRoom MyPodInt DNAMorph AlienWorldJungle GauntletShooter AlienRace Spaceport ReadyRoom AlienBattleGame TrainingRoom FaceOffGame AlienWorldIce AlienAdult SnatchItMB AlienRiderGame AlienBaby AlienBattleArena SpaceRacing Academy AlienRider Hangar AlienLarvaRoom MyPodInt DNAMorph AlienWorldJungle GauntletShooter AlienRace Spaceport ReadyRoom AlienBattleGame TrainingRoom FaceOffGame AlienWorldIce AlienAdult SnatchItMB AlienRiderGame AlienBaby AlienBattleArena SpaceRacing Academy AlienRider Hangar AlienLarvaRoom MyPodInt + + + + + 0x00600000 + 0x00600000 + DWMadPenguinHQINT UncleMilton EnemyValley LoungeIntUpper UncleMiltonBounceHouse Boardwalk MyRoomsInt DWMadEuropeAlps SpeedDrome WinterWonderland GemMineInt Beach TrainingIsland * IslandX SanctuaryBaby DWMadEuropeParis AdventureCanyon DWMadNYHarbor JumpStartBowlInt TownCenter SanctuaryFlying MultiplayerSystem DWMadNYCentralParkFunZone MainStreet LearningInt HomeBase Hollows FreeFallMtn ArcadeInt ShipWreckLagoon DWMadEuropeItaly MummyMazeInt EnchantedSanctuary MyVIPRoomInt DownTown DWMadNYCentralPark MyNeighborhood MountainJetpack DWMadNYTimesSquare MainStreetFunZone DuneBuggyZone LoungeInt JSStadiumInt SanctuaryAdult BroomStickArena RabbitHoleInt CoconutMall Lobby + + + + diff --git a/src/Schema/MMOConfig.cs b/src/Schema/MMOConfig.cs new file mode 100644 index 0000000..9fc173f --- /dev/null +++ b/src/Schema/MMOConfig.cs @@ -0,0 +1,10 @@ +using System.Xml.Serialization; + +namespace sodoff.Schema; + +[XmlRoot(ElementName = "MMOConfig", Namespace = "")] +[Serializable] +public class MMOConfig { + [XmlElement(ElementName = "Version")] + public MMOConfigEntry[] Versions; +} diff --git a/src/Schema/MMOConfigEntry.cs b/src/Schema/MMOConfigEntry.cs new file mode 100644 index 0000000..8f1501d --- /dev/null +++ b/src/Schema/MMOConfigEntry.cs @@ -0,0 +1,32 @@ +using System.Xml.Serialization; +using sodoff.Util; + +namespace sodoff.Schema; + +[XmlRoot(ElementName = "MMOConfigEntry", Namespace = "")] +[Serializable] +public class MMOConfigEntry { + [XmlElement(ElementName = "VersionMin")] + public string VersionMin { + get { return VersionFirst.ToString("X"); } + set { VersionFirst = XmlUtil.HexToUint(value); } + } + + [XmlIgnore] + public uint VersionFirst; + + [XmlElement(ElementName = "VersionMax")] + public string VersionMax { + get { return VersionLast.ToString("X"); } + set { VersionLast = XmlUtil.HexToUint(value); } + } + + [XmlIgnore] + public uint VersionLast; + + [XmlElement(ElementName = "ZoneList")] + public string ZoneList; + + [XmlElement(ElementName = "MMOServerInfo")] + public MMOServerData[] MMOServerDataArray; +} diff --git a/src/Services/MMOConfigService.cs b/src/Services/MMOConfigService.cs new file mode 100644 index 0000000..0cb8cdb --- /dev/null +++ b/src/Services/MMOConfigService.cs @@ -0,0 +1,47 @@ +using Microsoft.Extensions.Options; + +using sodoff.Schema; +using sodoff.Util; +using sodoff.Configuration; + +namespace sodoff.Services; + +public class MMOConfigService { + MMOConfig mmoconfig; + private readonly IOptions config; + + public MMOConfigService(IOptions config) { + this.config = config; + this.mmoconfig = XmlUtil.DeserializeXml(XmlUtil.ReadResourceXmlString("mmo")); + + char[] delimiterChars = { ' ', ',', '\t', '\n' }; + foreach (var v in mmoconfig.Versions) { + if (!String.IsNullOrEmpty(v.ZoneList)) { + List MMOServerDataList = new(); + foreach (var ZoneName in v.ZoneList.Split(delimiterChars)) { + if (!String.IsNullOrWhiteSpace(ZoneName)) { + MMOServerDataList.Add(new MMOServerData { + IPAddress = config.Value.MMOAdress, + Port = config.Value.MMOPort, + Version = "S2X", + isDefault = true, + ZoneName = ZoneName.Trim(), + RootZone = "JumpStart" + } ); + } + } + v.MMOServerDataArray = MMOServerDataList.ToArray(); + } + } + } + + public MMOServerInformation GetMMOServerInformation(uint version) { + if (version >= config.Value.MMOSupportMinVersion) { + return new MMOServerInformation { + MMOServerDataArray = mmoconfig.Versions.FirstOrDefault(c => c.VersionFirst >= version && c.VersionLast <= version)?.MMOServerDataArray + }; + } else { + return new MMOServerInformation(); + } + } +} diff --git a/src/Util/ClientVersion.cs b/src/Util/ClientVersion.cs index 50e2257..dda10e7 100644 --- a/src/Util/ClientVersion.cs +++ b/src/Util/ClientVersion.cs @@ -35,8 +35,4 @@ public class ClientVersion { } return 0; } - - public static bool IsMultiplayerSupported(string apiKey) { - return GetVersion(apiKey) >= 0xa3a19a0a; - } } diff --git a/src/Util/XmlUtil.cs b/src/Util/XmlUtil.cs index aaaaa2e..8d583b0 100644 --- a/src/Util/XmlUtil.cs +++ b/src/Util/XmlUtil.cs @@ -32,4 +32,10 @@ public class XmlUtil { result = reader.ReadToEnd(); return result; } + + public static uint HexToUint(string hex) { + if (hex.StartsWith("0x", StringComparison.CurrentCultureIgnoreCase)) + hex = hex.Substring(2); + return Convert.ToUInt32(hex, 16); + } } diff --git a/src/appsettings.json b/src/appsettings.json index a035add..349937c 100644 --- a/src/appsettings.json +++ b/src/appsettings.json @@ -41,13 +41,22 @@ "ApiServer": { "// ResponseURL": "When not empty is used as server url in some responses. Otherwise will be auto detected.", "ResponseURL": "", - + + "// MMOAdress": "MMO server address (IP or domain) to use in GetMMOServerInfo* responses.", + "MMOAdress": "127.0.0.1", + + "// MMOPort": "MMO server port to use in GetMMOServerInfo* responses.", + "MMOPort": 9933, + + "// MMOSupportMinVersion": "Minimum client version allowed to use MMO. For example: '0xa3a31a0a' mean SoD 3.31, '0xa0000000' mean all SoD version, 0 mean all games.", + "MMOSupportMinVersion": "0xa3a31a0a", + "// DbProvider": "Select database backend to use: SQLite, PostgreSQL, MySQL (availability may depend on build options)", "DbProvider": "SQLite", - + "// DbPath": "Path to SQLite database file. If empty, \"sodoff.db\" from current directory will be used.", "DbPath": "", - + "// DbConnection": "Database connection string for PostgreSQL and MySQL", "// DbConnection PostgreSQL Example": "Host=127.0.0.1;Database=sodoffdb;Username=sodoffuser;Password=secret", "// DbConnection MySQL Example": "Server=127.0.0.1;Database=sodoffdb;Uid=sodoffuser;Pwd=secret;Allow User Variables=True",