Merge branch 'main' into webSupport
This commit is contained in:
commit
3650878399
50 changed files with 365 additions and 319 deletions
2
.github/workflows/build-test.yml
vendored
2
.github/workflows/build-test.yml
vendored
|
|
@ -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
|
||||
|
|
|
|||
1
.github/workflows/create-release.yml
vendored
1
.github/workflows/create-release.yml
vendored
|
|
@ -3,6 +3,7 @@ name: Create Release
|
|||
on:
|
||||
repository_dispatch:
|
||||
types: [release]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
release:
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
<PublicRelease>true</PublicRelease>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<NoWarn>NU1603</NoWarn>
|
||||
<RuntimeIdentifiers>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</RuntimeIdentifiers>
|
||||
<RuntimeIdentifiers>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</RuntimeIdentifiers>
|
||||
<Configurations>Debug;Release;Analyze</Configurations>
|
||||
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<BuildOutputTargetFolder>analyzers</BuildOutputTargetFolder>
|
||||
</PropertyGroup>
|
||||
|
|
@ -21,9 +21,9 @@
|
|||
<Target Name="GetDependencyTargetPaths">
|
||||
<ItemGroup>
|
||||
<TargetPathWithTargetPlatformMoniker Include="$(PKGHumanizer_Core)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
|
||||
<TargetPathWithTargetPlatformMoniker Include="$(PKGSystem_Text_Json)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
|
||||
<TargetPathWithTargetPlatformMoniker Include="$(PKGSystem_Text_Encodings_Web)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
|
||||
<TargetPathWithTargetPlatformMoniker Include="$(PKGMicrosoft_Bcl_AsyncInterfaces)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
|
||||
<TargetPathWithTargetPlatformMoniker Include="$(PKGSystem_Text_Json)\lib\netstandard2.1\*.dll" IncludeRuntimeDependency="false" />
|
||||
<TargetPathWithTargetPlatformMoniker Include="$(PKGSystem_Text_Encodings_Web)\lib\netstandard2.1\*.dll" IncludeRuntimeDependency="false" />
|
||||
<TargetPathWithTargetPlatformMoniker Include="$(PKGMicrosoft_Bcl_AsyncInterfaces)\lib\netstandard2.1\*.dll" IncludeRuntimeDependency="false" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Humanizer.Core" Version="2.13.14" />
|
||||
<PackageReference Include="Microsoft.Build.Locator" Version="1.4.1" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.0.1" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="4.0.1" />
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<PackageReference Include="Moq" Version="4.16.1" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<PackageReference Include="Zlib.Bindings" Version="1.5.0" />
|
||||
<PackageReference Include="Zlib.Bindings" Version="1.7.2" />
|
||||
<ProjectReference Include="..\Server\Server.csproj" />
|
||||
<ProjectReference Include="..\UOContent\UOContent.csproj" />
|
||||
<DataFiles Include="$(SolutionDir)\Distribution\Data\**" />
|
||||
|
|
|
|||
|
|
@ -38,11 +38,11 @@ namespace Server
|
|||
|
||||
public static List<IPEndPoint> 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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -197,7 +197,9 @@ namespace Server.Network
|
|||
|
||||
public Pipe<byte> SendPipe { get; }
|
||||
|
||||
public Socket Connection { get; }
|
||||
public bool Running => _running;
|
||||
|
||||
public Socket Connection { get; private set; }
|
||||
|
||||
public bool CompressionEnabled { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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<NetState> Instances { get; } = new(2048);
|
||||
|
||||
private static readonly ConcurrentQueue<NetState> _connectedQueue = new();
|
||||
|
|
@ -52,7 +52,7 @@ namespace Server.Network
|
|||
public static void Start()
|
||||
{
|
||||
HashSet<IPEndPoint> listeningAddresses = new HashSet<IPEndPoint>();
|
||||
List<TcpListener> listeners = new List<TcpListener>();
|
||||
List<Socket> listeners = new List<Socket>();
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -36,11 +36,11 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Toolkit.HighPerformance" Version="7.1.2" />
|
||||
<PackageReference Include="PollGroup" Version="1.1.0" />
|
||||
<PackageReference Include="Zlib.Bindings" Version="1.5.0" />
|
||||
<PackageReference Include="Zlib.Bindings" Version="1.7.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SerializationGenerator\SerializationGenerator.csproj">
|
||||
<SetTargetFramework>TargetFramework=netstandard2.0</SetTargetFramework>
|
||||
<SetTargetFramework>TargetFramework=netstandard2.1</SetTargetFramework>
|
||||
<OutputItemType>Analyzer</OutputItemType>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -525,7 +525,7 @@ namespace Server
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static IEntity FindEntity(Serial serial, bool returnDeleted = false) => FindEntity<IEntity>(serial);
|
||||
public static IEntity FindEntity(Serial serial, bool returnDeleted = false) => FindEntity<IEntity>(serial, returnDeleted);
|
||||
|
||||
public static T FindEntity<T>(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<IEntity>(serial) as T;
|
||||
}
|
||||
|
||||
if (entity?.Deleted == false)
|
||||
{
|
||||
return entity;
|
||||
if (entity?.Deleted == false)
|
||||
{
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
||||
return entity?.Created <= reader.LastSerialized ? entity : null;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
using System.Collections.Generic;
|
||||
using Server.ContextMenus;
|
||||
using Server.Engines.Craft;
|
||||
|
||||
namespace Server.Items
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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<Mobile> Users { get; private set; }
|
||||
private HashSet<Mobile> _users;
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
|
|
@ -84,12 +84,8 @@ namespace Server.Items
|
|||
|
||||
from.RevealingAction();
|
||||
|
||||
Users ??= new List<Mobile>();
|
||||
|
||||
if (!Users.Contains(from))
|
||||
{
|
||||
Users.Add(from);
|
||||
}
|
||||
_users ??= new HashSet<Mobile>();
|
||||
_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<IEntity>.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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
using Server.Mobiles;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
using System;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<byte>((int)fs.Length, true);
|
||||
fs.Read(buffer);
|
||||
// VS_VERSION_INFO (unicode)
|
||||
Span<byte> 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.<br>This server recommends that your client version be at least {Required}.<br> <br>You are currently using version {m.NetState.Version}.<br> <br>To patch, run UOPatch.exe inside your Ultima Online folder.",
|
||||
$"Your client is invalid.<br>This server recommends that your client version is {GetVersionExpression()}.<br> <br>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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.NetworkInformation;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
using Server.Items;
|
||||
using Server.Misc;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Fifth
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ using Server.Collections;
|
|||
using Server.Items;
|
||||
using Server.Misc;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Fifth
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Fourth
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ using Server.Collections;
|
|||
using Server.Items;
|
||||
using Server.Misc;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Fourth
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using Server.Items;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Second
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using Server.Items;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Second
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Seventh
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ using System;
|
|||
using Server.Items;
|
||||
using Server.Misc;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Seventh
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
using Server.Collections;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Seventh
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Seventh
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
using Server.Items;
|
||||
using Server.Network;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Sixth
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Sixth
|
||||
{
|
||||
public class MassCurseSpell : MagerySpell, ISpellTargetingPoint3D
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ using System;
|
|||
using Server.Items;
|
||||
using Server.Misc;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Sixth
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Sixth
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
using Server.Items;
|
||||
using Server.Multis;
|
||||
using Server.Network;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Third
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using Server.Items;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Third
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
using Server.Items;
|
||||
using Server.Multis;
|
||||
using Server.Network;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Third
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
using System;
|
||||
using Server.Misc;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Third
|
||||
{
|
||||
|
|
|
|||
|
|
@ -41,13 +41,13 @@
|
|||
<PackageReference Include="MailKit" Version="2.15.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Toolkit.HighPerformance" Version="7.1.2" />
|
||||
<PackageReference Include="Zlib.Bindings" Version="1.5.0" />
|
||||
<PackageReference Include="Argon2.Bindings" Version="1.9.1" />
|
||||
<PackageReference Include="Zstd.Binaries" Version="1.0.0" />
|
||||
<PackageReference Include="Zlib.Bindings" Version="1.7.2" />
|
||||
<PackageReference Include="Argon2.Bindings" Version="1.11.0" />
|
||||
<PackageReference Include="Zstd.Binaries" Version="1.2.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SerializationGenerator\SerializationGenerator.csproj">
|
||||
<SetTargetFramework>TargetFramework=netstandard2.0</SetTargetFramework>
|
||||
<SetTargetFramework>TargetFramework=netstandard2.1</SetTargetFramework>
|
||||
<OutputItemType>Analyzer</OutputItemType>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue