private void CloseClientThread() { EWUnityExtensions.Log("##### ExerWorldPlugin close tcp connection "); if (clientThread != null) { try { if (tcpclient != null) { tcpclient.GetStream().Dispose(); } } catch (Exception) { } try { tcpclient.Close(); } catch (Exception) { } try { clientThread.Abort(); } catch { EWUnityExtensions.LogWarning("##### ExerWorldPlugin ExerLinker: client close Error"); } } else { EWUnityExtensions.LogWarning("##### ExerWorldPlugin ExerLinker: clientThread was null"); } }
private void ConnectToServer() { try { // be sure that there is no old client hanging around if (tcpclient != null) { tcpclient.Close(); } IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse(linker_ip), linker_tcp_port); tcpclient = new TcpClient(); tcpclient.NoDelay = true; tcpclient.Connect(endpoint); EWUnityExtensions.Log("##### ExerWorldPlugin ConnectToServer, tcpclient.Connected ? " + tcpclient.Connected); //No need to start checking the stream if no connection was established if (tcpclient.Connected) { StartClientThread(); } } catch (Exception e) { EWUnityExtensions.Log("##### ExerWorldPlugin ConnectToServer, Could not connect!!!! " + e); } connectThread.Abort(); }
protected void HandleStreamLoop() { EWUnityExtensions.Log("##### ExerWorldPlugin handleStreamLoop starting called"); while (true) { HandleStream(); // EWUnityExtensions.Log ("sleep!"); Thread.Sleep(UPDATE_EVERY); } }
void DestroyExerWorldLinker() { EWUnityExtensions.Log("Try to kill autobooted ExerWorldLinker"); //TODO: this needs to be extended for other platforms as well #if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN if (hasLinkerStarted) { procLinker.Kill(); } #endif }
// Use this for initialization void Start() { #if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN windowHandle = GetActiveWindow(); #endif if (killSelfWhenThereIsOtherOwn) { if (it == this.gameObject) { } else if (it == null) { it = this; } else { Destroy(this.gameObject); // kill yourself! EWUnityExtensions.Log("kill myself"); return; } } else { it = this; } if (inNames == null || inNames.Length == 0) { inNames = new string[ControlInput.allControlsList.Count]; ControlInput[] cis = this.GetComponents <ControlInput> (); for (int i = 0; i < cis.Length; i++) { ControlInput ci = cis[i]; if (ci is ControlInputMulti) { continue; } inNames [i] = ci.controlName; } } DontDestroyOnLoad(transform.gameObject); //This is not necessary as it auto connects in the update method //StartClientThread (); if (autoBootLinker) { AutoBootLinker(); } }
public void AutoBootLinker() { string pathToExerWorldLinker = ""; string exectuableName = ""; #if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN exectuableName = "ExerWorldLinker.exe"; #endif pathToExerWorldLinker = ""; if (Application.platform == RuntimePlatform.OSXPlayer) { pathToExerWorldLinker = "" + Application.dataPath + "/../../"; } else { pathToExerWorldLinker = "" + Application.dataPath + "/../"; } pathToExerWorldLinker += "ExerWorldLinker/"; string pathtoExerWorldLinkerWithExecutable = pathToExerWorldLinker + exectuableName; EWUnityExtensions.Log("Try to start ExerWorldLinker here:" + "'" + pathToExerWorldLinker + "'"); #if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN try { procLinker = new Process(); procLinker.StartInfo.FileName = pathtoExerWorldLinkerWithExecutable; procLinker.StartInfo.WorkingDirectory = pathToExerWorldLinker; // procLinker.StartInfo.Arguments = ... // Stop the process from opening a new window // TODO / FIXME nice to have but seems to block sth inside of exer.world's linker // procLinker.StartInfo.RedirectStandardOutput = true; // procLinker.StartInfo.UseShellExecute = false; // procLinker.StartInfo.CreateNoWindow = true; procLinker.Start(); hasLinkerStarted = true; // GainFocus(); StartCoroutine(GainFocusDelayed(0.1f)); } catch (Exception e) { EWUnityExtensions.LogWarning("Could not start ExerWorld's Linker from " + pathToExerWorldLinker + "\n" + e); } #endif }
void Update() { float curTime = Time.realtimeSinceStartup; // check if ControlInputs have to be created (needed for multiinputs which can dynamically grow) foreach (CreateQueueEntry entry in createQueue) { ControlInput parent = entry.ciParent; string multiId = entry.multiId; string multiFullName = entry.name; if (ControlInputMulti.allMultiControls.ContainsKey(multiFullName) == false) { EWUnityExtensions.Log("Create new multi val controlinput child for '" + multiFullName + "'"); ControlInputMulti ciChild = this.gameObject.AddComponent <ControlInputMulti> (); ciChild.multiId = multiId; ciChild.RegisterMulti(multiFullName); ciChild.multiParent = parent; ControlInput.MultiInputEntry multiEntry = new ControlInput.MultiInputEntry(); multiEntry.multiId = multiId; multiEntry.name = multiFullName; multiEntry.controlInput = ciChild; parent.multiInputs.Add(multiEntry); ciChild.SetCurrentValue(entry.initVal); } else { EWUnityExtensions.LogWarning("'" + multiFullName + "' already created!"); } } createQueue.Clear(); // TODO: restart client if closed... look for server (rendevous/zeroconf ? ) if (IsConnectionLost() && (curTime - timeLastConnectionTry) > cooldownConnectionTry) { timeLastConnectionTry = curTime; EWUnityExtensions.Log("Try to connect to server '" + linker_ip + ":" + linker_tcp_port + "'"); connectThread = new Thread(ConnectToServer); connectThread.Start(); } foreach (var kV in inValues) { EWUnityExtensions.Log("in Values => " + kV.Key + " -> " + kV.Value); } }
private void UpdateValues(string[] lines) { // EWUnityExtensions.Log("Update values: " + lines[0]); // TODO: actually only one line is needed ... // for (int i=0; i < lines.Length ; i++) { string line = lines [0]; if (debugShowData) { EWUnityExtensions.Log("Line to parse is '" + line + "'"); } JSONNode rootNode = JSON.Parse(line); // EWUnityExtensions.Log ("input interpreted as Json has values # " + rootNode.Count); JSONNode values = (JSONNode)rootNode ["values"]; if (values != null) { // EWUnityExtensions.Log ("=> values has => # " + values.Count); } for (int j = 0; j < inNames.Length; j++) { string inValName = inNames [j]; JSONNode valueArray = values [j]; // TODO: parse the values and split them appropriately. inputs can be look: // [[], [], [], [], [0.990325079762794], [-0.2852937250435257]] // OR [[0.990325079762794,0.123], [], [], [], [], [-0.2852937250435257]] // OR [[], [], [], [], [], []] // OR [[0.123], [0.123], [0.123], [0.123], [0.123], [0.123]] bool foundFitting = false; if (this.debugShowData) { // EWUnityExtensions.Log("# controlInputs to update: " + ControlInput.allControlsList.Count); } foreach (ControlInput ci in ControlInput.allControlsList) { if (ci.controlName == inValName) { float avg_val = 0; for (int ik = 0; ik < valueArray.Count; ik++) { JSONNode val = valueArray [ik]; bool isJsonClass = val is JSONClass; bool isJsonData = val is SimpleJSON.JSONData; if (debugShowData) { EWUnityExtensions.Log("val has count # " + val.Count + " and is json class ? " + isJsonClass); } if (isJsonClass && ci.isMultiInput) { JSONClass valDict = (JSONClass)val; if (debugShowData) { EWUnityExtensions.Log("valDict has children: #" + valDict.Count); } foreach (string key in valDict.GetKeys()) { float childVal = float.Parse(valDict [key]); if (debugShowData) { EWUnityExtensions.Log("=> found key " + key + " with value " + childVal); } string multiFullName = ControlInputMulti.MakeMultiValueName(ci.controlName, key); ControlInputMulti ciChild = null; if (ControlInputMulti.allMultiControls.ContainsKey(multiFullName) == false) { CreateQueueEntry entry = new CreateQueueEntry(); entry.ciParent = ci; entry.multiId = key; entry.name = multiFullName; entry.initVal = childVal; createQueue.Add(entry); } else { ciChild = ControlInputMulti.allMultiControls [multiFullName]; ciChild.SetCurrentValue(childVal); } } } else if (isJsonData) { avg_val += val.AsFloat; } else { EWUnityExtensions.LogWarning("Unknown json type" + val.ToString() + " " + val.GetType() + ", isMulti ? " + ci.isMultiInput); } } ci.SetCurrentValue(avg_val); foundFitting = true; break; } } if (foundFitting) { // EWUnityExtensions.Log("Found fitting control!"); } else { // EWUnityExtensions.Log("Found NOOOO fitting control!"); } } }
protected void HandleStream() { // EWUnityExtensions.Log("handleStream called"); NetworkStream stream = null; if (tcpclient != null && tcpclient.Connected) { stream = tcpclient.GetStream(); // reading if (stream != null && stream.DataAvailable) { int dataAvailable = tcpclient.Available; byte[] data = new byte[dataAvailable]; int bytesRead = 0; try { bytesRead = stream.Read(data, 0, data.Length); } catch { } if (bytesRead < data.Length) { byte[] lastData = data; data = new byte[bytesRead]; Array.ConstrainedCopy(lastData, 0, data, 0, bytesRead); // TODO / NOTE replace array with something unity like, so we can remove 'using system' } string data_str = ByteArrayToString(data); string[] lines = data_str.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None); if (debugShowData) { // EWUnityExtensions.Log("##### ExerWorldPlugin nr of lines " + lines.Length + " dataStr: " + data_str); } string[] usefulLines; // NOTE: there should be at least 2 lines when splitted by newlines if (lines.Length < 2) { // not enough // return; } else { // there are enough so use them // take the last line, before the empty last one usefulLines = new string[] { lines [lines.Length - 2] }; // TODO: ugly but works // ExerWorldPlugin.receivedAnyData = true; // TODO: remove / do different try { this.UpdateValues(usefulLines); } catch (SystemException e) { EWUnityExtensions.Log("ExerWorldPlugin something went terribly wrong while updateValues .... " + e); } } } else { EWUnityExtensions.Log("##### ExerWorldPlugin # readstream, no data available on stream"); } ////////////////////// writing if (stream != null) { // TODO: actually this info does not always have to be sent ... only when it changes ... /* // NOTE: old approach * string data = "#send# "; * * * // EWUnityExtensions.Log ("##### ExerWorldPlugin # inNames " + this.inNames.ToString() + " size: " + this.inNames.Length); * for (int i = 0; i < this.inNames.Length; i++) { * string inName = this.inNames [i]; * // EWUnityExtensions.Log ("inName is " + inName ); * data = data + inName + " "; * } */ string data = "#setName# " + this.gameID; // EWUnityExtensions.Log ("##### ExerWorldPlugin # data to send: '" + data + "'"); data += "\n"; // NOTE: this is important, because the master server will read till the new line delimiter byte[] byteData = Encoding.ASCII.GetBytes(data); stream.Write(byteData, 0, byteData.Length); stream.Flush(); } else { EWUnityExtensions.Log("##### ExerWorldPlugin # handleStream, writing fail ...."); } } else { EWUnityExtensions.LogSometimes("##### ExerWorldPlugin readStream: tcpclient not available"); } }