public async Task SendDead() { var rnd = new Random(); if (IsEnd) { return; } var buffer = new byte[1]; try { if (!MainGame.Settings.autoRespawn) { State = BotState.IsDead; buffer[0] = (byte)Message.m_dead; Console.WriteLine($"Bot {bot.Name} is dead!"); await webSocket.SendAsync(new ArraySegment <byte>(buffer, 0, buffer.Length), WebSocketMessageType.Binary, true, CancellationToken.None); } else { var rand_number = rnd.Next(MainGame.respawnList_X.Count - 1); bot.Energy = MainGame.Settings.EnergyStart; buffer[0] = (byte)Message.m_Respawn; BattleLogger.logger.info($"Bot {bot.Name} will respawn soon!"); await webSocket.SendAsync(new ArraySegment <byte>(buffer, 0, buffer.Length), WebSocketMessageType.Binary, true, CancellationToken.None); MapXY xy = MainGame.SearchEmptyCase(); if (MainGame.respawnList_X[rand_number] == xy.X && MainGame.respawnList_Y[rand_number] == xy.Y) { bot.X = (byte)MainGame.respawnList_X[rand_number]; bot.Y = (byte)MainGame.respawnList_Y[rand_number]; State = BotState.IsRespawned; } } } catch (Exception err) { Console.WriteLine($"[ERROR] {err.Message}"); State = BotState.Error; } if (MainGame.TheMap[bot.X, bot.Y] == CaseState.Ennemy) { MainGame.TheMap[bot.X, bot.Y] = CaseState.Energy; } MainGame.SendCockpitInfo(bot.GUID, new ArraySegment <byte>(buffer, 0, buffer.Length)); }
/// <summary> /// réception des messages /// fin si le client se déconnecte /// </summary> /// <returns></returns> public async Task WaitReceive() { //Console.WriteLine("First, listen for GUID"); // 1 - on attend la première data du client // qui doit etre son GUID var buffer = new byte[1024 * 4]; WebSocketReceiveResult result = null; try { result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None); Console.WriteLine($"[DEBUG] {result}"); } catch (Exception err) { Console.WriteLine($"[ERROR] {err.Message}"); //Console.WriteLine($"[ERROR] {err.Message}"); IsEnd = true; State = BotState.Disconnect; try { await webSocket.CloseAsync(WebSocketCloseStatus.ProtocolError, "Error waiting data", CancellationToken.None); } catch (Exception) { } return; } while (!result.CloseStatus.HasValue) { // 2 - réception du GUID if (State == BotState.WaitingGUID) { if (result.Count != 38 && result.Count != 36 && result.Count != 32) // pas de GUID ? { IsEnd = true; State = BotState.Disconnect; if (result.Count > 0) { var temp = System.Text.Encoding.UTF8.GetString(buffer, 0, result.Count); Console.WriteLine($"[ERROR GUID] {temp}"); } await webSocket.CloseAsync(WebSocketCloseStatus.ProtocolError, "No GUID", CancellationToken.None); return; } var text = System.Text.Encoding.UTF8.GetString(buffer, 0, result.Count); // check que l'on a reçu un GUID if (Guid.TryParse(text, out bot.GUID)) { // et qu'il soit ok ! bot.Name = bot.GUID.ToString(); MapXY xy = MainGame.SearchEmptyCase(); MainGame.TheMap[xy.X, xy.Y] = CaseState.Ennemy; bot.X = xy.X; bot.Y = xy.Y; bot.Energy = MainGame.Settings.EnergyStart; bot.Score = 0; Console.WriteLine($"[NEW BOT] {bot.GUID} @ {xy.X}/{xy.Y}"); State = BotState.Ready; await SendMessage("OK"); //MainGame.RefreshViewer(); SendPositionToCockpit(); //await StartNewTurn(); } else { IsEnd = true; State = BotState.Disconnect; await webSocket.CloseAsync(WebSocketCloseStatus.ProtocolError, $"[{text}] is not a GUID", CancellationToken.None); return; } } // réception GUID else { // exécute une action if (result.Count < 1) { MainGame.TheMap[bot.X, bot.Y] = CaseState.Empty; IsEnd = true; State = BotState.Disconnect; await webSocket.CloseAsync(WebSocketCloseStatus.ProtocolError, "Missing data in answer", CancellationToken.None); return; } Console.WriteLine($"State {State}"); // On reçoit une commande du BOT switch (State) { case BotState.WaitingAnswerD: // le niveau de détection désiré pour ce tour string command = System.Text.Encoding.UTF8.GetString(buffer, 0, 1); if (command != "D") { MainGame.TheMap[bot.X, bot.Y] = CaseState.Empty; IsEnd = true; State = BotState.Disconnect; await webSocket.CloseAsync(WebSocketCloseStatus.ProtocolError, $"[ERROR] Not the right answer, waiting D#, receive {command}", CancellationToken.None); return; } // commande D sans niveau... if (result.Count < 1) { MainGame.TheMap[bot.X, bot.Y] = CaseState.Empty; IsEnd = true; State = BotState.Disconnect; await webSocket.CloseAsync(WebSocketCloseStatus.ProtocolError, "Missing data in answer 'D'", CancellationToken.None); return; } // do a scan of size value and send answer byte distance = buffer[1]; Console.WriteLine($"{bot.Name}: scan distance={distance}"); if (distance > 0) { if (distance < bot.Energy) { bot.Energy -= distance; await SendChangeInfo(); await DoScan(distance); } else { bot.Energy = 0; State = BotState.IsDead; await SendChangeInfo(); await SendDead(); } } else { // ici cas simple du scan à 0, pas de conso d'énergie await DoScan(distance); } break; case BotState.WaitingAction: // l'action a effectuer BotAction action = (BotAction)buffer[0]; switch (action) { case BotAction.None: // None State = BotState.Ready; Console.WriteLine($"Bot {bot.Name} do nothing"); await SendMessage("OK"); break; case BotAction.Move: // move if (result.Count < 2) { MainGame.TheMap[bot.X, bot.Y] = CaseState.Empty; IsEnd = true; State = BotState.Disconnect; await webSocket.CloseAsync(WebSocketCloseStatus.ProtocolError, "Missing data in answer 'M'", CancellationToken.None); return; } byte direction = buffer[1]; Console.WriteLine($"Bot {bot.Name} moving direction {(MoveDirection)direction}"); await DoMove((MoveDirection)direction); State = BotState.Ready; await SendMessage("OK"); MainGame.RefreshViewer(); break; case BotAction.ShieldLevel: // shield if (result.Count < 3) { MainGame.TheMap[bot.X, bot.Y] = CaseState.Empty; IsEnd = true; State = BotState.Disconnect; await webSocket.CloseAsync(WebSocketCloseStatus.ProtocolError, "Missing data in answer 'S'", CancellationToken.None); return; } UInt16 shieldLevel = (UInt16)(buffer[1] + (buffer[2] << 8)); Console.WriteLine($"Bot {bot.Name} activate shield level {shieldLevel}"); bot.Energy += bot.ShieldLevel; bot.ShieldLevel = shieldLevel; MainGame.ViewerPlayerShield(bot.X, bot.Y, (byte)bot.ShieldLevel); if (shieldLevel > bot.Energy) { bot.ShieldLevel = 0; bot.Energy = 0; await SendChangeInfo(); await SendDead(); } else bot.Energy -= shieldLevel; State = BotState.Ready; await SendMessage("OK"); break; case BotAction.CloakLevel: // cloak if (result.Count < 3) { MainGame.TheMap[bot.X, bot.Y] = CaseState.Empty; IsEnd = true; State = BotState.Disconnect; await webSocket.CloseAsync(WebSocketCloseStatus.ProtocolError, "Missing data in answer 'C'", CancellationToken.None); return; } UInt16 cloakLevel = (UInt16)(buffer[1] + (buffer[2] << 8)); Console.WriteLine($"Bot {bot.Name} activate cloak level {cloakLevel}"); // on récupère l'énergie actuelle dans le cloak bot.Energy += (UInt16)(bot.CloakLevel / MainGame.Settings.EnergyCloakCostMultiplier); // a-t-on assez d'énergie pour le niveau demandé ? if (cloakLevel * MainGame.Settings.EnergyCloakCostMultiplier > bot.Energy) { bot.CloakLevel = 0; bot.Energy = 0; await SendChangeInfo(); await SendDead(); } else { bot.Energy -= (UInt16)(cloakLevel * MainGame.Settings.EnergyCloakCostMultiplier); bot.CloakLevel = cloakLevel; MainGame.ViewerPlayerCloak(bot.X, bot.Y, (byte)bot.CloakLevel); } State = BotState.Ready; await SendMessage("OK"); break; case BotAction.Shoot: if (result.Count < 2) { MainGame.TheMap[bot.X, bot.Y] = CaseState.Empty; IsEnd = true; State = BotState.Disconnect; await webSocket.CloseAsync(WebSocketCloseStatus.ProtocolError, "Missing data in answer 'F'", CancellationToken.None); return; } byte fireDirection = buffer[1]; Console.WriteLine($"Bot {bot.Name} shoot in direction {fireDirection}"); if (bot.Energy >= MainGame.Settings.EnergyLostShot) { bot.Energy -= MainGame.Settings.EnergyLostShot; if (turn == 1) await IsHit(); else DoShoot(fireDirection); } else bot.Energy = 0; if (bot.Energy == 0) { await SendChangeInfo(); await SendDead(); } State = BotState.Ready; await SendMessage("OK"); break; default: Console.WriteLine($"[ERROR] lost with command {action} for state Action"); MainGame.TheMap[bot.X, bot.Y] = CaseState.Empty; IsEnd = true; State = BotState.Disconnect; await webSocket.CloseAsync(WebSocketCloseStatus.ProtocolError, $"[ERROR] lost with command {action} for state Action", CancellationToken.None); return; } break; default: string cmd = System.Text.Encoding.UTF8.GetString(buffer, 0, 1); // on reçoit le nom du BOT if (cmd == "N" && result.Count > 1) { bot.Name = System.Text.Encoding.UTF8.GetString(buffer, 1, result.Count - 1); Console.WriteLine($"Le BOT {bot.GUID} se nomme {bot.Name}"); State = BotState.Ready; //MainGame.SendCockpitInfo(bot.GUID, "N" + bot.Name); MainGame.RefreshViewer(); await SendMessage("OK"); break; } Console.WriteLine($"[ERROR] lost with state {State}"); MainGame.TheMap[bot.X, bot.Y] = CaseState.Empty; IsEnd = true; State = BotState.Disconnect; await webSocket.CloseAsync(WebSocketCloseStatus.ProtocolError, $"[ERROR] lost with state {State}", CancellationToken.None); return; } /*var text = System.Text.Encoding.UTF8.GetString(buffer, 0, result.Count); if (text.IndexOf(ClientGuid.ToString()) < 0) MainGame.Broadcast(text + " " + ClientGuid.ToString()); */ /*text = text + " et " + text + " :)"; buffer = System.Text.Encoding.UTF8.GetBytes(text); await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, buffer.Length), result.MessageType, result.EndOfMessage, CancellationToken.None); */ } //result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None); try { result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None); } catch (Exception err) { Console.WriteLine($"[ERROR] {err.Message}"); if (MainGame.TheMap[bot.X, bot.Y] == CaseState.Ennemy) MainGame.TheMap[bot.X, bot.Y] = CaseState.Empty; IsEnd = true; State = BotState.Disconnect; try { await webSocket.CloseAsync(WebSocketCloseStatus.ProtocolError, "Error waiting data", CancellationToken.None); } catch (Exception) { } return; } } if (MainGame.TheMap[bot.X, bot.Y] == CaseState.Ennemy) MainGame.TheMap[bot.X, bot.Y] = CaseState.Empty; await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); IsEnd = true; State = BotState.Disconnect; }