Implement generic script loaders to greatly reduce code duplication

This commit is contained in:
hondacrx
2017-07-20 19:43:24 -04:00
parent 19220d29d9
commit 2db988576a
89 changed files with 28255 additions and 36473 deletions
+58 -5
View File
@@ -49,11 +49,12 @@ namespace Game.Scripting
{
InstanceMap instance = obj.GetMap().ToInstanceMap();
if (instance != null && instance.GetInstanceScript() != null)
if (instance.GetScriptId() == Global.ObjectMgr.GetScriptId(scriptName))
if (instance.GetScriptName() == scriptName)
return (T)Activator.CreateInstance(typeof(T), new object[] { obj });
return null;
}
public static T GetInstanceAI<T>(WorldObject obj) where T : class
{
InstanceMap instance = obj.GetMap().ToInstanceMap();
@@ -66,23 +67,57 @@ namespace Game.Scripting
string _name;
}
class GenericSpellScriptLoader<S> : SpellScriptLoader where S : SpellScript
{
public GenericSpellScriptLoader(string name, object[] args) : base(name)
{
_args = args;
}
public override SpellScript GetSpellScript() { return (S)Activator.CreateInstance(typeof(S), _args); }
object[] _args;
}
class GenericAuraScriptLoader<A> : AuraScriptLoader where A : AuraScript
{
public GenericAuraScriptLoader(string name, object[] args) : base(name)
{
_args = args;
}
public override AuraScript GetAuraScript() { return (A)Activator.CreateInstance(typeof(A), _args); }
object[] _args;
}
public class SpellScriptLoader : ScriptObject
{
public SpellScriptLoader(string name) : base(name)
{
Global.ScriptMgr.AddScript(this);
Global.ScriptMgr.AddScript<SpellScriptLoader>(this);
}
public override bool IsDatabaseBound() { return true; }
// Should return a fully valid SpellScript.
public virtual SpellScript GetSpellScript() { return null; }
}
public class AuraScriptLoader : ScriptObject
{
public AuraScriptLoader(string name) : base(name)
{
Global.ScriptMgr.AddScript<AuraScriptLoader>(this);
}
public override bool IsDatabaseBound() { return true; }
// Should return a fully valid AuraScript.
public virtual AuraScript GetAuraScript() { return null; }
}
class WorldScript : ScriptObject
public class WorldScript : ScriptObject
{
protected WorldScript(string name) : base(name)
{
@@ -113,7 +148,7 @@ namespace Game.Scripting
// Called when the world is actually shut down.
public virtual void OnShutdown() { }
}
public class FormulaScript : ScriptObject
{
public FormulaScript(string name) : base(name) { }
@@ -258,11 +293,29 @@ namespace Game.Scripting
public virtual void ModifySpellDamageTaken(Unit target, Unit attacker, ref int damage) { }
}
public class GenericCreatureScript<AI> : CreatureScript where AI : CreatureAI
{
public GenericCreatureScript(string name, object[] args) : base(name)
{
_args = args;
}
public override CreatureAI GetAI(Creature me)
{
if (me.GetInstanceScript() != null)
return GetInstanceAI<AI>(me);
else
return (AI)Activator.CreateInstance(typeof(AI), me, _args);
}
object[] _args;
}
public class CreatureScript : UnitScript
{
public CreatureScript(string name) : base(name, false)
{
Global.ScriptMgr.AddScript(this);
Global.ScriptMgr.AddScript<CreatureScript>(this);
}
public override bool IsDatabaseBound() { return true; }
+84 -10
View File
@@ -54,7 +54,7 @@ namespace Game.Scripting
Log.outInfo(LogFilter.ServerLoading, "Loading C# scripts");
FillSpellSummary();
//FillSpellSummary();
if (LoadScripts())
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} C# scripts in {1} ms", GetScriptCount(), Time.GetMSTimeDiffToNow(oldMSTime));
@@ -103,12 +103,62 @@ namespace Game.Scripting
foreach (var attribute in attributes)
{
if (!constructors.Any(p => p.GetParameters().Length == attribute.Args.Length))
var genericType = type;
string name = type.Name;
switch (type.BaseType.Name)
{
Log.outError(LogFilter.Scripts, "Type: {0} has ScriptAttribute that does not match paramter count: {1} Can't load script.", type.Name, attribute.Args.Length);
continue;
case "SpellScript":
genericType = typeof(GenericSpellScriptLoader<>).MakeGenericType(type);
name = name.Replace("_SpellScript", "");
break;
case "AuraScript":
genericType = typeof(GenericAuraScriptLoader<>).MakeGenericType(type);
name = name.Replace("_AuraScript", "");
break;
case "SpellScriptLoader":
case "AuraScriptLoader":
case "WorldScript":
case "FormulaScript":
case "WorldMapScript":
case "InstanceMapScript":
case "BattlegroundMapScript":
case "ItemScript":
case "UnitScript":
case "CreatureScript":
case "GameObjectScript":
case "AreaTriggerScript":
case "OutdoorPvPScript":
case "WeatherScript":
case "AuctionHouseScript":
case "ConditionScript":
case "VehicleScript":
case "DynamicObjectScript":
case "TransportScript":
case "AchievementCriteriaScript":
case "PlayerScript":
case "GuildScript":
case "GroupScript":
case "AreaTriggerEntityScript":
case "SceneScript":
if (!attribute.Name.IsEmpty())
name = attribute.Name;
if (attribute.Args.Empty())
Activator.CreateInstance(genericType);
else
Activator.CreateInstance(genericType, new object[] { name }.Combine(attribute.Args));
continue;
default:
genericType = typeof(GenericCreatureScript<>).MakeGenericType(type);
break;
}
Activator.CreateInstance(type, attribute.Args);
if (!attribute.Name.IsEmpty())
name = attribute.Name;
Activator.CreateInstance(genericType, name, attribute.Args);
}
}
}
@@ -389,7 +439,7 @@ namespace Game.Scripting
var scriptList = new List<AuraScript>();
var bounds = Global.ObjectMgr.GetSpellScriptsBounds(spellId);
var reg = GetScriptRegistry<SpellScriptLoader>();
var reg = GetScriptRegistry<AuraScriptLoader>();
if (reg == null)
return scriptList;
@@ -432,6 +482,26 @@ namespace Game.Scripting
return scriptDic;
}
public Dictionary<AuraScriptLoader, uint> CreateAuraScriptLoaders(uint spellId)
{
var scriptDic = new Dictionary<AuraScriptLoader, uint>();
var bounds = Global.ObjectMgr.GetSpellScriptsBounds(spellId);
var reg = GetScriptRegistry<AuraScriptLoader>();
if (reg == null)
return scriptDic;
foreach (var id in bounds)
{
var tmpscript = reg.GetScriptById(id);
if (tmpscript == null)
continue;
scriptDic.Add(tmpscript, id);
}
return scriptDic;
}
//WorldScript
public void OnOpenStateChange(bool open)
@@ -1299,7 +1369,7 @@ namespace Game.Scripting
return m_mPointMoveMap.LookupByKey(creatureEntry);
}
ScriptRegistry<T> GetScriptRegistry<T>() where T : ScriptObject
public ScriptRegistry<T> GetScriptRegistry<T>() where T : ScriptObject
{
if (ScriptStorage.ContainsKey(typeof(T)))
return (ScriptRegistry<T>)ScriptStorage[typeof(T)];
@@ -1312,8 +1382,8 @@ namespace Game.Scripting
Hashtable ScriptStorage = new Hashtable();
MultiMap<uint, ScriptPointMove> m_mPointMoveMap = new MultiMap<uint, ScriptPointMove>();
// creature entry + chain ID
// creature entry + chain ID
MultiMap<Tuple<uint, ushort>, SplineChainLink> m_mSplineChainsMap = new MultiMap<Tuple<uint, ushort>, SplineChainLink>(); // spline chains
}
@@ -1415,11 +1485,15 @@ namespace Game.Scripting
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class ScriptAttribute : Attribute
{
public ScriptAttribute(params object[] args)
//public ScriptAttribute() { }
public ScriptAttribute(string name="", params object[] args)
{
Name = name;
Args = args;
}
public string Name { get; private set; }
public object[] Args { get; private set; }
}
}