diff --git a/TestingAI.d b/TestingAI.d index 74bc055..1be95c2 100644 --- a/TestingAI.d +++ b/TestingAI.d @@ -6,6 +6,7 @@ import std.socket; import std.conv; import std.utf; import std.string; +import std.array; string receiveWait(Socket sock){ bool blocking = sock.blocking; @@ -33,17 +34,27 @@ void sendWait(Socket sock, string data){ } void main() { - writeln("Start"); + writeln("Start");stdout.flush; auto sock = new TcpSocket; sock.blocking = true; sock.connect(new InternetAddress("127.0.0.1", 8080)); - writeln("Connected"); + writeln("Connected");stdout.flush; - sock.sendWait(`{"action":"bind","target":"testnpc"}`); + sock.sendWait(`{"type":"bind","target":"testnpc"}`); writeln(sock.receiveWait); - Thread.sleep(dur!"seconds"(1)); - sock.shutdown(SocketShutdown.BOTH); + while(1){ + write(">");stdout.flush; + auto cmd = stdin.readln().strip; + if(cmd == "")break; + writeln("==>",`{"type":"command","cmd":["`~cmd.replace(`"`,`\"`)~`"]}`);stdout.flush(); + sock.sendWait(`{"type":"command","cmd":["`~cmd.replace(`"`,`\"`)~`"]}`); + //writeln(sock.receiveWait); + } + + writeln("Close");stdout.flush; + sock.shutdown(SocketShutdown.BOTH); Thread.sleep(dur!"seconds"(1)); + writeln("Exit");stdout.flush; } \ No newline at end of file diff --git a/nwn2ai_onmoduleload/Agent.cs b/nwn2ai_onmoduleload/Agent.cs index d20ec7d..64c627e 100644 --- a/nwn2ai_onmoduleload/Agent.cs +++ b/nwn2ai_onmoduleload/Agent.cs @@ -18,7 +18,8 @@ using Newtonsoft.Json; namespace CLRScript { - class Agent : CLRScriptBase{ + using NWScript = nwn2ai_onmoduleload; + class Agent{ public uint objref; public Agent(uint obj){ @@ -31,7 +32,7 @@ namespace CLRScript } set{ _facing = value; - AssignCommand(objref, ()=>{SetFacing(_facing, TRUE);}); + NWScript.get.AssignCommand(objref, ()=>{NWScript.get.SetFacing(_facing, 1);}); } } @@ -41,11 +42,14 @@ namespace CLRScript } set{ _loc = value; - AssignCommand(objref, ()=>{ActionForceMoveToLocation(_loc, TRUE, 6f);}); + NWScript.get.AssignCommand(objref, ()=>{NWScript.get.ActionForceMoveToLocation(_loc, 1, 6f);}); //Link effect - RemoveSEFFromObject(objref, "nwai_beam_loc"); - ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectNWN2SpecialEffectFile("nwai_beam_loc", OBJECT_INVALID, GetPositionFromLocation(_loc)), objref, -1f); + NWScript.get.RemoveSEFFromObject(objref, "nwai_beam_loc"); + NWScript.get.ApplyEffectToObject( + NWScript.DURATION_TYPE_PERMANENT, + NWScript.get.EffectNWN2SpecialEffectFile("nwai_beam_loc", NWScript.OBJECT_INVALID, NWScript.get.GetPositionFromLocation(_loc)), + objref, -1f); } } @@ -53,45 +57,45 @@ namespace CLRScript //======================================================================= public bool hasWallFront(float distance=10f){ - Vector3 pointFront = Add(GetPositionFromLocation(loc), Multiply(AngleToVector(facing), distance)); - return LineOfSightVector(GetPosition(objref), pointFront)==1; + Vector3 pointFront = Add(NWScript.get.GetPositionFromLocation(loc), Multiply(NWScript.get.AngleToVector(facing), distance)); + return NWScript.get.LineOfSightVector(NWScript.get.GetPosition(objref), pointFront)==1; } public bool isInCombat(){ - return GetIsInCombat(objref)==1; + return NWScript.get.GetIsInCombat(objref)==1; } //Json containing // {"valid":"true", "id":"366642", "name":"Goblin", "distance":"13.37", "difficulty":"13", "hp":"12"} public dynamic getNearestEnemy(float distanceMax=15f){ - uint nearestEnemy = GetNearestCreature( - CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, + uint nearestEnemy = NWScript.get.GetNearestCreature( + NWScript.CREATURE_TYPE_REPUTATION, NWScript.REPUTATION_TYPE_ENEMY, objref, 1, - CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN_AND_HEARD, - CREATURE_TYPE_IS_ALIVE, CREATURE_ALIVE_TRUE); + NWScript.CREATURE_TYPE_PERCEPTION, NWScript.PERCEPTION_SEEN_AND_HEARD, + NWScript.CREATURE_TYPE_IS_ALIVE, NWScript.CREATURE_ALIVE_TRUE); - float dist = GetDistanceBetween(nearestEnemy, objref); + float dist = NWScript.get.GetDistanceBetween(nearestEnemy, objref); return JsonConvert.DeserializeObject("{" - + "\"valid\":\""+(GetIsObjectValid(nearestEnemy)==TRUE && dist<=distanceMax).ToString()+"\"," + + "\"valid\":\""+(NWScript.get.GetIsObjectValid(nearestEnemy)==1 && dist<=distanceMax).ToString()+"\"," + "\"id\":\""+(nearestEnemy).ToString()+"\"," - + "\"name\":\""+GetName(nearestEnemy)+"\"" + + "\"name\":\""+NWScript.get.GetName(nearestEnemy)+"\"" + "\"distance\":\""+(dist).ToString()+"\"," - + "\"difficulty\":\""+GetChallengeRating(nearestEnemy)+"\"" - + "\"hp\":\""+GetCurrentHitPoints(nearestEnemy)+"\"" + + "\"difficulty\":\""+NWScript.get.GetChallengeRating(nearestEnemy)+"\"" + + "\"hp\":\""+NWScript.get.GetCurrentHitPoints(nearestEnemy)+"\"" + "}"); } //Json containing // {"valid":"true", "id":"366642", "name":"Guethenoc", "distance":"13.37"} public dynamic getNearestPlayer(float distanceMax=15f){ - uint pc = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, objref, 1, -1,-1,-1,-1); + uint pc = NWScript.get.GetNearestCreature(NWScript.CREATURE_TYPE_PLAYER_CHAR, NWScript.PLAYER_CHAR_IS_PC, objref, 1, -1,-1,-1,-1); - float dist = GetDistanceBetween(pc, objref); + float dist = NWScript.get.GetDistanceBetween(pc, objref); return JsonConvert.DeserializeObject("{" - + "\"valid\":\""+(GetIsObjectValid(pc)==TRUE && dist<=distanceMax).ToString()+"\"," + + "\"valid\":\""+(NWScript.get.GetIsObjectValid(pc)==1 && dist<=distanceMax).ToString()+"\"," + "\"id\":\""+(pc).ToString()+"\"," - + "\"name\":\""+GetName(pc)+"\"" + + "\"name\":\""+NWScript.get.GetName(pc)+"\"" + "\"distance\":\""+(dist).ToString()+"\"," + "}"); } @@ -105,8 +109,8 @@ namespace CLRScript //See NWN2DataLib.AreaSurfaceMesh.PathExists - Vector3 pointFront = Add(GetPositionFromLocation(loc), Multiply(AngleToVector(facing), distance)); - loc = Location(GetAreaFromLocation(loc), pointFront, facing); + Vector3 pointFront = Add(NWScript.get.GetPositionFromLocation(loc), Multiply(NWScript.get.AngleToVector(facing), distance)); + loc = NWScript.get.Location(NWScript.get.GetAreaFromLocation(loc), pointFront, facing); return true; } @@ -115,7 +119,7 @@ namespace CLRScript if(!nearest.valid) return false; - AssignCommand(objref, ()=>{ActionAttack(nearest.id, FALSE);}); + NWScript.get.AssignCommand(objref, ()=>{NWScript.get.ActionAttack(nearest.id, 0);}); return true; } @@ -125,7 +129,7 @@ namespace CLRScript } public bool say(string message){ - AssignCommand(objref, ()=>{SpeakString(message, TALKVOLUME_TALK);}); + NWScript.get.AssignCommand(objref, ()=>{NWScript.get.SpeakString(message, NWScript.TALKVOLUME_TALK);}); return getNearestPlayer().valid; } diff --git a/nwn2ai_onmoduleload/nwn2ai_onmoduleload.cs b/nwn2ai_onmoduleload/nwn2ai_onmoduleload.cs index 9243335..5b82395 100644 --- a/nwn2ai_onmoduleload/nwn2ai_onmoduleload.cs +++ b/nwn2ai_onmoduleload/nwn2ai_onmoduleload.cs @@ -29,12 +29,15 @@ using Newtonsoft.Json; namespace CLRScript { + public partial class nwn2ai_onmoduleload : CLRScriptBase, ICLRScriptImplementation, IGeneratedScriptProgram { + public static nwn2ai_onmoduleload get; public nwn2ai_onmoduleload([In] NWScriptJITIntrinsics Intrinsics, [In] INWScriptProgram Host) { InitScript(Intrinsics, Host); + get = this; } private nwn2ai_onmoduleload([In] nwn2ai_onmoduleload Other) @@ -42,6 +45,7 @@ namespace CLRScript InitScript(Other); LoadScriptGlobals(Other.SaveScriptGlobals()); + get = this; } // @@ -59,7 +63,7 @@ namespace CLRScript Debug("====================================> Start"); sockBufferIn = new Queue>(); - sockClients = new Dictionary(); + sockClients = new Dictionary(); SocketConfigure(); AssignCommand(OBJECT_SELF, delegate() { ActionSpeakString("Start!", TALKVOLUME_TALK); }); @@ -80,38 +84,64 @@ namespace CLRScript Tuple req = sockBufferIn.Dequeue(); var socket = req.Item2; - var json = JsonConvert.DeserializeObject(req.Item1); - //TODO: check if json correctly parsed - switch ((string)json.action) { - case "bind": { - Debug("Bind request to '"+json.target+"'"); + try { - try { - if (!sockClients.ContainsKey((string)json.target)) { + var json = JsonConvert.DeserializeObject(req.Item1); + //TODO: check if json correctly parsed + switch ((string)json.type) { + case "bind": { + Debug("Bind request to '"+json.target+"'"); + string npcTag = (string)json.target; + uint npcID = GetObjectByTag(npcTag, 0); - sockClients.Add((string)json.target, socket); + try { + try{ + var res = sockClients.First((kvp)=>kvp.Value.objref==npcID); + //Will continue if the socket is already registered + socket.Send(Encoding.UTF8.GetBytes( + "{\"action\":\"bindack\", \"result\":\"failed\", \"message\":\"Socket already binded with this NPC\"}" + )); + } + catch (Exception e) { + //Will go here if the socket is nbot registered + Agent npc = new Agent(npcID); + sockClients.Add(socket, npc); + socket.Send(Encoding.UTF8.GetBytes( + "{\"action\":\"bindack\", \"result\":\"ok\"}" + )); + + //handle env recording + } + + } + catch (Exception e) { socket.Send(Encoding.UTF8.GetBytes( - "{\"action\":\"bindack\", \"result\":\"ok\"}" + "{\"action\":\"bindack\", \"result\":\"failed\", \"message\":\"Thrown exception: "+e.ToString().Replace("\"","\\\"")+"\"}" )); - - //handle env + } + }break; + case "command": { + Debug("command"); + if (sockClients.ContainsKey(socket)) { + Agent npc = sockClients[socket]; + foreach(var cmd in json.cmd){ + Debug("exec "+(string)cmd); + try { + npc.callCommand((string)cmd); + } + catch(Exception e){ + Debug(e.ToString()); + } + } } else { - socket.Send(Encoding.UTF8.GetBytes( - "{\"action\":\"bindack\", \"result\":\"failed\", \"message\":\"Socket already binded with this NPC\"}" - )); + Debug("Commands must be executed on a binded NPC"); } - } - catch (Exception e) { - socket.Send(Encoding.UTF8.GetBytes( - "{\"action\":\"bindack\", \"result\":\"failed\", \"message\":\"Thrown exception: "+e.ToString().Replace("\"","\\\"")+"\"}" - )); - } - }break; - case "decision": { - - - }break; + }break; + } + } + catch(Exception e){ + Debug("Heartbeat Thrown exception: "+e.ToString()); } } } @@ -161,8 +191,7 @@ namespace CLRScript //Remove stored bind Debug("EXIT"); - var sock = sockClients.First(kvp => kvp.Value==sockClient); - sockClients.Remove(sock.Key); + sockClients.Remove(sockClient); } public static bool IsSocketConnected(Socket socket) @@ -174,7 +203,7 @@ namespace CLRScript Socket sockServer; Queue> sockBufferIn;//Request & client - Dictionary sockClients;//PNJ tag => Client socket + Dictionary sockClients;//Client socket=>NPC ref private void Debug(string msg){ debugFile.WriteLine(DateTime.Now.ToLongTimeString()+": "+msg);