/// <summary> /// Execute a command and wait for a response, blocking main calling thread. Once response given return. /// </summary> /// <param name="Cmd">Command to be sent to the rcon server for the minecraft server to execute.</param> /// <returns>If command is sent and a response given, the repsonse is removed from the response que an returned.</returns> public async Task <string> ExecuteCmd(string Cmd) { var sw = new System.Diagnostics.Stopwatch(); var ts = TimeSpan.FromSeconds(5); sw.Restart(); if (AbortTCP == true) { return("RCON_ABORTED"); } RconPacket p; StringBuilder sb = new StringBuilder(); TimeCheck tc = new TimeCheck(); QueCommand(Cmd); while (Count == 0) { await Task.Delay(100); if (AbortTCP == true) { break; } if (sw.Elapsed > ts) { break; } } while (Count > 0) { p = Dequeue(); sb.Append(p.Response); if (AbortTCP == true) { break; } } return(sb.ToString()); }
/// <summary> /// Start the asynchronous communication process. /// </summary> /// <returns>True of successfully started, otherwise false.</returns> public bool StartComms() { if (bgCommThread != null) { if (bgCommThread.IsAlive) { StopComms(); } } bgCommThread = null; TimeCheck tc; tc = new TimeCheck(10000); bgCommThread = new Thread(ConnectAndProcess) { IsBackground = true }; StateTCP = TCPState.IDLE; StateRCon = RConState.IDLE; bgCommThread.Start(); while (tc.Expired == false) { if (StateTCP == TCPState.CONNECTED) { if (StateRCon == RConState.READY) { return(true); } } if (StateTCP == TCPState.ABORTED) { break; } } return(false); }
public async Task <string> ExecuteCmdAsync(string cmd) { if (AbortTCP == true) { return("RCON_ABORTED"); } RconPacket p; StringBuilder sb = new StringBuilder(); TimeCheck tc = new TimeCheck(); QueCommand(cmd); while (Count == 0) { await Task.Delay(100); if (AbortTCP == true) { break; } if (tc.Expired == true) { break; } } while (Count > 0) { p = Dequeue(); sb.Append(p.Response); if (AbortTCP == true) { break; } } return(sb.ToString()); }
/// <summary> /// Execute a command and wait for a response, blocking main calling thread. Once response given return. /// </summary> /// <param name="Cmd">Command to be sent to the rcon server for the minecraft server to execute.</param> /// <returns>If command is sent and a response given, the repsonse is removed from the response que an returned.</returns> public string ExecuteCmd(string Cmd) { if (AbortTCP == true) { return("RCON_ABORTED"); } RconPacket p; StringBuilder sb = new StringBuilder(); TimeCheck tc = new TimeCheck(); QueCommand(Cmd); while (Count == 0) { Thread.Sleep(100); if (AbortTCP == true) { break; } if (tc.Expired == true) { break; } } while (Count > 0) { p = Dequeue(); sb.Append(p.Response); if (AbortTCP == true) { break; } } return(sb.ToString()); }
/// <summary> /// Without knowing the safe heighth to be teleported to, a search is done. /// Several command exchanges will occur with the server as fast as they can /// which may require throttle controlls. If a safe space cannot be found, the player /// is returned from the location found prior to the transfer. Any operators on the server will /// receive RCON spam. /// </summary> /// <param name="r">The active RCon connection.</param> /// <param name="sb">Output cache from RCon interaction, html encoded.</param> /// <param name="player">Player name on the server, must be logged in.</param> /// <param name="x">X axis</param> /// <param name="y">Y axis</param> /// <param name="z">Z axis</param> public void TeleportSafeSearch(TCPRcon r, StringBuilder sb, String player, Int32 x, Int32 y, Int32 z) { if (isbusy == true) { sb.AppendFormat(@"<br/>{0} Teleporter busy, try again in a bit...", DateTime.Now); return; } else { isbusy = true; } if (r.IsReadyForCommands) { try { string resp = ""; bool safeTp = false; r.ExecuteCmd("tell {0} To lands unknown you go!!!", player); r.ExecuteCmd("gamemode sp {0}", player); r.ExecuteCmd("tp {3} {0} {1} {2}", x, y, z, player); sb.AppendFormat(@"<br/>{0} Initiated TP sequence for {1}. Waiting for chunk loads", DateTime.Now, player); TimeCheck tchk = new TimeCheck(8000); while (tchk.Expired == false) { resp = r.ExecuteCmd(@"testforblock {0} {1} {2} minecraft:air", x, y, z); if (!resp.Contains("Cannot test")) { break; } Thread.Sleep(1000); } if (!resp.Contains("Successfully") && r.ExecuteCmd("testforblock {0} {1} {2} minecraft:air", x, y + 1, z).Contains("Successfully") && !r.ExecuteCmd("testforblock {0} {1} {2} minecraft:air", x, y - 1, z).Contains("Successfully") && !r.ExecuteCmd("testforblock {0} {1} {2} minecraft:lava", x, y - 1, z).Contains("Successfully")) { sb.AppendFormat(@"<br/>{0} Found safe landing at {1} {3} {2}", DateTime.Now, x, z, y); safeTp = true; } else { sb.AppendFormat(@"<br/>{0} Scanning for safe landing", DateTime.Now); r.ExecuteCmd("tell {0} Looking for safe tp landing site...", player); for (Int32 yy = 255; yy > 1; yy = yy - 15) { if (!r.ExecuteCmd("testforblock {0} {1} {2} minecraft:air", x, yy, z).Contains("Successfully") || yy < 30) { for (Int32 ys = yy + 15; ys > 1; ys--) { if (!r.ExecuteCmd("testforblock {0} {1} {2} minecraft:air", x, ys, z).Contains("Successfully") && !r.ExecuteCmd("testforblock {0} {1} {2} minecraft:lava", x, ys, z).Contains("Successfully")) { if (r.ExecuteCmd("testforblock {0} {1} {2} minecraft:air", x, ys + 1, z).Contains("Successfully") && r.ExecuteCmd("testforblock {0} {1} {2} minecraft:air", x, ys + 2, z).Contains("Successfully")) { r.ExecuteCmd("tp {3} {0} {1} {2}", x, ys + 1, z, player); sb.AppendFormat(@"<br/>{0} Found safe landing at {1} {3} {2}", DateTime.Now, x, z, ys + 1); safeTp = true; break; } } } } if (safeTp) { break; } } } if (safeTp == false) { sb.AppendFormat(@"<br/>{0} No safe landing found, return to nexus", DateTime.Now); r.ExecuteCmd("tell {0} No safe tp found, returned to nexus", player); r.ExecuteCmd("tp {0} 0 65 0", player); r.ExecuteCmd("gamemode s {0}", player); } else { r.ExecuteCmd("tell {0} Welcome to your new adventure...", player); r.ExecuteCmd("gamemode s {0}", player); } } catch (Exception) { sb.AppendFormat(@"<br/>{0} Unexpected error occured in processing safe teleport", DateTime.Now); } } isbusy = false; }
private void Comms(TcpClient cli) { TimeCheck tc = new TimeCheck(); Int32 dT = 200; cli.SendTimeout = 5000; cli.ReceiveTimeout = 20000; try { if (cli.Connected == false) //Not connected, shut it down... { StateRCon = RConState.NETWORK_FAIL; StateTCP = TCPState.ABORTED; AbortTCP = true; } tc.Reset(dT); while (AbortTCP == false) { do { if (cli.Client.Poll(0, SelectMode.SelectRead)) { byte[] buff = new byte[1]; if (cli.Client.Receive(buff, SocketFlags.Peek) == 0) { //client seems to be closed - lets close it StateTCP = TCPState.CLOSED; StateRCon = RConState.NETWORK_FAIL; AbortTCP = true; break; } } if (cli.Available > 0) { RconPacket resp = new RconPacket(); resp.ReadFromNetworkSteam(cli.GetStream()); if (resp.IsBadPacket == true) { StateTCP = TCPState.ABORTED; StateRCon = RConState.NETWORK_FAIL; AbortTCP = true; break; } if (Count > 1500) { StateRCon = RConState.IDLE; StateTCP = TCPState.ABORTED; AbortTCP = true; break; } else { Enqueue(resp); StateRCon = RConState.READY; } if (tc.Expired == false) { tc.Reset(dT); } } Thread.Sleep(1); } while (tc.Expired == false || cli.Available > 0); if (AbortTCP == true) { break; } if (cmdQue.Count > 0) { RconPacket Cmd = cmdQue.Dequeue(); Cmd.SendToNetworkStream(cli.GetStream()); tc.Reset(dT); } Thread.Sleep(1); } } catch (Exception ee) { AbortTCP = true; var sb = new StringBuilder(); var ex = ee; do { sb.AppendLine(ex.Message); ex = ee.InnerException; } while (ex != null); LastTCPError = sb.ToString(); StateTCP = TCPState.ABORTED; StateRCon = RConState.NETWORK_FAIL; } if (cli.Connected) { cli.Close(); } }