2015-04-13 20:56:36 +00:00
|
|
|
|
//
|
|
|
|
|
// This script serves as a basis for new scripts. New scripts can copy this
|
|
|
|
|
// source file to start out.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.Reflection.Emit;
|
|
|
|
|
using CLRScriptFramework;
|
|
|
|
|
using NWScript;
|
|
|
|
|
using NWScript.ManagedInterfaceLayer.NWScriptManagedInterface;
|
|
|
|
|
|
|
|
|
|
using NWEffect = NWScript.NWScriptEngineStructure0;
|
|
|
|
|
using NWEvent = NWScript.NWScriptEngineStructure1;
|
|
|
|
|
using NWLocation = NWScript.NWScriptEngineStructure2;
|
|
|
|
|
using NWTalent = NWScript.NWScriptEngineStructure3;
|
|
|
|
|
using NWItemProperty = NWScript.NWScriptEngineStructure4;
|
|
|
|
|
|
2015-04-13 22:31:17 +00:00
|
|
|
|
using System.Threading;
|
2015-04-14 21:24:56 +00:00
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Net;
|
2015-04-16 21:58:33 +00:00
|
|
|
|
using System.Net.Sockets;
|
2015-04-21 21:45:52 +00:00
|
|
|
|
using Newtonsoft.Json;
|
2015-04-16 21:58:33 +00:00
|
|
|
|
|
2015-04-13 20:56:36 +00:00
|
|
|
|
namespace CLRScript
|
|
|
|
|
{
|
2015-05-02 00:35:05 +00:00
|
|
|
|
|
2015-04-17 19:36:14 +00:00
|
|
|
|
public partial class nwn2ai_onmoduleload : CLRScriptBase, ICLRScriptImplementation, IGeneratedScriptProgram
|
2015-04-13 20:56:36 +00:00
|
|
|
|
{
|
2015-05-02 00:35:05 +00:00
|
|
|
|
public static nwn2ai_onmoduleload get;
|
2015-04-13 20:56:36 +00:00
|
|
|
|
|
2015-04-17 19:36:14 +00:00
|
|
|
|
public nwn2ai_onmoduleload([In] NWScriptJITIntrinsics Intrinsics, [In] INWScriptProgram Host)
|
2015-04-13 20:56:36 +00:00
|
|
|
|
{
|
|
|
|
|
InitScript(Intrinsics, Host);
|
2015-05-02 00:35:05 +00:00
|
|
|
|
get = this;
|
2015-04-13 20:56:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-04-17 19:36:14 +00:00
|
|
|
|
private nwn2ai_onmoduleload([In] nwn2ai_onmoduleload Other)
|
2015-04-13 20:56:36 +00:00
|
|
|
|
{
|
|
|
|
|
InitScript(Other);
|
|
|
|
|
|
|
|
|
|
LoadScriptGlobals(Other.SaveScriptGlobals());
|
2015-05-02 00:35:05 +00:00
|
|
|
|
get = this;
|
2015-04-13 20:56:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Include the list of types for parameters to the main function here.
|
|
|
|
|
// An empty list means no parameters.
|
|
|
|
|
//
|
|
|
|
|
public static Type[] ScriptParameterTypes = { };
|
|
|
|
|
|
2015-04-17 19:36:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StreamWriter debugFile;
|
2015-04-13 20:56:36 +00:00
|
|
|
|
public Int32 ScriptMain([In] object[] ScriptParameters, [In] Int32 DefaultReturnCode)
|
|
|
|
|
{
|
2015-04-17 19:36:14 +00:00
|
|
|
|
debugFile = File.AppendText("nwnx4\\customlog.txt");
|
|
|
|
|
Debug("====================================> Start");
|
|
|
|
|
|
2015-04-21 20:47:54 +00:00
|
|
|
|
sockBufferIn = new Queue<Tuple<string,Socket>>();
|
2015-05-02 00:35:05 +00:00
|
|
|
|
sockClients = new Dictionary<Socket, Agent>();
|
2015-04-16 21:58:33 +00:00
|
|
|
|
SocketConfigure();
|
2015-04-13 22:31:17 +00:00
|
|
|
|
|
2015-04-14 21:24:56 +00:00
|
|
|
|
AssignCommand(OBJECT_SELF, delegate() { ActionSpeakString("Start!", TALKVOLUME_TALK); });
|
|
|
|
|
DelayCommand(0.5f, Heartbeat);
|
2015-04-13 22:31:17 +00:00
|
|
|
|
|
2015-04-14 21:24:56 +00:00
|
|
|
|
return DefaultReturnCode;
|
|
|
|
|
}
|
2015-04-13 22:31:17 +00:00
|
|
|
|
|
2015-04-14 21:24:56 +00:00
|
|
|
|
public void Heartbeat()
|
|
|
|
|
{
|
2015-04-21 21:45:52 +00:00
|
|
|
|
ActionSpeakString("hb", TALKVOLUME_SHOUT);
|
2015-04-14 21:24:56 +00:00
|
|
|
|
DelayCommand(0.5f, Heartbeat);
|
2015-04-16 21:58:33 +00:00
|
|
|
|
|
|
|
|
|
//Process queued requests
|
2015-04-27 21:10:07 +00:00
|
|
|
|
//Debug("Proc cmds");
|
2015-04-21 21:45:52 +00:00
|
|
|
|
|
|
|
|
|
while(sockBufferIn.Count>0){
|
|
|
|
|
Tuple<string, Socket> req = sockBufferIn.Dequeue();
|
2015-04-27 21:10:07 +00:00
|
|
|
|
var socket = req.Item2;
|
2015-04-21 21:45:52 +00:00
|
|
|
|
|
2015-05-02 00:35:05 +00:00
|
|
|
|
try {
|
|
|
|
|
|
|
|
|
|
var json = JsonConvert.DeserializeObject<dynamic>(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);
|
|
|
|
|
|
|
|
|
|
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) {
|
2015-04-27 21:10:07 +00:00
|
|
|
|
socket.Send(Encoding.UTF8.GetBytes(
|
2015-05-02 00:35:05 +00:00
|
|
|
|
"{\"action\":\"bindack\", \"result\":\"failed\", \"message\":\"Thrown exception: "+e.ToString().Replace("\"","\\\"")+"\"}"
|
2015-04-27 21:10:07 +00:00
|
|
|
|
));
|
2015-05-02 00:35:05 +00:00
|
|
|
|
}
|
|
|
|
|
}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());
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-04-27 21:10:07 +00:00
|
|
|
|
}
|
|
|
|
|
else {
|
2015-05-02 00:35:05 +00:00
|
|
|
|
Debug("Commands must be executed on a binded NPC");
|
2015-04-27 21:10:07 +00:00
|
|
|
|
}
|
2015-05-02 00:35:05 +00:00
|
|
|
|
}break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch(Exception e){
|
|
|
|
|
Debug("Heartbeat Thrown exception: "+e.ToString());
|
2015-04-21 21:45:52 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2015-04-14 21:24:56 +00:00
|
|
|
|
}
|
2015-04-13 20:56:36 +00:00
|
|
|
|
|
|
|
|
|
|
2015-04-16 21:58:33 +00:00
|
|
|
|
void SocketConfigure()
|
|
|
|
|
{
|
|
|
|
|
sockServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
|
|
|
|
IPEndPoint iep = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 8080);
|
|
|
|
|
sockServer.Bind(iep);
|
|
|
|
|
sockServer.Listen(10);
|
2015-04-13 20:56:36 +00:00
|
|
|
|
|
2015-04-21 20:47:54 +00:00
|
|
|
|
sockServer.BeginAccept(new AsyncCallback(RequestHandler), null);
|
2015-04-13 20:56:36 +00:00
|
|
|
|
}
|
2015-04-16 21:58:33 +00:00
|
|
|
|
|
|
|
|
|
void RequestHandler(IAsyncResult state)
|
|
|
|
|
{
|
2015-04-18 08:17:46 +00:00
|
|
|
|
Socket sockClient = sockServer.EndAccept(state);
|
2015-04-21 20:47:54 +00:00
|
|
|
|
sockServer.BeginAccept(new AsyncCallback(RequestHandler), null);
|
|
|
|
|
|
2015-05-01 16:30:39 +00:00
|
|
|
|
sockClient.Blocking = false;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
while (sockClient.Connected && IsSocketConnected(sockClient)) {
|
|
|
|
|
byte[] rawData = new byte[0];
|
|
|
|
|
byte[] buf = new byte[256];
|
|
|
|
|
int recv;
|
2015-04-21 20:47:54 +00:00
|
|
|
|
|
|
|
|
|
|
2015-05-01 16:30:39 +00:00
|
|
|
|
while (sockClient.Available>0 && (recv = sockClient.Receive(buf))>0) {
|
|
|
|
|
rawData = rawData.Concat(buf.Take(recv)).ToArray();
|
|
|
|
|
Thread.Sleep(10);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rawData.Length > 0) {
|
|
|
|
|
string data = Encoding.UTF8.GetString(rawData);
|
|
|
|
|
|
|
|
|
|
Debug("Queued "+data);
|
|
|
|
|
sockBufferIn.Enqueue(new Tuple<string,Socket>(data, sockClient));
|
|
|
|
|
}
|
|
|
|
|
Thread.Sleep(100);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e) {
|
|
|
|
|
Debug(e.ToString());
|
2015-04-21 20:47:54 +00:00
|
|
|
|
}
|
2015-04-18 08:17:46 +00:00
|
|
|
|
|
2015-04-27 21:10:07 +00:00
|
|
|
|
//Remove stored bind
|
2015-05-01 16:30:39 +00:00
|
|
|
|
Debug("EXIT");
|
2015-05-02 00:35:05 +00:00
|
|
|
|
sockClients.Remove(sockClient);
|
2015-04-27 21:10:07 +00:00
|
|
|
|
|
2015-04-16 21:58:33 +00:00
|
|
|
|
}
|
2015-05-01 16:30:39 +00:00
|
|
|
|
public static bool IsSocketConnected(Socket socket)
|
|
|
|
|
{
|
|
|
|
|
try { return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0); }
|
|
|
|
|
catch (SocketException) { return false; }
|
|
|
|
|
}
|
2015-04-16 21:58:33 +00:00
|
|
|
|
|
|
|
|
|
Socket sockServer;
|
2015-04-21 20:47:54 +00:00
|
|
|
|
Queue<Tuple<string,Socket>> sockBufferIn;//Request & client
|
2015-04-27 21:10:07 +00:00
|
|
|
|
|
2015-05-02 00:35:05 +00:00
|
|
|
|
Dictionary<Socket, Agent> sockClients;//Client socket=>NPC ref
|
2015-04-17 19:36:14 +00:00
|
|
|
|
|
|
|
|
|
private void Debug(string msg){
|
|
|
|
|
debugFile.WriteLine(DateTime.Now.ToLongTimeString()+": "+msg);
|
|
|
|
|
debugFile.Flush();
|
|
|
|
|
}
|
2015-04-13 20:56:36 +00:00
|
|
|
|
}
|
|
|
|
|
}
|