コード例 #1
0
    static void UpdatePlayerStatus(UdpClient client, uint pid, PlayerStatus status)
    {
        NetWerewolfPlayer ap = ConnectedPlayers.Find(p => p.PlayerID == pid);

        ap.Status = status;
        UpdatePlayerList.Invoke(pid, status == PlayerStatus.Dead);
    }
コード例 #2
0
    public static void ClientDisconnectedEventHandler(UdpClient client)
    {
        NetWerewolfPlayer player = client.GetPlayer();

        player.Status = PlayerStatus.Dead;
        ServerInstance.Send(2, player.PlayerID); // RemoteClientDisconnected(uint)
        ServerInstance.Send(5, 0u, $"{player.Name} has fallen...");

        try
        {
            ConnectedPlayers.Remove(player);
            GameInfo.Players.Remove(player);
        }
        catch { }

        try
        {
            NetWerewolfPlayer nextHost = ConnectedPlayers.First();
            if (nextHost != null && !nextHost.IsHost)
            {
                nextHost.IsHost = true;
                nextHost.PlayerClient.Send(199, true);
                ServerInstance.Send(5, 0, $"{nextHost.Name} is now the game master.");
            }
        }
        catch { } // No players left to be host
    }
コード例 #3
0
 public void AddPlayerToList(NetWerewolfPlayer player, bool localPlayer)
 {
     InvokerObj.Invoke(() => {
         LobbyPlayerPanelHelper newPlayer = Instantiate(LobbyPlayerPrefab, PlayerListContent);
         newPlayer.SetupText(player, localPlayer);
         playerPanels.Add(newPlayer);
     });
 }
コード例 #4
0
 public void SetupText(NetWerewolfPlayer player, bool localPlayer)
 {
     PlayerID            = player.PlayerID;
     Player              = player;
     PlayerNameText.text = $"[{PlayerID}] {player.Name}";
     if (localPlayer)
     {
         PlayerNameText.color = Color.yellow;
     }
 }
コード例 #5
0
 public static bool InitializeClientInstance(IPAddress ip, int port)
 {
     if (udpSv == null)
     {
         players = new List <NetWerewolfPlayer>();
     }
     udpCl       = new UdpClient(SharedSecret);
     LocalPlayer = new NetWerewolfPlayer(udpCl, PlayerSettings.Instance.PlayerName);
     udpCl.AddNetEventsFromAssembly(Assembly.GetExecutingAssembly(), ClientEventGroup);
     udpCl.ClientDisconnected += ClientNetEvents.ClientDisconnectedEventHandler;
     return(udpCl.VerifyAndListen(ip, port));
 }
コード例 #6
0
    static void VerifyRoleHashesAndSendClientList(UdpClient sender, string playerName, string[] roleHashes)
    {
        // TODO: verify the role hashes

        if (roleHashes.Length < LoadedRoleHashes.Count)
        {
            NetBase.WriteDebug($"Received role hash list from {sender.EndPoint as IPEndPoint} \"{playerName}\" has less roles than the server, impossible to verify roles.");
            ConnectedPlayers.Remove(sender.GetPlayer());
            sender.Disconnect();
            return;
        }

        for (int i = 0; i < LoadedRoleHashes.Count; ++i)
        {
            string hash = LoadedRoleHashes[i];
            if (!roleHashes.Contains(hash))
            {
                NetBase.WriteDebug($"Client {sender.EndPoint as IPEndPoint} \"{playerName}\" missing hash {hash} corresponding to role {LoadedRoleTypes.Values.ElementAt(i).AssemblyQualifiedName}!");
                ConnectedPlayers.Remove(sender.GetPlayer());
                sender.Disconnect();
                return;
            }
            else
            {
                NetBase.WriteDebug($"{sender.EndPoint as IPEndPoint}: {hash} {LoadedRoleTypes.Values.ElementAt(i).AssemblyQualifiedName} success!");
            }
        }

        NetWerewolfPlayer playerRef = sender.GetPlayer();

        playerRef.Name             = playerName;
        playerRef.RoleListVerified = true;

        GameInfo.AddPlayerAndAssignId(playerRef);

        ServerInstance.Send(5, 0u, GenRandomJoinMessage(playerName));

        if (GameInfo.Players.Count == 1)
        {
            playerRef.IsHost = true;
            sender.Send(199, true); //SetHost(UdpClient, bool)
            ServerInstance.Send(5, 0u, $"{playerRef.Name} is now the game master.");
        }

        sender.Send(200, playerRef.PlayerID, ConnectedPlayers.Select(p => p.PlayerID).ToArray(), ConnectedPlayers.Select(p => p.Name).ToArray()); // ReceivePlayerList(uint, uint[], string[]);

        foreach (string hash in ActiveRoleHashes)
        {
            sender.Send(190, hash, false);
        }

        ServerInstance.Send(1, playerRef.PlayerID, playerRef.Name); // UpdateClientInfo(uint, string)
    }
コード例 #7
0
 public static NetWerewolfPlayer GetPlayer(this UdpClient client)
 {
     for (int i = 0; i < ConnectedPlayers.Count; ++i)
     {
         NetWerewolfPlayer p = ConnectedPlayers[i];
         if (p.PlayerClient != null)
         {
             if (p.PlayerClient.EndPoint.Equals(client.EndPoint))
             {
                 return(p);
             }
         }
     }
     return(null);
 }
コード例 #8
0
    static void UpdateClientInfo(UdpClient client, uint pid, string name)
    {
        NetWerewolfPlayer player = ConnectedPlayers.FirstOrDefault(p => p.PlayerID == pid);

        if ((player == null) || (player.PlayerID != LocalPlayer.PlayerID))
        {
            player = new NetWerewolfPlayer(pid, name);
            if (ServerInstance == null)
            {
                ConnectedPlayers.Add(player);
            }
            UpdatePlayerList.Invoke(player.PlayerID, false);
        }
        else
        {
            player.Name = name;
        }
    }
コード例 #9
0
    static void BroadcastChatMessage(UdpClient sender, string message)
    {
        NetWerewolfPlayer p = sender.GetPlayer();

        if (p != null)
        {
            double secondsSinceLast = (DateTime.Now - p.LastMessageTime).TotalSeconds;
            if (secondsSinceLast >= 3.5)
            {
                ServerInstance.Send(5, p.PlayerID, message); // ReceivedChatMessage(uint, string)
                p.LastMessageTime = DateTime.Now;
            }
            else
            {
                sender.Send(5, 0, $"Please wait another {Math.Round(3.5 - secondsSinceLast, 1)} seconds before sending another message."); // ReceivedChatMessage(uint, string)
            }
        }
    }
コード例 #10
0
    static void ReceivePlayerList(UdpClient client, uint myPID, uint[] playerIDs, string[] playerNames)
    {
        LocalPlayer.PlayerID = myPID;

        for (int i = 0; i < playerIDs.Length; ++i)
        {
            bool isLocalPlayer          = LocalPlayer.PlayerID == playerIDs[i];
            NetWerewolfPlayer netPlayer = isLocalPlayer ? LocalPlayer : new NetWerewolfPlayer(playerIDs[i], playerNames[i]);

            if (isLocalPlayer)
            {
                LocalPlayer.Name = playerNames[i];
            }

            if (ServerInstance == null)
            {
                ConnectedPlayers.Add(netPlayer);
            }

            UpdatePlayerList.Invoke(netPlayer.PlayerID, false);
        }
    }
コード例 #11
0
    public void WriteChatMessage(NetWerewolfPlayer player, string message)
    {
        InvokerObj.Invoke(() =>
        {
            float oldPos = ChatScrollView.normalizedPosition.y;

            if (player != null)
            {
                ChatTextField.text += $"[{player.PlayerID}] {player.Name}: {message}{Environment.NewLine}";
            }
            else
            {
                ChatTextField.text += $"SYSTEM: {message}{Environment.NewLine}";
            }

            LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)ChatScrollView.transform);

            if (oldPos <= 0.0001f)
            {
                ChatScrollView.normalizedPosition = Vector2.zero;
            }
        });
    }
コード例 #12
0
    public static async Task NetGameLoop()
    {
        CurrentGameState = GameState.Discussion;
        CurrentDay       = 0;
        StateTime        = 25;
        StateChanged     = true;
        PlayerOnTrial    = null;

        while (true)
        {
            if (StateChanged)
            {
                foreach (NetWerewolfPlayer p in ConnectedPlayers)
                {
                    p.TrialTargetPID = 0u;
                    p.TrialVotes     = 0;
                    p.VotedForKill   = false;
                }

                switch (CurrentGameState)
                {
                case GameState.Discussion:
                    ServerInstance.Send(5, 0u, "Discussion has begun.");
                    break;

                case GameState.Night:
                    ServerInstance.Send(5, 0u, "The sun has retreated as the moon rises...");
                    break;

                case GameState.Dawn:
                    List <NetWerewolfPlayer> affectedPlayers = GameInfo.ResolveNightEvents().ConvertAll(p => p as NetWerewolfPlayer);
                    affectedPlayers.ForEach(p =>
                    {
                        ServerInstance.Send(50, p.PlayerID, p.Status);     // UpdatePlayerStatus(UdpClient, uint, PlayerStatus)
                        ServerInstance.Send(5, 0u, $"{p.Name} is {p.Status}!{(p.Status == PlayerStatus.Dead ? $" Their role was {p.Role.Name}" : "")}");
                    });
                    break;

                case GameState.Trial:
                    if (PlayerOnTrial != null)
                    {
                        ServerInstance.Send(5, 0u, $"The town has decided to trial {PlayerOnTrial.Name}! Select their name to vote them guilty.");
                    }
                    else
                    {
                        StateTime = 0;
                    }
                    break;

                case GameState.End:
                    ServerInstance.Send(5, 0u, $"The following players have won: {string.Join(", ", ConnectedPlayers.Where(p => WinningAlignments.Contains(p.Role.Alignment)).Select(p => p.Name))}");
                    break;
                }
            }

            StateChanged = false;

            await Task.Delay(1000);

            StateTime--;

            if (StateTime < 0)
            {
                switch (CurrentGameState)
                {
                case GameState.Discussion:
                    CurrentGameState = GameState.Night;
                    StateTime        = 15;
                    break;

                case GameState.Night:
                    CurrentGameState = GameState.Dawn;
                    StateTime        = 10;
                    CurrentDay++;
                    break;

                case GameState.Dawn:
                    (bool End, IRoleAlignment[] WinList)result = GameInfo.CheckIfWinConditionMet();

                    if (result.End)
                    {
                        WinningAlignments = result.WinList;
                        CurrentGameState  = GameState.End;
                        StateTime         = 20;
                        break;
                    }

                    CurrentGameState = GameState.Discussion;
                    StateTime        = 120;
                    break;


                case GameState.Trial:
                    // TODO: Straight to night if voted out
                    if (PlayerOnTrial != null && PlayerOnTrial.Status != PlayerStatus.Dead)
                    {
                        int votes  = players.Count(p => p.VotedForKill);
                        int voters = players.Count(p => p.PlayerID != PlayerOnTrial.PlayerID && p.Status == PlayerStatus.Alive);

                        if (votes >= Mathf.CeilToInt(voters / 2.0f))
                        {
                            PlayerOnTrial.Status = PlayerStatus.Dead;
                            ServerInstance.Send(50, PlayerOnTrial.PlayerID, PlayerOnTrial.Status);     // UpdatePlayerStatus(uint, PlayerStatus)
                            ServerInstance.Send(5, 0u, $"The town has decided to execute {PlayerOnTrial.Name}! They were a {PlayerOnTrial.Role.Name}!");

                            (bool End, IRoleAlignment[] WinList)trialResult = GameInfo.CheckIfWinConditionMet();

                            if (trialResult.End)
                            {
                                WinningAlignments = trialResult.WinList;
                                CurrentGameState  = GameState.End;
                                StateTime         = 20;
                                break;
                            }

                            CurrentGameState = GameState.Night;
                            StateTime        = 15;

                            break;
                        }
                    }

                    CurrentGameState = GameState.Discussion;
                    StateTime        = 50;
                    break;

                case GameState.End:
                    // TODO: Reset the lobby

                    ConnectedPlayers.ForEach(p => {
                        p.Status = PlayerStatus.Spectating;
                        p.Role   = null;
                    });

                    ActiveRoleHashes = new List <string>();
                    PlayerOnTrial    = null;

                    ServerInstance.Send(192);     // InvokeSceneFlip();
                    return;
                }
                StateChanged  = true;
                PlayerOnTrial = null;
            }

            ServerInstance.Send(6, StateTime); // SetTimerValue(int);
        }
    }
コード例 #13
0
    static void RequestActionOnPlayer(UdpClient sender, uint pid)
    {
        NetWerewolfPlayer player = sender.GetPlayer();
        NetWerewolfPlayer target = ConnectedPlayers.Find(p => p.PlayerID == pid);

        switch (player.Status)
        {
        case PlayerStatus.Dead:
            sender.Send(5, 0u, $"You are dead and cannot perform any more actions!");
            return;

        case PlayerStatus.Spectating:
            sender.Send(5, 0u, $"Spectators cannot perform in-game actions.");
            return;
        }

        if (target == null)
        {
            sender.Send(5, 0u, $"Targeted player with ID {pid} not found.");
            return;
        }

        if (CurrentDay == 0 && CurrentGameState == GameState.Discussion)
        {
            sender.Send(5, 0u, $"No votes for execution will be considered until the first night is over!");
            return;
        }

        switch (CurrentGameState)
        {
        case GameState.Dawn:
            sender.Send(5, 0u, $"Please wait until dawn is over to begin voting.");
            break;

        case GameState.Discussion:
            // TODO: Vote against player
            if (target.PlayerID == player.PlayerID)
            {
                sender.Send(5, 0u, $"You cannot vote yourself onto trial!");
                break;
            }

            if (player.TrialTargetPID != target.PlayerID)
            {
                player.TrialTargetPID = target.PlayerID;
                target.TrialVotes++;
                ServerInstance.Send(5, 0u, $"{player.Name} has voted to trial {target.Name}! ({target.TrialVotes}/2)");

                if (target.TrialVotes >= 2 && PlayerOnTrial == null)
                {
                    PlayerOnTrial    = target;
                    CurrentGameState = GameState.Trial;
                    StateChanged     = true;
                    StateTime        = 20;
                }
            }

            else if (player.TrialTargetPID == target.PlayerID)
            {
                player.TrialTargetPID = 0u;
                target.TrialVotes--;
                ServerInstance.Send(5, 0u, $"{player.Name} has revoked their vote to trial {target.Name}. ({target.TrialVotes}/2)");
            }

            break;

        case GameState.Trial:
            if (PlayerOnTrial != null && PlayerOnTrial.Status != PlayerStatus.Dead)
            {
                if (player.PlayerID == PlayerOnTrial.PlayerID)
                {
                    sender.Send(5, 0u, $"You are on trial and cannot vote to execute yourself!");
                    break;
                }

                player.VotedForKill = !player.VotedForKill;

                if (player.VotedForKill)
                {
                    sender.Send(5, 0u, $"You have voted to kill {PlayerOnTrial.Name}.");
                }
                else
                {
                    sender.Send(5, 0u, $"You have decided to revoke your vote to kill {PlayerOnTrial.Name}.");
                }
            }
            else
            {
                sender.Send(5, 0u, $"The player who was on trial can no longer be voted against.");
            }
            break;

        case GameState.Night:
            // TODO: Night abilities
            if (player.Role.NightEvent == null)
            {
                sender.Send(5, 0u, $"The {player.Role.Name} role does not have a night ability!");
                break;
            }

            if (player.Role.NightEvent.EventTargets == 0)
            {
                sender.Send(5, 0u, $"Your night ability is passive and does not require a target.");
                break;
            }

            if (player.Role.NightEvent.TargetPlayers[0] == null || player.Role.NightEvent.TargetPlayers[0].PlayerID != target.PlayerID)
            {
                player.Role.NightEvent.TargetPlayers[0] = target;
                sender.Send(5, 0u, $"You have decided to target {target.Name}.");     // TODO: custom action text
            }
            else
            {
                player.Role.NightEvent.TargetPlayers[0] = null;
                sender.Send(5, 0u, $"You have instead decided not to perform your night ability.");
            }

            break;

        case GameState.End:
            sender.Send(5, 0u, $"The game is already over!");
            break;
        }
    }