start of work moving commands to lua

This commit is contained in:
Tahir Akhlaq
2016-06-16 01:50:13 +01:00
parent 1159c75ab8
commit 57b9d5ab99
20 changed files with 703 additions and 67 deletions

View File

@@ -455,7 +455,7 @@ namespace FFXIVClassic_Map_Server
return; // catch any invalid warps here
}
private void doWeather(ConnectedPlayer client, string weatherID, string value)
private void DoWeather(ConnectedPlayer client, string weatherID, string value)
{
ushort weather = Convert.ToUInt16(weatherID);
@@ -499,18 +499,55 @@ namespace FFXIVClassic_Map_Server
internal bool DoCommand(string input, ConnectedPlayer client)
{
if (!input.Any())
return false;
input.Trim();
if (input.StartsWith("!"))
input = input.Substring(1);
input = input.StartsWith("!") ? input.Substring(1) : input;
var split = input.Split('"')
.Select((str, index) => index % 2 == 0
? str.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
: new String[] { str }
)
.SelectMany(str => str).ToArray();
String[] split = input.Split(' ');
split = split.Select(temp => temp.ToLower()).ToArray(); // Ignore case on commands
split = split.Where(temp => temp != "").ToArray(); // strips extra whitespace from commands
// Debug
//SendMessage(client, string.Join(",", split));
if (split.Length >= 1)
var cmd = split?.ElementAt(0);
if (cmd.Any())
{
// if client isnt null, take player to be the player actor
var player = client?.GetActor();
if (cmd.Equals("help"))
{
// if there's another string after this, take it as the command we want the description for
if (split.Length > 1)
{
LuaEngine.RunGMCommand(player, split[1], null, true);
return true;
}
// print out all commands
foreach (var str in Directory.GetFiles("./scripts/commands/gm/"))
{
var c = str.Replace(".lua", "");
c = c.Replace("./scripts/commands/gm/", "");
LuaEngine.RunGMCommand(player, c, null, true);
}
return true;
}
LuaEngine.RunGMCommand(player, cmd.ToString(), split.ToArray());
return true;
}
// Debug
//SendMessage(client, string.Join(",", split));
if (split.Length >= 1)
{
#region !help
if (split[0].Equals("help"))
@@ -582,7 +619,7 @@ namespace FFXIVClassic_Map_Server
{
try
{
doWeather(client, split[2], split[3]);
DoWeather(client, split[2], split[3]);
return true;
}
catch (Exception e)
@@ -622,7 +659,7 @@ namespace FFXIVClassic_Map_Server
client.GetActor().SendInstanceUpdate();
client.QueuePacket(BasePacket.CreatePacket(SendMessagePacket.BuildPacket(client.actorID, client.actorID, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", String.Format("Reseting zone {0}...", client.GetActor().zoneId)), true, false));
}
Server.GetWorldManager().reloadZone(client.GetActor().zoneId);
Server.GetWorldManager().ReloadZone(client.GetActor().zoneId);
return true;
}
#endregion

View File

@@ -18,9 +18,9 @@ namespace FFXIVClassic_Map_Server
public static Logger Log;
static void Main(string[] args)
{
// set up logging
{
// set up logging
Log = LogManager.GetCurrentClassLogger();
#if DEBUG
TextWriterTraceListener myWriter = new TextWriterTraceListener(System.Console.Out);

View File

@@ -464,7 +464,7 @@ namespace FFXIVClassic_Map_Server
LuaEngine.OnZoneIn(player);
}
public void reloadZone(uint zoneId)
public void ReloadZone(uint zoneId)
{
if (!zoneList.ContainsKey(zoneId))
return;

View File

@@ -11,7 +11,7 @@ using FFXIVClassic_Map_Server.actors.area;
namespace FFXIVClassic_Map_Server.Actors
{
class Actor
{
{
public uint actorId;
public string actorName;
@@ -58,12 +58,12 @@ namespace FFXIVClassic_Map_Server.Actors
public SubPacket CreateAddActorPacket(uint playerActorId, byte val)
{
return AddActorPacket.BuildPacket(actorId, playerActorId, val);
}
}
public SubPacket CreateNamePacket(uint playerActorId)
{
return SetActorNamePacket.BuildPacket(actorId, playerActorId, displayNameId, displayNameId == 0xFFFFFFFF | displayNameId == 0x0 ? customDisplayName : "");
}
}
public SubPacket CreateSpeedPacket(uint playerActorId)
{
@@ -95,10 +95,10 @@ namespace FFXIVClassic_Map_Server.Actors
{
SubPacket spawnPacket;
spawnPacket = SetActorPositionPacket.BuildPacket(actorId, playerActorId, 0xFFFFFFFF, positionX, positionY, positionZ, rotation, spawnType, false);
spawnPacket = SetActorPositionPacket.BuildPacket(actorId, playerActorId, 0xFFFFFFFF, positionX, positionY, positionZ, rotation, spawnType, false);
//return SetActorPositionPacket.BuildPacket(actorId, playerActorId, -211.895477f, 190.000000f, 29.651011f, 2.674819f, SetActorPositionPacket.SPAWNTYPE_PLAYERWAKE);
spawnPacket.DebugPrintSubPacket();
return spawnPacket;
@@ -124,8 +124,8 @@ namespace FFXIVClassic_Map_Server.Actors
if (eventConditions.talkEventConditions != null)
{
foreach (EventList.TalkEventCondition condition in eventConditions.talkEventConditions)
subpackets.Add(SetTalkEventCondition.BuildPacket(playerActorId, actorId, condition));
foreach (EventList.TalkEventCondition condition in eventConditions.talkEventConditions)
subpackets.Add(SetTalkEventCondition.BuildPacket(playerActorId, actorId, condition));
}
if (eventConditions.noticeEventConditions != null)
@@ -171,8 +171,8 @@ namespace FFXIVClassic_Map_Server.Actors
if (eventConditions.talkEventConditions != null)
{
foreach (EventList.TalkEventCondition condition in eventConditions.talkEventConditions)
subpackets.Add(SetEventStatus.BuildPacket(playerActorId, actorId, true, 1, condition.conditionName));
foreach (EventList.TalkEventCondition condition in eventConditions.talkEventConditions)
subpackets.Add(SetEventStatus.BuildPacket(playerActorId, actorId, true, 1, condition.conditionName));
}
if (eventConditions.noticeEventConditions != null)
@@ -219,7 +219,7 @@ namespace FFXIVClassic_Map_Server.Actors
}
public virtual BasePacket GetSpawnPackets(uint playerActorId)
{
{
return GetSpawnPackets(playerActorId, 0x1);
}
@@ -229,13 +229,13 @@ namespace FFXIVClassic_Map_Server.Actors
subpackets.Add(CreateAddActorPacket(playerActorId, 8));
subpackets.AddRange(GetEventConditionPackets(playerActorId));
subpackets.Add(CreateSpeedPacket(playerActorId));
subpackets.Add(CreateSpawnPositonPacket(playerActorId, spawnType));
subpackets.Add(CreateSpawnPositonPacket(playerActorId, spawnType));
subpackets.Add(CreateNamePacket(playerActorId));
subpackets.Add(CreateStatePacket(playerActorId));
subpackets.Add(CreateIsZoneingPacket(playerActorId));
subpackets.Add(CreateScriptBindPacket(playerActorId));
return BasePacket.CreatePacket(subpackets, true, false);
}
}
public virtual BasePacket GetInitPackets(uint playerActorId)
{
@@ -301,7 +301,7 @@ namespace FFXIVClassic_Map_Server.Actors
SubPacket ChangeSpeedPacket = SetActorSpeedPacket.BuildPacket(actorId, actorId, moveSpeeds[0], moveSpeeds[1], moveSpeeds[2]);
zone.BroadcastPacketAroundActor(this, ChangeSpeedPacket);
}
public void generateActorName(int actorNumber)
{
//Format Class Name
@@ -311,7 +311,7 @@ namespace FFXIVClassic_Map_Server.Actors
.Replace("MapObj", "Map")
.Replace("Object", "Obj")
.Replace("Retainer", "Rtn")
.Replace("Standard", "Std");
.Replace("Standard", "Std");
className = Char.ToLowerInvariant(className[0]) + className.Substring(1);
//Format Zone Name
@@ -335,7 +335,7 @@ namespace FFXIVClassic_Map_Server.Actors
className = className.Substring(0, 20 - zoneName.Length);
}
catch (ArgumentOutOfRangeException e)
{}
{ }
//Convert actor number to base 63
string classNumber = Utils.ToStringBase63(actorNumber);
@@ -349,6 +349,34 @@ namespace FFXIVClassic_Map_Server.Actors
actorName = String.Format("{0}_{1}_{2}@{3:X3}{4:X2}", className, zoneName, classNumber, zoneId, privLevel);
}
public List<float> GetPos()
{
List<float> pos = new List<float>();
pos.Add(positionX);
pos.Add(positionY);
pos.Add(positionZ);
pos.Add(rotation);
pos.Add(zoneId);
return pos;
}
public void SetPos(float x, float y, float z, float rot = 0, uint zoneId = 0)
{
oldPositionX = positionX;
oldPositionY = positionY;
oldPositionZ = positionZ;
oldRotation = rotation;
positionX = x;
positionY = y;
positionZ = z;
rotation = rot;
// todo: handle zone?
zone.BroadcastPacketAroundActor(this, MoveActorToPositionPacket.BuildPacket(this.actorId, this.actorId, x, y, z, rot, moveState));
}
}
}

View File

@@ -292,7 +292,7 @@ namespace FFXIVClassic_Map_Server.Actors
{
if (a is Player)
{
if (((Player)a).customDisplayName.Equals(name))
if (((Player)a).customDisplayName.ToLower().Equals(name.ToLower()))
return (Player)a;
}
}

View File

@@ -1,5 +1,4 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.packets;
using FFXIVClassic_Map_Server.packets;
using FFXIVClassic_Map_Server.actors.director;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.dataobjects;
@@ -12,6 +11,7 @@ using MoonSharp.Interpreter.Loaders;
using System;
using System.Collections.Generic;
using System.IO;
using System.Diagnostics;
namespace FFXIVClassic_Map_Server.lua
{
@@ -36,13 +36,13 @@ namespace FFXIVClassic_Map_Server.lua
{
luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName());
if (File.Exists(luaPath))
{
{
Script script = LoadScript(luaPath);
if (script == null)
return null;
DynValue result = script.Call(script.Globals["init"], target);
DynValue result = RunScript(script, script.Globals["init"], target);
List<LuaParam> lparams = LuaUtils.CreateLuaParamList(result);
return lparams;
}
@@ -54,8 +54,8 @@ namespace FFXIVClassic_Map_Server.lua
}
return null;
}
}
public static void DoActorOnEventStarted(Player player, Actor target, EventStartPacket eventStart)
{
if (target is Npc)
@@ -74,7 +74,7 @@ namespace FFXIVClassic_Map_Server.lua
{
luaPath = String.Format(FILEPATH_DIRECTORS, target.GetName());
}
else
else
luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName());
if (File.Exists(luaPath))
@@ -95,13 +95,13 @@ namespace FFXIVClassic_Map_Server.lua
//Run Script
if (!script.Globals.Get("onEventStarted").IsNil())
script.Call(script.Globals["onEventStarted"], objects.ToArray());
RunScript(script, script.Globals["onEventStarted"], objects.ToArray());
}
else
{
SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName()));
}
}
}
public static void DoActorOnSpawn(Player player, Npc target)
@@ -117,7 +117,7 @@ namespace FFXIVClassic_Map_Server.lua
//Run Script
if (!script.Globals.Get("onSpawn").IsNil())
script.Call(script.Globals["onSpawn"], player, target);
RunScript(script, script.Globals["onSpawn"], player, target);
}
else
{
@@ -134,12 +134,12 @@ namespace FFXIVClassic_Map_Server.lua
return;
}
string luaPath;
if (target is Command)
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());
luaPath = String.Format(FILEPATH_DIRECTORS, target.GetName());
else
luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName());
@@ -159,18 +159,18 @@ namespace FFXIVClassic_Map_Server.lua
//Run Script
if (!script.Globals.Get("onEventUpdate").IsNil())
script.Call(script.Globals["onEventUpdate"], objects.ToArray());
RunScript(script, script.Globals["onEventUpdate"], objects.ToArray());
}
else
{
SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName()));
}
}
}
public static void OnZoneIn(Player player)
{
string luaPath = String.Format(FILEPATH_ZONE, player.GetZone().actorId);
string luaPath = String.Format(FILEPATH_ZONE, player.GetZone().actorId);
if (File.Exists(luaPath))
{
Script script = LoadScript(luaPath);
@@ -180,8 +180,8 @@ namespace FFXIVClassic_Map_Server.lua
//Run Script
if (!script.Globals.Get("onZoneIn").IsNil())
script.Call(script.Globals["onZoneIn"], player);
}
RunScript(script, script.Globals["onZoneIn"], player);
}
}
public static void OnBeginLogin(Player player)
@@ -195,7 +195,7 @@ namespace FFXIVClassic_Map_Server.lua
//Run Script
if (!script.Globals.Get("onBeginLogin").IsNil())
script.Call(script.Globals["onBeginLogin"], player);
RunScript(script, script.Globals["onBeginLogin"], player);
}
}
@@ -210,29 +210,175 @@ namespace FFXIVClassic_Map_Server.lua
//Run Script
if (!script.Globals.Get("onLogin").IsNil())
script.Call(script.Globals["onLogin"], player);
RunScript(script, script.Globals["onLogin"], player);
}
}
#region RunGMCommand
public static void RunGMCommand(Player player, String cmd, string[] param, bool help = false)
{
// load from scripts/commands/gm/ directory
var path = String.Format("./scripts/commands/gm/{0}.lua", cmd.ToString().ToLower());
// check if the file exists
if (File.Exists(path))
{
// load global functions
Script script = LoadGlobals();
// see if this script has any syntax errors
try
{
script.DoFile(path);
}
catch (Exception e)
{
Program.Log.Error("LuaEngine.RunGMCommand: {0}.", e.Message);
return;
}
// can we run this script
if (!script.Globals.Get("onTrigger").IsNil())
{
// can i run this command
var permissions = 0;
// parameter types (string, integer, double, float)
var parameters = "";
var description = "!" + cmd + ": ";
// get the properties table
var res = script.Globals.Get("properties");
// make sure properties table exists
if (!res.IsNil())
{
try
{
// returns table if one is found
var table = res.Table;
// find each key/value pair
foreach (var pair in table.Pairs)
{
if (pair.Key.String == "permissions")
{
permissions = (int)pair.Value.Number;
}
else if (pair.Key.String == "parameters")
{
parameters = pair.Value.String;
}
else if (pair.Key.String == "description")
{
description = pair.Value.String;
}
}
}
catch (Exception e) { Program.Log.Error("LuaEngine.RunGMCommand: " + e.Message); return; }
}
// if this isnt a console command, make sure player exists
if (player != null)
{
if (permissions > 0 && !player.isGM)
{
Program.Log.Info("LuaEngine.RunGMCommand: {0}'s GM level is too low to use command {1}.", player.actorName, cmd);
return;
}
// i hate to do this, but cant think of a better way to keep !help
else if (help)
{
player.SendMessage(SendMessagePacket.MESSAGE_TYPE_SYSTEM_ERROR, String.Format("[Commands] [{0}]", cmd), description);
return;
}
}
else if (help)
{
Program.Log.Info("[Commands] [{0}]: {1}", cmd, description);
return;
}
// we'll push our lua params here
List<object> LuaParam = new List<object>();
var i = 0;
for (; i < parameters.Length; ++i)
{
try
{
// convert chat parameters to command parameters
switch (parameters[i])
{
case 'i':
LuaParam.Add(Convert.ChangeType(param[i + 1], typeof(int)));
continue;
case 'd':
LuaParam.Add(Convert.ChangeType(param[i + 1], typeof(double)));
continue;
case 'f':
LuaParam.Add(Convert.ChangeType(param[i + 1], typeof(float)));
continue;
case 's':
LuaParam.Add(param[i + 1]);
continue;
default:
Program.Log.Info("LuaEngine.RunGMCommand: {0} unknown parameter {1}.", path, parameters[i]);
LuaParam.Add(param[i + 1]);
continue;
}
}
catch (Exception e)
{
if (e is IndexOutOfRangeException) break;
LuaParam.Add(param[i + 1]);
}
}
// the script can double check the player exists, we'll push them anyways
LuaParam.Insert(0, player);
// push the arg count too
LuaParam.Insert(1, i);
// run the script
RunScript(script, script.Globals["onTrigger"], LuaParam.ToArray());
return;
}
}
Program.Log.Error("LuaEngine.RunGMCommand: Unable to find script {0}", path);
return;
}
#endregion
public static Script LoadScript(string filename)
{
Script script = new Script();
((FileSystemScriptLoader)script.Options.ScriptLoader).ModulePaths = FileSystemScriptLoader.UnpackStringPaths("./scripts/?;./scripts/?.lua");
script.Globals["GetWorldManager"] = (Func<WorldManager>)Server.GetWorldManager;
script.Globals["GetStaticActor"] = (Func<string, Actor>)Server.GetStaticActors;
script.Globals["GetWorldMaster"] = (Func<Actor>)Server.GetWorldManager().GetActor;
script.Globals["GetItemGamedata"] = (Func<uint, Item>)Server.GetItemGamedata;
Script script = LoadGlobals();
try
{
script.DoFile(filename);
}
catch(SyntaxErrorException e)
catch (SyntaxErrorException e)
{
Program.Log.Error("LUAERROR: {0}.", e.DecoratedMessage);
return null;
}
return script;
}
public static Script LoadGlobals(Script script = null)
{
script = script ?? new Script();
// register and load all global functions here
((FileSystemScriptLoader)script.Options.ScriptLoader).ModulePaths = FileSystemScriptLoader.UnpackStringPaths("./scripts/?;./scripts/?.lua");
script.Globals["GetWorldManager"] = (Func<WorldManager>)Server.GetWorldManager;
script.Globals["GetStaticActor"] = (Func<string, Actor>)Server.GetStaticActors;
script.Globals["GetWorldMaster"] = (Func<Actor>)Server.GetWorldManager().GetActor;
script.Globals["GetItemGamedata"] = (Func<uint, Item>)Server.GetItemGamedata;
script.Options.DebugPrint = s => { Program.Log.Debug(s); };
return script;
}
public static void SendError(Player player, string message)
@@ -257,7 +403,7 @@ namespace FFXIVClassic_Map_Server.lua
//Run Script
if (!script.Globals.Get("onTalked").IsNil())
script.Call(script.Globals["onTalked"], player, npc);
RunScript(script, script.Globals["onTalked"], player, npc);
}
else
{
@@ -278,12 +424,154 @@ namespace FFXIVClassic_Map_Server.lua
//Run Script
if (!script.Globals.Get("onCommand").IsNil())
script.Call(script.Globals["onCommand"], player, command);
RunScript(script, script.Globals["onCommand"], player, command);
}
else
{
SendError(player, String.Format("ERROR: Could not find script for director {0}.", director.GetName()));
}
}
}
#region RunScript
//
// Summary:
// Calls the specified function.
//
// Parameters:
// function:
// The Lua/MoonSharp function to be called
//
// Returns:
// The return value(s) of the function call.
//
// Exceptions:
// T:System.ArgumentException:
// Thrown if function is not of DataType.Function
public static DynValue RunScript(Script script, DynValue function)
{
DynValue res = null;
try
{
res = script.Call(function);
}
catch (InterpreterException e)
{
Program.Log.Error(e.DecoratedMessage);
}
return res;
}
//
// Summary:
// Calls the specified function.
//
// Parameters:
// function:
// The Lua/MoonSharp function to be called
//
// Exceptions:
// T:System.ArgumentException:
// Thrown if function is not of DataType.Function
public static DynValue RunScript(Script script, object function)
{
DynValue res = null;
try
{
res = script.Call(function);
}
catch (InterpreterException e)
{
Program.Log.Error(e.DecoratedMessage);
}
return res;
}
//
// Summary:
// Calls the specified function.
//
// Parameters:
// function:
// The Lua/MoonSharp function to be called
//
// args:
// The arguments to pass to the function.
//
// Exceptions:
// T:System.ArgumentException:
// Thrown if function is not of DataType.Function
public static DynValue RunScript(Script script, object function, params object[] args)
{
DynValue res = null;
try
{
res = script.Call(function, args);
}
catch (InterpreterException e)
{
Program.Log.Error(e.DecoratedMessage);
}
return res;
}
//
// Summary:
// Calls the specified function.
//
// Parameters:
// function:
// The Lua/MoonSharp function to be called
//
// args:
// The arguments to pass to the function.
//
// Returns:
// The return value(s) of the function call.
//
// Exceptions:
// T:System.ArgumentException:
// Thrown if function is not of DataType.Function
public static DynValue RunScript(Script script, DynValue function, params DynValue[] args)
{
DynValue res = null;
try
{
res = script.Call(function, args);
}
catch (InterpreterException e)
{
Program.Log.Error(e.DecoratedMessage);
}
return res;
}
//
// Summary:
// Calls the specified function.
//
// Parameters:
// function:
// The Lua/MoonSharp function to be called
//
// args:
// The arguments to pass to the function.
//
// Returns:
// The return value(s) of the function call.
//
// Exceptions:
// T:System.ArgumentException:
// Thrown if function is not of DataType.Function
public static DynValue RunScript(Script script, DynValue function, params object[] args)
{
DynValue res = null;
try
{
res = script.Call(function, args);
}
catch (InterpreterException e)
{
Program.Log.Error(e.DecoratedMessage);
}
return res;
}
#endregion
}
}