diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj index f5673e7c..dcd48884 100644 --- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj +++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj @@ -126,10 +126,7 @@ - - - diff --git a/FFXIVClassic Map Server/PacketProcessor.cs b/FFXIVClassic Map Server/PacketProcessor.cs index 90330659..5a175e6d 100644 --- a/FFXIVClassic Map Server/PacketProcessor.cs +++ b/FFXIVClassic Map Server/PacketProcessor.cs @@ -119,16 +119,16 @@ namespace FFXIVClassic_Map_Server case 0x0006: LangaugeCodePacket langCode = new LangaugeCodePacket(subpacket.data); session = mServer.AddSession(subpacket.header.targetId); - LuaEngine.OnBeginLogin(session.GetActor()); + + LuaEngine.GetInstance().CallLuaFunction(session.GetActor(), session.GetActor(), "onBeginLogin"); Server.GetWorldManager().DoZoneIn(session.GetActor(), true, 0x1); - LuaEngine.OnLogin(session.GetActor()); + LuaEngine.GetInstance().CallLuaFunction(session.GetActor(), session.GetActor(), "onLogin"); session.languageCode = langCode.languageCode; break; //Unknown - Happens a lot at login, then once every time player zones case 0x0007: - subpacket.DebugPrintSubPacket(); - ZoneInCompletePacket zoneInCompletePacket = new ZoneInCompletePacket(subpacket.data); - LuaEngine.OnZoneInDone(session.GetActor()); + //subpacket.DebugPrintSubPacket(); + ZoneInCompletePacket zoneInCompletePacket = new ZoneInCompletePacket(subpacket.data); break; //Update Position case 0x00CA: diff --git a/FFXIVClassic Map Server/Server.cs b/FFXIVClassic Map Server/Server.cs index b7ac9fa2..d39bcce0 100644 --- a/FFXIVClassic Map Server/Server.cs +++ b/FFXIVClassic Map Server/Server.cs @@ -23,8 +23,7 @@ namespace FFXIVClassic_Map_Server private Socket mServerSocket; private Dictionary mSessionList = new Dictionary(); - private LuaEngine mLuaEngine = new LuaEngine(); - + private static CommandProcessor mCommandProcessor = new CommandProcessor(); private static ZoneConnection mWorldConnection = new ZoneConnection(); private static WorldManager mWorldManager; diff --git a/FFXIVClassic Map Server/WorldManager.cs b/FFXIVClassic Map Server/WorldManager.cs index 2a1951d6..43fb8c8a 100644 --- a/FFXIVClassic Map Server/WorldManager.cs +++ b/FFXIVClassic Map Server/WorldManager.cs @@ -447,12 +447,12 @@ namespace FFXIVClassic_Map_Server player.SendMessage(0x20, "", "Doing Seamless Zone Change"); - LuaEngine.OnZoneIn(player); + LuaEngine.GetInstance().CallLuaFunction(player, newZone, "onZoneIn"); } //Adds a second zone to pull actors from. Used for an improved seamless zone change. public void MergeZones(Player player, uint mergedZoneId) - { + { //Add player to new zone and update Zone mergedZone = GetZone(mergedZoneId); @@ -467,7 +467,7 @@ namespace FFXIVClassic_Map_Server player.SendMessage(0x20, "", "Merging Zones"); - LuaEngine.OnZoneIn(player); + LuaEngine.GetInstance().CallLuaFunction(player, mergedZone, "onZoneIn"); } //Checks all seamless bounding boxes in region to see if player needs to merge or zonechange @@ -602,7 +602,7 @@ namespace FFXIVClassic_Map_Server if (newArea is PrivateArea) player.SendGameMessage(GetActor(), 34108, 0x20); - LuaEngine.OnZoneIn(player); + LuaEngine.GetInstance().CallLuaFunction(player, newArea, "onZoneIn"); } //Moves actor within zone to spawn position @@ -680,7 +680,7 @@ namespace FFXIVClassic_Map_Server player.playerSession.LockUpdates(false); - LuaEngine.OnZoneIn(player); + LuaEngine.GetInstance().CallLuaFunction(player, playerArea, "onZoneIn"); } public void ReloadZone(uint zoneId) diff --git a/FFXIVClassic Map Server/actors/chara/npc/Npc.cs b/FFXIVClassic Map Server/actors/chara/npc/Npc.cs index fac897d6..9f0fbede 100644 --- a/FFXIVClassic Map Server/actors/chara/npc/Npc.cs +++ b/FFXIVClassic Map Server/actors/chara/npc/Npc.cs @@ -88,7 +88,7 @@ namespace FFXIVClassic_Map_Server.Actors List lParams; Player player = Server.GetWorldManager().GetPCInWorld(playerActorId); - lParams = DoActorInit(player); + lParams = LuaEngine.GetInstance().CallLuaFunctionForReturn(player, this, "init"); if (uniqueIdentifier.Equals("1")) { @@ -372,159 +372,14 @@ namespace FFXIVClassic_Map_Server.Actors this.eventConditions = conditions; } - public List DoActorInit(Player player) + public void DoOnActorSpawn(Player player) { - LuaScript parent = null, child = null; - - if (File.Exists("./scripts/base/" + classPath + ".lua")) - parent = LuaEngine.LoadScript("./scripts/base/" + classPath + ".lua"); - - if (zone is PrivateArea) - { - if (File.Exists(String.Format("./scripts/unique/{0}/privatearea/{1}/{2}/{3}.lua", zone.zoneName, ((PrivateArea)zone).GetPrivateAreaName(), className, uniqueIdentifier))) - child = LuaEngine.LoadScript(String.Format("./scripts/unique/{0}/privatearea/{1}/{2}/{3}.lua", zone.zoneName, ((PrivateArea)zone).GetPrivateAreaName(), className, uniqueIdentifier)); - } - else - { - if (File.Exists(String.Format("./scripts/unique/{0}/{1}/{2}.lua", zone.zoneName, className, uniqueIdentifier))) - child = LuaEngine.LoadScript(String.Format("./scripts/unique/{0}/{1}/{2}.lua", zone.zoneName, className, uniqueIdentifier)); - } - - if (parent == null && child == null) - { - LuaEngine.SendError(player, String.Format("ERROR: Could not find script for actor {0}.", GetName())); - return null; - } - - DynValue result; - - if (child != null && child.Globals["init"] != null) - result = child.Call(child.Globals["init"], this); - else if (parent != null && parent.Globals["init"] != null) - result = parent.Call(parent.Globals["init"], this); - else - return null; - - List lparams = LuaUtils.CreateLuaParamList(result); - return lparams; - } - - public Coroutine GetEventStartCoroutine(Player player) - { - LuaScript parent = null, child = null; - - if (File.Exists("./scripts/base/" + classPath + ".lua")) - parent = LuaEngine.LoadScript("./scripts/base/" + classPath + ".lua"); - if (zone is PrivateArea) - { - if (File.Exists(String.Format("./scripts/unique/{0}/privatearea/{1}/{2}/{3}.lua", zone.zoneName, ((PrivateArea)zone).GetPrivateAreaName(), className, uniqueIdentifier))) - child = LuaEngine.LoadScript(String.Format("./scripts/unique/{0}/privatearea/{1}/{2}/{3}.lua", zone.zoneName, ((PrivateArea)zone).GetPrivateAreaName(), className, uniqueIdentifier)); - } - else - { - if (File.Exists(String.Format("./scripts/unique/{0}/{1}/{2}.lua", zone.zoneName, className, uniqueIdentifier))) - child = LuaEngine.LoadScript(String.Format("./scripts/unique/{0}/{1}/{2}.lua", zone.zoneName, className, uniqueIdentifier)); - } - - if (parent == null && child == null) - { - LuaEngine.SendError(player, String.Format("ERROR: Could not find script for actor {0}.", GetName())); - return null; - } - - //Run Script - Coroutine coroutine; - - if (child != null && !child.Globals.Get("onEventStarted").IsNil()) - coroutine = child.CreateCoroutine(child.Globals["onEventStarted"]).Coroutine; - else if (parent.Globals.Get("onEventStarted") != null && !parent.Globals.Get("onEventStarted").IsNil()) - coroutine = parent.CreateCoroutine(parent.Globals["onEventStarted"]).Coroutine; - else - return null; - - return coroutine; - } - - public void DoEventUpdate(Player player, EventUpdatePacket eventUpdate) - { - LuaScript parent = null, child = null; - - if (File.Exists("./scripts/base/" + classPath + ".lua")) - parent = LuaEngine.LoadScript("./scripts/base/" + classPath + ".lua"); - if (File.Exists(String.Format("./scripts/unique/{0}/{1}/{2}.lua", zone.zoneName, className, uniqueIdentifier))) - child = LuaEngine.LoadScript(String.Format("./scripts/unique/{0}/{1}/{2}.lua", zone.zoneName, className, uniqueIdentifier)); - - if (parent == null && child == null) - { - //LuaEngine.SendError(player, String.Format("ERROR: Could not find script for actor {0}.", GetName())); - return; - } - - //Have to do this to combine LuaParams - List objects = new List(); - objects.Add(player); - objects.Add(this); - objects.Add(eventUpdate.val2); - objects.AddRange(LuaUtils.CreateLuaParamObjectList(eventUpdate.luaParams)); - - //Run Script - DynValue result; - - if (child != null && !child.Globals.Get("onEventUpdate").IsNil()) - result = child.Call(child.Globals["onEventUpdate"], objects.ToArray()); - else if (!parent.Globals.Get("onEventUpdate").IsNil()) - result = parent.Call(parent.Globals["onEventUpdate"], objects.ToArray()); - else - return; - - } - - internal void DoOnActorSpawn(Player player) - { - LuaScript parent = null, child = null; - - if (File.Exists("./scripts/base/" + classPath + ".lua")) - parent = LuaEngine.LoadScript("./scripts/base/" + classPath + ".lua"); - if (File.Exists(String.Format("./scripts/unique/{0}/{1}/{2}.lua", zone.zoneName, className, uniqueIdentifier))) - child = LuaEngine.LoadScript(String.Format("./scripts/unique/{0}/{1}/{2}.lua", zone.zoneName, className, uniqueIdentifier)); - - if (parent == null && child == null) - { - //LuaEngine.SendError(player, String.Format("ERROR: Could not find script for actor {0}.", GetName())); - return; - } - - //Run Script - if (child != null && child.Globals["onSpawn"] != null) - child.Call(child.Globals["onSpawn"], player, this); - else if (parent != null && parent.Globals["onSpawn"] != null) - parent.Call(parent.Globals["onSpawn"], player, this); - else - return; + LuaEngine.GetInstance().CallLuaFunction(player, this, "onSpawn"); } public void Update(double deltaTime) { - LuaScript parent = null, child = null; - - if (File.Exists("./scripts/base/" + classPath + ".lua")) - parent = LuaEngine.LoadScript("./scripts/base/" + classPath + ".lua"); - if (File.Exists(String.Format("./scripts/unique/{0}/{1}/{2}.lua", zone.zoneName, className, uniqueIdentifier))) - child = LuaEngine.LoadScript(String.Format("./scripts/unique/{0}/{1}/{2}.lua", zone.zoneName, className, uniqueIdentifier)); - - if (parent == null && child == null) - { - //LuaEngine.SendError(player, String.Format("ERROR: Could not find script for actor {0}.", GetName())); - return; - } - - //Run Script - if (child != null && child.Globals["onThink"] != null) - child.Call(child.Globals["onThink"], this, deltaTime); - else if (parent != null && parent.Globals["onThink"] != null) - parent.Call(parent.Globals["onThink"], this, deltaTime); - else - return; + LuaEngine.GetInstance().CallLuaFunction(null, this, "onUpdate", deltaTime); } //A party member list packet came, set the party diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index e89b79c0..e0796018 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -1226,98 +1226,12 @@ namespace FFXIVClassic_Map_Server.Actors public void StartEvent(Actor owner, EventStartPacket start) { - //Have to do this to combine LuaParams - List objects = new List(); - objects.Add(this); - objects.Add(owner); - objects.Add(start.triggerName); - - if (start.luaParams != null) - objects.AddRange(LuaUtils.CreateLuaParamObjectList(start.luaParams)); - - if (owner is Npc) - { - currentEventRunning = ((Npc)owner).GetEventStartCoroutine(this); - - if (currentEventRunning != null) - { - try - { - currentEventRunning.Resume(objects.ToArray()); - } - catch (ScriptRuntimeException e) - { - Program.Log.Error("[LUA] {0}", e.DecoratedMessage); - EndEvent(); - } - } - else - { - EndEvent(); - } - } - else if (owner is Director) - { - currentEventRunning = ((Director)owner).GetEventStartCoroutine(this); - - if (currentEventRunning != null) - { - try - { - currentEventRunning.Resume(objects.ToArray()); - } - catch (ScriptRuntimeException e) - { - Program.Log.Error("[LUA] {0}", e.DecoratedMessage); - EndEvent(); - } - } - else - { - EndEvent(); - } - } - else - { - currentEventRunning = LuaEngine.DoActorOnEventStarted(this, owner, start); - - if (currentEventRunning != null) - { - try - { - currentEventRunning.Resume(objects.ToArray()); - } - catch (ScriptRuntimeException e) - { - Program.Log.Error("[LUA] {0}", e.DecoratedMessage); - EndEvent(); - } - } - else - { - EndEvent(); - } - } - + LuaEngine.GetInstance().EventStarted(this, owner, start); } public void UpdateEvent(EventUpdatePacket update) { - if (currentEventRunning == null) - return; - - if (currentEventRunning.State == CoroutineState.Suspended) - { - try - { - currentEventRunning.Resume(LuaUtils.CreateLuaParamObjectList(update.luaParams)); - } - catch (ScriptRuntimeException e) - { - Program.Log.Error("[LUA] {0}", e.DecoratedMessage); - EndEvent(); - } - } + LuaEngine.GetInstance().OnEventUpdate(this); } public void KickEvent(Actor actor, string conditionName, params object[] parameters) @@ -1455,7 +1369,7 @@ namespace FFXIVClassic_Map_Server.Actors public void Update(double delta) { - LuaEngine.OnPlayerUpdate(this, delta); + LuaEngine.GetInstance().CallLuaFunction(this, this, "OnUpdate", delta); } } diff --git a/FFXIVClassic Map Server/actors/director/Director.cs b/FFXIVClassic Map Server/actors/director/Director.cs index e120a284..e1011a43 100644 --- a/FFXIVClassic Map Server/actors/director/Director.cs +++ b/FFXIVClassic Map Server/actors/director/Director.cs @@ -70,39 +70,23 @@ namespace FFXIVClassic_Map_Server.actors.director public void OnTalkEvent(Player player, Npc npc) { - if (File.Exists("./scripts/directors/" + directorScriptPath + ".lua")) - { - LuaScript script = LuaEngine.LoadScript("./scripts/directors/" + directorScriptPath + ".lua"); - - if (script == null) - return; - - //Run Script - if (!script.Globals.Get("onTalkEvent").IsNil()) - script.Call(script.Globals["onTalkEvent"], player, npc); - } - else - { - LuaEngine.SendError(player, String.Format("ERROR: Could not find script for director {0}.", GetName())); - } + LuaEngine.GetInstance().CallLuaFunction(player, this, "onTalkEvent", npc); } public void OnCommandEvent(Player player, Command command) { - if (File.Exists("./scripts/directors/" + directorScriptPath + ".lua")) - { - LuaScript script = LuaEngine.LoadScript("./scripts/directors/" + directorScriptPath + ".lua"); + LuaEngine.GetInstance().CallLuaFunction(player, this, "onCommandEvent", command); + } - if (script == null) - return; - - //Run Script - if (!script.Globals.Get("onCommandEvent").IsNil()) - script.Call(script.Globals["onCommandEvent"], player, command); - } - else + public void DoActorInit(string directorPath) + { + List lparams = LuaEngine.GetInstance().CallLuaFunctionForReturn(null, this, "init"); + + if (lparams.Count == 1 && lparams[0].value is string) { - LuaEngine.SendError(player, String.Format("ERROR: Could not find script for director {0}.", GetName())); + classPath = (string)lparams[0].value; + className = classPath.Substring(classPath.LastIndexOf("/") + 1); + isCreated = true; } } @@ -126,52 +110,6 @@ namespace FFXIVClassic_Map_Server.actors.director Server.GetWorldManager().GetZone(zoneId).DeleteDirector(actorId); } - public void DoActorInit(string directorPath) - { - LuaScript script = null; - - if (File.Exists("./scripts/directors/" + directorPath + ".lua")) - script = LuaEngine.LoadScript("./scripts/directors/" + directorPath + ".lua"); - else - return; - - DynValue result; - - if (script != null && script.Globals["init"] != null) - result = script.Call(script.Globals["init"], this); - else - return; - - List lparams = LuaUtils.CreateLuaParamList(result); - - if (lparams.Count == 1 && lparams[0].value is string) - { - classPath = (string)lparams[0].value; - className = classPath.Substring(classPath.LastIndexOf("/") + 1); - isCreated = true; - } - } - - public Coroutine GetEventStartCoroutine(Player player) - { - LuaScript script = null; - - if (File.Exists("./scripts/directors/" + directorScriptPath + ".lua")) - script = LuaEngine.LoadScript("./scripts/directors/" + directorScriptPath + ".lua"); - else - return null; - - //Run Script - Coroutine coroutine; - - if (script != null && !script.Globals.Get("onEventStarted").IsNil()) - coroutine = script.CreateCoroutine(script.Globals["onEventStarted"]).Coroutine; - else - return null; - - return coroutine; - } - public bool IsCreated() { return isCreated; diff --git a/FFXIVClassic Map Server/lua/LuaEngine.cs b/FFXIVClassic Map Server/lua/LuaEngine.cs index 331af8cc..e03f9c49 100644 --- a/FFXIVClassic Map Server/lua/LuaEngine.cs +++ b/FFXIVClassic Map Server/lua/LuaEngine.cs @@ -14,6 +14,8 @@ using System.IO; using System.Diagnostics; using FFXIVClassic_Map_Server.lua; using FFXIVClassic.Common; +using FFXIVClassic_Map_Server.actors.area; +using System.Threading; namespace FFXIVClassic_Map_Server.lua { @@ -23,216 +25,285 @@ namespace FFXIVClassic_Map_Server.lua const string FILEPATH_ZONE = "./scripts/unique/{0}/zone.lua"; const string FILEPATH_COMMANDS = "./scripts/commands/{0}.lua"; const string FILEPATH_DIRECTORS = "./scripts/directors/{0}.lua"; - const string FILEPATH_NPCS = "./scripts/zones/{0}/npcs/{1}.lua"; + const string FILEPATH_NPCS = "./scripts/unique/{0}/{1}/{2}.lua"; - public LuaEngine() + private static LuaEngine mThisEngine; + private Dictionary mSleepingOnTime = new Dictionary(); + private Dictionary> mSleepingOnSignal = new Dictionary>(); + private Dictionary mSleepingOnPlayerEvent = new Dictionary(); + + private Timer luaTimer; + + + private LuaEngine() { UserData.RegistrationPolicy = InteropRegistrationPolicy.Automatic; + + luaTimer = new Timer(new TimerCallback(PulseSleepingOnTime), + null, TimeSpan.Zero, TimeSpan.FromMilliseconds(50)); } - public static List DoActorInstantiate(Player player, Actor target) + public static LuaEngine GetInstance() { - string luaPath; + if (mThisEngine == null) + mThisEngine = new LuaEngine(); - if (target is Npc) + return mThisEngine; + } + + public void AddWaitCoroutine(Coroutine coroutine, float seconds) + { + ulong time = Utils.MilisUnixTimeStampUTC() + (ulong)(seconds * 1000); + mSleepingOnTime.Add(coroutine, time); + } + + public void AddWaitSignalCoroutine(Coroutine coroutine, string signal) + { + if (!mSleepingOnSignal.ContainsKey(signal)) + mSleepingOnSignal.Add(signal, new List()); + mSleepingOnSignal[signal].Add(coroutine); + } + + public void AddWaitEventCoroutine(Player player, Coroutine coroutine) + { + if (!mSleepingOnPlayerEvent.ContainsKey(player.actorId)) + mSleepingOnPlayerEvent.Add(player.actorId, coroutine); + } + + public void PulseSleepingOnTime(object state) + { + ulong currentTime = Utils.MilisUnixTimeStampUTC(); + List mToAwake = new List(); + + foreach (KeyValuePair entry in mSleepingOnTime) { - luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName()); - if (File.Exists(luaPath)) - { - LuaScript script = LoadScript(luaPath); + if (entry.Value <= currentTime) + mToAwake.Add(entry.Key); + } - if (script == null) - return null; + foreach (Coroutine key in mToAwake) + { + mSleepingOnTime.Remove(key); + DynValue value = key.Resume(); + ResolveResume(key, value); + } + } - DynValue result = script.Call(script.Globals["init"], target); + public void OnSignal(string signal) + { + List mToAwake = new List(); + + if (mSleepingOnSignal.ContainsKey(signal)) + { + mToAwake.AddRange(mSleepingOnSignal[signal]); + mSleepingOnSignal.Remove(signal); + } + + foreach (Coroutine key in mToAwake) + { + DynValue value = key.Resume(); + ResolveResume(key, value); + } + } + + public void OnEventUpdate(Player player) + { + if (mSleepingOnPlayerEvent.ContainsKey(player.actorId)) + { + mSleepingOnPlayerEvent[player.actorId].Resume(); + mSleepingOnPlayerEvent.Remove(player.actorId); + } + else + player.EndEvent(); + } + + private static string GetScriptPath(Actor target) + { + if (target is Player) + { + return String.Format(FILEPATH_PLAYER); + } + else if (target is Npc) + { + return null; + } + else if (target is Command) + { + return String.Format(FILEPATH_COMMANDS, target.GetName()); + } + else if (target is Director) + { + return String.Format(FILEPATH_DIRECTORS, ((Director)target).GetScriptPath()); + } + else if (target is Area) + { + return String.Format(FILEPATH_ZONE, ((Zone)target).zoneName); + } + else + return ""; + } + + private List CallLuaFunctionNpcForReturn(Player player, Npc target, string funcName, params object[] args) + { + LuaScript parent = null, child = null; + + if (File.Exists("./scripts/base/" + target.classPath + ".lua")) + parent = LuaEngine.LoadScript("./scripts/base/" + target.classPath + ".lua"); + + Area area = target.zone; + if (area is PrivateArea) + { + if (File.Exists(String.Format("./scripts/unique/{0}/privatearea/{1}/{2}/{3}.lua", area.zoneName, ((PrivateArea)area).GetPrivateAreaName(), target.className, target.GetUniqueId()))) + child = LuaEngine.LoadScript(String.Format("./scripts/unique/{0}/privatearea/{1}/{2}/{3}.lua", area.zoneName, ((PrivateArea)area).GetPrivateAreaName(), target.className, target.GetUniqueId())); + } + else + { + if (File.Exists(String.Format("./scripts/unique/{0}/{1}/{2}.lua", area.zoneName, target.className, target.GetUniqueId()))) + child = LuaEngine.LoadScript(String.Format("./scripts/unique/{0}/{1}/{2}.lua", area.zoneName, target.className, target.GetUniqueId())); + } + + if (parent == null && child == null) + { + LuaEngine.SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName())); + } + + //Run Script + DynValue result; + + if (child != null && child.Globals[funcName] != null) + result = child.Call(child.Globals[funcName], this); + else if (parent != null && parent.Globals[funcName] != null) + result = parent.Call(parent.Globals[funcName], this); + else + return null; + + List lparams = LuaUtils.CreateLuaParamList(result); + return lparams; + } + + private void CallLuaFunctionNpc(Player player, Npc target, string funcName, params object[] args) + { + LuaScript parent = null, child = null; + + if (File.Exists("./scripts/base/" + target.classPath + ".lua")) + parent = LuaEngine.LoadScript("./scripts/base/" + target.classPath + ".lua"); + + Area area = target.zone; + if (area is PrivateArea) + { + if (File.Exists(String.Format("./scripts/unique/{0}/privatearea/{1}/{2}/{3}.lua", area.zoneName, ((PrivateArea)area).GetPrivateAreaName(), target.className, target.GetUniqueId()))) + child = LuaEngine.LoadScript(String.Format("./scripts/unique/{0}/privatearea/{1}/{2}/{3}.lua", area.zoneName, ((PrivateArea)area).GetPrivateAreaName(), target.className, target.GetUniqueId())); + } + else + { + if (File.Exists(String.Format("./scripts/unique/{0}/{1}/{2}.lua", area.zoneName, target.className, target.GetUniqueId()))) + child = LuaEngine.LoadScript(String.Format("./scripts/unique/{0}/{1}/{2}.lua", area.zoneName, target.className, target.GetUniqueId())); + } + + if (parent == null && child == null) + { + LuaEngine.SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName())); + } + + //Run Script + Coroutine coroutine = null; + + if (child != null && !child.Globals.Get(funcName).IsNil()) + coroutine = child.CreateCoroutine(child.Globals[funcName]).Coroutine; + else if (parent.Globals.Get(funcName) != null && !parent.Globals.Get(funcName).IsNil()) + coroutine = parent.CreateCoroutine(parent.Globals[funcName]).Coroutine; + + if (coroutine != null) + { + DynValue value = coroutine.Resume(); + ResolveResume(coroutine, value); + } + } + + public List CallLuaFunctionForReturn(Player player, Actor target, string funcName, params object[] args) + { + //Need a seperate case for NPCs cause that child/parent thing. + if (target is Npc) + return CallLuaFunctionNpcForReturn(player, (Npc)target, funcName, args); + + string luaPath = GetScriptPath(target); + LuaScript script = LoadScript(luaPath); + if (script != null) + { + if (!script.Globals.Get(funcName).IsNil()) + { + //Run Script + DynValue result = script.Call(script.Globals[funcName], this); List lparams = LuaUtils.CreateLuaParamList(result); return lparams; } else { - SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName())); - return null; + SendError(player, String.Format("ERROR: Could not find function '{0}' for actor {1}.", funcName, target.GetName())); } } - + else + { + SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName())); + } return null; } - public static Coroutine DoActorOnEventStarted(Player player, Actor target, EventStartPacket eventStart) - { - string luaPath; - - if (target is Command) - { - luaPath = String.Format(FILEPATH_COMMANDS, target.GetName()); - } - else if (target is Director) - { - luaPath = String.Format(FILEPATH_DIRECTORS, target.GetName()); - } - else - luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName()); - - if (File.Exists(luaPath)) - { - LuaScript script = LoadScript(luaPath); - - if (script == null) - return null; - - if (!script.Globals.Get("onEventStarted").IsNil()) - return script.CreateCoroutine(script.Globals["onEventStarted"]).Coroutine; - else - return null; - } - else - { - SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName())); - return null; - } - - } - - public static void DoActorOnSpawn(Player player, Npc target) - { - string luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName()); - - if (File.Exists(luaPath)) - { - LuaScript script = LoadScript(luaPath); - - if (script == null) - return; - - //Run Script - if (!script.Globals.Get("onSpawn").IsNil()) - script.Call(script.Globals["onSpawn"], player, target); - } - else - { - SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName())); - } - - } - - public static void DoActorOnEventUpdated(Player player, Actor target, EventUpdatePacket eventUpdate) + public void CallLuaFunction(Player player, Actor target, string funcName, params object[] args) { + //Need a seperate case for NPCs cause that child/parent thing. if (target is Npc) + CallLuaFunctionNpc(player, (Npc)target, funcName, args); + + string luaPath = GetScriptPath(target); + LuaScript script = LoadScript(luaPath); + if (script != null) { - ((Npc)target).DoEventUpdate(player, eventUpdate); - return; - } - - string luaPath; - - if (target is Command) - luaPath = String.Format(FILEPATH_COMMANDS, target.GetName()); - else if (target is Director) - luaPath = String.Format(FILEPATH_DIRECTORS, target.GetName()); - else - luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName()); - - if (File.Exists(luaPath)) - { - LuaScript script = LoadScript(luaPath); - - if (script == null) - return; - - //Have to Do this to combine LuaParams - List objects = new List(); - objects.Add(player); - objects.Add(target); - objects.Add(eventUpdate.val2); - objects.AddRange(LuaUtils.CreateLuaParamObjectList(eventUpdate.luaParams)); - - //Run Script - if (!script.Globals.Get("onEventUpdate").IsNil()) - script.Call(script.Globals["onEventUpdate"], objects.ToArray()); + if (!script.Globals.Get(funcName).IsNil()) + { + Coroutine coroutine = script.CreateCoroutine(script.Globals[funcName]).Coroutine; + coroutine.Resume(player, target, args); + } + else + { + SendError(player, String.Format("ERROR: Could not find function '{0}' for actor {1}.", funcName, target.GetName())); + } } else { SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName())); - } + } } - public static void OnZoneIn(Player player) + public void EventStarted(Player player, Actor target, EventStartPacket eventStart) { - string luaPath = String.Format(FILEPATH_ZONE, player.GetZone().zoneName); - - if (File.Exists(luaPath)) - { - LuaScript script = LoadScript(luaPath); - - if (script == null) - return; - - //Run Script - if (!script.Globals.Get("onZoneIn").IsNil()) - script.Call(script.Globals["onZoneIn"], player.GetZone(), player); - } + CallLuaFunction(player, target, "onEventStarted"); } - public static void OnZoneInDone(Player player) + private DynValue ResolveResume(Coroutine coroutine, DynValue value) { - string luaPath = String.Format(FILEPATH_ZONE, player.GetZone().zoneName); + if (value == null || value.IsVoid()) + return value; - if (File.Exists(luaPath)) + if (value.Tuple != null && value.Tuple.Length >= 1 && value.Tuple[0].String != null) { - LuaScript script = LoadScript(luaPath); - - if (script == null) - return; - - //Run Script - if (!script.Globals.Get("onZoneInDone").IsNil()) - script.Call(script.Globals["onZoneInDone"], player.GetZone(), player); + switch (value.Tuple[0].String) + { + case "_WAIT_TIME": + GetInstance().AddWaitCoroutine(coroutine, (float)value.Tuple[1].Number); + break; + case "_WAIT_SIGNAL": + GetInstance().AddWaitSignalCoroutine(coroutine, (string)value.Tuple[1].String); + break; + case "_WAIT_EVENT": + GetInstance().AddWaitEventCoroutine(new Player(null, 0), coroutine); + break; + default: + return value; + } } - } - public static void OnBeginLogin(Player player) - { - if (File.Exists(FILEPATH_PLAYER)) - { - LuaScript script = LoadScript(FILEPATH_PLAYER); - - if (script == null) - return; - - //Run Script - if (!script.Globals.Get("onBeginLogin").IsNil()) - script.Call(script.Globals["onBeginLogin"], player); - } - } - - public static void OnLogin(Player player) - { - if (File.Exists(FILEPATH_PLAYER)) - { - LuaScript script = LoadScript(FILEPATH_PLAYER); - - if (script == null) - return; - - //Run Script - if (!script.Globals.Get("onLogin").IsNil()) - script.Call(script.Globals["onLogin"], player); - } - } - - public static void OnPlayerUpdate(Player player, double delta) - { - if (File.Exists(FILEPATH_PLAYER)) - { - LuaScript script = LoadScript(FILEPATH_PLAYER); - - if (script == null) - return; - - //Run Script - if (!script.Globals.Get("onUpdate").IsNil()) - script.Call(script.Globals["onUpdate"], player); - } + return value; } #region RunGMCommand @@ -361,8 +432,12 @@ namespace FFXIVClassic_Map_Server.lua // push the arg count too LuaParam.Insert(1, i); - // run the script - script.Call(script.Globals["onTrigger"], LuaParam.ToArray()); + // run the script + //script.Call(script.Globals["onTrigger"], LuaParam.ToArray()); + + Coroutine coroutine = script.CreateCoroutine(script.Globals["onTrigger"]).Coroutine; + DynValue value = coroutine.Resume(player, LuaParam.ToArray()); + GetInstance().ResolveResume(coroutine, value); return; } } @@ -371,13 +446,16 @@ namespace FFXIVClassic_Map_Server.lua } #endregion - public static LuaScript LoadScript(string filename) + public static LuaScript LoadScript(string path) { + if (!File.Exists(path)) + return null; + LuaScript script = LoadGlobals(); try { - script.DoFile(filename); + script.DoFile(path); } catch (SyntaxErrorException e) { @@ -398,13 +476,16 @@ namespace FFXIVClassic_Map_Server.lua script.Globals["GetStaticActorById"] = (Func)Server.GetStaticActors; script.Globals["GetWorldMaster"] = (Func)Server.GetWorldManager().GetActor; script.Globals["GetItemGamedata"] = (Func)Server.GetItemGamedata; + script.Globals["GetLuaInstance"] = (Func)LuaEngine.GetInstance; script.Options.DebugPrint = s => { Program.Log.Debug(s); }; return script; } - public static void SendError(Player player, string message) + private static void SendError(Player player, string message) { + if (player == null) + return; List SendError = new List(); SendError.Add(EndEventPacket.BuildPacket(player.actorId, player.currentEventOwner, player.currentEventName)); player.SendMessage(SendMessagePacket.MESSAGE_TYPE_SYSTEM_ERROR, "", message); diff --git a/FFXIVClassic Map Server/lua/LuaEvent.cs b/FFXIVClassic Map Server/lua/LuaEvent.cs deleted file mode 100644 index a22aae1b..00000000 --- a/FFXIVClassic Map Server/lua/LuaEvent.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace FFXIVClassic_Map_Server.lua -{ - class LuaEvent - { - public static void GetStep() - { - - } - - public static void GetParam() - { - - } - - } -} diff --git a/FFXIVClassic Map Server/lua/LuaNpc.cs b/FFXIVClassic Map Server/lua/LuaNpc.cs deleted file mode 100644 index 78d240ea..00000000 --- a/FFXIVClassic Map Server/lua/LuaNpc.cs +++ /dev/null @@ -1,19 +0,0 @@ -using FFXIVClassic_Map_Server.Actors; -using MoonSharp.Interpreter; - -namespace FFXIVClassic_Map_Server.lua -{ - - [MoonSharpUserData] - class LuaNpc - { - private Npc npc; - - public LuaNpc(Npc npc) - { - this.npc = npc; - } - - - } -} diff --git a/FFXIVClassic Map Server/lua/LuaPlayer.cs b/FFXIVClassic Map Server/lua/LuaPlayer.cs deleted file mode 100644 index 5ad16978..00000000 --- a/FFXIVClassic Map Server/lua/LuaPlayer.cs +++ /dev/null @@ -1,70 +0,0 @@ -using FFXIVClassic_Map_Server.Actors; -using FFXIVClassic_Map_Server.packets.send; -using MoonSharp.Interpreter; -using System.Collections.Generic; - -namespace FFXIVClassic_Map_Server.lua -{ - [MoonSharpUserData] - class LuaPlayer - { - private Player player; - - public LuaPlayer(Player player) - { - this.player = player; - } - - public void SetMusic(ushort musicID, ushort playMode) - { - player.playerSession.QueuePacket(SetMusicPacket.BuildPacket(player.actorId, musicID, playMode), true, false); - } - - public void SetWeather(ushort weatherID) - { - player.playerSession.QueuePacket(SetWeatherPacket.BuildPacket(player.actorId, weatherID, 1), true, false); - } - - public void GetParameter(string paramName) - { - - } - - public void SetParameter(string paramName, object value, string uiToRefresh) - { - - } - - public void GetAttributePoints() - { - - } - - public void SetAttributePoints(int str, int vit, int dex, int inte, int min, int pie) - { - - } - - public void Logout() - { - player.playerSession.QueuePacket(LogoutPacket.BuildPacket(player.actorId), true, false); - } - - public void QuitGame() - { - player.playerSession.QueuePacket(QuitPacket.BuildPacket(player.actorId), true, false); - } - - public void RunEvent(string functionName, params object[] parameters) - { - List lParams = LuaUtils.CreateLuaParamList(parameters); - // player.playerSession.QueuePacket(RunEventFunctionPacket.BuildPacket(player.actorId, player.eventCurrentOwner, player.eventCurrentStarter, functionName, lParams), true, false); - } - - public void EndEvent() - { - // player.playerSession.QueuePacket(EndEventPacket.BuildPacket(player.actorId, player.eventCurrentOwner, player.eventCurrentStarter), true, false); - } - - } -} diff --git a/data/scripts/global.lua b/data/scripts/global.lua index 7f9c8211..bad49181 100644 --- a/data/scripts/global.lua +++ b/data/scripts/global.lua @@ -54,11 +54,23 @@ INVENTORY_EQUIPMENT_OTHERPLAYER = 0x00F9; --Max 0x23 --UTILS function callClientFunction(player, functionName, ...) - player:RunEventFunction(functionName, ...); - result = coroutine.yield(); + player:RunEventFunction(functionName, ...); + result = coroutine.yield("_WAIT_EVENT"); return result; end +function wait(seconds) + return coroutine.yield(_WAIT_TIME, seconds); +end + +function waitForSignal(signal) + return coroutine.yield("_WAIT_SIGNAL", signal); +end + +function sendSignal(signal) + GetLuaInstance():OnSignal(signal); +end + function printf(s, ...) if ... then print(s:format(...));