diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 8e8872f94..3a2b28871 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -30,4 +30,4 @@ jobs: - name: Build run: ./publish.cmd - name: Test - run: dotnet test --no-restore --framework net6.0 + run: dotnet test --no-restore diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index f08889d15..b2d3a260a 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -3,6 +3,7 @@ name: Create Release on: repository_dispatch: types: [release] + workflow_dispatch: jobs: release: diff --git a/Directory.Build.props b/Directory.Build.props index c48855eab..aa4172a54 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -11,7 +11,7 @@ true true NU1603 - win-x64;debian.10-x64;debian.9-x64;ubuntu.16.04-x64;ubuntu.18.04-x64;ubuntu.20.04-x64;centos.7-x64;centos.8-x64;fedora.32-x64;fedora.33-x64;rhel.7-x64;rhel.8-x64;osx-x64 + win-x64;debian.9-x64;debian.10-x64;debian.11-x64;ubuntu.16.04-x64;ubuntu.18.04-x64;ubuntu.20.04-x64;centos.7-x64;centos.8-x64;fedora.32-x64;fedora.33-x64;fedora.34-x64;rhel.7-x64;rhel.8-x64;osx-x64 Debug;Release;Analyze false true diff --git a/Projects/SerializationGenerator/SerializationGenerator.csproj b/Projects/SerializationGenerator/SerializationGenerator.csproj index f74e5e965..1daae2ff1 100755 --- a/Projects/SerializationGenerator/SerializationGenerator.csproj +++ b/Projects/SerializationGenerator/SerializationGenerator.csproj @@ -1,6 +1,6 @@ - netstandard2.0 + netstandard2.1 preview analyzers @@ -21,9 +21,9 @@ - - - + + + diff --git a/Projects/SerializationSchemaGenerator/SerializationSchemaGenerator.csproj b/Projects/SerializationSchemaGenerator/SerializationSchemaGenerator.csproj index d3d1a168e..1df2df68a 100755 --- a/Projects/SerializationSchemaGenerator/SerializationSchemaGenerator.csproj +++ b/Projects/SerializationSchemaGenerator/SerializationSchemaGenerator.csproj @@ -12,6 +12,7 @@ + diff --git a/Projects/Server.Tests/Server.Tests.csproj b/Projects/Server.Tests/Server.Tests.csproj index 46a5a0981..6536e8cab 100644 --- a/Projects/Server.Tests/Server.Tests.csproj +++ b/Projects/Server.Tests/Server.Tests.csproj @@ -7,7 +7,7 @@ - + diff --git a/Projects/Server/Configuration/ServerConfiguration.cs b/Projects/Server/Configuration/ServerConfiguration.cs index 7463aadff..d32519748 100644 --- a/Projects/Server/Configuration/ServerConfiguration.cs +++ b/Projects/Server/Configuration/ServerConfiguration.cs @@ -38,11 +38,11 @@ namespace Server public static List Listeners => m_Settings.Listeners; - public static string GetSetting(string key, string defaultValue) - { - m_Settings.Settings.TryGetValue(key, out var value); - return value ?? defaultValue; - } + public static ClientVersion GetSetting(string key, ClientVersion defaultValue) => + m_Settings.Settings.TryGetValue(key, out var value) ? new ClientVersion(value) : defaultValue; + + public static string GetSetting(string key, string defaultValue) => + m_Settings.Settings.TryGetValue(key, out var value) ? value : defaultValue; public static int GetSetting(string key, int defaultValue) { diff --git a/Projects/Server/Network/NetState/NetState.cs b/Projects/Server/Network/NetState/NetState.cs index 5c0f91e60..46a9622aa 100755 --- a/Projects/Server/Network/NetState/NetState.cs +++ b/Projects/Server/Network/NetState/NetState.cs @@ -197,7 +197,9 @@ namespace Server.Network public Pipe SendPipe { get; } - public Socket Connection { get; } + public bool Running => _running; + + public Socket Connection { get; private set; } public bool CompressionEnabled { get; set; } diff --git a/Projects/Server/Network/TcpServer.cs b/Projects/Server/Network/TcpServer.cs index a9b9f1955..b78e67a41 100644 --- a/Projects/Server/Network/TcpServer.cs +++ b/Projects/Server/Network/TcpServer.cs @@ -39,7 +39,7 @@ namespace Server.Network private static readonly byte[] _socketRejected = { 0x82, 0xFF }; public static IPEndPoint[] ListeningAddresses { get; private set; } - public static TcpListener[] Listeners { get; private set; } + public static Socket[] Listeners { get; private set; } public static HashSet Instances { get; } = new(2048); private static readonly ConcurrentQueue _connectedQueue = new(); @@ -52,7 +52,7 @@ namespace Server.Network public static void Start() { HashSet listeningAddresses = new HashSet(); - List listeners = new List(); + List listeners = new List(); foreach (var ipep in ServerConfiguration.Listeners) { @@ -88,7 +88,7 @@ namespace Server.Network { foreach (var listener in Listeners) { - listener.Server.Close(); + listener.Close(); } } @@ -99,21 +99,19 @@ namespace Server.Network .Select(uip => new IPEndPoint(uip.Address, ipep.Port)) ); - public static TcpListener CreateListener(IPEndPoint ipep) + public static Socket CreateListener(IPEndPoint ipep) { - var listener = new TcpListener(ipep) + var listener = new Socket(ipep.AddressFamily, SocketType.Stream, ProtocolType.Tcp) { - Server = - { - LingerState = new LingerOption(false, 0), - ExclusiveAddressUse = true, - NoDelay = true - } + LingerState = new LingerOption(false, 0), + ExclusiveAddressUse = true, + NoDelay = true }; try { - listener.Start(32); + listener.Bind(ipep); + listener.Listen(32); return listener; } catch (SocketException se) @@ -148,13 +146,14 @@ namespace Server.Network } } - private static async void BeginAcceptingSockets(this TcpListener listener) + private static async void BeginAcceptingSockets(this Socket listener) { while (true) { try { - var socket = await listener.AcceptSocketAsync(); + var socket = await listener.AcceptAsync(); + var rejected = false; if (Instances.Count >= MaxConnections) { diff --git a/Projects/Server/Serialization/BufferReader.cs b/Projects/Server/Serialization/BufferReader.cs index e04135db5..309ac26f4 100644 --- a/Projects/Server/Serialization/BufferReader.cs +++ b/Projects/Server/Serialization/BufferReader.cs @@ -37,7 +37,7 @@ namespace Server _encoding = encoding ?? TextEncoding.UTF8; } - public BufferReader(byte[] buffer, DateTime LastSerialized) : this(buffer) => LastSerialized = LastSerialized; + public BufferReader(byte[] buffer, DateTime lastSerialized) : this(buffer) => LastSerialized = lastSerialized; public void Reset(byte[] newBuffer, out byte[] oldBuffer) { @@ -47,7 +47,7 @@ namespace Server } // Compatible with BinaryReader.ReadString() - public DateTime LastSerialized { get; init; } = DateTime.MinValue; + public DateTime LastSerialized { get; init; } public string ReadString(bool intern = false) { diff --git a/Projects/Server/Server.csproj b/Projects/Server/Server.csproj index f2cc0ec7a..4efc9e1a9 100755 --- a/Projects/Server/Server.csproj +++ b/Projects/Server/Server.csproj @@ -36,11 +36,11 @@ - + - TargetFramework=netstandard2.0 + TargetFramework=netstandard2.1 Analyzer false all diff --git a/Projects/Server/Targeting/Target.cs b/Projects/Server/Targeting/Target.cs index e60231322..69cec2c75 100644 --- a/Projects/Server/Targeting/Target.cs +++ b/Projects/Server/Targeting/Target.cs @@ -79,6 +79,72 @@ namespace Server.Targeting OnTargetFinish(from); } + protected virtual bool CanTarget(Mobile from, LandTarget landTarget, ref Point3D loc, ref Map map) + { + if (!AllowGround) + { + // We should actually never get here. If we do, it's probably a misbehaving client/macro. + OnTargetCancel(from, TargetCancelType.Canceled); + return false; + } + + loc = landTarget.Location; + map = from.Map; + return true; + } + + protected virtual bool CanTarget(Mobile from, StaticTarget staticTarget, ref Point3D loc, ref Map map) + { + loc = staticTarget.Location; + map = from.Map; + return true; + } + + protected virtual bool CanTarget(Mobile from, Item item, ref Point3D loc, ref Map map) + { + if (item.Deleted) + { + OnTargetDeleted(from, item); + return false; + } + + if (!item.CanTarget) + { + OnTargetUntargetable(from, item); + return false; + } + + if (!AllowNonlocal && item.RootParent is Mobile && item.RootParent != from && + from.AccessLevel == AccessLevel.Player) + { + OnNonlocalTarget(from, item); + return false; + } + + loc = item.GetWorldLocation(); + map = item.Map; + return true; + } + + protected virtual bool CanTarget(Mobile from, Mobile mobile, ref Point3D loc, ref Map map) + { + if (mobile.Deleted) + { + OnTargetDeleted(from, mobile); + return false; + } + + if (!mobile.CanTarget) + { + OnTargetUntargetable(from, mobile); + return false; + } + + loc = mobile.Location; + map = mobile.Map; + return true; + } + public void Invoke(Mobile from, object targeted) { CancelTimeout(); @@ -91,76 +157,32 @@ namespace Server.Targeting return; } - Point3D loc; - Map map; + Point3D loc = default; + Map map = null; + Item item = null; + Mobile mobile = null; + bool isValidTargetType = true; - var item = targeted as Item; - var mobile = targeted as Mobile; + bool valid = targeted switch + { + LandTarget landTarget => CanTarget(from, landTarget, ref loc, ref map), + StaticTarget staticTarget => CanTarget(from, staticTarget, ref loc, ref map), + Item i => CanTarget(from, item = i, ref loc, ref map), + Mobile m => CanTarget(from, mobile = m, ref loc, ref map), + _ => isValidTargetType = false + }; - if (targeted is LandTarget target) + if (!valid) { - loc = target.Location; - map = from.Map; - } - else if (targeted is StaticTarget staticTarget) - { - loc = staticTarget.Location; - map = from.Map; - } - else if (mobile != null) - { - if (mobile.Deleted) + if (!isValidTargetType) { - OnTargetDeleted(from, mobile); - OnTargetFinish(from); - return; + OnTargetCancel(from, TargetCancelType.Canceled); } - if (!mobile.CanTarget) - { - OnTargetUntargetable(from, mobile); - OnTargetFinish(from); - return; - } - - loc = mobile.Location; - map = mobile.Map; - } - else if (item != null) - { - if (item.Deleted) - { - OnTargetDeleted(from, item); - OnTargetFinish(from); - return; - } - - if (!item.CanTarget) - { - OnTargetUntargetable(from, item); - OnTargetFinish(from); - return; - } - - if (!AllowNonlocal && item.RootParent is Mobile && item.RootParent != from && - from.AccessLevel == AccessLevel.Player) - { - OnNonlocalTarget(from, item); - OnTargetFinish(from); - return; - } - - loc = item.GetWorldLocation(); - map = item.Map; - } - else - { - OnTargetCancel(from, TargetCancelType.Canceled); OnTargetFinish(from); - return; } - if (map == null || map != from.Map || Range != -1 && !from.InRange(loc, Range)) + if (map == null || map != from.Map || Range >= 0 && !from.InRange(loc, Range)) { OnTargetOutOfRange(from, targeted); } diff --git a/Projects/Server/World/World.cs b/Projects/Server/World/World.cs index a5d57436a..1db4b3e30 100644 --- a/Projects/Server/World/World.cs +++ b/Projects/Server/World/World.cs @@ -525,7 +525,7 @@ namespace Server } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static IEntity FindEntity(Serial serial, bool returnDeleted = false) => FindEntity(serial); + public static IEntity FindEntity(Serial serial, bool returnDeleted = false) => FindEntity(serial, returnDeleted); public static T FindEntity(Serial serial, bool returnDeleted = false) where T : class, IEntity { @@ -669,15 +669,17 @@ namespace Server if (typeof(BaseGuild).IsAssignableFrom(typeT)) { entity = FindGuild(serial) as T; + // If we check for `entity.Deleted` here during deserialization then all guilds are deleted because + // Deleted -> Disbanded -> No leader, which is the case before deserialization. + // TODO: Use a deleted flag instead, and actively check for dibanded guilds properly. } else { entity = FindEntity(serial) as T; - } - - if (entity?.Deleted == false) - { - return entity; + if (entity?.Deleted == false) + { + return entity; + } } return entity?.Created <= reader.LastSerialized ? entity : null; diff --git a/Projects/UOContent/Items/Addons/AddonComponent.cs b/Projects/UOContent/Items/Addons/AddonComponent.cs index f32576ff7..90d74dbc0 100644 --- a/Projects/UOContent/Items/Addons/AddonComponent.cs +++ b/Projects/UOContent/Items/Addons/AddonComponent.cs @@ -1,5 +1,3 @@ -using System.Collections.Generic; -using Server.ContextMenus; using Server.Engines.Craft; namespace Server.Items diff --git a/Projects/UOContent/Items/Deeds/VendorRentalContract.cs b/Projects/UOContent/Items/Deeds/VendorRentalContract.cs index 37969839b..437d4d0f4 100644 --- a/Projects/UOContent/Items/Deeds/VendorRentalContract.cs +++ b/Projects/UOContent/Items/Deeds/VendorRentalContract.cs @@ -290,9 +290,8 @@ namespace Server.Items } else if (BaseHouse.FindHouseAt(from) != house) { - from.SendLocalizedMessage( - 1062339 - ); // You must be located inside of the house in which you are trying to place the contract. + // You must be located inside of the house in which you are trying to place the contract. + from.SendLocalizedMessage(1062339); } else if (!house.IsAosRules) { @@ -320,15 +319,13 @@ namespace Server.Items if (vendor) { - from.SendLocalizedMessage( - 1062342 - ); // You may not place a rental contract at this location while other beings occupy it. + // You may not place a rental contract at this location while other beings occupy it. + from.SendLocalizedMessage(1062342); } else if (contract) { - from.SendLocalizedMessage( - 1062341 - ); // That location is cluttered. Please clear out any objects there and try again. + // That location is cluttered. Please clear out any objects there and try again. + from.SendLocalizedMessage(1062341); } else { diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/BaseExplosionPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/BaseExplosionPotion.cs index 3ada8a14a..01de15b12 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/BaseExplosionPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/BaseExplosionPotion.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; +using Server.Collections; using Server.Network; using Server.Spells; using Server.Targeting; @@ -30,7 +30,7 @@ namespace Server.Items public override bool RequireFreeHand => false; - public List Users { get; private set; } + private HashSet _users; public override void Serialize(IGenericWriter writer) { @@ -84,12 +84,8 @@ namespace Server.Items from.RevealingAction(); - Users ??= new List(); - - if (!Users.Contains(from)) - { - Users.Add(from); - } + _users ??= new HashSet(); + _users.Add(from); from.Target = new ThrowTarget(this); @@ -195,65 +191,69 @@ namespace Server.Items Consume(); - for (var i = 0; i < Users?.Count; ++i) + foreach (var user in _users) { - var m = Users[i]; - - if (m.Target is ThrowTarget targ && targ.Potion == this) + if (user.Target is ThrowTarget targ && targ.Potion == this) { - Target.Cancel(m); + Target.Cancel(user); } } + _users.Clear(); + if (map == null) { return; } Effects.PlaySound(loc, map, 0x307); - Effects.SendLocationEffect(loc, map, 0x36B0, 9); - var alchemyBonus = 0; + var alchemyBonus = 0; if (direct) { alchemyBonus = (int)(from.Skills.Alchemy.Value / (Core.AOS ? 5 : 10)); } var eable = map.GetObjectsInRange(loc, ExplosionRange, LeveledExplosion); + using var queue = PooledRefQueue.Create(); + var toDamage = 0; + foreach (var entity in eable) + { + if (entity == this) + { + continue; + } - var toExplode = eable.Where( - o => + if (entity is Mobile mobile) + { + if (from == null || SpellHelper.ValidIndirectTarget(from, mobile) && from.CanBeHarmful(mobile, false)) { - if (!(o is Mobile mobile) || from != null && - (!SpellHelper.ValidIndirectTarget(from, mobile) || !from.CanBeHarmful(mobile, false))) - { - return o is BaseExplosionPotion && o != this; - } - ++toDamage; - return true; + queue.Enqueue(entity); } - ) - .ToList(); + } + else if (entity is BaseExplosionPotion) + { + queue.Enqueue(entity); + } + } eable.Free(); var min = Scale(from, MinDamage); var max = Scale(from, MaxDamage); - for (var i = 0; i < toExplode.Count; ++i) + while (queue.Count > 0) { - var o = toExplode[i]; + var entity = queue.Dequeue(); - if (o is Mobile m) + if (entity is Mobile m) { from?.DoHarmful(m); - var damage = Utility.RandomMinMax(min, max); - - damage += alchemyBonus; + var damage = Utility.RandomMinMax(min, max) + alchemyBonus; if (!Core.AOS && damage > 40) { @@ -266,7 +266,7 @@ namespace Server.Items AOS.Damage(m, from, damage, 0, 100, 0, 0, 0); } - else if (o is BaseExplosionPotion pot) + else if (entity is BaseExplosionPotion pot) { pot.Explode(from, false, pot.GetWorldLocation(), pot.Map); } diff --git a/Projects/UOContent/Items/Weapons/Abilities/Bladeweave.cs b/Projects/UOContent/Items/Weapons/Abilities/Bladeweave.cs index 48e69f012..3ac67b7e2 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/Bladeweave.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/Bladeweave.cs @@ -1,4 +1,3 @@ -using Server.Mobiles; using System; using System.Collections.Generic; diff --git a/Projects/UOContent/Items/Weapons/Abilities/DoubleShot.cs b/Projects/UOContent/Items/Weapons/Abilities/DoubleShot.cs index 8f01dea14..c32132fac 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/DoubleShot.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/DoubleShot.cs @@ -1,5 +1,3 @@ -using System; - namespace Server.Items { /// diff --git a/Projects/UOContent/Items/Weapons/Abilities/ParalyzingBlow.cs b/Projects/UOContent/Items/Weapons/Abilities/ParalyzingBlow.cs index 43f985df1..ecd9ebf1b 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/ParalyzingBlow.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/ParalyzingBlow.cs @@ -17,9 +17,31 @@ namespace Server.Items public override int BaseMana => 30; - // When using Wrestling, tactics isnt needed. + // When using Wrestling, tactics isn't needed. public override bool RequiresTactics(Mobile from) => - !(from.Weapon is BaseWeapon weapon && weapon.Skill == SkillName.Wrestling); + Core.AOS && from.Weapon is not BaseWeapon { Skill: SkillName.Wrestling }; + + public override bool CheckSkills(Mobile from) + { + if (!base.CheckSkills(from)) + { + return false; + } + + if (Core.AOS || from.Weapon is not Fists) + { + return true; + } + + if (from.Skills[SkillName.Anatomy] is { Value: >= 80.0 }) + { + return true; + } + + from.SendLocalizedMessage(1061811); // You lack the required anatomy skill to perform that attack! + + return false; + } public override bool OnBeforeSwing(Mobile attacker, Mobile defender) { @@ -56,8 +78,15 @@ namespace Server.Items var duration = defender.Player ? PlayerFreezeDuration : NPCFreezeDuration; - // Treat it as paralyze not as freeze, effect must be removed when damaged. - defender.Paralyze(duration); + // Pub 21: Treat it as paralyze, not as freeze, effect must be removed when damaged. + if (Core.AOS) + { + defender.Paralyze(duration); + } + else + { + defender.Freeze(duration); + } BeginImmunity(defender, duration + FreezeDelayDuration); } diff --git a/Projects/UOContent/Misc/ClientVerification.cs b/Projects/UOContent/Misc/ClientVerification.cs index 23764174a..7b264eec8 100644 --- a/Projects/UOContent/Misc/ClientVerification.cs +++ b/Projects/UOContent/Misc/ClientVerification.cs @@ -1,6 +1,7 @@ using System; -using System.Diagnostics; +using System.Buffers.Binary; using System.IO; +using Server.Buffers; using Server.Gumps; using Server.Logging; using Server.Mobiles; @@ -12,29 +13,36 @@ namespace Server.Misc { private static readonly ILogger logger = LogFactory.GetLogger(typeof(ClientVerification)); - private static bool m_DetectClientRequirement; - private static OldClientResponse m_OldClientResponse; + private static bool _enable; + private static bool _detectClientRequirement; + private static InvalidClientResponse _invalidClientResponse; + private static string _versionExpression; - private static TimeSpan m_AgeLeniency; - private static TimeSpan m_GameTimeLeniency; + private static TimeSpan _ageLeniency; + private static TimeSpan _gameTimeLeniency; - public static ClientVersion Required { get; set; } + public static ClientVersion MinRequired { get; private set; } + public static ClientVersion MaxRequired { get; private set; } - public static bool AllowRegular { get; set; } = true; - - public static bool AllowUOTD { get; set; } = true; - - public static bool AllowGod { get; set; } = true; - - public static TimeSpan KickDelay { get; set; } + public static bool AllowRegular => true; + public static bool AllowUOTD => false; + public static TimeSpan KickDelay { get; private set; } public static void Configure() { - m_DetectClientRequirement = ServerConfiguration.GetOrUpdateSetting("clientVerification.enable", true); - m_OldClientResponse = - ServerConfiguration.GetOrUpdateSetting("clientVerification.oldClientResponse", OldClientResponse.Kick); - m_AgeLeniency = ServerConfiguration.GetOrUpdateSetting("clientVerification.ageLeniency", TimeSpan.FromDays(10)); - m_GameTimeLeniency = ServerConfiguration.GetOrUpdateSetting( + MinRequired = ServerConfiguration.GetSetting("clientVerification.minRequired", (ClientVersion)null); + MaxRequired = ServerConfiguration.GetSetting("clientVerification.maxRequired", (ClientVersion)null); + + if (MinRequired == null && MaxRequired == null) + { + _detectClientRequirement = ServerConfiguration.GetOrUpdateSetting("clientVerification.detectFromClientExe", true); + } + + _enable = ServerConfiguration.GetOrUpdateSetting("clientVerification.enable", true); + _invalidClientResponse = + ServerConfiguration.GetOrUpdateSetting("clientVerification.invalidClientResponse", InvalidClientResponse.Kick); + _ageLeniency = ServerConfiguration.GetOrUpdateSetting("clientVerification.ageLeniency", TimeSpan.FromDays(10)); + _gameTimeLeniency = ServerConfiguration.GetOrUpdateSetting( "clientVerification.gameTimeLeniency", TimeSpan.FromHours(25) ); @@ -45,121 +53,154 @@ namespace Server.Misc { EventSink.ClientVersionReceived += EventSink_ClientVersionReceived; - if (m_DetectClientRequirement) + if (_detectClientRequirement) { var path = Core.FindDataFile("client.exe", false); if (File.Exists(path)) { - var info = FileVersionInfo.GetVersionInfo(path); - - if (info.FileMajorPart != 0 || info.FileMinorPart != 0 || info.FileBuildPart != 0 || - info.FilePrivatePart != 0) + using FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); + var buffer = GC.AllocateUninitializedArray((int)fs.Length, true); + fs.Read(buffer); + // VS_VERSION_INFO (unicode) + Span vsVersionInfo = stackalloc byte[] { - Required = new ClientVersion( - info.FileMajorPart, - info.FileMinorPart, - info.FileBuildPart, - info.FilePrivatePart - ); + 0x56, 0x00, 0x53, 0x00, 0x5F, 0x00, 0x56, 0x00, + 0x45, 0x00, 0x52, 0x00, 0x53, 0x00, 0x49, 0x00, + 0x4F, 0x00, 0x4E, 0x00, 0x5F, 0x00, 0x49, 0x00, + 0x4E, 0x00, 0x46, 0x00, 0x4F, 0x00 + }; + + for (var i = 0; i < buffer.Length; i++) + { + if (vsVersionInfo.SequenceEqual(buffer.AsSpan(i, 30))) + { + var offset = i + 42; // 30 + 12 + + var minorPart = BinaryPrimitives.ReadUInt16LittleEndian(buffer.AsSpan(offset)); + var majorPart = BinaryPrimitives.ReadUInt16LittleEndian(buffer.AsSpan(offset + 2)); + var privatePart = BinaryPrimitives.ReadUInt16LittleEndian(buffer.AsSpan(offset + 4)); + var buildPart = BinaryPrimitives.ReadUInt16LittleEndian(buffer.AsSpan(offset + 6)); + + MinRequired = new ClientVersion(majorPart, minorPart, buildPart, privatePart); + break; + } } } } - if (Required != null) + if (MinRequired != null || MaxRequired != null) { logger.Information( - "Restricting client version to {0}. Action to be taken: {1}", - Required, - m_OldClientResponse + $"Restricting client version to {GetVersionExpression()}. Action to be taken: {_invalidClientResponse}" ); } } + private static string GetVersionExpression() + { + if (_versionExpression == null) + { + if (MinRequired != null && MaxRequired != null) + { + _versionExpression = $"{MinRequired}-{MaxRequired}"; + } + else if (MinRequired != null) + { + _versionExpression = $"{MinRequired} or newer"; + } + else + { + _versionExpression = $"{MaxRequired} or older"; + } + } + + return _versionExpression; + } + private static void EventSink_ClientVersionReceived(NetState state, ClientVersion version) { - string kickMessage = null; + using var message = new ValueStringBuilder(); - if (state.Mobile?.AccessLevel != AccessLevel.Player) + if (!_enable || state.Mobile?.AccessLevel != AccessLevel.Player) { return; } - if (Required != null && version < Required && (m_OldClientResponse == OldClientResponse.Kick || - m_OldClientResponse == OldClientResponse.LenientKick && - Core.Now - state.Mobile.Created > m_AgeLeniency && - state.Mobile is PlayerMobile mobile && - mobile.GameTime > m_GameTimeLeniency)) + var strictRequirement = _invalidClientResponse == InvalidClientResponse.Kick || + _invalidClientResponse == InvalidClientResponse.LenientKick && + Core.Now - state.Mobile.Created > _ageLeniency && + state.Mobile is PlayerMobile mobile && + mobile.GameTime > _gameTimeLeniency; + + bool shouldKick = false; + + if (MinRequired != null && version < MinRequired) { - kickMessage = $"This server requires your client version be at least {Required}."; + message.Append($"This server doesn't support clients older than {MinRequired}."); + shouldKick = strictRequirement; } - else if (!AllowGod || !AllowRegular || !AllowUOTD) + else if (MaxRequired != null && version > MaxRequired) { - if (!AllowGod && version.Type == ClientType.God) + message.Append($"This server doesn't support clients newer than {MaxRequired}."); + shouldKick = strictRequirement; + } + else if (!AllowRegular || !AllowUOTD) + { + if (!AllowRegular && version.Type == ClientType.Regular) { - kickMessage = "This server does not allow god clients to connect."; - } - else if (!AllowRegular && version.Type == ClientType.Regular) - { - kickMessage = "This server does not allow regular clients to connect."; + message.Append("This server does not allow regular clients to connect."); + shouldKick = true; } else if (!AllowUOTD && state.IsUOTDClient) { - kickMessage = "This server does not allow UO:TD clients to connect."; + message.Append("This server does not allow UO:TD clients to connect."); + shouldKick = true; } - if (!AllowGod && !AllowRegular && !AllowUOTD) - { - kickMessage = "This server does not allow any clients to connect."; - } - else if (AllowGod && !AllowRegular && !AllowUOTD && version.Type != ClientType.God) - { - kickMessage = "This server requires you to use the god client."; - } - else if (kickMessage != null) + if (message.Length > 0) { if (AllowRegular && AllowUOTD) { - kickMessage += " You can use regular or UO:TD clients."; + message.Append(" You can use regular or UO:TD clients."); } else if (AllowRegular) { - kickMessage += " You can use regular clients."; + message.Append(" You can use regular clients."); } else if (AllowUOTD) { - kickMessage += " You can use UO:TD clients."; + message.Append(" You can use UO:TD clients."); } } } - if (kickMessage != null) + if (message.Length > 0) { - state.Mobile.SendMessage(0x22, kickMessage); - state.Mobile.SendMessage(0x22, "You will be disconnected in {0} seconds.", KickDelay.TotalSeconds); - - Timer.StartTimer(KickDelay, () => OnKick(state)); + state.Mobile.SendMessage(0x22, message.ToString()); } - else if (Required != null && version < Required) + + if (shouldKick) { - switch (m_OldClientResponse) + state.Mobile.SendMessage(0x22, "You will be disconnected in {0} seconds.", KickDelay.TotalSeconds); + Timer.StartTimer(KickDelay, () => OnKick(state)); + return; + } + + if (message.Length > 0) + { + switch (_invalidClientResponse) { - case OldClientResponse.Warn: + case InvalidClientResponse.Warn: { state.Mobile.SendMessage( 0x22, - "Your client is out of date. Please update your client.", - Required - ); - state.Mobile.SendMessage( - 0x22, - "This server recommends that your client version be at least {0}.", - Required + $"This server recommends that your client version is {GetVersionExpression()}." ); break; } - case OldClientResponse.LenientKick: - case OldClientResponse.Annoy: + case InvalidClientResponse.LenientKick: + case InvalidClientResponse.Annoy: { SendAnnoyGump(state.Mobile); break; @@ -170,10 +211,11 @@ namespace Server.Misc private static void OnKick(NetState ns) { - if (ns.Connection != null) + if (ns.Running) { - ns.LogInfo("Disconnecting, bad version"); - ns.Disconnect($"Invalid client version {ns.Version}."); + var version = ns.Version; + ns.LogInfo($"Disconnecting, bad version ({version})"); + ns.Disconnect($"Invalid client version {version}."); } } @@ -181,12 +223,12 @@ namespace Server.Misc { from.SendMessage("You will be reminded of this again."); - if (m_OldClientResponse == OldClientResponse.LenientKick) + if (_invalidClientResponse == InvalidClientResponse.LenientKick) { from.SendMessage( - "Old clients will be kicked after {0} days of character age and {1} hours of play time", - m_AgeLeniency, - m_GameTimeLeniency + "Invalid clients will be kicked after {0} days of character age and {1} hours of play time", + _ageLeniency, + _gameTimeLeniency ); } @@ -195,28 +237,29 @@ namespace Server.Misc private static void SendAnnoyGump(Mobile m) { - if (m.NetState != null && m.NetState.Version < Required) + if (m.NetState != null) { Gump g = new WarningGump( 1060637, 30720, - $"Your client is out of date. Please update your client.
This server recommends that your client version be at least {Required}.

You are currently using version {m.NetState.Version}.

To patch, run UOPatch.exe inside your Ultima Online folder.", + $"Your client is invalid.
This server recommends that your client version is {GetVersionExpression()}.

You are currently using version {m.NetState.Version}.", 0xFFC000, 480, 360, okay => KickMessage(m, okay), false - ); - - g.Draggable = false; - g.Closable = false; - g.Resizable = false; + ) + { + Draggable = false, + Closable = false, + Resizable = false, + }; m.SendGump(g); } } - private enum OldClientResponse + private enum InvalidClientResponse { Ignore, Warn, diff --git a/Projects/UOContent/Misc/Guild.cs b/Projects/UOContent/Misc/Guild.cs index dd891a8b1..bccad8bb9 100644 --- a/Projects/UOContent/Misc/Guild.cs +++ b/Projects/UOContent/Misc/Guild.cs @@ -661,15 +661,7 @@ namespace Server.Guilds public AllianceInfo Alliance { - get - { - if (m_AllianceInfo != null) - { - return m_AllianceInfo; - } - - return m_AllianceLeader?.m_AllianceInfo; - } + get => m_AllianceInfo ?? m_AllianceLeader?.m_AllianceInfo; set { var current = Alliance; @@ -1359,10 +1351,10 @@ namespace Server.Guilds alliance = Alliance; // CheckLeader could possibly change the value of this.Alliance - if (alliance?.IsMember(this) == false && !alliance.IsPendingMember(this) - ) // This block is there to fix a bug in the code in an older version. + // This block is there to fix a bug in the code in an older version. + if (alliance?.IsMember(this) == false && !alliance.IsPendingMember(this)) { - Alliance = null; // Will call Alliance.RemoveGuild which will set it null & perform all the pertient checks as far as alliacne disbanding + Alliance = null; // Will call Alliance.RemoveGuild which will set it null & perform all the pertinent checks as far as alliance disbanding } } @@ -1616,10 +1608,10 @@ namespace Server.Guilds if (m_Leader != winner && winner != null) { - GuildMessage(1018015, true, winner.Name); // Guild Message: Guildmaster changed to: + Leader = winner; + GuildMessage(1018015, true, winner.RawName); // Guild Message: Guildmaster changed to: } - Leader = winner; LastFealty = Core.Now; } diff --git a/Projects/UOContent/Misc/ServerList.cs b/Projects/UOContent/Misc/ServerList.cs index 7d3a95194..d457a102a 100644 --- a/Projects/UOContent/Misc/ServerList.cs +++ b/Projects/UOContent/Misc/ServerList.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using System.Net; using System.Net.Http; using System.Net.NetworkInformation; diff --git a/Projects/UOContent/Skills/Inscribe.cs b/Projects/UOContent/Skills/Inscribe.cs index 3c97e95ee..dbcca17e8 100644 --- a/Projects/UOContent/Skills/Inscribe.cs +++ b/Projects/UOContent/Skills/Inscribe.cs @@ -112,9 +112,8 @@ namespace Server.SkillHandlers { if (cancelType == TargetCancelType.Timeout) { - from.SendLocalizedMessage( - 501619 - ); // You have waited too long to make your inscribe selection, your inscription attempt has timed out. + // You have waited too long to make your inscribe selection, your inscription attempt has timed out. + from.SendLocalizedMessage(501619); } } } @@ -172,9 +171,8 @@ namespace Server.SkillHandlers { if (cancelType == TargetCancelType.Timeout) { - from.SendLocalizedMessage( - 501619 - ); // You have waited too long to make your inscribe selection, your inscription attempt has timed out. + // You have waited too long to make your inscribe selection, your inscription attempt has timed out. + from.SendLocalizedMessage(501619); } } diff --git a/Projects/UOContent/Spells/Base/Spell.cs b/Projects/UOContent/Spells/Base/Spell.cs index 85c8c4ceb..73afcba5b 100644 --- a/Projects/UOContent/Spells/Base/Spell.cs +++ b/Projects/UOContent/Spells/Base/Spell.cs @@ -790,9 +790,7 @@ namespace Server.Spells return false; } - public bool CheckBSequence(Mobile target) => CheckBSequence(target, false); - - public bool CheckBSequence(Mobile target, bool allowDead) + public bool CheckBSequence(Mobile target, bool allowDead = false) { if (!target.Alive && !allowDead) { diff --git a/Projects/UOContent/Spells/Fifth/DispelField.cs b/Projects/UOContent/Spells/Fifth/DispelField.cs index ff0241410..ac0bfe41e 100644 --- a/Projects/UOContent/Spells/Fifth/DispelField.cs +++ b/Projects/UOContent/Spells/Fifth/DispelField.cs @@ -1,6 +1,5 @@ using Server.Items; using Server.Misc; -using Server.Targeting; namespace Server.Spells.Fifth { diff --git a/Projects/UOContent/Spells/Fifth/PoisonField.cs b/Projects/UOContent/Spells/Fifth/PoisonField.cs index bbc26fb85..8a55f0d0b 100644 --- a/Projects/UOContent/Spells/Fifth/PoisonField.cs +++ b/Projects/UOContent/Spells/Fifth/PoisonField.cs @@ -3,7 +3,6 @@ using Server.Collections; using Server.Items; using Server.Misc; using Server.Mobiles; -using Server.Targeting; namespace Server.Spells.Fifth { diff --git a/Projects/UOContent/Spells/Fourth/ArchCure.cs b/Projects/UOContent/Spells/Fourth/ArchCure.cs index f7be3f3e9..3d7158499 100644 --- a/Projects/UOContent/Spells/Fourth/ArchCure.cs +++ b/Projects/UOContent/Spells/Fourth/ArchCure.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Linq; using Server.Mobiles; -using Server.Targeting; namespace Server.Spells.Fourth { diff --git a/Projects/UOContent/Spells/Fourth/ArchProtection.cs b/Projects/UOContent/Spells/Fourth/ArchProtection.cs index a798ad83b..d924d4c82 100644 --- a/Projects/UOContent/Spells/Fourth/ArchProtection.cs +++ b/Projects/UOContent/Spells/Fourth/ArchProtection.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using Server.Collections; using Server.Engines.PartySystem; using Server.Spells.Second; -using Server.Targeting; namespace Server.Spells.Fourth { diff --git a/Projects/UOContent/Spells/Fourth/FireField.cs b/Projects/UOContent/Spells/Fourth/FireField.cs index e685fd6c0..c3979af90 100644 --- a/Projects/UOContent/Spells/Fourth/FireField.cs +++ b/Projects/UOContent/Spells/Fourth/FireField.cs @@ -3,7 +3,6 @@ using Server.Collections; using Server.Items; using Server.Misc; using Server.Mobiles; -using Server.Targeting; namespace Server.Spells.Fourth { diff --git a/Projects/UOContent/Spells/Necromancy/AnimateDeadSpell.cs b/Projects/UOContent/Spells/Necromancy/AnimateDeadSpell.cs index 47448544b..f67cdeb78 100644 --- a/Projects/UOContent/Spells/Necromancy/AnimateDeadSpell.cs +++ b/Projects/UOContent/Spells/Necromancy/AnimateDeadSpell.cs @@ -4,7 +4,6 @@ using Server.Engines.Quests; using Server.Engines.Quests.Necro; using Server.Items; using Server.Mobiles; -using Server.Targeting; using Server.Utilities; namespace Server.Spells.Necromancy diff --git a/Projects/UOContent/Spells/Second/MagicTrap.cs b/Projects/UOContent/Spells/Second/MagicTrap.cs index 13200240f..baf6e346f 100644 --- a/Projects/UOContent/Spells/Second/MagicTrap.cs +++ b/Projects/UOContent/Spells/Second/MagicTrap.cs @@ -1,5 +1,4 @@ using Server.Items; -using Server.Targeting; namespace Server.Spells.Second { diff --git a/Projects/UOContent/Spells/Second/RemoveTrap.cs b/Projects/UOContent/Spells/Second/RemoveTrap.cs index 3850205c0..cb800ddf2 100644 --- a/Projects/UOContent/Spells/Second/RemoveTrap.cs +++ b/Projects/UOContent/Spells/Second/RemoveTrap.cs @@ -1,5 +1,4 @@ using Server.Items; -using Server.Targeting; namespace Server.Spells.Second { diff --git a/Projects/UOContent/Spells/Seventh/ChainLightning.cs b/Projects/UOContent/Spells/Seventh/ChainLightning.cs index 0286729fe..6f3ec9923 100644 --- a/Projects/UOContent/Spells/Seventh/ChainLightning.cs +++ b/Projects/UOContent/Spells/Seventh/ChainLightning.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using Server.Targeting; namespace Server.Spells.Seventh { diff --git a/Projects/UOContent/Spells/Seventh/EnergyField.cs b/Projects/UOContent/Spells/Seventh/EnergyField.cs index 98177d63f..d802cd5e8 100644 --- a/Projects/UOContent/Spells/Seventh/EnergyField.cs +++ b/Projects/UOContent/Spells/Seventh/EnergyField.cs @@ -2,7 +2,6 @@ using System; using Server.Items; using Server.Misc; using Server.Mobiles; -using Server.Targeting; namespace Server.Spells.Seventh { diff --git a/Projects/UOContent/Spells/Seventh/MassDispel.cs b/Projects/UOContent/Spells/Seventh/MassDispel.cs index 9e40a0930..1b355af71 100644 --- a/Projects/UOContent/Spells/Seventh/MassDispel.cs +++ b/Projects/UOContent/Spells/Seventh/MassDispel.cs @@ -1,7 +1,6 @@ using Server.Collections; using Server.Items; using Server.Mobiles; -using Server.Targeting; namespace Server.Spells.Seventh { diff --git a/Projects/UOContent/Spells/Seventh/MeteorSwarm.cs b/Projects/UOContent/Spells/Seventh/MeteorSwarm.cs index 1d6e56825..19899f7b0 100644 --- a/Projects/UOContent/Spells/Seventh/MeteorSwarm.cs +++ b/Projects/UOContent/Spells/Seventh/MeteorSwarm.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using Server.Targeting; namespace Server.Spells.Seventh { diff --git a/Projects/UOContent/Spells/Sixth/Mark.cs b/Projects/UOContent/Spells/Sixth/Mark.cs index 0f8d7d6a1..d656ea5bd 100644 --- a/Projects/UOContent/Spells/Sixth/Mark.cs +++ b/Projects/UOContent/Spells/Sixth/Mark.cs @@ -1,6 +1,5 @@ using Server.Items; using Server.Network; -using Server.Targeting; namespace Server.Spells.Sixth { diff --git a/Projects/UOContent/Spells/Sixth/MassCurse.cs b/Projects/UOContent/Spells/Sixth/MassCurse.cs index bbd7e183e..069805a0f 100644 --- a/Projects/UOContent/Spells/Sixth/MassCurse.cs +++ b/Projects/UOContent/Spells/Sixth/MassCurse.cs @@ -1,5 +1,3 @@ -using Server.Targeting; - namespace Server.Spells.Sixth { public class MassCurseSpell : MagerySpell, ISpellTargetingPoint3D diff --git a/Projects/UOContent/Spells/Sixth/ParalyzeField.cs b/Projects/UOContent/Spells/Sixth/ParalyzeField.cs index 475bc4406..8a018caba 100644 --- a/Projects/UOContent/Spells/Sixth/ParalyzeField.cs +++ b/Projects/UOContent/Spells/Sixth/ParalyzeField.cs @@ -2,7 +2,6 @@ using System; using Server.Items; using Server.Misc; using Server.Mobiles; -using Server.Targeting; namespace Server.Spells.Sixth { diff --git a/Projects/UOContent/Spells/Sixth/Reveal.cs b/Projects/UOContent/Spells/Sixth/Reveal.cs index 653594d25..edaf005a3 100644 --- a/Projects/UOContent/Spells/Sixth/Reveal.cs +++ b/Projects/UOContent/Spells/Sixth/Reveal.cs @@ -1,5 +1,4 @@ using Server.Mobiles; -using Server.Targeting; namespace Server.Spells.Sixth { diff --git a/Projects/UOContent/Spells/Targeting/SpellTargetItem.cs b/Projects/UOContent/Spells/Targeting/SpellTargetItem.cs index 0bab04b1d..3d29a33a5 100644 --- a/Projects/UOContent/Spells/Targeting/SpellTargetItem.cs +++ b/Projects/UOContent/Spells/Targeting/SpellTargetItem.cs @@ -16,12 +16,12 @@ namespace Server.Spells public ISpell Spell => _spell; + protected override bool CanTarget(Mobile from, StaticTarget staticTarget, ref Point3D loc, ref Map map) => false; + protected override bool CanTarget(Mobile from, Mobile mobile, ref Point3D loc, ref Map map) => false; + protected override void OnTarget(Mobile from, object o) { - if (o is Item item) - { - _spell.Target(item); - } + _spell.Target(o as Item); } protected override void OnTargetFinish(Mobile from) diff --git a/Projects/UOContent/Spells/Targeting/SpellTargetMobile.cs b/Projects/UOContent/Spells/Targeting/SpellTargetMobile.cs index b8e245cf7..c97511dcd 100644 --- a/Projects/UOContent/Spells/Targeting/SpellTargetMobile.cs +++ b/Projects/UOContent/Spells/Targeting/SpellTargetMobile.cs @@ -16,6 +16,9 @@ namespace Server.Spells public ISpell Spell => _spell; + protected override bool CanTarget(Mobile from, StaticTarget staticTarget, ref Point3D loc, ref Map map) => false; + protected override bool CanTarget(Mobile from, Item item, ref Point3D loc, ref Map map) => false; + protected override void OnTarget(Mobile from, object o) { _spell.Target(o as Mobile); diff --git a/Projects/UOContent/Spells/Targeting/SpellTargetPoint3D.cs b/Projects/UOContent/Spells/Targeting/SpellTargetPoint3D.cs index 40da7d383..ba6b4838b 100644 --- a/Projects/UOContent/Spells/Targeting/SpellTargetPoint3D.cs +++ b/Projects/UOContent/Spells/Targeting/SpellTargetPoint3D.cs @@ -24,10 +24,7 @@ namespace Server.Spells protected override void OnTarget(Mobile from, object o) { - if (o is IPoint3D p) - { - _spell.Target(p); - } + _spell.Target(o as IPoint3D); } protected override void OnTargetOutOfLOS(Mobile from, object o) diff --git a/Projects/UOContent/Spells/Third/MagicLock.cs b/Projects/UOContent/Spells/Third/MagicLock.cs index 55da042cc..76b0ef7a6 100644 --- a/Projects/UOContent/Spells/Third/MagicLock.cs +++ b/Projects/UOContent/Spells/Third/MagicLock.cs @@ -1,7 +1,6 @@ using Server.Items; using Server.Multis; using Server.Network; -using Server.Targeting; namespace Server.Spells.Third { diff --git a/Projects/UOContent/Spells/Third/Telekinesis.cs b/Projects/UOContent/Spells/Third/Telekinesis.cs index f41be5a7f..aeb3a24be 100644 --- a/Projects/UOContent/Spells/Third/Telekinesis.cs +++ b/Projects/UOContent/Spells/Third/Telekinesis.cs @@ -1,5 +1,4 @@ using Server.Items; -using Server.Targeting; namespace Server.Spells.Third { diff --git a/Projects/UOContent/Spells/Third/Teleport.cs b/Projects/UOContent/Spells/Third/Teleport.cs index c2797f9f4..9e2b2236a 100644 --- a/Projects/UOContent/Spells/Third/Teleport.cs +++ b/Projects/UOContent/Spells/Third/Teleport.cs @@ -5,7 +5,6 @@ using Server.Regions; using Server.Spells.Fifth; using Server.Spells.Fourth; using Server.Spells.Sixth; -using Server.Targeting; namespace Server.Spells.Third { diff --git a/Projects/UOContent/Spells/Third/Unlock.cs b/Projects/UOContent/Spells/Third/Unlock.cs index 6476bd0c7..715cf1e82 100644 --- a/Projects/UOContent/Spells/Third/Unlock.cs +++ b/Projects/UOContent/Spells/Third/Unlock.cs @@ -1,7 +1,6 @@ using Server.Items; using Server.Multis; using Server.Network; -using Server.Targeting; namespace Server.Spells.Third { diff --git a/Projects/UOContent/Spells/Third/WallOfStone.cs b/Projects/UOContent/Spells/Third/WallOfStone.cs index fd4bd0b2d..0be6b4b9c 100644 --- a/Projects/UOContent/Spells/Third/WallOfStone.cs +++ b/Projects/UOContent/Spells/Third/WallOfStone.cs @@ -1,7 +1,6 @@ using System; using Server.Misc; using Server.Mobiles; -using Server.Targeting; namespace Server.Spells.Third { diff --git a/Projects/UOContent/UOContent.csproj b/Projects/UOContent/UOContent.csproj index 2ef0f6dfc..c5561de3d 100755 --- a/Projects/UOContent/UOContent.csproj +++ b/Projects/UOContent/UOContent.csproj @@ -41,13 +41,13 @@ - - - + + + - TargetFramework=netstandard2.0 + TargetFramework=netstandard2.1 Analyzer false all diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 6923ed2ae..38df04622 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -14,11 +14,6 @@ jobs: vmImage: 'windows-latest' steps: - - task: UseDotNet@2 - displayName: 'Install .NET 5' - inputs: - packageType: sdk - version: 5.0.403 - task: UseDotNet@2 displayName: 'Install .NET 6' inputs: @@ -27,7 +22,7 @@ jobs: - task: NuGetAuthenticate@0 - script: ./publish.cmd Release win displayName: 'Build' - - script: dotnet test --no-restore --framework net6.0 + - script: dotnet test --no-restore displayName: 'Test' - job: BuildLinux @@ -39,14 +34,11 @@ jobs: 'CentOS 7': containerImage: centos:7 os: centos.7 - 'Debian 10': - containerImage: mcr.microsoft.com/dotnet/sdk:5.0-buster-slim - os: debian.10 - # 'Debian 11': - # containerImage: amd64/buildpack-deps:bullseye - # os: debian.11-x64 + 'Debian 11': + containerImage: mcr.microsoft.com/dotnet/sdk:6.0-bullseye-slim + os: debian.11 'Ubuntu 20': - containerImage: mcr.microsoft.com/dotnet/sdk:5.0-focal + containerImage: mcr.microsoft.com/dotnet/sdk:6.0-focal os: ubuntu.20.04 'Fedora 32': containerImage: fedora:32 @@ -54,6 +46,9 @@ jobs: 'Fedora 33': containerImage: fedora:33 os: fedora.33 + 'Fedora 34': + containerImage: fedora:34 + os: fedora.34 displayName: Linux @@ -63,11 +58,6 @@ jobs: container: $[ variables['containerImage'] ] steps: - - task: UseDotNet@2 - displayName: 'Install .NET 5' - inputs: - packageType: sdk - version: 5.0.403 - task: UseDotNet@2 displayName: 'Install .NET 6' inputs: @@ -76,5 +66,5 @@ jobs: - task: NuGetAuthenticate@0 - script: ./publish.cmd Release $(os) displayName: 'Build' - - script: dotnet test --no-restore --framework net6.0 + - script: dotnet test --no-restore displayName: 'Test'