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'