Fixes dupe exception (#258)

- [X] Cleans up ActivatorUtil
- [X] Fixes dupe exception
- [X] Fixes a bug in BasePotion
- [X] Fixes a few possible memory leaks

Bumps release version
This commit is contained in:
Kamron Batman 2020-09-19 15:46:07 -07:00 committed by GitHub
parent 4d6e584b6c
commit e9c1e4cbba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
66 changed files with 597 additions and 496 deletions

View file

@ -0,0 +1,95 @@
using Server.Utilities;
using Xunit;
namespace Server.Tests
{
public class ActivatorExtensionsTests
{
[Fact]
public void TestZeroParamsActivator()
{
var result = typeof(TestZeroParamsClass).CreateInstance<TestZeroParamsClass>();
Assert.IsType<TestZeroParamsClass>(result);
}
[Fact]
public void TestZeroParamsNullActivator()
{
var result = typeof(TestZeroParamsClass).CreateInstance<TestZeroParamsClass>(null, null);
Assert.IsType<TestZeroParamsClass>(result);
}
[Fact]
public void TestTwoParamsActivator()
{
var result = typeof(TestTwoParamsClass).CreateInstance<TestTwoParamsClass>(10, "ModernUO");
Assert.IsType<TestTwoParamsClass>(result);
Assert.Equal(10, result.Amount);
Assert.Equal("ModernUO", result.Name);
}
[Fact]
public void TestAllParamsOptionalActivator()
{
var result = typeof(TestTwoOptionalParamsClass).CreateInstance<TestTwoOptionalParamsClass>();
Assert.IsType<TestTwoOptionalParamsClass>(result);
Assert.Equal(1, result.Amount);
Assert.Equal("Test ModernUO", result.Name);
}
[Fact]
public void TestAllParamsNullOptionalActivator()
{
var result = typeof(TestTwoOptionalParamsClass).CreateInstance<TestTwoOptionalParamsClass>(null);
Assert.IsType<TestTwoOptionalParamsClass>(result);
Assert.Equal(1, result.Amount);
Assert.Equal("Test ModernUO", result.Name);
}
[Fact]
public void TestLessParamsOptionalActivator()
{
var result = typeof(TestTwoOptionalParamsClass).CreateInstance<TestTwoOptionalParamsClass>(10);
Assert.IsType<TestTwoOptionalParamsClass>(result);
Assert.Equal(10, result.Amount);
Assert.Equal("Test ModernUO", result.Name);
}
[Fact]
public void TestTwoParamsOptionalActivator()
{
var result = typeof(TestTwoOptionalParamsClass).CreateInstance<TestTwoOptionalParamsClass>(10, "Prod ModernUO");
Assert.IsType<TestTwoOptionalParamsClass>(result);
Assert.Equal(10, result.Amount);
Assert.Equal("Prod ModernUO", result.Name);
}
private class TestZeroParamsClass
{
}
private class TestTwoParamsClass
{
public int Amount;
public string Name;
public TestTwoParamsClass(int amount, string name)
{
Amount = amount;
Name = name;
}
}
private class TestTwoOptionalParamsClass
{
public int Amount;
public string Name;
public TestTwoOptionalParamsClass(int amount = 1, string name = "Test ModernUO")
{
Amount = amount;
Name = name;
}
}
}
}

View file

@ -5738,7 +5738,7 @@ namespace Server
Item item;
try
{
item = (Item)ActivatorUtil.CreateInstance(oldItem.GetType());
item = oldItem.GetType().CreateInstance<Item>();
}
catch
{

View file

@ -46,7 +46,7 @@ namespace Server
continue;
}
var region = ActivatorUtil.CreateInstance(type, json, JsonConfig.DefaultOptions) as Region;
var region = type.CreateInstance<Region>(json, JsonConfig.DefaultOptions);
region?.Register();
count++;
}

View file

@ -0,0 +1,153 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ActivatorExtensions.cs *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
using System.Reflection;
namespace Server.Utilities
{
public static class ActivatorExtensions
{
public static ConstructorInfo GetConstructor(
this Type type,
Predicate<ConstructorInfo> predicate = null,
Type[] args = null
) => type.GetConstructor(predicate, args, out _);
public static ConstructorInfo GetConstructor(
this Type type,
Predicate<ConstructorInfo> predicate,
Type[] args,
out int paramCount
)
{
args ??= Array.Empty<Type>();
var ctors = type.GetConstructors();
try
{
for (int i = 0; i < ctors.Length; i++)
{
ConstructorInfo info = ctors[i];
if (predicate?.Invoke(info) == false)
{
continue;
}
var parameters = info.GetParameters();
paramCount = parameters.Length;
if (args.Length > parameters.Length)
{
continue;
}
bool validated = true;
// Check that all args match params
for (var j = 0; j < parameters.Length; j++)
{
ParameterInfo param = parameters[j];
// All extra parameters must be optional
if (j >= args.Length)
{
if (!param.IsOptional)
{
validated = false;
break;
}
continue;
}
var arg = args[j];
if (arg == null && param.ParameterType.IsValueType)
{
validated = false;
break;
}
if (arg != null && !param.ParameterType.IsAssignableFrom(arg))
{
validated = false;
break;
}
}
if (validated)
{
return info;
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
paramCount = 0;
return null;
}
public static T CreateInstance<T>(
this Type type,
params object[] args
) where T : class => type.CreateInstance<T>(null, args);
public static T CreateInstance<T>(
this Type type,
Predicate<ConstructorInfo> predicate,
object[] args = null
) where T : class
{
var argLength = args?.Length ?? 0;
var types = argLength > 0 ? new Type[argLength] : Array.Empty<Type>();
for (int i = 0; i < types.Length; i++)
{
types[i] = args![i]?.GetType();
}
var ctor = type.GetConstructor(predicate, types, out var paramCount);
if (ctor == null)
{
Console.WriteLine("There is no constructor for {0} that matches the given predicate.", type);
return default;
}
object[] paramArgs;
if (paramCount == 0)
{
paramArgs = Array.Empty<object>();
}
else if (argLength == paramCount)
{
paramArgs = args;
}
else
{
paramArgs = new object[paramCount];
for (int i = 0; i < paramCount; i++)
{
paramArgs[i] = i < argLength ? args![i] : Type.Missing;
}
}
return ctor.Invoke(paramArgs) as T;
}
}
}

View file

@ -1,155 +0,0 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ActivatorUtil.cs *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
using System.Linq;
using System.Reflection;
namespace Server.Utilities
{
public static class ActivatorUtil
{
public static ConstructorInfo GetConstructor(Type type, Predicate<ConstructorInfo> predicate = null)
{
var emptyCtor = type.GetConstructor(Type.EmptyTypes);
if (emptyCtor != null && predicate?.Invoke(emptyCtor) != false)
{
return emptyCtor;
}
var optionalCtor = type.GetConstructors()
.SingleOrDefault(
info =>
predicate?.Invoke(info) != false && info.GetParameters().All(x => x.IsOptional)
);
if (optionalCtor != null)
{
return optionalCtor;
}
throw new TypeInitializationException(
type.ToString(),
new Exception($"There is no empty/default constructor for {type} that matches predicate.")
);
}
public static ConstructorInfo GetConstructor(Type type, Predicate<ConstructorInfo> predicate, params Type[] args)
{
try
{
ConstructorInfo ctor;
if (args.All(x => x != null))
{
ctor = type.GetConstructor(args);
if (ctor != null && predicate?.Invoke(ctor) != false)
{
return ctor;
}
}
else
{
ctor = type.GetConstructors()
.SingleOrDefault(
info =>
{
if (predicate?.Invoke(info) == false)
{
return false;
}
var paramList = info.GetParameters().ToList();
// If more args are given than parameters, skip.
if (args.Length > paramList.Count)
{
return false;
}
// check all given args map to params.
for (var i = 0; i < args.Length; i++)
// if a null reference is passed, but the type is not nullable
{
if (args[i] == null && paramList[i].ParameterType.IsValueType
// or if an arg is not null and is not assignable to the parameter type, skip.
|| !(args[i] == null || paramList[i].ParameterType.IsAssignableFrom(args[i])))
{
return false;
}
}
// If there are more parameters, check if they any are not optional, if any are not, skip.
// Otherwise all checks have passed. We have found a match
return args.Length <= paramList.Count || paramList
.GetRange(args.Length, paramList.Count - args.Length)
.All(x => x.IsOptional);
}
);
if (ctor != null)
{
return ctor;
}
}
throw new Exception($"There is no empty/default constructor for {type} that matches predicate.");
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
public static object CreateInstance(Type type, Predicate<ConstructorInfo> constructorPredicate = null)
{
var cctor = GetConstructor(type, constructorPredicate);
var args = cctor.GetParameters();
if (args.Length == 0)
{
return cctor.Invoke(Type.EmptyTypes);
}
var argList = new object[args.Length];
Array.Fill(argList, Type.Missing);
return cctor.Invoke(argList);
}
public static object CreateInstance(
Type type, Predicate<ConstructorInfo> constructorPredicate = null,
params object[] args
)
{
if (args == null || args.Length == 0)
{
return CreateInstance(type, constructorPredicate);
}
var cctor = GetConstructor(type, constructorPredicate, args.Select(x => x?.GetType()).ToArray());
return cctor.Invoke(args);
}
public static object CreateInstance(Type type, params object[] args) => CreateInstance(type, null, args);
public static T CreateInstance<T>(Predicate<ConstructorInfo> constructorPredicate = null) =>
(T)CreateInstance(typeof(T), constructorPredicate);
public static T CreateInstance<T>(params object[] args) => (T)CreateInstance(typeof(T), null, args);
}
}

View file

@ -0,0 +1,46 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: EntityActivatorExtensions.cs *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
using System.Reflection;
namespace Server.Utilities
{
public static class EntityActivatorExtensions
{
public static T CreateEntityInstance<T>(
this Type type,
params object[] args
) where T : IEntity => type.CreateEntityInstance<T>(null, args);
public static T CreateEntityInstance<T>(
this Type type,
Predicate<ConstructorInfo> predicate,
object[] args = null
) where T : IEntity
{
var entity = type.CreateInstance<IEntity>(predicate, args);
if (entity is T t)
{
return t;
}
// Handles memory leaks by deleting the offending entity
entity?.Delete();
return default;
}
}
}

View file

@ -5,7 +5,7 @@ using Server.Utilities;
namespace Server.Commands
{
public class Dupe
public static class Dupe
{
public static void Initialize()
{
@ -111,7 +111,7 @@ namespace Server.Commands
pack = from.Backpack;
}
var c = ActivatorUtil.GetConstructor(copy.GetType());
var c = copy.GetType().GetConstructor();
if (c != null)
{
var paramList = c.GetParameters();
@ -128,7 +128,7 @@ namespace Server.Commands
{
if (c.Invoke(args) is Item newItem)
{
CopyProperties(newItem, copy); // copy.Dupe( item, copy.Amount );
CopyProperties(newItem, copy);
copy.OnAfterDuped(newItem);
newItem.Parent = null;
@ -166,7 +166,7 @@ namespace Server.Commands
if (!done)
{
from.SendMessage("Unable to dupe. Item must have a 0 parameter constructor.");
from.SendMessage("Unable to dupe. Item must have a constructor with zero required parameters.");
}
}
}

View file

@ -563,7 +563,7 @@ namespace Server.Commands.Generic
var conditionalType = typeBuilder.CreateType();
return (IConditional)ActivatorUtil.CreateInstance(conditionalType);
return conditionalType.CreateInstance<IConditional>();
}
}
}

View file

@ -248,7 +248,7 @@ namespace Server.Commands.Generic
var comparerType = typeBuilder.CreateType();
return (IComparer<T>)ActivatorUtil.CreateInstance(comparerType);
return comparerType.CreateInstance<IComparer<T>>();
}
}
}

View file

@ -161,7 +161,7 @@ namespace Server.Commands.Generic
}
var comparerType = typeBuilder.CreateType();
return (IComparer<T>)ActivatorUtil.CreateInstance(comparerType);
return comparerType.CreateInstance<IComparer<T>>();
}
}
}

View file

@ -300,7 +300,7 @@ namespace Server.Commands
public CategoryTypeEntry(Type type)
{
Type = type;
Object = ActivatorUtil.CreateInstance(type);
Object = type.CreateInstance<object>();
}
public Type Type { get; }

View file

@ -405,11 +405,11 @@ namespace Server.Commands
if (fill)
{
item = (Item)ActivatorUtil.CreateInstance(m_Type, content);
item = m_Type.CreateInstance<Item>(content);
}
else
{
item = (Item)ActivatorUtil.CreateInstance(m_Type);
item = m_Type.CreateInstance<Item>();
}
}
else if (m_Type.IsSubclassOf(typeofBaseDoor))
@ -430,11 +430,11 @@ namespace Server.Commands
}
}
item = (Item)ActivatorUtil.CreateInstance(m_Type, facing);
item = m_Type.CreateInstance<Item>(facing);
}
else
{
item = (Item)ActivatorUtil.CreateInstance(m_Type);
item = m_Type.CreateInstance<Item>();
}
}
catch (Exception e)

View file

@ -402,11 +402,11 @@ namespace Server.Commands
if (fill)
{
item = (Item)ActivatorUtil.CreateInstance(m_Type, content);
item = m_Type.CreateInstance<Item>(content);
}
else
{
item = (Item)ActivatorUtil.CreateInstance(m_Type);
item = m_Type.CreateInstance<Item>();
}
}
else if (m_Type.IsSubclassOf(typeofBaseDoor))
@ -427,11 +427,11 @@ namespace Server.Commands
}
}
item = (Item)ActivatorUtil.CreateInstance(m_Type, facing);
item = m_Type.CreateInstance<Item>(facing);
}
else
{
item = (Item)ActivatorUtil.CreateInstance(m_Type);
item = m_Type.CreateInstance<Item>();
}
}
catch (Exception e)

View file

@ -395,10 +395,11 @@ namespace Server.Engines.CannedEvil
{
try
{
prot.SendLocalizedMessage(1049368); // You have been rewarded for your dedication to Justice!
var scrollDupe = scroll.GetType().CreateEntityInstance<SpecialScroll>();
if (ActivatorUtil.CreateInstance(scroll.GetType()) is SpecialScroll scrollDupe)
if (scrollDupe != null)
{
prot.SendLocalizedMessage(1049368); // You have been rewarded for your dedication to Justice!
scrollDupe.Skill = scroll.Skill;
scrollDupe.Value = scroll.Value;
prot.AddToBackpack(scrollDupe);
@ -619,7 +620,7 @@ namespace Server.Engines.CannedEvil
try
{
Champion = ActivatorUtil.CreateInstance(ChampionSpawnInfo.GetInfo(m_Type).Champion) as Mobile;
Champion = ChampionSpawnInfo.GetInfo(m_Type).Champion.CreateInstance<Mobile>();
}
catch
{
@ -782,7 +783,7 @@ namespace Server.Engines.CannedEvil
{
try
{
return ActivatorUtil.CreateInstance(types.RandomElement()) as Mobile;
return types.RandomElement().CreateInstance<Mobile>();
}
catch
{

View file

@ -244,7 +244,7 @@ namespace Server.Engines.Craft
try
{
item = ActivatorUtil.CreateInstance(type) as Item;
item = type.CreateInstance<Item>();
}
catch
{
@ -1188,7 +1188,7 @@ namespace Server.Engines.Craft
}
else
{
item = ActivatorUtil.CreateInstance(ItemType) as Item;
item = ItemType.CreateInstance<Item>();
}
if (item != null)
@ -1428,27 +1428,22 @@ namespace Server.Engines.Craft
if (typeof(CustomCraft).IsAssignableFrom(m_CraftItem.ItemType))
{
CustomCraft cc = null;
try
{
cc = ActivatorUtil.CreateInstance(
m_CraftItem.ItemType,
m_CraftItem.ItemType.CreateInstance<CustomCraft>(
m_From,
m_CraftItem,
m_CraftSystem,
m_TypeRes,
m_Tool,
quality
) as CustomCraft;
)?.EndCraftAction();
}
catch
catch (Exception e)
{
// ignored
Console.WriteLine(e);
}
cc?.EndCraftAction();
return;
}

View file

@ -94,7 +94,7 @@ namespace Server.Engines.Craft
}
var resourceType = info.ResourceTypes[0];
var ingot = (Item)ActivatorUtil.CreateInstance(resourceType);
var ingot = resourceType.CreateInstance<Item>();
if (item is DragonBardingDeed || item is BaseArmor armor && armor.PlayerConstructed ||
item is BaseWeapon weapon && weapon.PlayerConstructed ||

View file

@ -37,7 +37,7 @@ namespace Server.Engines.Craft
public override int GumpTitleNumber => 1044009;
public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefInscription());
public static CraftSystem CraftSystem => m_CraftSystem ??= new DefInscription();
public override double GetChanceAtMin(CraftItem item) => 0.0;
@ -55,9 +55,9 @@ namespace Server.Engines.Craft
if (typeItem != null)
{
var o = ActivatorUtil.CreateInstance(typeItem);
var scroll = typeItem.CreateEntityInstance<SpellScroll>();
if (o is SpellScroll scroll)
if (scroll != null)
{
var hasSpell = Spellbook.Find(from, scroll.SpellID)?.HasSpell(scroll.SpellID) == true;
@ -65,11 +65,6 @@ namespace Server.Engines.Craft
return hasSpell ? 0 : 1042404; // null : You don't have that spell!
}
if (o is Item item)
{
item.Delete();
}
}
return 0;

View file

@ -340,16 +340,11 @@ namespace Server.Engines.Doom
return;
}
var obj = ActivatorUtil.CreateInstance(type);
var mob = type.CreateEntityInstance<Mobile>();
if (obj is Item item)
{
item.Delete();
}
else if (obj is Mobile mob)
if (mob != null)
{
mob.MoveToWorld(GetWorldLocation(), Map);
Creatures.Add(mob);
}
}

View file

@ -19,7 +19,7 @@ namespace Server.Factions
{
try
{
return ActivatorUtil.CreateInstance(Definition.Type) as BaseFactionGuard;
return Definition.Type.CreateInstance<BaseFactionGuard>();
}
catch
{

View file

@ -41,7 +41,7 @@ namespace Server.Factions
{
try
{
return ActivatorUtil.CreateInstance(type);
return type.CreateInstance<object>();
}
catch
{

View file

@ -19,7 +19,7 @@ namespace Server.Factions
{
try
{
return ActivatorUtil.CreateInstance(Definition.Type, town, faction) as BaseFactionVendor;
return Definition.Type.CreateInstance<BaseFactionVendor>(town, faction);
}
catch
{

View file

@ -55,7 +55,7 @@ namespace Server
{
if (weight < item.Weight)
{
var obj = item.Construct();
var obj = item.Type.CreateInstance<Item>();
if (obj != null)
{
@ -188,8 +188,6 @@ namespace Server
public int Weight { get; }
public Type Type { get; }
public Item Construct() => ActivatorUtil.CreateInstance(Type) as Item;
}
}
}

View file

@ -51,7 +51,7 @@ namespace Server.Factions
{
try
{
return ActivatorUtil.CreateInstance(TrapType, m_Faction, from) as BaseFactionTrap;
return TrapType.CreateInstance<BaseFactionTrap>(m_Faction, from);
}
catch
{

View file

@ -91,7 +91,7 @@ namespace Server.Factions
if (entry.Chance > Utility.Random(100))
{
releaseTime = DateTime.UtcNow + entry.Hold;
return (Spell)ActivatorUtil.CreateInstance(entry.Spell, mob, null);
return entry.Spell.CreateInstance<Spell>(mob, null);
}
}
@ -406,9 +406,9 @@ namespace Server.Factions
{
if (m_Mobile.Target != null)
m_Mobile.Target.Cancel( m_Mobile, TargetCancelType.Canceled );
new TeleportSpell( m_Mobile, null ).Cast();
m_Mobile.DebugSay( "I am stuck, I'm going to try teleporting away" );
}
else*/
@ -744,7 +744,7 @@ namespace Server.Factions
}
else if (types.Count == 1)
{
spell = ActivatorUtil.CreateInstance(types[0], m_Guard, null) as Spell;
spell = types[0].CreateInstance<Spell>(m_Guard, null);
}
}
else if (types.Count > 0)
@ -796,7 +796,7 @@ namespace Server.Factions
}
else if (types.Count == 1)
{
spell = (Spell)ActivatorUtil.CreateInstance(types[0], m_Guard, null);
spell = types[0].CreateInstance<Spell>(m_Guard, null);
}
}
}
@ -804,24 +804,14 @@ namespace Server.Factions
if (spell != null && m_Guard.HitsMax - m_Guard.Hits + 10 > Utility.Random(100))
{
Type type = null;
if (spell is GreaterHealSpell)
Type type = spell switch
{
type = typeof(BaseHealPotion);
}
else if (spell is CureSpell)
{
type = typeof(BaseCurePotion);
}
else if (spell is StrengthSpell)
{
type = typeof(BaseStrengthPotion);
}
else if (spell is AgilitySpell)
{
type = typeof(BaseAgilityPotion);
}
GreaterHealSpell _ => typeof(BaseHealPotion),
CureSpell _ => typeof(BaseCurePotion),
StrengthSpell _ => typeof(BaseStrengthPotion),
AgilitySpell _ => typeof(BaseAgilityPotion),
_ => null
};
if (type == typeof(BaseHealPotion) && !m_Guard.CanBeginAction(type))
{

View file

@ -268,7 +268,7 @@ namespace Server.Engines.Harvest
{
try
{
return ActivatorUtil.CreateInstance(type) as Item;
return type.CreateInstance<Item>();
}
catch
{

View file

@ -387,16 +387,17 @@ namespace Server.Engines.Harvest
if (res == resource && res.Types.Length >= 3)
{
var map = from.Map;
if (map == null)
{
return;
}
try
{
var map = from.Map;
if (map == null)
{
return;
}
if (ActivatorUtil.CreateInstance(res.Types[2], 25) is BaseCreature spawned)
var spawned = res.Types[2].CreateEntityInstance<BaseCreature>(25);
if (spawned != null)
{
var offset = Utility.Random(8) * 2;

View file

@ -69,7 +69,7 @@ namespace Server.Engines.MLQuests
try
{
quest = ActivatorUtil.CreateInstance(type) as MLQuest;
quest = type.CreateInstance<MLQuest>();
}
catch
{

View file

@ -49,17 +49,17 @@ namespace Server.Engines.MLQuests.Objectives
for (var i = 0; i < Amount; ++i)
{
if (!(ActivatorUtil.CreateInstance(Delivery) is Item item))
{
continue;
}
var item = Delivery.CreateEntityInstance<Item>();
delivery.Add(item);
if (item.Stackable && Amount > 1)
if (item != null)
{
item.Amount = Amount;
break;
delivery.Add(item);
if (item.Stackable && Amount > 1)
{
item.Amount = Amount;
break;
}
}
}

View file

@ -54,7 +54,7 @@ namespace Server.Engines.MLQuests.Rewards
try
{
spawnedItem = ActivatorUtil.CreateInstance(m_Type) as Item;
spawnedItem = m_Type.CreateInstance<Item>();
}
catch (Exception e)
{

View file

@ -310,18 +310,12 @@ namespace Server.Items
foreach (var taep in m_Table)
{
var contains = false;
for (var i = 0; !contains && i < taep.Tiles.Length; i += 2)
for (var i = 0; i < taep.Tiles.Length; i += 2)
{
contains = tileID >= taep.Tiles[i] && tileID <= taep.Tiles[i + 1];
}
if (contains)
{
var effect =
(GreenThornsEffect)ActivatorUtil.CreateInstance(taep.Effect, land.Location, from.Map, from);
return effect;
if (tileID >= taep.Tiles[i] && tileID <= taep.Tiles[i + 1])
{
return taep.Effect.CreateInstance<GreenThornsEffect>(land.Location, from.Map, from);
}
}
}

View file

@ -45,6 +45,6 @@ namespace Server.Engines.Plants
return null;
}
public Item CreateResource() => (Item)ActivatorUtil.CreateInstance(ResourceType);
public Item CreateResource() => ResourceType.CreateInstance<Item>();
}
}

View file

@ -3,13 +3,13 @@ using Server.Utilities;
namespace Server.Engines.Quests
{
public class QuestSerializer
public static class QuestSerializer
{
public static object Construct(Type type)
{
try
{
return ActivatorUtil.CreateInstance(type);
return type.CreateInstance<object>();
}
catch
{

View file

@ -563,153 +563,162 @@ namespace Server.Engines.Spawners
var type = AssemblyHandler.FindFirstTypeForName(entry.SpawnedName);
if (type != null)
if (type == null)
{
try
flags = EntryFlags.InvalidType;
return false;
}
try
{
IEntity entity = null;
string[] paramargs;
string[] propargs;
propargs = string.IsNullOrEmpty(entry.Properties)
? Array.Empty<string>()
: CommandSystem.Split(entry.Properties.Trim());
var props = FormatProperties(propargs);
var realProps = GetTypeProperties(type, props);
if (realProps == null)
{
object o = null;
string[] paramargs;
string[] propargs;
flags = EntryFlags.InvalidProps;
return false;
}
propargs = string.IsNullOrEmpty(entry.Properties)
? Array.Empty<string>()
: CommandSystem.Split(entry.Properties.Trim());
paramargs = string.IsNullOrEmpty(entry.Parameters)
? Array.Empty<string>()
: entry.Parameters.Trim().Split(' ');
var props = FormatProperties(propargs);
if (paramargs.Length == 0)
{
entity = type.CreateInstance<IEntity>(
ci => Add.IsConstructible(ci, AccessLevel.Developer)
);
}
else
{
var ctors = type.GetConstructors();
var realProps = GetTypeProperties(type, props);
if (realProps == null)
for (var i = 0; i < ctors.Length; ++i)
{
flags = EntryFlags.InvalidProps;
return false;
}
var ctor = ctors[i];
paramargs = string.IsNullOrEmpty(entry.Parameters)
? Array.Empty<string>()
: entry.Parameters.Trim().Split(' ');
if (paramargs.Length == 0)
{
o = ActivatorUtil.CreateInstance(type, ci => Add.IsConstructible(ci, AccessLevel.Developer));
}
else
{
var ctors = type.GetConstructors();
for (var i = 0; i < ctors.Length; ++i)
if (Add.IsConstructible(ctor, AccessLevel.Developer))
{
var ctor = ctors[i];
var paramList = ctor.GetParameters();
if (Add.IsConstructible(ctor, AccessLevel.Developer))
if (paramargs.Length == paramList.Length)
{
var paramList = ctor.GetParameters();
var paramValues = Add.ParseValues(paramList, paramargs);
if (paramargs.Length == paramList.Length)
if (paramValues != null)
{
var paramValues = Add.ParseValues(paramList, paramargs);
if (paramValues != null)
{
o = ctor.Invoke(paramValues);
break;
}
entity = ctor.Invoke(paramValues) as IEntity;
break;
}
}
}
}
for (var i = 0; i < realProps.Length; i++)
{
if (realProps[i] != null)
{
object toSet = null;
var result = Properties.ConstructFromString(
realProps[i].PropertyType,
o,
props[i, 1],
ref toSet
);
if (result == null)
{
realProps[i].SetValue(o, toSet, null);
}
else
{
flags = EntryFlags.InvalidProps;
(o as ISpawnable)?.Delete();
return false;
}
}
}
if (o is Mobile m)
{
Spawned.Add(m, entry);
entry.Spawned.Add(m);
var loc = m is BaseVendor ? Location : GetSpawnPosition(m, map);
m.OnBeforeSpawn(loc, map);
InvalidateProperties();
m.MoveToWorld(loc, map);
if (m is BaseCreature c)
{
var walkrange = GetWalkingRange();
c.RangeHome = walkrange >= 0 ? walkrange : m_HomeRange;
c.CurrentWayPoint = WayPoint;
if (m_Team > 0)
{
c.Team = m_Team;
}
c.Home = Location;
c.HomeMap = Map;
}
m.Spawner = this;
m.OnAfterSpawn();
}
else if (o is Item item)
{
Spawned.Add(item, entry);
entry.Spawned.Add(item);
var loc = GetSpawnPosition(item, map);
item.OnBeforeSpawn(loc, map);
item.MoveToWorld(loc, map);
item.Spawner = this;
item.OnAfterSpawn();
}
else
{
flags = EntryFlags.InvalidType | EntryFlags.InvalidParams;
return false;
}
}
catch (Exception e)
if (entity == null)
{
Console.WriteLine($"EXCEPTION CAUGHT: {Serial}");
Console.WriteLine(e);
flags = EntryFlags.InvalidType | EntryFlags.InvalidParams;
return false;
}
InvalidateProperties();
return true;
for (var i = 0; i < realProps.Length; i++)
{
if (realProps[i] != null)
{
object toSet = null;
var result = Properties.ConstructFromString(
realProps[i].PropertyType,
entity,
props[i, 1],
ref toSet
);
if (result == null)
{
realProps[i].SetValue(entity, toSet, null);
}
else
{
flags = EntryFlags.InvalidProps;
(entity as ISpawnable)?.Delete();
return false;
}
}
}
if (entity is Mobile m)
{
Spawned.Add(m, entry);
entry.Spawned.Add(m);
var loc = m is BaseVendor ? Location : GetSpawnPosition(m, map);
m.OnBeforeSpawn(loc, map);
InvalidateProperties();
m.MoveToWorld(loc, map);
if (m is BaseCreature c)
{
var walkrange = GetWalkingRange();
c.RangeHome = walkrange >= 0 ? walkrange : m_HomeRange;
c.CurrentWayPoint = WayPoint;
if (m_Team > 0)
{
c.Team = m_Team;
}
c.Home = Location;
c.HomeMap = Map;
}
m.Spawner = this;
m.OnAfterSpawn();
}
else if (entity is Item item)
{
Spawned.Add(item, entry);
entry.Spawned.Add(item);
var loc = GetSpawnPosition(item, map);
item.OnBeforeSpawn(loc, map);
item.MoveToWorld(loc, map);
item.Spawner = this;
item.OnAfterSpawn();
}
else
{
// Other IEntity types that might get created are simply not supported
flags = EntryFlags.InvalidType | EntryFlags.InvalidParams;
return false;
}
}
catch (Exception e)
{
Console.WriteLine($"EXCEPTION CAUGHT: {Serial}");
Console.WriteLine(e);
return false;
}
flags = EntryFlags.InvalidType;
return false;
InvalidateProperties();
return true;
}
public virtual int GetWalkingRange() => m_WalkingRange;

View file

@ -96,7 +96,7 @@ namespace Server.Engines.Spawners
try
{
var spawner = ActivatorUtil.CreateInstance(type, json, options) as ISpawner;
var spawner = type.CreateInstance<ISpawner>(json, options);
spawner!.MoveToWorld(location, map);
spawner!.Respawn();

View file

@ -157,47 +157,40 @@ namespace Server.Misc
var chance = A * Math.Pow(10, B * x);
if (chance > Utility.RandomDouble())
if (chance <= Utility.RandomDouble())
{
Item i = null;
return;
}
try
Item i;
try
{
i = m_LesserArtifacts[(int)DropEra - 1].RandomElement().CreateInstance<Item>();
}
catch
{
return;
}
// For your valor in combating the fallen beast, a special artifact has been bestowed on you.
pm.SendLocalizedMessage(1062317);
if (!pm.PlaceInBackpack(i))
{
if (pm.BankBox?.TryDropItem(killer, i, false) == true)
{
i = ActivatorUtil.CreateInstance(
m_LesserArtifacts[(int)DropEra - 1].RandomElement()
)
as
Item;
pm.SendLocalizedMessage(1079730); // The item has been placed into your bank box.
}
catch
else
{
// ignored
}
if (i != null)
{
pm.SendLocalizedMessage(
1062317
); // For your valor in combating the fallen beast, a special artifact has been bestowed on you.
if (!pm.PlaceInBackpack(i))
{
if (pm.BankBox?.TryDropItem(killer, i, false) == true)
{
pm.SendLocalizedMessage(1079730); // The item has been placed into your bank box.
}
else
{
pm.SendLocalizedMessage(
1072523
); // You find an artifact, but your backpack and bank are too full to hold it.
i.MoveToWorld(pm.Location, pm.Map);
}
}
pm.ToTTotalMonsterFame = 0;
// You find an artifact, but your backpack and bank are too full to hold it.
pm.SendLocalizedMessage(1072523);
i.MoveToWorld(pm.Location, pm.Map);
}
}
pm.ToTTotalMonsterFame = 0;
}
}
}
@ -594,7 +587,7 @@ namespace Server.Gumps
try
{
item = (Item)ActivatorUtil.CreateInstance(t.Type);
item = t.Type.CreateInstance<Item>();
}
catch
{

View file

@ -69,7 +69,7 @@ namespace Server.Engines.VeteranRewards
{
try
{
var item = ActivatorUtil.CreateInstance(ItemType, Args) as Item;
var item = ItemType.CreateInstance<Item>(Args);
if (item is IRewardItem rewardItem)
{

View file

@ -45,7 +45,7 @@ namespace Server.Gumps
{
try
{
item = ActivatorUtil.CreateInstance(type) as Item;
item = type.CreateInstance<Item>();
}
catch (Exception ex)
{

View file

@ -36,8 +36,8 @@ namespace Server.Events.Halloween
public static DateTime FinishHalloween => new DateTime(2012, 11, 15);
public static Item RandomGMBeggerItem =>
(Item)ActivatorUtil.CreateInstance(m_GMBeggarTreats.RandomElement());
m_GMBeggarTreats.RandomElement().CreateInstance<Item>();
public static Item RandomTreat => (Item)ActivatorUtil.CreateInstance(m_Treats.RandomElement());
public static Item RandomTreat => m_Treats.RandomElement().CreateInstance<Item>();
}
}

View file

@ -842,7 +842,7 @@ namespace Server.Items
try
{
item = ActivatorUtil.CreateInstance(m_Decorations[random]) as Item;
item = m_Decorations[random].CreateInstance<Item>();
}
catch
{

View file

@ -594,7 +594,7 @@ namespace Server.Items
{
try
{
var res = (Item)ActivatorUtil.CreateInstance(CraftResources.GetInfo(m_Resource).ResourceTypes[0]);
var res = CraftResources.GetInfo(m_Resource).ResourceTypes[0].CreateInstance<Item>();
ScissorHelper(from, res, PlayerConstructed ? item.Resources[0].Amount / 2 : 1);
return true;

View file

@ -237,7 +237,7 @@ namespace Server.Items
var resourceType = info.ResourceTypes?[0] ?? item.Resources[0].ItemType;
var res = (Item)ActivatorUtil.CreateInstance(resourceType);
var res = resourceType.CreateInstance<Item>();
ScissorHelper(from, res, PlayerConstructed ? item.Resources[0].Amount / 2 : 1);

View file

@ -88,8 +88,7 @@ namespace Server.Items
_ => 0.0
};
var resourceType = info.ResourceTypes[0];
var ingot = (Item)ActivatorUtil.CreateInstance(resourceType);
var ingot = info.ResourceTypes[0].CreateInstance<Item>();
if (item is DragonBardingDeed || item is BaseArmor armor && armor.PlayerConstructed ||
item is BaseWeapon weapon && weapon.PlayerConstructed ||

View file

@ -304,7 +304,7 @@ namespace Server.Items
if (level == 6 && Core.AOS)
{
cont.DropItem((Item)ActivatorUtil.CreateInstance(Artifacts.RandomElement()));
cont.DropItem(Artifacts.RandomElement().CreateInstance<Item>());
}
}

View file

@ -346,7 +346,7 @@ namespace Server.Items
public Item CreateInstance()
{
var item = (Item)ActivatorUtil.CreateInstance(Type);
var item = Type.CreateInstance<Item>();
if (Hue > 0)
{

View file

@ -245,7 +245,7 @@ namespace Server.Items
try
{
bc = (BaseCreature)ActivatorUtil.CreateInstance(m_SpawnTypes[level].RandomElement());
bc = m_SpawnTypes[level].RandomElement().CreateInstance<BaseCreature>();
}
catch
{

View file

@ -174,8 +174,7 @@ namespace Server.Items
if (NextSpawn < DateTime.UtcNow)
{
var map = Map;
var bc =
(BaseCreature)ActivatorUtil.CreateInstance(Creatures.RandomElement());
var bc = Creatures.RandomElement().CreateInstance<BaseCreature>();
var spawnLoc = GetSpawnPosition();

View file

@ -72,8 +72,14 @@ namespace Server.Items
bool ICommodity.IsDeedable => Core.ML;
public int OnCraft(
int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool,
CraftItem craftItem, int resHue
int quality,
bool makersMark,
Mobile from,
CraftSystem craftSystem,
Type typeRes,
BaseTool tool,
CraftItem craftItem,
int resHue
)
{
if (craftSystem is DefAlchemy)
@ -151,11 +157,11 @@ namespace Server.Items
{
if (this is BaseExplosionPotion && Amount > 1)
{
var pot = (BasePotion)ActivatorUtil.CreateInstance(GetType());
var pot = GetType().CreateInstance<BaseExplosionPotion>();
Amount--;
if (from.Backpack?.Deleted != false)
if (from.Backpack?.Deleted == false)
{
from.Backpack.DropItem(pot);
}

View file

@ -90,7 +90,7 @@ namespace Server.Items
{
if (weapon.UsesRemaining > 0)
{
var ammo = ActivatorUtil.CreateInstance(weapon.AmmoType, weapon.UsesRemaining) as Item;
var ammo = weapon.AmmoType.CreateInstance<Item>(weapon.UsesRemaining);
if (ammo is INinjaAmmo ninaAmmo)
{

View file

@ -451,18 +451,18 @@ namespace Server.Items
if (type != null)
{
object obj;
IEntity entity;
try
{
obj = ActivatorUtil.CreateInstance(type);
entity = type.CreateInstance<IEntity>();
}
catch
{
obj = null;
entity = null;
}
if (obj is Item item)
if (entity is Item item)
{
var count = 1;
@ -492,7 +492,7 @@ namespace Server.Items
if (i + 1 < count)
{
item = ActivatorUtil.CreateInstance(type) as Item;
item = type.CreateInstance<Item>();
}
}
@ -513,7 +513,7 @@ namespace Server.Items
from.SendLocalizedMessage(1074853, m_Summoner.Name.ToString()); // You have been given ~1_name~
}
}
else if (obj is BaseCreature mob)
else if (entity is BaseCreature mob)
{
if (m_Creature?.Deleted == false || from.Followers + mob.ControlSlots > from.FollowersMax)
{
@ -536,6 +536,10 @@ namespace Server.Items
m_Creature = mob;
}
else
{
entity?.Delete();
}
OnAfterUse(from);
}

View file

@ -780,7 +780,7 @@ namespace Server
try
{
return ActivatorUtil.CreateInstance(type) as Item;
return type.CreateInstance<Item>();
}
catch
{

View file

@ -1066,7 +1066,7 @@ namespace Server
}
else
{
item = ActivatorUtil.CreateInstance(Type) as Item;
item = Type.CreateInstance<Item>();
}
return item;

View file

@ -29,7 +29,9 @@ namespace Server
public static void GiveArtifactTo(Mobile m)
{
if (!(ActivatorUtil.CreateInstance(Artifacts.RandomElement()) is Item item))
var item = Artifacts.RandomElement().CreateInstance<Item>();
if (item == null)
{
return;
}

View file

@ -2820,17 +2820,9 @@ namespace Server.Mobiles
m_SpellDefense.Add(type);
}
public Spell GetAttackSpellRandom()
{
var type = m_SpellAttack.RandomElement();
return type == null ? null : ActivatorUtil.CreateInstance(type, this, null) as Spell;
}
public Spell GetAttackSpellRandom() => m_SpellAttack.RandomElement()?.CreateInstance<Spell>(this, null);
public Spell GetDefenseSpellRandom()
{
var type = m_SpellDefense.RandomElement();
return type == null ? null : ActivatorUtil.CreateInstance(type, this, null) as Spell;
}
public Spell GetDefenseSpellRandom() => m_SpellDefense.RandomElement()?.CreateInstance<Spell>(this, null);
public Spell GetSpellSpecific(Type type)
{
@ -2840,7 +2832,7 @@ namespace Server.Mobiles
{
if (m_SpellAttack[i] == type)
{
return ActivatorUtil.CreateInstance(type, this, null) as Spell;
return type.CreateInstance<Spell>(this, null);
}
}
@ -2848,7 +2840,7 @@ namespace Server.Mobiles
{
if (m_SpellDefense[i] == type)
{
return ActivatorUtil.CreateInstance(type, this, null) as Spell;
return type.CreateInstance<Spell>(this, null);
}
}

View file

@ -3838,7 +3838,7 @@ namespace Server.Mobiles
try
{
ammo = ActivatorUtil.CreateInstance(kvp.Key) as Item;
ammo = kvp.Key.CreateInstance<Item>();
}
catch
{

View file

@ -215,7 +215,7 @@ namespace Server.Mobiles
public static void GiveArtifactTo(Mobile m)
{
var item = (Item)ActivatorUtil.CreateInstance(Artifacts.RandomElement());
var item = Artifacts.RandomElement().CreateInstance<Item>();
if (m.AddToBackpack(item))
{

View file

@ -41,6 +41,6 @@ namespace Server.Mobiles
public override bool CanCacheDisplay => false;
public override IEntity GetEntity() => (IEntity)ActivatorUtil.CreateInstance(Type, m_Content);
public override IEntity GetEntity() => Type.CreateInstance<IEntity>(m_Content);
}
}

View file

@ -97,16 +97,7 @@ namespace Server.Mobiles
public int MaxAmount { get; set; }
// get a new instance of an object (we just bought it)
public virtual IEntity GetEntity()
{
if (Args == null || Args.Length == 0)
{
return (IEntity)ActivatorUtil.CreateInstance(Type);
}
return (IEntity)ActivatorUtil.CreateInstance(Type, Args);
// return (Item)ActivatorUtil.CreateInstance( m_Type );
}
public virtual IEntity GetEntity() => Type.CreateInstance<IEntity>(Args);
// Attempt to restock with item, (return true if restock successful)
public bool Restock(Item item, int amount) => false;

View file

@ -265,7 +265,7 @@ namespace Server.Mobiles
}
}
var g = ActivatorUtil.CreateInstance(buyInfo.GumpType, args) as Gump;
var g = buyInfo.GumpType.CreateInstance<Gump>(args);
m_From.SendGump(g);
}

View file

@ -1971,7 +1971,7 @@ namespace Server.Items
args = new object[] { from };
}
return ActivatorUtil.CreateInstance(Type, args) as BaseHouse;
return Type.CreateInstance<BaseHouse>(args);
}
catch
{

View file

@ -181,7 +181,7 @@ namespace Server.Regions
try
{
ActivatorUtil.CreateInstance(m_GuardType, m_GuardParams);
m_GuardType.CreateInstance<object>(m_GuardParams);
}
catch
{

View file

@ -91,7 +91,7 @@ namespace Server.Spells
try
{
spm = ActivatorUtil.CreateInstance(type) as SpecialMove;
spm = type.CreateInstance<SpecialMove>();
}
catch
{
@ -139,9 +139,9 @@ namespace Server.Spells
try
{
return (Spell)ActivatorUtil.CreateInstance(t, m_Params);
return t.CreateInstance<Spell>(m_Params);
}
catch (Exception e)
catch
{
// ignored
}
@ -167,7 +167,7 @@ namespace Server.Spells
try
{
return (Spell)ActivatorUtil.CreateInstance(t, m_Params);
return t.CreateInstance<Spell>(m_Params);
}
catch
{

View file

@ -68,7 +68,7 @@ namespace Server.Spells.Fifth
{
try
{
var creature = (BaseCreature)ActivatorUtil.CreateInstance(m_Types.RandomElement());
var creature = m_Types.RandomElement().CreateInstance<BaseCreature>();
// creature.ControlSlots = 2;

View file

@ -73,18 +73,16 @@ namespace Server.Spells.First
public Item Create()
{
Item item;
try
{
item = (Item)ActivatorUtil.CreateInstance(Type);
return Type.CreateInstance<Item>();
}
catch
{
item = null;
// ignored
}
return item;
return null;
}
}
}

View file

@ -343,7 +343,7 @@ namespace Server.Spells.Necromancy
try
{
summoned = ActivatorUtil.CreateInstance(toSummon) as Mobile;
summoned = toSummon.CreateInstance<Mobile>();
}
catch
{

View file

@ -181,7 +181,7 @@ namespace Server.Spells.Necromancy
{
try
{
var bc = (BaseCreature)ActivatorUtil.CreateInstance(entry.Type);
var bc = entry.Type.CreateInstance<BaseCreature>();
// TODO: Is this right?
bc.Skills.MagicResist.Base = m_From.Skills.MagicResist.Base;

View file

@ -42,7 +42,7 @@ namespace Server.Spells.Spellweaving
try
{
bc = ActivatorUtil.CreateInstance<T>();
bc = typeof(T).CreateInstance<BaseCreature>();
}
catch
{