Putting scripts togther

by Dares   Last Updated May 15, 2019 13:13 PM

I am trying to replace the exe file UCI connection in Unity from this file

using UnityEngine;
using System.Collections;
using System.IO;
using System.Net;
using System.Diagnostics; 

// This is more a sample of possibilities to connect Unity3D to popular chess servers...
// Of course, everything may be improved.
// Present version just goes to freechess.org and plays a game offered by others (minimum 10minutes)
// Telnet session is more reliable then direct sockets programming by non-professional, and it's slower because of
// long way for data via multiple step-by-step  interfaces... Unity3d-FicsCall.exe-PuttyTelnet-Unix server of Fics.org

public class Ch_socket : MonoBehaviour {
		

	string login="guest";
	string password="anonymous";
	
	int status=0;											// Connection statuss
	
	bool FicsAccessible=false;
	
	string FicsConnFile="";
	string FicsConnPath="";

	Process pFicsConn= new Process();
	float FicsConnTime=0;										// to pause Fics socket connection trying before Putty telnet started...
	float time_difference=0.2f;								// default local web-connection update interval...
	float lastUpdate=0;											// seconds after last update
	float wantPlayTime=0;										// to escape too long waiting for game accepts
	
	string MoveMade="";
	
	bool autoCmds=true;									// automatic mode on/off

	// Use this for initialization
	void Start ()
		{
		FicsAccessible=false;                   // Fics just for Windows Editor or Windows Standalone... (no WebPlayer)
        if ((Application.platform.ToString()).IndexOf("Win") >= 0)
        {
            string editpath = Application.dataPath;
            if ((Application.platform.ToString()).IndexOf("WindowsEditor") < 0) editpath = "";
            else editpath = editpath.Substring(0, editpath.LastIndexOf("Assets")) + "standalone\\Windows\\";

            FicsConnFile = editpath + "FICSconn\\FicsConn.exe";

            FicsAccessible = System.IO.File.Exists(FicsConnFile);           // if file exists...
            if (FicsAccessible)
            {
                int at = FicsConnFile.LastIndexOf("\\");
                FicsConnPath = ((at < 0) ? "" : FicsConnFile.Substring(0, at + 1));
                pFicsConn = null;
            }
        }


        Let3DknowAccess();
		}
		
	void Let3DknowAccess()
		{
		(GameObject.Find("Script2")).SendMessage("TcpAccess", (FicsAccessible?"YES":"NO"));
		if(!FicsAccessible) status = -1;
		}
	
	void ConnectServer(string parm)			// Start local web & telnet program (1.step)
		{
		if(FicsAccessible)
			{
			(GameObject.Find("Script2")).SendMessage("TcpAddMessage", "Trying to connect and start a game"+"\n" +
				"Press Esc to turn on command mode (login keyboard, fics commands, help, etc."+"\n\n");
				
			pFicsConn= new Process();
			pFicsConn.StartInfo.WorkingDirectory = FicsConnPath;	// !!! just make it as a comment to avoid build-compile error for Web platform !!!
            pFicsConn.StartInfo.CreateNoWindow = true;
			pFicsConn.StartInfo.FileName = FicsConnFile;		// Call FicsConn.exe to establish local sockets server+telnet to FICS...
            pFicsConn.StartInfo.Arguments = "";
			pFicsConn.StartInfo.UseShellExecute = false;
			pFicsConn.Start();
			
			if(pFicsConn==null) { FicsAccessible=false; Let3DknowAccess(); }
			else { FicsConnTime=Time.time;  status=1; Status2MainScript(); }			// Process started...
			
			}
		}
	
		void ConnectServer2()							// Try to establish connection to local web (2.step) with program started on step1
		{
		if(FicsAccessible)
			{
			//TcpClient Client = new TcpClient("127.0.0.1", 5050);		// Local on 5050 port... FicsConn.exe
			status = 2;			// Ok, use sockets later...
			}
		}
			
		
	void ReadFromServer()							// Buffered get from local web... Fast enough. Don't like reading bytes from sockets...
		{
		if(FicsAccessible && (status>1))
		{
		string buffer="";
		HttpWebRequest request;
		HttpWebResponse response;
		StreamReader reader;
		request = WebRequest.Create("http://localhost:5050/IN_BUFFER.txt") as HttpWebRequest;
		using (response = request.GetResponse() as HttpWebResponse)  
			{  
			reader = new StreamReader(response.GetResponseStream());  
			buffer=reader.ReadToEnd(); 
			reader.Close();
			}
	
		if((response==null) || (buffer.IndexOf("[PUTTY-FICS-IN-BUFFER-OK]")<0))
			{
			// do nothing, next request can be successfull...(especially in the middle of a game)		
			// FicsAccessible=false; Let3DknowAccess();
			}
			
		string sLine="";						//Separate lines...
		for(; buffer.Length>0; )
			{
			int a1=buffer.IndexOf("\n");
			if(a1<0) { sLine=buffer; buffer=""; }
			else { sLine=buffer.Substring(0,a1); buffer=buffer.Substring(a1+1); }
			if( (sLine.Length>0) && (sLine.IndexOf("[PUTTY-FICS-IN-BUFFER-OK]")<0))
				{
				ProcessLineIN(sLine); 
				(GameObject.Find("Script2")).SendMessage("TcpAddMessage", sLine+"\n");
				}
			}
		}
		}
		
				// analyse incomming data from stream...
		void ProcessLineIN(string sLine)
		{
			string play_cmd;
			string real_nick;
			
			if(autoCmds && (status==2) && ((sLine.ToUpper()).IndexOf("LOGIN")>=0)) status=3;
			if(autoCmds && (status==4) && ((sLine.ToUpper()).IndexOf("PASSWORD")>=0)) status=6;
			if((status==5) && (sLine.IndexOf("Press return to enter the server")>=0))
				{
				real_nick=sLine.Substring(sLine.IndexOf("\"")+1);
				real_nick=real_nick.Substring(0,real_nick.IndexOf("\""));
				login=real_nick;				// the right login name...	
				status=6;
				}
				
			if(status==7)
				{

					// hate chats & dumb messages...
				SendLinesOUT("set silence 1");	// Set silence mode...	
				SendLinesOUT("set shout 0");
				SendLinesOUT("set kibitz 0");	
				SendLinesOUT("set tell 0");	
				SendLinesOUT("set chanoff 1");	
				SendLinesOUT("set echo 1");	
					
				//	There is no big reason in style12, because connection is buffered and fics sends all the board in single bunch of bytes...
				//	This version doesn't resume after lost connection, that is worse then other lacks of code...
				//SendLinesOUT("set style 12");			// Set single-line information about game...	
				status=9;
				}
			
			if((status==11) && (sLine.IndexOf("seek is not available")>=0)) status=9;			// game not possible...
			if((status==11)	&& ((sLine.ToUpper()).IndexOf("CREATING")>=0)) status=20;			// game is possible...		
			
						// after successfully logged in, catch any offered 10/15/20 min. blitz/standard game just to play
			if( ((sLine.ToUpper()).IndexOf("PLAY")>=0) &&
				( ((sLine.ToUpper()).IndexOf("BLITZ")>=0) || ((sLine.ToUpper()).IndexOf("STANDARD")>=0) ) &&
						(((sLine.ToUpper()).IndexOf("SEEKING 10 ")>=0) ||
						((sLine.ToUpper()).IndexOf("SEEKING 15 ")>=0) ||
						((sLine.ToUpper()).IndexOf("SEEKING 20 ")>=0)) )
				{
				if((status==9) && autoCmds)
					{
					play_cmd=sLine.Substring(sLine.IndexOf("\"")+1);
					play_cmd=play_cmd.Substring(0,play_cmd.IndexOf("\""));	
					status=10;						// Ready to play...
					SendLinesOUT(play_cmd);	// try to process this game...
					}
				else if(status<9) status=9;		// when manual login performed...
				}
			if(status==20)
				{
												// Should send information about our color...
				if((sLine.IndexOf(" vs. ")>=0) && (sLine.IndexOf(login)>=0))
					{
					(GameObject.Find("Script2")).SendMessage("TcpOurColor",((sLine.IndexOf(login+")")>=0) ? "black" : "white"));
					status=21;
					}
				}
		}
				// send data according status...
		void SendLinesOUT(string txt)
		{
			if((txt.Length>5) && (txt.Substring(0,5)=="CMD: "))
				{
				string cmd=txt.Substring(5);
				SendToServer(cmd);		// cmd mode...
				if(status==2)
					{
					login=cmd.Replace(" ","");		// the right login name...	
					status=4;
					}
				}
			else if(status==3)			// login...
				{
				if(login.IndexOf("guest")>=0)
					{	
					password="";		// just enter...
					status=5; 
					}
				else status=4;
					
				SendToServer(login);
				}
			else if(status==6)		// password...
				{
				SendToServer(password); status=7;
				}
			else if(status==7)		// at first, goes configuration of fics settings...
				{
				SendToServer(txt);
				}
			else if(status==10)	// want to play a game found in incomming seek...
				{
				SendToServer(txt); status=11;
				}
			else if(status==21)		// when game goes on, can press buttons...
				{
				if(((txt.Length>=6) && (txt=="resign")) || ((txt.Length>=4) && (txt=="draw")) )
					{
					SendToServer(txt);
					}
				else if(MoveMade.Length>0)		// After mousedrag-piece-movement on board here comes the last move that should be sent to the server... 
					{
					SendToServer(MoveMade); 			// when move arrived...
					MoveMade="";
					}
				}
		}

	void SendToServer(string tLine)							// Buffered put to local web... all the string goes in one url-type post request...
		{
		if(FicsAccessible && (status>1))
		{
		string buffer="";
		HttpWebRequest request;
		HttpWebResponse response;
		StreamReader reader;
		request = WebRequest.Create("http://localhost:5050/OUT_BUFFER.txt?OUT_BUFFER="+tLine+"\n") as HttpWebRequest;
		using (response = request.GetResponse() as HttpWebResponse)  
			{  
			reader = new StreamReader(response.GetResponseStream());  
			buffer=reader.ReadToEnd(); 
			reader.Close();
			}

		if((response==null) || (buffer.IndexOf("[PUTTY-FICS-OUT-BUFFER-OK]")<0))
			{
			// do nothing, next request can be successfull...(especially in the middle of a game)
			//	FicsAccessible=false; Let3DknowAccess();
			}
		}
		}
		
	// Update is called once per frame
	void Update ()
		{
		if((FicsConnTime>0) && ((Time.time-FicsConnTime)>4))
			{
			ConnectServer2(); FicsConnTime=0;			// wait 4 seconds to check sockets...& maybe Esc press...
			}
		if((Time.time-lastUpdate)>time_difference)		// a bit interval just not to make connection too tied... (actually it's local & fast enaugh)
			{
			ReadFromServer();				// Read input streamed data...
				
			SendLinesOUT("");				// Send to server lines what & when    needed...
				
			lastUpdate=Time.time;
				
			Status2MainScript();		// Informs main script about current status... - no direct memory access via 3D...
			}
			
		if(status==9) wantPlayTime=Time.time;					
		if((status==10) && ((Time.time-wantPlayTime)>20)) status=9;		// If long waiting then look for other game...
		}
	
	void Status2MainScript()
		{
		(GameObject.Find("Script2")).SendMessage("TcpStatus", status.ToString());
		}
		
	void Movement(string move)
		{
		MoveMade=move;
		}
		
	void StartNextGame(string parm)
		{
		status=9;		// Search for next game...
		}
	void AutoMode(string sw)
		{
		autoCmds =(sw=="ON");		// When automated processing mode on...
		}
		
	// On monobehaviour ends, this is called....
	void OnApplicationQuit()
		{
		SendToServer("EXIT_FICSCALL");		// FicsCall forced exit - just not to left running in memory...
		}

And I have this 2 scripts: 1. webserver

using UnityEngine;
using System.Collections;
using System.Net.Sockets;
using System.Threading;
using System.Collections.Generic;
using System.IO;
using System;

namespace UniWebServer
{


    public class EmbeddedWebServerComponent : MonoBehaviour
    {
        public bool startOnAwake = true;
        public int port = 5050;
        public int workerThreads = 2;
        public bool processRequestsInMainThread = true;
        public bool logRequests = true;

        WebServer server;

        Dictionary<string, IWebResource> resources = new Dictionary<string, IWebResource> ();

        void Start ()
        {
            if (processRequestsInMainThread)
                Application.runInBackground = true;
            server = new WebServer (port, workerThreads, processRequestsInMainThread);
            server.logRequests = logRequests;
            server.HandleRequest += HandleRequest;
            if (startOnAwake) {
                server.Start ();
            }
        }

        void OnApplicationQuit ()
        {
            server.Dispose ();
        }

        void Update ()
        {
            if (server.processRequestsInMainThread) {
                server.ProcessRequests ();    
            }
        }

        void HandleRequest (Request request, Response response)
        {
            if (resources.ContainsKey (request.uri.LocalPath)) {
                try {
                    resources [request.uri.LocalPath].HandleRequest (request, response);
                } catch (Exception e) {
                    response.statusCode = 500;
                    response.Write (e.Message);
                }
            } else {
                response.statusCode = 404;
                response.message = "Not Found.";
                response.Write (request.uri.LocalPath + " not found.");
            }
        }

        public void AddResource (string path, IWebResource resource)
        {
            resources [path] = resource;
        }

    }
}

  1. Telnet connection

// minimalistic telnet implementation
// conceived by Tom Janssens on 2007/06/06  for codeproject
//
// http://www.corebvba.be

// Modifications
//
// Date         Person      Description
// ==========   =========   =======================================================================
// 2013-06-06   jsagara     Implements IDisposable. Miscellaneous refactoring.

using System;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace MinimalisticTelnet
{
    public class TelnetConnection : IDisposable
    {
        private TcpClient tcpSocket;
        private int TimeoutMs = 100;

        public bool IsConnected
        {
            get
            {
                return tcpSocket.Connected;
            }
        }

        public TelnetConnection(string hostname, int port)
        {
            tcpSocket = new TcpClient(hostname, port);
        }

        ~TelnetConnection()
        {
            Dispose(false);
        }

        public string Login(string username, string password, int loginTimeoutMs)
        {
            int oldTimeoutMs = TimeoutMs;
            TimeoutMs = loginTimeoutMs;

            string s = Read();
            if (!s.TrimEnd().EndsWith(":"))
            {
                throw new Exception("Failed to connect : no login prompt");
            }

            WriteLine(username);

            s += Read();
            if (!s.TrimEnd().EndsWith(":"))
            {
                throw new Exception("Failed to connect : no password prompt");
            }

            WriteLine(password);

            s += Read();

            TimeoutMs = oldTimeoutMs;

            return s;
        }

        public void WriteLine(string cmd)
        {
            Write(cmd + "\n");
        }

        public void Write(string cmd)
        {
            if (!tcpSocket.Connected)
            {
                return;
            }

            byte[] buf = ASCIIEncoding.ASCII.GetBytes(cmd.Replace("\0xFF", "\0xFF\0xFF"));
            tcpSocket.GetStream().Write(buf, 0, buf.Length);
        }

        public string Read()
        {
            if (!tcpSocket.Connected)
            {
                return null;
            }

            var sb = new StringBuilder();
            do
            {
                ParseTelnet(sb);
                Thread.Sleep(TimeoutMs);

            } while (tcpSocket.Available > 0);

            return sb.ToString();
        }

        private void ParseTelnet(StringBuilder sb)
        {
            while (tcpSocket.Available > 0)
            {
                int input = tcpSocket.GetStream().ReadByte();
                switch (input)
                {
                    case -1:
                        break;

                    case (int)Verbs.Iac:
                        // interpret as command
                        int inputVerb = tcpSocket.GetStream().ReadByte();
                        if (inputVerb == -1)
                        {
                            break;
                        }

                        switch (inputVerb)
                        {
                            case (int)Verbs.Iac:
                                // literal IAC = 255 escaped, so append char 255 to string
                                sb.Append(inputVerb);
                                break;

                            case (int)Verbs.Do:
                            case (int)Verbs.Dont:
                            case (int)Verbs.Will:
                            case (int)Verbs.Wont:
                                // reply to all commands with "WONT", unless it is SGA (suppres go ahead)
                                int inputoption = tcpSocket.GetStream().ReadByte();
                                if (inputoption == -1)
                                {
                                    break;
                                }

                                tcpSocket.GetStream().WriteByte((byte)Verbs.Iac);

                                if (inputoption == (int)Options.Sga)
                                {
                                    tcpSocket.GetStream().WriteByte(inputVerb == (int)Verbs.Do ? (byte)Verbs.Will : (byte)Verbs.Do);
                                }
                                else
                                {
                                    tcpSocket.GetStream().WriteByte(inputVerb == (int)Verbs.Do ? (byte)Verbs.Wont : (byte)Verbs.Dont);
                                }

                                tcpSocket.GetStream().WriteByte((byte)inputoption);
                                break;
                        }

                        break;

                    default:
                        sb.Append((char)input);
                        break;
                }
            }
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (tcpSocket != null)
                {
                    ((IDisposable)tcpSocket).Dispose();
                    tcpSocket = null;
                }
            }
        }


        #region Private Enums

        enum Verbs
        {
            Will = 251,
            Wont = 252,
            Do = 253,
            Dont = 254,
            Iac = 255
        }

        enum Options
        {
            Sga = 3
        }

        #endregion
    }
}

The problem is I have no idea how to start and how to end All I have are is this readme files:

FicsConn.exe is a console application to call as process from Unitry3D.

Starts as Web server from local socket requests on given port (port.dat file) and starts a telnet session to freechess.org via PUTTY's PLINK.EXE
(redirects stdin/stdout)

That way Unity3D on frames-per-second intervals sends/requests buffers of streams to local socket and gets it all from stable telnet session to fics.
Direct sockets were unstable and connection was lost almost all the time.

For tests:
1.Start FicsConn.exe and get FICS first screen through browser by (REQUEST)

	http://localhost:5050/IN_BUFFER.txt

2.Send Guest login by (DATA SEND)

	http://localhost:5050/OUT_BUFFER.txt?OUT_BUFFER=guest

 and send just empty enter press by
	http://localhost:5050/OUT_BUFFER.txt?OUT_BUFFER=

So, after next REQUEST by

	http://localhost:5050/IN_BUFFER.txt

 You'll see that You are logged in freechess.org & chess game seeks
 on FICS server right in the browser.


Server name (or IP address) is in the file FICS.dat.

All the help will be very much appreciated.



Related Questions


Application like Planner5D in unity

Updated October 12, 2017 06:13 AM

Composition Based Spell System

Updated July 04, 2018 09:13 AM

Using a Singleton for an EditorWindow

Updated January 30, 2019 15:13 PM


Ability/Skill system

Updated March 11, 2017 21:13 PM