/// <summary> /// [Bet365.com][Score] Методы для обработки информации с рынков в единое целое. /// </summary> /// <param name="b365SingleData"> Вся информация с рынка betfair</param> private void ParseAllData(List <Scores> b365SingleData) { var count = 0; try { var eventId = b365SingleData[0].name + "|" + b365SingleData[1].name; foreach (var allMarket in AllMarketsHashSet) { if (allMarket.Bet365EventId != null && allMarket.Bet365EventId.Equals(eventId)) { allMarket.Player1.ScoreBet366 = b365SingleData[0].score; allMarket.Player2.ScoreBet366 = b365SingleData[1].score; //allMarket.MarketName = b365SingleData.CompetitionType; PlayerChanged?.Invoke(new ScoreUpdEventArgs(allMarket)); } } count = 0; } catch (Exception) { count++; if (count >= 20) { throw new Exception("Ошибка в обработке маркетов"); } } }
/// <summary> /// [SkyBet.com][Score] Метод для обработки информации с рынков в единое целлое /// </summary> /// <param name="skyBetSingleData">Вся полученная информация с рынка skyBet</param> private void ParseAllData(List <TO.NewSkyBet.Scores> skyBetSingleData) { var count = 0; try { var eventId = skyBetSingleData[0].eventId; foreach (var allMarket in AllMarketsHashSet) { if (allMarket.SkyBetEventId != null && allMarket.SkyBetEventId.Equals(eventId)) { allMarket.Player1.ScoreSkyBet = skyBetSingleData[1].score; allMarket.Player2.ScoreSkyBet = skyBetSingleData[2].score; allMarket.SkyBetEventId = eventId; PlayerChanged?.Invoke(new ScoreUpdEventArgs(allMarket)); break; } } count = 0; } catch (Exception) { count++; if (count >= 20) { throw new Exception("Ошибка в обработке маркетов"); } } }
public string DirectionPlayer(Field field, Gamer gamer, KeyEventArgs args, string direction) { var dir = direction; var playerX = gamer.PlayerPic.Location.X; var playerY = gamer.PlayerPic.Location.Y; switch (args.KeyCode.ToString()) { case "D" when CanMove(field.Dic, playerX + 50, playerY): dir = "Right"; PlayerChanged?.Invoke("playerRightGIF.gif"); break; case "A" when CanMove(field.Dic, playerX - 50, playerY): dir = "Left"; PlayerChanged?.Invoke("playerLeftGIF.gif"); break; case "W" when CanMove(field.Dic, playerX, playerY - 50): dir = "Up"; PlayerChanged?.Invoke("playerUpGIF.gif"); break; case "S" when CanMove(field.Dic, playerX, playerY + 50): dir = "Down"; PlayerChanged?.Invoke("playerDownGIF.gif"); break; } return(dir); }
public override void OnServerDisconnect(NetworkConnection conn) { base.OnServerDisconnect(conn); PlayerChanged?.Invoke(this, new PlayerChangedEventArgs(PlayerChangedEventArgs.Change.Disconnected, 0)); End(); }
public void AutoMoving(Dictionary <Point, PictureBox> dic, string direction, PictureBox enemyRed, PictureBox enemyYellow, RandomBox box) { var playerX = PlayerPic.Location.X; var playerY = PlayerPic.Location.Y; if (PlayerPic.Location == enemyRed.Location) { Application.Exit(); } if (PlayerPic.Location == enemyYellow.Location) { Application.Exit(); } if (PlayerPic.Location == box.boxPic.Location) { box.Roulete(); } switch (direction) { case "Right" when playerX + 50 == 750 && playerY == 400: CoinChanged?.Invoke(dic, playerX, playerY); PlayerPic.Location = new Point(0, 400); PlayerChanged?.Invoke("playerRightGIF.gif"); break; case "Right" when CanMove(dic, playerX + 50, playerY): CoinChanged?.Invoke(dic, playerX, playerY); PlayerPic.Left += 50; break; case "Left" when playerX - 50 == -50 && playerY == 400: CoinChanged?.Invoke(dic, playerX, playerY); PlayerPic.Location = new Point(700, 400); PlayerChanged?.Invoke("playerLeftGIF.gif"); break; case "Left" when CanMove(dic, playerX - 50, playerY): CoinChanged?.Invoke(dic, playerX, playerY); PlayerPic.Left -= 50; break; case "Up" when CanMove(dic, playerX, playerY - 50): CoinChanged?.Invoke(dic, playerX, playerY); PlayerPic.Top -= 50; break; case "Down" when CanMove(dic, playerX, playerY + 50): CoinChanged?.Invoke(dic, playerX, playerY); PlayerPic.Top += 50; break; } }
public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId) { var playerSpawnPos = GetMyStartPosition(); var player = Instantiate(playerPrefab, playerSpawnPos, Quaternion.identity); NetworkServer.AddPlayerForConnection(conn, player, playerControllerId); numPlayer++; Debug.Log("Got connection, sending event"); PlayerChanged?.Invoke(this, new PlayerChangedEventArgs(PlayerChangedEventArgs.Change.Connected, numPlayer)); }
public void Start(string firstPlayerName, string secondPlayerName) { GameField = new Field(); GameDeck = new Deck(); UserPlayer = CreatePlayer(firstPlayerName); BotPlayer = CreatePlayer(secondPlayerName); _isUserCurrent = UserIsFirst(); var wordForm = _isUserCurrent ? "ходишь ты" : "ходит AI"; MessageBox.Show($@"Первым {wordForm}"); ChangeStage(GameStage.Play); PlayerChanged?.Invoke(CurrentPlayer, true); }
private void BrowserOnConsoleMessage(object sender, ConsoleMessageEventArgs e) { if (isIgnoredMarket) { Debug.WriteLine("[IGNORED][SkyBet]Console: " + e.Message); return; } Debug.WriteLine("[SkyBet]Console: " + e.Message); if (e.Message.Contains("FINISHED")) { State = ThreadState.Stopped; } if (e.Message[0] == '1') { var tmp = e.Message.Split('|'); var main = tmp[1]; var scores = JsonConvert.DeserializeObject <List <Scores> >(main); var score1 = scores[1].score; var score2 = scores[2].score; var eventId = scores[0].eventId; if ((!string.IsNullOrWhiteSpace(prevScoreOne)) && (!string.IsNullOrWhiteSpace(prevScoreTwo))) { if (!((score1 == "0") && (score2 == "0"))) { if (((score1 == "0") && (score1 != prevScoreOne)) || ((score2 == "0") && (score2 != prevScoreTwo))) { return; } } } foreach (var currentMarket in allMarkets.ParsingInfo.AllMarketsHashSet) { if ((!string.IsNullOrWhiteSpace(currentMarket.SkyBetEventId)) && (currentMarket.SkyBetEventId.Equals(eventId))) { prevScoreOne = score1; prevScoreTwo = score2; currentMarket.Player1.ScoreSkyBet = score1; currentMarket.Player2.ScoreSkyBet = score2; PlayerChanged?.Invoke(new ScoreUpdEventArgs(currentMarket)); break; } } } if (e.Message[0] == '2') { var str = e.Message.Split('|'); var elem = str[1]; MessageChanged?.Invoke(new MessagesEventArgs(elem, TypeDBO.SkyBet)); } }
/// <summary> /// [betfair.com][Score] Методы для обработки информации с рынков в единое целое. /// </summary> /// <param name="betfairSingleData"> Вся информация с рынка betfair</param> private void ParseAllData(List <GetScore> betfairSingleData) { var count = 0; try { if (betfairSingleData == null) { throw new ArgumentNullException(nameof(betfairSingleData)); } if (betfairSingleData.Count == 0) { return; } var eventId = betfairSingleData[0].eventId; foreach (var allMarket in AllMarketsHashSet) { if (allMarket.BetfairEventId != null && eventId == int.Parse(allMarket.BetfairEventId)) { allMarket.Player1.ScoreBetfair1 = betfairSingleData[0].score.home.score; allMarket.Player2.ScoreBetfair1 = betfairSingleData[0].score.away.score; allMarket.Player2.Name = betfairSingleData[0].score.away.name; allMarket.Player1.Name = betfairSingleData[0].score.home.name; if (betfairSingleData[0].matchStatus.ToLower() == "finished") { allMarket.IsClose = true; } PlayerChanged?.Invoke(new ScoreUpdEventArgs(allMarket)); } } count = 0; } catch (Exception) { count++; if (count >= 20) { throw new Exception("Ошибка в обработке маркетов"); } } }
public Player ChangePlayer(Player i_FirstPlayer, Player i_SecondPlayer) { Player nextTurnPlayer; if (this == i_FirstPlayer) { nextTurnPlayer = i_SecondPlayer; } else { nextTurnPlayer = i_FirstPlayer; } if (PlayerChanged != null) { PlayerChanged.Invoke(); } return(nextTurnPlayer); }
private void BrowserOnConsoleMessage(object sender, ConsoleMessageEventArgs consoleMessageEventArgs) { if (isIgnoredMarket) { Console.WriteLine("[IGNORED][Bet365]Console: " + consoleMessageEventArgs.Message); return; } Console.WriteLine("[Bet365]Console: " + consoleMessageEventArgs.Message); if (consoleMessageEventArgs.Message.Contains("Mixed Content")) { isLoad = true; browser.LoadingStateChanged += BrowserOnLoadingStateChanged; browser.EvaluateScriptAsync("clickToTennis()"); BrowserOnLoadingStateChanged(sender, new LoadingStateChangedEventArgs(null, false, false, false)); } if (consoleMessageEventArgs.Message[0] == '1') { var tmp = consoleMessageEventArgs.Message.Split('|'); var elem = tmp[1]; var scores = JsonConvert.DeserializeObject <List <Scores> >(elem); var player1 = scores[0]; var player2 = scores[1]; var eventId = player1.name + "|" + player2.name; if ((!string.IsNullOrWhiteSpace(prevScoreOne)) && (!string.IsNullOrWhiteSpace(prevScoreTwo))) { var score1 = player1.score; var score2 = player2.score; if (!((score1 == "0") && (score2 == "0"))) { if (((score1 == "0") && (score1 != prevScoreOne)) || ((score2 == "0") && (score2 != prevScoreTwo))) { return; } } } foreach (var currentMarket in allMarkets.ParsingInfo.AllMarketsHashSet) { if (!(string.IsNullOrEmpty(currentMarket.Bet365EventId)) && (currentMarket.Bet365EventId.Equals(eventId))) { prevScoreOne = player1.score; prevScoreTwo = player2.score; currentMarket.Player1.ScoreBet366 = player1.score; currentMarket.Player2.ScoreBet366 = player2.score; PlayerChanged?.Invoke(new ScoreUpdEventArgs(currentMarket)); break; } } } if (consoleMessageEventArgs.Message[0] == '2') { var elem = consoleMessageEventArgs.Message.Split('/'); var tmp = elem[1].Split('|'); if (tmp.Length == 2) { var player1Message = tmp[0]; var player2Message = tmp[1]; MessageChanged?.Invoke(new MessagesEventArgs(TypeDBO.Bet365, player1Message, player2Message)); } } }
protected virtual void OnPlayerChanged(EventArgs e) { PlayerChanged?.Invoke(this, e); }
private void OnPlayerChanged() { PlayerChanged?.Invoke(this, EventArgs.Empty); }
public void RunLoop() { while (true) { try { if (!ProcessMemory.getInstance().IsHooked || ProcessMemory.getInstance().process is null || ProcessMemory.getInstance().process.HasExited) { if (!ProcessMemory.getInstance().HookProcess("Among Us")) { Thread.Sleep(1000); continue; } Settings.conInterface.WriteModuleTextColored("GameMemReader", Color.Lime, $"Connected to Among Us process ({Color.Red.ToTextColor()}{ProcessMemory.getInstance().process.Id}{Settings.conInterface.getNormalColor().ToTextColor()})"); var foundModule = false; while (true) { foreach (var module in ProcessMemory.getInstance().modules) { if (module.Name.Equals("GameAssembly.dll", StringComparison.OrdinalIgnoreCase)) { GameAssemblyPtr = module.BaseAddress; if (!GameVerifier.VerifySteamHash(module.FileName)) { cracked = true; Settings.conInterface.WriteModuleTextColored("GameVerifier", Color.Red, $"Client verification: {Color.Red.ToTextColor()}FAIL{Settings.conInterface.getNormalColor().ToTextColor()}."); } else { cracked = false; Settings.conInterface.WriteModuleTextColored("GameVerifier", Color.Red, $"Client verification: {Color.Lime.ToTextColor()}PASS{Settings.conInterface.getNormalColor().ToTextColor()}."); } using (SHA256Managed sha256 = new SHA256Managed()) { using (FileStream fs = new FileStream(module.FileName, FileMode.Open, FileAccess.Read)) { using (var bs = new BufferedStream(fs)) { var hash = sha256.ComputeHash(bs); StringBuilder GameAssemblyhashSb = new StringBuilder(2 * hash.Length); foreach (byte byt in hash) { GameAssemblyhashSb.AppendFormat("{0:X2}", byt); } Console.WriteLine( $"GameAssembly Hash: {GameAssemblyhashSb.ToString()}"); GameHash = GameAssemblyhashSb.ToString(); CurrentOffsets = offMan.FetchForHash(GameAssemblyhashSb.ToString()); if (CurrentOffsets is not null) { Settings.conInterface.WriteModuleTextColored("GameMemReader", Color.Lime, $"Loaded offsets: {CurrentOffsets.Description}"); } else { Settings.conInterface.WriteModuleTextColored("GameMemReader", Color.Lime, $"No offsets found for: {Color.Aqua.ToTextColor()}{GameAssemblyhashSb.ToString()}{Settings.conInterface.getNormalColor().ToTextColor()}."); } } } } foundModule = true; break; } } if (!foundModule) { Settings.conInterface.WriteModuleTextColored("GameMemReader", Color.Lime, "Still looking for modules..."); //Program.conInterface.WriteModuleTextColored("GameMemReader", Color.Green, "Still looking for modules..."); // TODO: This still isn't functional, we need to re-hook to reload module addresses Thread.Sleep(500); // delay and try again ProcessMemory.getInstance().LoadModules(); } else { break; // we have found all modules } } try { if (CurrentOffsets is not null) { prevChatBubsVersion = ProcessMemory.getInstance().Read <int>(GameAssemblyPtr, CurrentOffsets.HudManagerOffset, 0x5C, 0, 0x28, 0xC, 0x14, 0x10); } // prevGameOverReason = ProcessMemory.getInstance().Read<GameOverReason>(GameAssemblyPtr, _gameOffsets.TempDataOffset, 0x5c, 4); } catch { Settings.conInterface.WriteModuleTextColored("ERROR", Color.Red, "Outdated version of the game."); } } if (cracked && ProcessMemory.getInstance().IsHooked) { var result = Settings.conInterface.CrackDetected(); if (!result) { Environment.Exit(0); } else { cracked = false; } continue; } if (CurrentOffsets is null) { continue; } GameState state; //int meetingHudState = /*meetingHud_cachePtr == 0 ? 4 : */ProcessMemory.ReadWithDefault<int>(GameAssemblyPtr, 4, 0xDA58D0, 0x5C, 0, 0x84); // 0 = Discussion, 1 = NotVoted, 2 = Voted, 3 = Results, 4 = Proceeding var meetingHud = ProcessMemory.getInstance() .Read <IntPtr>(GameAssemblyPtr, CurrentOffsets.MeetingHudOffset, 0x5C, 0); var meetingHud_cachePtr = meetingHud == IntPtr.Zero ? 0 : ProcessMemory.getInstance().Read <uint>(meetingHud, 0x8); var meetingHudState = meetingHud_cachePtr == 0 ? 4 : ProcessMemory.getInstance().ReadWithDefault(meetingHud, 4, 0x84); // 0 = Discussion, 1 = NotVoted, 2 = Voted, 3 = Results, 4 = Proceeding var gameState = ProcessMemory.getInstance().Read <int>(GameAssemblyPtr, CurrentOffsets.AmongUsClientOffset, 0x5C, 0, 0x64); // 0 = NotJoined, 1 = Joined, 2 = Started, 3 = Ended (during "defeat" or "victory" screen only) switch (gameState) { case 0: state = GameState.MENU; exileCausesEnd = false; break; case 1: case 3: state = GameState.LOBBY; exileCausesEnd = false; break; default: { if (exileCausesEnd) { state = GameState.LOBBY; } else if (meetingHudState < 4) { state = GameState.DISCUSSION; } else { state = GameState.TASKS; } break; } } //Console.WriteLine($"Got state: {state}"); var allPlayersPtr = ProcessMemory.getInstance() .Read <IntPtr>(GameAssemblyPtr, CurrentOffsets.GameDataOffset, 0x5C, 0, 0x24); var allPlayers = ProcessMemory.getInstance().Read <IntPtr>(allPlayersPtr, 0x08); var playerCount = ProcessMemory.getInstance().Read <int>(allPlayersPtr, 0x0C); var playerAddrPtr = allPlayers + 0x10; // check if exile causes end if (oldState == GameState.DISCUSSION && state == GameState.TASKS) { var exiledPlayerId = ProcessMemory.getInstance().ReadWithDefault <byte>(GameAssemblyPtr, 255, CurrentOffsets.MeetingHudOffset, 0x5C, 0, 0x94, 0x08); int impostorCount = 0, innocentCount = 0; for (var i = 0; i < playerCount; i++) { var pi = ProcessMemory.getInstance().Read <PlayerInfo>(playerAddrPtr, 0, 0); playerAddrPtr += 4; if (pi.PlayerId == exiledPlayerId) { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.Exiled, Name = pi.GetPlayerName(), IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } // skip invalid, dead and exiled players if (pi.PlayerName == 0 || pi.PlayerId == exiledPlayerId || pi.IsDead == 1 || pi.Disconnected == 1) { continue; } if (pi.IsImpostor == 1) { impostorCount++; } else { innocentCount++; } } if (impostorCount == 0 || impostorCount >= innocentCount) { exileCausesEnd = true; state = GameState.LOBBY; } } if (state != oldState || shouldForceTransmitState) { GameStateChanged?.Invoke(this, new GameStateChangedEventArgs { NewState = state }); shouldForceTransmitState = false; } if (state != oldState && state == GameState.LOBBY) { shouldReadLobby = true; // will eventually transmit } if ((oldState == GameState.DISCUSSION || oldState == GameState.TASKS) && (state == GameState.LOBBY || state == GameState.MENU)) // game ended { int rawGameOverReason = ProcessMemory.getInstance() .Read <int>(GameAssemblyPtr, CurrentOffsets.TempDataOffset, 0x5c, 0x4); GameOverReason gameOverReason = (GameOverReason)rawGameOverReason; bool humansWon = rawGameOverReason <= 1 || rawGameOverReason == 5; if (humansWon) // we will be reading humans data, so set all to simps { foreach (string playerName in CachedPlayerInfos.Keys) { try { CachedPlayerInfos[playerName].IsImpostor = true; } catch (KeyNotFoundException e) { Console.WriteLine($"Could not find User: \"{playerName}\" in CachedPlayerinfos"); } } } var winningPlayersPtr = ProcessMemory.getInstance() .Read <IntPtr>(GameAssemblyPtr, CurrentOffsets.TempDataOffset, 0x5C, 0xC); var winningPlayers = ProcessMemory.getInstance().Read <IntPtr>(winningPlayersPtr, 0x08); var winningPlayerCount = ProcessMemory.getInstance().Read <int>(winningPlayersPtr, 0x0C); var winnerAddrPtr = winningPlayers + 0x10; for (var i = 0; i < winningPlayerCount; i++) { WinningPlayerData wpi = ProcessMemory.getInstance() .Read <WinningPlayerData>(winnerAddrPtr, 0, 0); winnerAddrPtr += 4; try { CachedPlayerInfos[wpi.GetPlayerName()].IsImpostor = wpi.IsImpostor; } catch (KeyNotFoundException e) { Console.WriteLine($"Could not find player with name \"{wpi.GetPlayerName()}\" in CachedPlayerInfos. JSON: {JsonConvert.SerializeObject(CachedPlayerInfos, Formatting.Indented)}"); } } ImmutablePlayer[] endingPlayerInfos = new ImmutablePlayer[CachedPlayerInfos.Count]; CachedPlayerInfos.Values.CopyTo(endingPlayerInfos, 0); GameOver?.Invoke(this, new GameOverEventArgs { GameOverReason = gameOverReason, PlayerInfos = endingPlayerInfos }); } GameState cachedOldState = oldState; oldState = state; newPlayerInfos.Clear(); playerAddrPtr = allPlayers + 0x10; for (var i = 0; i < playerCount; i++) { var pi = ProcessMemory.getInstance().Read <PlayerInfo>(playerAddrPtr, 0, 0); playerAddrPtr += 4; if (pi.PlayerName == 0) { continue; } var playerName = pi.GetPlayerName(); if (playerName.Length == 0) { continue; } newPlayerInfos[playerName] = pi; // add to new playerinfos for comparison later if (!oldPlayerInfos.ContainsKey(playerName)) // player wasn't here before, they just joined { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.Joined, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } else { // player was here before, we have an old playerInfo to compare against var oldPlayerInfo = oldPlayerInfos[playerName]; if (!oldPlayerInfo.GetIsDead() && pi.GetIsDead()) // player just died { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.Died, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } if (oldPlayerInfo.ColorId != pi.ColorId) { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.ChangedColor, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } if (!oldPlayerInfo.GetIsDisconnected() && pi.GetIsDisconnected()) { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.Disconnected, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } } } foreach (var kvp in oldPlayerInfos) { var pi = kvp.Value; var playerName = kvp.Key; if (!newPlayerInfos.ContainsKey(playerName)) // player was here before, isn't now, so they left { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.Left, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } } oldPlayerInfos.Clear(); var emitAll = false; if (shouldForceUpdatePlayers) { shouldForceUpdatePlayers = false; emitAll = true; } if (state != cachedOldState && (state == GameState.DISCUSSION || state == GameState.TASKS) ) // game started, or at least we're still in game { CachedPlayerInfos.Clear(); foreach (var kvp in newPlayerInfos ) // do this instead of assignment so they don't point to the same object { var pi = kvp.Value; string playerName = pi.GetPlayerName(); CachedPlayerInfos[playerName] = new ImmutablePlayer() { Name = playerName, IsImpostor = false }; } } foreach (var kvp in newPlayerInfos ) // do this instead of assignment so they don't point to the same object { var pi = kvp.Value; oldPlayerInfos[kvp.Key] = pi; if (emitAll) { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.ForceUpdated, Name = kvp.Key, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } } var chatBubblesPtr = ProcessMemory.getInstance().Read <IntPtr>(GameAssemblyPtr, CurrentOffsets.HudManagerOffset, 0x5C, 0, 0x28, 0xC, 0x14); var poolSize = 20; // = ProcessMemory.Read<int>(GameAssemblyPtr, 0xD0B25C, 0x5C, 0, 0x28, 0xC, 0xC) var numChatBubbles = ProcessMemory.getInstance().Read <int>(chatBubblesPtr, 0xC); var chatBubsVersion = ProcessMemory.getInstance().Read <int>(chatBubblesPtr, 0x10); var chatBubblesAddr = ProcessMemory.getInstance().Read <IntPtr>(chatBubblesPtr, 0x8) + 0x10; var chatBubblePtrs = ProcessMemory.getInstance().ReadArray(chatBubblesAddr, numChatBubbles); var newMsgs = 0; if (chatBubsVersion > prevChatBubsVersion) // new message has been sent { if (chatBubsVersion > poolSize) // increments are twofold (push to and pop from pool) { if (prevChatBubsVersion > poolSize) { newMsgs = (chatBubsVersion - prevChatBubsVersion) >> 1; } else { newMsgs = poolSize - prevChatBubsVersion + ((chatBubsVersion - poolSize) >> 1); } } else // single increments { newMsgs = chatBubsVersion - prevChatBubsVersion; } } else if (chatBubsVersion < prevChatBubsVersion) // reset { if (chatBubsVersion > poolSize) // increments are twofold (push to and pop from pool) { newMsgs = poolSize + ((chatBubsVersion - poolSize) >> 1); } else // single increments { newMsgs = chatBubsVersion; } } prevChatBubsVersion = chatBubsVersion; for (var i = numChatBubbles - newMsgs; i < numChatBubbles; i++) { var msgText = ProcessMemory.getInstance() .ReadString(ProcessMemory.getInstance().Read <IntPtr>(chatBubblePtrs[i], 0x20, 0x28)); if (msgText.Length == 0) { continue; } var msgSender = ProcessMemory.getInstance() .ReadString(ProcessMemory.getInstance().Read <IntPtr>(chatBubblePtrs[i], 0x1C, 0x28)); var oldPlayerInfo = oldPlayerInfos[msgSender]; ChatMessageAdded?.Invoke(this, new ChatMessageEventArgs { Sender = msgSender, Message = msgText, Color = oldPlayerInfo.GetPlayerColor() }); } if (shouldReadLobby) { var gameCode = ProcessMemory.getInstance().ReadString(ProcessMemory.getInstance().Read <IntPtr>( GameAssemblyPtr, CurrentOffsets.GameStartManagerOffset, 0x5c, 0, 0x20, 0x28)); string[] split; if (gameCode != null && gameCode.Length > 0 && (split = gameCode.Split('\n')).Length == 2) { PlayRegion region = (PlayRegion)((4 - (ProcessMemory.getInstance() .Read <int>(GameAssemblyPtr, CurrentOffsets.ServerManagerOffset, 0x5c, 0, 0x10, 0x8, 0x8) & 0b11)) % 3); // do NOT ask //Recheck for GameOptionsOffset PlayMap map = (PlayMap)ProcessMemory.getInstance().Read <int>(GameAssemblyPtr, CurrentOffsets.GameOptionsOffset, 0x5c, 0x4, 0x10); this.latestLobbyEventArgs = new LobbyEventArgs() { LobbyCode = split[1], Region = region, Map = map, }; shouldReadLobby = false; shouldTransmitLobby = true; // since this is probably new info } } if (shouldTransmitLobby) { if (this.latestLobbyEventArgs != null) { JoinedLobby?.Invoke(this, this.latestLobbyEventArgs); } shouldTransmitLobby = false; } Thread.Sleep(250); } catch (Exception e) { Settings.conInterface.WriteModuleTextColored("ERROR", Color.Red, $"Message: {e.Message} stack: {e.StackTrace}"); Console.WriteLine(e); } } }
protected virtual void OnPlayerChanged(EventArgs e) { PlayerChanged?.Invoke(CurrentPlayer, e); }
internal void Trigger(Character actor) => PlayerChanged?.Invoke(actor);
//called when a player related event occurs (e.g. win, lose, health increase) protected virtual void OnPlayer(EventData eventData) { PlayerChanged?.Invoke(eventData); }
public void RunLoop() { while (true) { try { if (!ProcessMemory.getInstance().IsHooked) { if (!ProcessMemory.getInstance().HookProcess("Among Us")) { Thread.Sleep(1000); continue; } Settings.conInterface.WriteModuleTextColored("GameMemReader", Color.Lime, $"Connected to Among Us process ({Color.Red.ToTextColorPango(ProcessMemory.getInstance().process.Id.ToString())})"); // Check for a modified Among Us.exe & GameAssembly.dll // This generally doesn't mean that the game is pirated, but might mean that // the user is running an unsupported version, such as the beta. var foundModule = false; while (true) { foreach (var module in ProcessMemory.getInstance().modules) { if (module.Name.Equals("GameAssembly.dll", StringComparison.OrdinalIgnoreCase)) { GameAssemblyPtr = module.BaseAddress; using (SHA256Managed sha256 = new SHA256Managed()) { using (FileStream fs = new FileStream(module.FileName, FileMode.Open, FileAccess.Read)) { using (var bs = new BufferedStream(fs)) { var hash = sha256.ComputeHash(bs); StringBuilder GameAssemblyhashSb = new StringBuilder(2 * hash.Length); foreach (byte byt in hash) { GameAssemblyhashSb.AppendFormat("{0:X2}", byt); } Hash = GameAssemblyhashSb.ToString(); Settings.GameOffsets.GameHash = Hash; generateOffsets(); } } } if (!GameVerifier.VerifyGameHash(module.FileName)) { invalidversion = true; } else { invalidversion = false; } Settings.conInterface.WriteModuleTextColored("GameVerifier", Color.Red, $"Game Version Check: {(invalidversion ? Color.Red.ToTextColorPango("FAIL") : Color.Lime.ToTextColorPango("PASS"))}"); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && !GameVerifier.VerifySteamHash(module.FileName)) { cracked = true; } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && !GameVerifier.VerifySteamHash(module.FileName)) { cracked = true; } else { cracked = false; } Settings.conInterface.WriteModuleTextColored("GameVerifier", Color.Red, $"Game Validity Check: {(cracked ? Color.Red.ToTextColorPango("FAIL") : Color.Lime.ToTextColorPango("PASS"))}"); foundModule = true; break; } } if (!foundModule) { Settings.conInterface.WriteModuleTextColored("GameMemReader", Color.Lime, "Still looking for modules..."); //Program.conInterface.WriteModuleTextColored("GameMemReader", Color.Green, "Still looking for modules..."); // TODO: This still isn't functional, we need to re-hook to reload module addresses Thread.Sleep(500); // delay and try again ProcessMemory.getInstance().LoadModules(); } else { break; // we have found all modules } } prevChatBubsVersion = ProcessMemory.getInstance().Read <int>(GameAssemblyPtr, _gameOffsets.HudManagerOffset, 0x5C, 0, 0x28, 0xC, 0x14, 0x10); } while (paused) { Thread.Sleep(100); } if ((cracked || invalidversion) && ProcessMemory.getInstance().IsHooked) { GameVersionUnverified?.Invoke(this, new ValidatorEventArgs() { Validity = (cracked ? AmongUsValidity.STEAM_VERIFICAITON_FAIL : AmongUsValidity.OK) | (invalidversion ? AmongUsValidity.GAME_VERIFICATION_FAIL : AmongUsValidity.OK) }); paused = true; continue; } GameState state; //int meetingHudState = /*meetingHud_cachePtr == 0 ? 4 : */ProcessMemory.getInstance().ReadWithDefault<int>(GameAssemblyPtr, 4, 0xDA58D0, 0x5C, 0, 0x84); // 0 = Discussion, 1 = NotVoted, 2 = Voted, 3 = Results, 4 = Proceeding var meetingHud = ProcessMemory.getInstance() .Read <IntPtr>(GameAssemblyPtr, _gameOffsets.MeetingHudOffset, 0x5C, 0); var meetingHud_cachePtr = meetingHud == IntPtr.Zero ? 0 : ProcessMemory.getInstance().Read <uint>(meetingHud, 0x8); var meetingHudState = meetingHud_cachePtr == 0 ? 4 : ProcessMemory.getInstance().ReadWithDefault(meetingHud, 4, 0x84); // 0 = Discussion, 1 = NotVoted, 2 = Voted, 3 = Results, 4 = Proceeding var gameState = ProcessMemory.getInstance().Read <int>(GameAssemblyPtr, _gameOffsets.AmongUsClientOffset, 0x5C, 0, 0x64); // 0 = NotJoined, 1 = Joined, 2 = Started, 3 = Ended (during "defeat" or "victory" screen only) switch (gameState) { case 0: state = GameState.MENU; exileCausesEnd = false; break; case 1: case 3: state = GameState.LOBBY; exileCausesEnd = false; break; default: { if (exileCausesEnd) { state = GameState.LOBBY; } else if (meetingHudState < 4) { state = GameState.DISCUSSION; } else { state = GameState.TASKS; } break; } } var allPlayersPtr = ProcessMemory.getInstance() .Read <IntPtr>(GameAssemblyPtr, _gameOffsets.GameDataOffset, 0x5C, 0, 0x24); var allPlayers = ProcessMemory.getInstance().Read <IntPtr>(allPlayersPtr, 0x08); var playerCount = ProcessMemory.getInstance().Read <int>(allPlayersPtr, 0x0C); var playerAddrPtr = allPlayers + 0x10; // check if exile causes end if (oldState == GameState.DISCUSSION && state == GameState.TASKS) { var exiledPlayerId = ProcessMemory.getInstance().ReadWithDefault <byte>(GameAssemblyPtr, 255, _gameOffsets.MeetingHudOffset, 0x5C, 0, 0x94, 0x08); int impostorCount = 0, innocentCount = 0; for (var i = 0; i < playerCount; i++) { var pi = ProcessMemory.getInstance().Read <PlayerInfo>(playerAddrPtr, 0, 0); playerAddrPtr += 4; if (pi.PlayerId == exiledPlayerId) { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.Exiled, Name = pi.GetPlayerName(), IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } // skip invalid, dead and exiled players if (pi.PlayerName == 0 || pi.PlayerId == exiledPlayerId || pi.IsDead == 1 || pi.Disconnected == 1) { continue; } if (pi.IsImpostor == 1) { impostorCount++; } else { innocentCount++; } } if (impostorCount == 0 || impostorCount >= innocentCount) { exileCausesEnd = true; state = GameState.LOBBY; } } if (state != oldState || shouldForceTransmitState) { GameStateChanged?.Invoke(this, new GameStateChangedEventArgs { NewState = state }); shouldForceTransmitState = false; } if (state != oldState && state == GameState.LOBBY) { shouldReadLobby = true; // will eventually transmit } oldState = state; newPlayerInfos.Clear(); playerAddrPtr = allPlayers + 0x10; for (var i = 0; i < playerCount; i++) { var pi = ProcessMemory.getInstance().Read <PlayerInfo>(playerAddrPtr, 0, 0); playerAddrPtr += 4; if (pi.PlayerName == 0) { continue; } var playerName = pi.GetPlayerName(); if (playerName.Length == 0) { continue; } newPlayerInfos[playerName] = pi; // add to new playerinfos for comparison later if (!oldPlayerInfos.ContainsKey(playerName)) // player wasn't here before, they just joined { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.Joined, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } else { // player was here before, we have an old playerInfo to compare against var oldPlayerInfo = oldPlayerInfos[playerName]; if (!oldPlayerInfo.GetIsDead() && pi.GetIsDead()) // player just died { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.Died, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } if (oldPlayerInfo.ColorId != pi.ColorId) { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.ChangedColor, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } if (!oldPlayerInfo.GetIsDisconnected() && pi.GetIsDisconnected()) { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.Disconnected, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } } } foreach (var kvp in oldPlayerInfos) { var pi = kvp.Value; var playerName = kvp.Key; if (!newPlayerInfos.ContainsKey(playerName) ) // player was here before, isn't now, so they left { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.Left, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } } oldPlayerInfos.Clear(); var emitAll = false; if (shouldForceUpdatePlayers) { shouldForceUpdatePlayers = false; emitAll = true; } foreach (var kvp in newPlayerInfos ) // do this instead of assignment so they don't point to the same object { var pi = kvp.Value; oldPlayerInfos[kvp.Key] = pi; if (emitAll) { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.ForceUpdated, Name = kvp.Key, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } } var chatBubblesPtr = ProcessMemory.getInstance().Read <IntPtr>(GameAssemblyPtr, _gameOffsets.HudManagerOffset, 0x5C, 0, 0x28, 0xC, 0x14); var poolSize = 20; // = ProcessMemory.getInstance().Read<int>(GameAssemblyPtr, 0xD0B25C, 0x5C, 0, 0x28, 0xC, 0xC) var numChatBubbles = ProcessMemory.getInstance().Read <int>(chatBubblesPtr, 0xC); var chatBubsVersion = ProcessMemory.getInstance().Read <int>(chatBubblesPtr, 0x10); var chatBubblesAddr = ProcessMemory.getInstance().Read <IntPtr>(chatBubblesPtr, 0x8) + 0x10; var chatBubblePtrs = ProcessMemory.getInstance().ReadArray(chatBubblesAddr, numChatBubbles); var newMsgs = 0; if (chatBubsVersion > prevChatBubsVersion) // new message has been sent { if (chatBubsVersion > poolSize) // increments are twofold (push to and pop from pool) { if (prevChatBubsVersion > poolSize) { newMsgs = (chatBubsVersion - prevChatBubsVersion) >> 1; } else { newMsgs = poolSize - prevChatBubsVersion + ((chatBubsVersion - poolSize) >> 1); } } else // single increments { newMsgs = chatBubsVersion - prevChatBubsVersion; } } else if (chatBubsVersion < prevChatBubsVersion) // reset { if (chatBubsVersion > poolSize) // increments are twofold (push to and pop from pool) { newMsgs = poolSize + ((chatBubsVersion - poolSize) >> 1); } else // single increments { newMsgs = chatBubsVersion; } } prevChatBubsVersion = chatBubsVersion; for (var i = numChatBubbles - newMsgs; i < numChatBubbles; i++) { var msgText = ProcessMemory.getInstance() .ReadString(ProcessMemory.getInstance().Read <IntPtr>(chatBubblePtrs[i], 0x20, 0x28)); if (msgText.Length == 0) { continue; } var msgSender = ProcessMemory.getInstance() .ReadString(ProcessMemory.getInstance().Read <IntPtr>(chatBubblePtrs[i], 0x1C, 0x28)); var oldPlayerInfo = oldPlayerInfos[msgSender]; ChatMessageAdded?.Invoke(this, new ChatMessageEventArgs { Sender = msgSender, Message = msgText, Color = oldPlayerInfo.GetPlayerColor() }); } if (shouldReadLobby) { var gameCode = ProcessMemory.getInstance().ReadString(ProcessMemory.getInstance() .Read <IntPtr>( GameAssemblyPtr, _gameOffsets.GameStartManagerOffset, 0x5c, 0, 0x20, 0x28)); string[] split; if (gameCode != null && gameCode.Length > 0 && (split = gameCode.Split('\n')).Length == 2) { PlayRegion region = (PlayRegion)((4 - (ProcessMemory.getInstance() .Read <int>(GameAssemblyPtr, _gameOffsets.ServerManagerOffset, 0x5c, 0, 0x10, 0x8, 0x8) & 0b11)) % 3); // do NOT ask this.latestLobbyEventArgs = new LobbyEventArgs() { LobbyCode = split[1], Region = region }; shouldReadLobby = false; shouldTransmitLobby = true; // since this is probably new info } } if (shouldTransmitLobby) { if (this.latestLobbyEventArgs != null) { JoinedLobby?.Invoke(this, this.latestLobbyEventArgs); } shouldTransmitLobby = false; } } catch (ProcessMemory.CaptureMemoryException ex) { if (ex.ErrorCode == ProcessMemory.CaptureErrorCode.InsufficientPermissions) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { Settings.conInterface.WriteModuleTextColored("GameMemReader", Color.Lime, "AmongUsCapture does not have permission to link to the Among Us process. This is due to a kernel security setting that disallows programs from reading the memory of other processes. Please check the readme for more information."); } else { Settings.conInterface.WriteModuleTextColored("GameMemReader", Color.Lime, "AmongUsCapture does not have permission to link to the Among Us process."); } } Settings.conInterface.WriteModuleTextColored("GameMemReader", Color.Lime, "GameMemReader has encountered a problem. Please restart the program."); paused = true; } Thread.Sleep(250); } }
public void RunLoop() { while (true) { if (!ProcessMemory.IsHooked) { if (!ProcessMemory.HookProcess("Among Us")) { Thread.Sleep(1000); continue; } else { Program.conInterface.WriteLine($"Connected to Among Us process ({ProcessMemory.process.Id})"); bool foundModule = false; while (true) { foreach (ProcessMemory.Module module in ProcessMemory.modules) { if (module.Name.Equals("GameAssembly.dll", StringComparison.OrdinalIgnoreCase)) { GameAssemblyPtr = module.BaseAddress; foundModule = true; break; } } if (!foundModule) { Program.conInterface.WriteLine("Still looking for modules..."); // TODO: This still isn't functional, we need to re-hook to reload module addresses Thread.Sleep(500); // delay and try again } else { break; // we have found all modules } } Console.WriteLine($"({GameAssemblyPtr})"); prevChatBubsVersion = ProcessMemory.Read <int>(GameAssemblyPtr, HudManagerOffset, 0x5C, 0, 0x28, 0xC, 0x14, 0x10); } } GameState state; //int meetingHudState = /*meetingHud_cachePtr == 0 ? 4 : */ProcessMemory.ReadWithDefault<int>(GameAssemblyPtr, 4, 0xDA58D0, 0x5C, 0, 0x84); // 0 = Discussion, 1 = NotVoted, 2 = Voted, 3 = Results, 4 = Proceeding IntPtr meetingHud = ProcessMemory.Read <IntPtr>(GameAssemblyPtr, MeetingHudOffset, 0x5C, 0); uint meetingHud_cachePtr = meetingHud == IntPtr.Zero ? 0 : ProcessMemory.Read <uint>(meetingHud, 0x8); int meetingHudState = meetingHud_cachePtr == 0 ? 4 : ProcessMemory.ReadWithDefault <int>(meetingHud, 4, 0x84); // 0 = Discussion, 1 = NotVoted, 2 = Voted, 3 = Results, 4 = Proceeding int gameState = ProcessMemory.Read <int>(GameAssemblyPtr, AmongUsClientOffset, 0x5C, 0, 0x64); // 0 = NotJoined, 1 = Joined, 2 = Started, 3 = Ended (during "defeat" or "victory" screen only) if (gameState == 0) { state = GameState.MENU; exileCausesEnd = false; } else if (gameState == 1 || gameState == 3) { state = GameState.LOBBY; exileCausesEnd = false; } else if (exileCausesEnd) { state = GameState.LOBBY; } else if (meetingHudState < 4) { state = GameState.DISCUSSION; } else { state = GameState.TASKS; } IntPtr allPlayersPtr = ProcessMemory.Read <IntPtr>(GameAssemblyPtr, GameDataOffset, 0x5C, 0, 0x24); IntPtr allPlayers = ProcessMemory.Read <IntPtr>(allPlayersPtr, 0x08); int playerCount = ProcessMemory.Read <int>(allPlayersPtr, 0x0C); IntPtr playerAddrPtr = allPlayers + 0x10; // check if exile causes end if (oldState == GameState.DISCUSSION && state == GameState.TASKS) { byte exiledPlayerId = ProcessMemory.ReadWithDefault <byte>(GameAssemblyPtr, 255, MeetingHudOffset, 0x5C, 0, 0x94, 0x08); int impostorCount = 0, innocentCount = 0; for (int i = 0; i < playerCount; i++) { PlayerInfo pi = ProcessMemory.Read <PlayerInfo>(playerAddrPtr, 0, 0); playerAddrPtr += 4; if (pi.PlayerId == exiledPlayerId) { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs() { Action = PlayerAction.Exiled, Name = pi.GetPlayerName(), IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } // skip invalid, dead and exiled players if (pi.PlayerName == 0 || pi.PlayerId == exiledPlayerId || pi.IsDead == 1 || pi.Disconnected == 1) { continue; } if (pi.IsImpostor == 1) { impostorCount++; } else { innocentCount++; } } if (impostorCount == 0 || impostorCount >= innocentCount) { exileCausesEnd = true; state = GameState.LOBBY; } } if (this.shouldTransmitState) { shouldTransmitState = false; GameStateChanged?.Invoke(this, new GameStateChangedEventArgs() { NewState = state }); } else if (state != oldState) { GameStateChanged?.Invoke(this, new GameStateChangedEventArgs() { NewState = state }); } oldState = state; newPlayerInfos.Clear(); playerAddrPtr = allPlayers + 0x10; for (int i = 0; i < playerCount; i++) { PlayerInfo pi = ProcessMemory.Read <PlayerInfo>(playerAddrPtr, 0, 0); playerAddrPtr += 4; if (pi.PlayerName == 0) { continue; } string playerName = pi.GetPlayerName(); newPlayerInfos[playerName] = pi; // add to new playerinfos for comparison later if (!oldPlayerInfos.ContainsKey(playerName)) // player wasn't here before, they just joined { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs() { Action = PlayerAction.Joined, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } else // player was here before, we have an old playerInfo to compare against { PlayerInfo oldPlayerInfo = oldPlayerInfos[playerName]; if (!oldPlayerInfo.GetIsDead() && pi.GetIsDead()) // player just died { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs() { Action = PlayerAction.Died, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } if (oldPlayerInfo.ColorId != pi.ColorId) { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs() { Action = PlayerAction.ChangedColor, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } if (!oldPlayerInfo.GetIsDisconnected() && pi.GetIsDisconnected()) { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs() { Action = PlayerAction.Disconnected, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } } } foreach (KeyValuePair <string, PlayerInfo> kvp in oldPlayerInfos) { PlayerInfo pi = kvp.Value; string playerName = kvp.Key; if (!newPlayerInfos.ContainsKey(playerName)) // player was here before, isn't now, so they left { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs() { Action = PlayerAction.Left, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } } oldPlayerInfos.Clear(); bool emitAll = false; if (shouldForceUpdate) { shouldForceUpdate = false; emitAll = true; } foreach (KeyValuePair <string, PlayerInfo> kvp in newPlayerInfos) // do this instead of assignment so they don't point to the same object { PlayerInfo pi = kvp.Value; oldPlayerInfos[kvp.Key] = pi; if (emitAll) { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs() { Action = PlayerAction.ForceUpdated, Name = kvp.Key, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } } IntPtr chatBubblesPtr = ProcessMemory.Read <IntPtr>(GameAssemblyPtr, HudManagerOffset, 0x5C, 0, 0x28, 0xC, 0x14); int poolSize = 20; // = ProcessMemory.Read<int>(GameAssemblyPtr, 0xD0B25C, 0x5C, 0, 0x28, 0xC, 0xC) int numChatBubbles = ProcessMemory.Read <int>(chatBubblesPtr, 0xC); int chatBubsVersion = ProcessMemory.Read <int>(chatBubblesPtr, 0x10); IntPtr chatBubblesAddr = ProcessMemory.Read <IntPtr>(chatBubblesPtr, 0x8) + 0x10; IntPtr[] chatBubblePtrs = ProcessMemory.ReadArray(chatBubblesAddr, numChatBubbles); int newMsgs = 0; if (chatBubsVersion > prevChatBubsVersion) // new message has been sent { if (chatBubsVersion > poolSize) // increments are twofold (push to and pop from pool) { if (prevChatBubsVersion > poolSize) { newMsgs = (chatBubsVersion - prevChatBubsVersion) >> 1; } else { newMsgs = (poolSize - prevChatBubsVersion) + ((chatBubsVersion - poolSize) >> 1); } } else // single increments { newMsgs = chatBubsVersion - prevChatBubsVersion; } } else if (chatBubsVersion < prevChatBubsVersion) // reset { if (chatBubsVersion > poolSize) // increments are twofold (push to and pop from pool) { newMsgs = poolSize + ((chatBubsVersion - poolSize) >> 1); } else // single increments { newMsgs = chatBubsVersion; } } prevChatBubsVersion = chatBubsVersion; for (int i = numChatBubbles - newMsgs; i < numChatBubbles; i++) { string msgText = ProcessMemory.ReadString(ProcessMemory.Read <IntPtr>(chatBubblePtrs[i], 0x20, 0x28)); if (msgText.Length == 0) { continue; } string msgSender = ProcessMemory.ReadString(ProcessMemory.Read <IntPtr>(chatBubblePtrs[i], 0x1C, 0x28)); ChatMessageAdded?.Invoke(this, new ChatMessageEventArgs() { Sender = msgSender, Message = msgText }); } //string gameCode = ProcessMemory.ReadString(ProcessMemory.Read<IntPtr>(GameAssemblyPtr, GameStartManagerOffset, 0x5c, 0, 0x20, 0x28)); //Console.WriteLine(gameCode); Thread.Sleep(250); } }
public void RunLoop() { while (true) { if (!ProcessMemory.IsHooked) { if (!ProcessMemory.HookProcess("Among Us")) { Thread.Sleep(1000); continue; } else { Console.WriteLine("Connected to Among Us process ({0})", ProcessMemory.process.Id); bool foundModule = false; while (true) { foreach (ProcessMemory.Module module in ProcessMemory.modules) { if (module.Name.Equals("GameAssembly.dll", StringComparison.OrdinalIgnoreCase)) { GameAssemblyPtr = module.BaseAddress; foundModule = true; break; } } if (!foundModule) { Console.WriteLine("Still looking for modules..."); // TODO: This still isn't functional, we need to re-hook to reload module addresses Thread.Sleep(500); // delay and try again } else { break; // we have found all modules } } Console.WriteLine($"({GameAssemblyPtr})"); } } GameState state; int meetingHudState = ProcessMemory.ReadWithDefault <int>(GameAssemblyPtr, 4, 0xDA58D0, 0x5C, 0, 0x84); // 0 = Discussion, 1 = NotVoted, 2 = Voted, 3 = Results, 4 = Proceeding int gameState = ProcessMemory.Read <int>(GameAssemblyPtr, 0xDA5ACC, 0x5C, 0, 0x64); // 0 = NotJoined, 1 = Joined, 2 = Started, 3 = Ended (during "defeat" or "victory" screen only) if (gameState == 0) { state = GameState.MENU; exileCausesEnd = false; } else if (gameState == 1 || gameState == 3) { state = GameState.LOBBY; exileCausesEnd = false; } else if (exileCausesEnd) { state = GameState.LOBBY; } else if (meetingHudState < 4) { state = GameState.DISCUSSION; } else { state = GameState.TASKS; } IntPtr allPlayersPtr = ProcessMemory.Read <IntPtr>(GameAssemblyPtr, 0xDA5A60, 0x5C, 0, 0x24); IntPtr allPlayers = ProcessMemory.Read <IntPtr>(allPlayersPtr, 0x08); int playerCount = ProcessMemory.Read <int>(allPlayersPtr, 0x0C); IntPtr playerAddrPtr = allPlayers + 0x10; // check if exile causes end if (oldState == GameState.DISCUSSION && state == GameState.TASKS) { byte exiledPlayerId = ProcessMemory.ReadWithDefault <byte>(GameAssemblyPtr, 255, 0xDA58D0, 0x5C, 0, 0x94, 0x08); Console.WriteLine($"Player with id {exiledPlayerId} was exiled."); int impostorCount = 0, innocentCount = 0; for (int i = 0; i < playerCount; i++) { PlayerInfo pi = ProcessMemory.Read <PlayerInfo>(playerAddrPtr, 0, 0); playerAddrPtr += 4; // skip invalid, dead and exiled players if (pi.PlayerName == 0 || pi.PlayerId == exiledPlayerId || pi.IsDead == 1) { continue; } if (pi.IsImpostor == 1) { impostorCount++; } else { innocentCount++; } } if (impostorCount == 0 || impostorCount >= innocentCount) { exileCausesEnd = true; state = GameState.LOBBY; } } if (this.shouldTransmitState) { shouldTransmitState = false; GameStateChanged.Invoke(this, new GameStateChangedEventArgs() { NewState = state }); } else if (state != oldState) { if (oldState == GameState.DISCUSSION && state == GameState.TASKS) // send delayed { Task.Delay(7000).ContinueWith((task) => { this.ForceTransmitState(); }); } else { GameStateChanged.Invoke(this, new GameStateChangedEventArgs() { NewState = state }); } } oldState = state; newPlayerInfos.Clear(); playerAddrPtr = allPlayers + 0x10; for (int i = 0; i < playerCount; i++) { PlayerInfo pi = ProcessMemory.Read <PlayerInfo>(playerAddrPtr, 0, 0); playerAddrPtr += 4; if (pi.PlayerName == 0) { continue; } string playerName = pi.GetPlayerName(); newPlayerInfos[playerName] = pi; // add to new playerinfos for comparison later if (!oldPlayerInfos.ContainsKey(playerName)) // player wasn't here before, they just joined { PlayerChanged.Invoke(this, new PlayerChangedEventArgs() { Action = PlayerAction.Joined, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } else // player was here before, we have an old playerInfo to compare against { PlayerInfo oldPlayerInfo = oldPlayerInfos[playerName]; if (!oldPlayerInfo.GetIsDead() && pi.GetIsDead()) // player just died { PlayerChanged.Invoke(this, new PlayerChangedEventArgs() { Action = PlayerAction.Died, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } if (oldPlayerInfo.ColorId != pi.ColorId) { PlayerChanged.Invoke(this, new PlayerChangedEventArgs() { Action = PlayerAction.ChangedColor, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } } } foreach (KeyValuePair <string, PlayerInfo> kvp in oldPlayerInfos) { PlayerInfo pi = kvp.Value; string playerName = kvp.Key; if (!newPlayerInfos.ContainsKey(playerName)) // player was here before, isn't now, so they left { PlayerChanged.Invoke(this, new PlayerChangedEventArgs() { Action = PlayerAction.Left, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } } oldPlayerInfos.Clear(); bool emitAll = false; if (shouldForceUpdate) { shouldForceUpdate = false; emitAll = true; } foreach (KeyValuePair <string, PlayerInfo> kvp in newPlayerInfos) // do this instead of assignment so they don't point to the same object { PlayerInfo pi = kvp.Value; oldPlayerInfos[kvp.Key] = pi; if (emitAll) { PlayerChanged.Invoke(this, new PlayerChangedEventArgs() { Action = PlayerAction.ForceUpdated, Name = kvp.Key, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } } //foreach (KeyValuePair<string, PlayerInfo> kvp in oldPlayerInfos) //{ // PlayerInfo pi = kvp.Value; // Console.WriteLine($"Player ID {pi.PlayerId}; Name: {ProcessMemory.ReadString((IntPtr)pi.PlayerName)}; Color: {pi.ColorId}; Dead: " + ((pi.IsDead > 0) ? "yes" : "no")); //} Thread.Sleep(250); } }
public void OnPlayerChanged() { PlayerChanged?.Invoke("hello", 21, 3.14f); }
public void RunLoop() { while (true) { if (!ProcessMemory.getInstance().IsHooked || ProcessMemory.getInstance().process is null || ProcessMemory.getInstance().process.HasExited) { if (!ProcessMemory.getInstance().HookProcess("Among Us")) { Thread.Sleep(1000); continue; } Settings.conInterface.WriteModuleTextColored("GameMemReader", Color.Lime, $"Connected to Among Us process ({Color.Red.ToTextColor()}{ProcessMemory.getInstance().process.Id}{Settings.conInterface.getNormalColor().ToTextColor()})"); var foundModule = false; while (true) { foreach (var module in ProcessMemory.getInstance().modules) { if (module.Name.Equals("GameAssembly.dll", StringComparison.OrdinalIgnoreCase)) { GameAssemblyPtr = module.BaseAddress; if (!GameVerifier.VerifySteamHash(module.FileName)) { cracked = true; Settings.conInterface.WriteModuleTextColored("GameVerifier", Color.Red, $"Client verification: {Color.Red.ToTextColor()}FAIL{Settings.conInterface.getNormalColor().ToTextColor()}."); } else { cracked = false; Settings.conInterface.WriteModuleTextColored("GameVerifier", Color.Red, $"Client verification: {Color.Lime.ToTextColor()}PASS{Settings.conInterface.getNormalColor().ToTextColor()}."); } foundModule = true; break; } } if (!foundModule) { Settings.conInterface.WriteModuleTextColored("GameMemReader", Color.Lime, "Still looking for modules..."); //Program.conInterface.WriteModuleTextColored("GameMemReader", Color.Green, "Still looking for modules..."); // TODO: This still isn't functional, we need to re-hook to reload module addresses Thread.Sleep(500); // delay and try again ProcessMemory.getInstance().LoadModules(); } else { break; // we have found all modules } } try { prevChatBubsVersion = ProcessMemory.getInstance().Read <int>(GameAssemblyPtr, _gameOffsets.HudManagerOffset, 0x5C, 0, 0x28, 0xC, 0x14, 0x10); } catch { Settings.conInterface.WriteModuleTextColored("ERROR", Color.Red, "Outdated version of the game."); } } if (cracked && ProcessMemory.getInstance().IsHooked) { var result = Settings.conInterface.CrackDetected(); if (!result) { Environment.Exit(0); } else { cracked = false; } continue; } GameState state; //int meetingHudState = /*meetingHud_cachePtr == 0 ? 4 : */ProcessMemory.ReadWithDefault<int>(GameAssemblyPtr, 4, 0xDA58D0, 0x5C, 0, 0x84); // 0 = Discussion, 1 = NotVoted, 2 = Voted, 3 = Results, 4 = Proceeding var meetingHud = ProcessMemory.getInstance().Read <IntPtr>(GameAssemblyPtr, _gameOffsets.MeetingHudOffset, 0x5C, 0); var meetingHud_cachePtr = meetingHud == IntPtr.Zero ? 0 : ProcessMemory.getInstance().Read <uint>(meetingHud, 0x8); var meetingHudState = meetingHud_cachePtr == 0 ? 4 : ProcessMemory.getInstance().ReadWithDefault(meetingHud, 4, 0x84); // 0 = Discussion, 1 = NotVoted, 2 = Voted, 3 = Results, 4 = Proceeding var gameState = ProcessMemory.getInstance().Read <int>(GameAssemblyPtr, _gameOffsets.AmongUsClientOffset, 0x5C, 0, 0x64); // 0 = NotJoined, 1 = Joined, 2 = Started, 3 = Ended (during "defeat" or "victory" screen only) switch (gameState) { case 0: state = GameState.MENU; exileCausesEnd = false; break; case 1: case 3: state = GameState.LOBBY; exileCausesEnd = false; break; default: { if (exileCausesEnd) { state = GameState.LOBBY; } else if (meetingHudState < 4) { state = GameState.DISCUSSION; } else { state = GameState.TASKS; } break; } } var allPlayersPtr = ProcessMemory.getInstance().Read <IntPtr>(GameAssemblyPtr, _gameOffsets.GameDataOffset, 0x5C, 0, 0x24); var allPlayers = ProcessMemory.getInstance().Read <IntPtr>(allPlayersPtr, 0x08); var playerCount = ProcessMemory.getInstance().Read <int>(allPlayersPtr, 0x0C); var playerAddrPtr = allPlayers + 0x10; // check if exile causes end if (oldState == GameState.DISCUSSION && state == GameState.TASKS) { var exiledPlayerId = ProcessMemory.getInstance().ReadWithDefault <byte>(GameAssemblyPtr, 255, _gameOffsets.MeetingHudOffset, 0x5C, 0, 0x94, 0x08); int impostorCount = 0, innocentCount = 0; for (var i = 0; i < playerCount; i++) { var pi = ProcessMemory.getInstance().Read <PlayerInfo>(playerAddrPtr, 0, 0); playerAddrPtr += 4; if (pi.PlayerId == exiledPlayerId) { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.Exiled, Name = pi.GetPlayerName(), IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } // skip invalid, dead and exiled players if (pi.PlayerName == 0 || pi.PlayerId == exiledPlayerId || pi.IsDead == 1 || pi.Disconnected == 1) { continue; } if (pi.IsImpostor == 1) { impostorCount++; } else { innocentCount++; } } if (impostorCount == 0 || impostorCount >= innocentCount) { exileCausesEnd = true; state = GameState.LOBBY; } } if (state != oldState || shouldForceTransmitState) { GameStateChanged?.Invoke(this, new GameStateChangedEventArgs { NewState = state }); shouldForceTransmitState = false; } if (state != oldState && state == GameState.LOBBY) { shouldReadLobby = true; // will eventually transmit } oldState = state; newPlayerInfos.Clear(); playerAddrPtr = allPlayers + 0x10; for (var i = 0; i < playerCount; i++) { var pi = ProcessMemory.getInstance().Read <PlayerInfo>(playerAddrPtr, 0, 0); playerAddrPtr += 4; if (pi.PlayerName == 0) { continue; } var playerName = pi.GetPlayerName(); if (playerName.Length == 0) { continue; } newPlayerInfos[playerName] = pi; // add to new playerinfos for comparison later if (!oldPlayerInfos.ContainsKey(playerName)) // player wasn't here before, they just joined { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.Joined, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } else { // player was here before, we have an old playerInfo to compare against var oldPlayerInfo = oldPlayerInfos[playerName]; if (!oldPlayerInfo.GetIsDead() && pi.GetIsDead()) // player just died { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.Died, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } if (oldPlayerInfo.ColorId != pi.ColorId) { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.ChangedColor, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } if (!oldPlayerInfo.GetIsDisconnected() && pi.GetIsDisconnected()) { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.Disconnected, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } } } foreach (var kvp in oldPlayerInfos) { var pi = kvp.Value; var playerName = kvp.Key; if (!newPlayerInfos.ContainsKey(playerName)) // player was here before, isn't now, so they left { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.Left, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } } oldPlayerInfos.Clear(); var emitAll = false; if (shouldForceUpdatePlayers) { shouldForceUpdatePlayers = false; emitAll = true; } foreach (var kvp in newPlayerInfos ) // do this instead of assignment so they don't point to the same object { var pi = kvp.Value; oldPlayerInfos[kvp.Key] = pi; if (emitAll) { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.ForceUpdated, Name = kvp.Key, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor() }); } } var chatBubblesPtr = ProcessMemory.getInstance().Read <IntPtr>(GameAssemblyPtr, _gameOffsets.HudManagerOffset, 0x5C, 0, 0x28, 0xC, 0x14); var poolSize = 20; // = ProcessMemory.Read<int>(GameAssemblyPtr, 0xD0B25C, 0x5C, 0, 0x28, 0xC, 0xC) var numChatBubbles = ProcessMemory.getInstance().Read <int>(chatBubblesPtr, 0xC); var chatBubsVersion = ProcessMemory.getInstance().Read <int>(chatBubblesPtr, 0x10); var chatBubblesAddr = ProcessMemory.getInstance().Read <IntPtr>(chatBubblesPtr, 0x8) + 0x10; var chatBubblePtrs = ProcessMemory.getInstance().ReadArray(chatBubblesAddr, numChatBubbles); var newMsgs = 0; if (chatBubsVersion > prevChatBubsVersion) // new message has been sent { if (chatBubsVersion > poolSize) // increments are twofold (push to and pop from pool) { if (prevChatBubsVersion > poolSize) { newMsgs = (chatBubsVersion - prevChatBubsVersion) >> 1; } else { newMsgs = poolSize - prevChatBubsVersion + ((chatBubsVersion - poolSize) >> 1); } } else // single increments { newMsgs = chatBubsVersion - prevChatBubsVersion; } } else if (chatBubsVersion < prevChatBubsVersion) // reset { if (chatBubsVersion > poolSize) // increments are twofold (push to and pop from pool) { newMsgs = poolSize + ((chatBubsVersion - poolSize) >> 1); } else // single increments { newMsgs = chatBubsVersion; } } prevChatBubsVersion = chatBubsVersion; for (var i = numChatBubbles - newMsgs; i < numChatBubbles; i++) { var msgText = ProcessMemory.getInstance().ReadString(ProcessMemory.getInstance().Read <IntPtr>(chatBubblePtrs[i], 0x20, 0x28)); if (msgText.Length == 0) { continue; } var msgSender = ProcessMemory.getInstance().ReadString(ProcessMemory.getInstance().Read <IntPtr>(chatBubblePtrs[i], 0x1C, 0x28)); var oldPlayerInfo = oldPlayerInfos[msgSender]; ChatMessageAdded?.Invoke(this, new ChatMessageEventArgs { Sender = msgSender, Message = msgText, Color = oldPlayerInfo.GetPlayerColor() }); } if (shouldReadLobby) { var gameCode = ProcessMemory.getInstance().ReadString(ProcessMemory.getInstance().Read <IntPtr>(GameAssemblyPtr, _gameOffsets.GameStartManagerOffset, 0x5c, 0, 0x20, 0x28)); string[] split; if (gameCode != null && gameCode.Length > 0 && (split = gameCode.Split('\n')).Length == 2) { PlayRegion region = (PlayRegion)((4 - (ProcessMemory.getInstance().Read <int>(GameAssemblyPtr, _gameOffsets.ServerManagerOffset, 0x5c, 0, 0x10, 0x8, 0x8) & 0b11)) % 3); // do NOT ask this.latestLobbyEventArgs = new LobbyEventArgs() { LobbyCode = split[1], Region = region }; shouldReadLobby = false; shouldTransmitLobby = true; // since this is probably new info } } if (shouldTransmitLobby) { if (this.latestLobbyEventArgs != null) { JoinedLobby?.Invoke(this, this.latestLobbyEventArgs); } shouldTransmitLobby = false; } Thread.Sleep(250); } }
public void SetPlayer(PlayerModel player) { PlayerModel = player; PlayerChanged?.Invoke(player); }
public void OnPlayerChanged(EventData evt) { PlayerChanged?.Invoke("player changed data..." + evt); }
public void MoveToNextPlayer() { _isUserCurrent = !_isUserCurrent; PlayerChanged?.Invoke(CurrentPlayer, false); }
private GameState handlePlayers(GameState state) { var allPlayersPtr = ProcessMemory.Read <IntPtr>(GameAssemblyPtr, GameOffsets.GameDataOffset, 0x5C, 0, 0x24); var allPlayers = ProcessMemory.Read <IntPtr>(allPlayersPtr, 0x08); var playerCount = ProcessMemory.Read <int>(allPlayersPtr, 0x0C); var playerAddrPtr = allPlayers + 0x10; // check if exile causes end if (oldState == GameState.DISCUSSION && state == GameState.TASKS) { var exiledPlayerId = ProcessMemory.ReadWithDefault <byte>(GameAssemblyPtr, 255, GameOffsets.MeetingHudOffset, 0x5C, 0, 0x94, 0x08); int impostorCount = 0, innocentCount = 0; for (var i = 0; i < playerCount; i++) { var pi = ProcessMemory.Read <PlayerInfo>(playerAddrPtr, 0, 0); playerAddrPtr += 4; if (pi.PlayerId == exiledPlayerId) { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.Exiled, Name = pi.GetPlayerName(), IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor(), isImposter = pi.IsImpostor }); } // skip invalid, dead and exiled players if (pi.PlayerName == 0 || pi.PlayerId == exiledPlayerId || pi.IsDead == 1 || pi.Disconnected == 1) { continue; } if (pi.IsImpostor == 1) { impostorCount++; } else { innocentCount++; } } if (impostorCount == 0 || impostorCount >= innocentCount) { exileCausesEnd = true; state = GameState.LOBBY; } } if (state != oldState || shouldForceTransmitState) { GameStateChanged?.Invoke(this, new GameStateChangedEventArgs { NewState = state }); shouldForceTransmitState = false; } if (state != oldState && state == GameState.LOBBY) { shouldReadLobby = true; // will eventually transmit } oldState = state; newPlayerInfos.Clear(); playerAddrPtr = allPlayers + 0x10; for (var i = 0; i < playerCount; i++) { var pi = ProcessMemory.Read <PlayerInfo>(playerAddrPtr, 0, 0); playerAddrPtr += 4; if (pi.PlayerName == 0) { continue; } var playerName = pi.GetPlayerName(); if (playerName.Length == 0) { continue; } newPlayerInfos[playerName] = pi; // add to new playerinfos for comparison later if (!oldPlayerInfos.ContainsKey(playerName)) // player wasn't here before, they just joined { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.Joined, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor(), isImposter = pi.IsImpostor }); } else { // player was here before, we have an old playerInfo to compare against var oldPlayerInfo = oldPlayerInfos[playerName]; if (!oldPlayerInfo.GetIsDead() && pi.GetIsDead()) // player just died { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.Died, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor(), isImposter = pi.IsImpostor }); } if (oldPlayerInfo.ColorId != pi.ColorId) { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.ChangedColor, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor(), isImposter = pi.IsImpostor }); } if (!oldPlayerInfo.GetIsDisconnected() && pi.GetIsDisconnected()) { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.Disconnected, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor(), isImposter = pi.IsImpostor }); } } } foreach (var kvp in oldPlayerInfos) { var pi = kvp.Value; var playerName = kvp.Key; if (!newPlayerInfos.ContainsKey(playerName)) // player was here before, isn't now, so they left { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.Left, Name = playerName, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor(), isImposter = pi.IsImpostor }); } } oldPlayerInfos.Clear(); var emitAll = false; if (shouldForceUpdatePlayers) { shouldForceUpdatePlayers = false; emitAll = true; } foreach (var kvp in newPlayerInfos) // do this instead of assignment so they don't point to the same object { var pi = kvp.Value; oldPlayerInfos[kvp.Key] = pi; if (emitAll) { PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { Action = PlayerAction.ForceUpdated, Name = kvp.Key, IsDead = pi.GetIsDead(), Disconnected = pi.GetIsDisconnected(), Color = pi.GetPlayerColor(), isImposter = pi.IsImpostor }); } } return(state); }
private void OnChanged() { PlayerChanged handler = Changed; if (handler != null) handler(this, EventArgs.Empty); }
public virtual void FirePlayerChanged() => PlayerChanged?.Invoke(this, EventArgs.Empty);
public void NotifyPlayerChanged(bool fromView, string player) { PlayerChanged?.Invoke(fromView, player); }