Пример #1
0
 private static void SpawnFlags()
 {
     for (int i = 0; i < CTF.TeamCount; i++)
     {
         CTF.SpawnAtHome(i);
     }
 }
Пример #2
0
        static bool Prefix(Item __instance, Collider other)
        {
            //Debug.Log("OnTriggerEnter " + __instance.m_type + " server =" + Overload.NetworkManager.IsServer() + " index=" + __instance.m_index);
            if (__instance.m_type != ItemType.KEY_SECURITY || !CTF.IsActive)
            {
                return(true);
            }
            if (other.attachedRigidbody == null)
            {
                return(false);
            }
            PlayerShip component = other.attachedRigidbody.GetComponent <PlayerShip>();

            if (component == null)
            {
                return(false);
            }
            Player c_player = component.c_player;

            if (!(bool)ItemIsReachable.Invoke(__instance, new object[] { other }) || (bool)component.m_dying)
            {
                return(false);
            }
            if (Overload.NetworkManager.IsServer() && !NetworkMatch.m_postgame && !c_player.c_player_ship.m_dying)
            {
                if (!CTF.Pickup(c_player, __instance.m_index))
                {
                    return(false);
                }
                c_player.CallRpcPlayItemPickupFX(__instance.m_type, __instance.m_super);
                UnityEngine.Object.Destroy(__instance.c_go);
            }
            return(false);
        }
Пример #3
0
        private static void Prefix(float ___m_alpha, UIElement __instance)
        {
            if (!GameplayManager.IsMultiplayerActive)
            {
                return;
            }
            var position = new Vector2();

            position.x = 0f;
            position.y = -230f;
            float num = -25f;

            for (int i = 0; i < GameplayManager.RecentMessageString.Length; i++)
            {
                if (GameplayManager.RecentMessageTimer[i] > 0f && GameplayManager.RecentMessageString[i] != string.Empty)
                {
                    __instance.DrawStringSmall(GameplayManager.RecentMessageString[i], position, 0.5f, StringOffset.CENTER, (!GameplayManager.RecentMessagePriority[i]) ? UIManager.m_col_ui3 : UIManager.m_col_hi5, Mathf.Min(1f, GameplayManager.RecentMessageTimer[i] * 2f));
                    position.y -= 25f;
                    num        += 25f;
                }
            }

            if (!CTF.IsActive)
            {
                return;
            }
            position.x = 510f;
            position.y = -230f;

            position.x -= 100f;
            position.x -= 110f;
            position.y += 20f;
            CTF.DrawFlags(__instance, position, ___m_alpha);
        }
Пример #4
0
        private static void OnCTFLose(NetworkMessage rawMsg)
        {
            var msg = rawMsg.ReadMessage <PlayerFlagMessage>();

            if (!CTF.IsActiveServer)
            {
                if (CTF.PlayerHasFlag.ContainsKey(msg.m_player_id))
                {
                    CTF.PlayerHasFlag.Remove(msg.m_player_id);
                }
                CTF.FlagStates[msg.m_flag_id] = msg.m_flag_state;

                if (msg.m_flag_state == FlagState.LOST)
                {
                    CTF.FlagReturnTime[msg.m_flag_id] = Time.time + CTF.ReturnTimeAmount;
                }
            }

            if (!CTF.CarrierBoostEnabled && GameManager.m_player_ship.netId == msg.m_player_id)
            {
                GameManager.m_player_ship.m_boost_overheat_timer = 0;
                GameManager.m_player_ship.m_boost_heat           = 0;
            }

            // remove flag ring effect from carrier ship
            CTF.PlayerDisableRing(CTF.FindPlayerForEffect(msg.m_player_id));
        }
Пример #5
0
        private static void Prefix(Player __instance, DamageInfo di)
        {
            if (!CTF.IsActiveServer)
            {
                return;
            }

            if (!CTF.PlayerHasFlag.TryGetValue(__instance.netId, out int flag))
            {
                return;
            }

            CTF.NotifyAll(CTFEvent.CARRIER_DIED, null, __instance, flag);

            if (di.owner == null)
            {
                return;
            }

            Player attacker = di.owner.GetComponent <Player>();

            if (attacker == null || attacker.netId == __instance.netId)
            {
                return;
            }

            ServerStatLog.AddFlagEvent(attacker, "CarrierKill", MPTeams.AllTeams[flag]);
        }
Пример #6
0
        static void Prefix(Vector2 pos, UIElement __instance)
        {
            if (!CTF.IsActive)
            {
                return;
            }
            if (!CTF.PlayerHasFlag.TryGetValue(GameManager.m_local_player.netId, out int flag))
            {
                return;
            }
            var   m_alpha = __instance.m_alpha;
            Color col_ub  = UIManager.m_col_ub1;
            Color col_ui  = UIManager.m_col_ui2;

            //Color col_ui2 = UIManager.m_col_ui5;
            //Color color = Color.Lerp(UIManager.m_col_hi4, UIManager.m_col_hi5, UnityEngine.Random.value * UIElement.FLICKER);
            col_ui.a = m_alpha;
            pos.y   += ((!GameplayManager.VRActive) ? 50f : 25f);
            pos.x   += ((MenuManager.opt_hud_weapons != 0) ? (-35f) : 35f);
            pos.y   += 25f;

            var temp_pos = default(Vector2);

            pos.y -= 55f;
            pos.x += ((MenuManager.opt_hud_weapons != 0) ? (-102f) : 102f);

            pos.y       -= 16f;
            temp_pos.y   = pos.y;
            temp_pos.x   = pos.x - 13f;
            m_anim_state = (m_anim_state + RUtility.FRAMETIME_UI) % ((float)Math.PI * 2f);
            UIManager.DrawSpriteUIRotated(temp_pos, 0.2f, 0.2f, m_anim_state,
                                          CTF.FlagColorUI(flag), m_alpha, 84);
        }
Пример #7
0
 private static void Postfix()
 {
     if (!CTF.IsActiveServer)
     {
         return;
     }
     CTF.FindFlagSpawnPoints();
     SpawnFlags();
 }
Пример #8
0
        // pickup of flag item
        public static bool Pickup(Player player, int flag)
        {
            if (flag < 0 || flag >= FlagObjs.Count)
            {
                return(false);
            }
            var ownFlag = MPTeams.AllTeams[flag] == player.m_mp_team;

            if (ownFlag && FlagStates[flag] == FlagState.HOME)
            {
                if (CTF.PlayerHasFlag.ContainsKey(player.netId))
                {
                    CTF.Score(player);
                }
                return(false);
            }
            if (!ownFlag && (PlayerHasFlag.ContainsKey(player.netId) || PlayerHasFlag.ContainsValue(flag)))
            {
                return(false);
            }

            // this also sends to 'client 0' so it'll get processed on the server as well
            CTFEvent evt;

            if (ownFlag)
            {
                SendCTFFlagUpdate(-1, player.netId, flag, FlagState.HOME);
                SpawnAtHome(flag);
                evt = CTFEvent.RETURN;
            }
            else
            {
                SendCTFPickup(-1, player.netId, flag, FlagState.PICKEDUP);
                if (!CTF.CarrierBoostEnabled)
                {
                    player.c_player_ship.m_boosting             = false;
                    player.c_player_ship.m_boost_overheat_timer = float.MaxValue;
                }
                evt = CTFEvent.PICKUP;
            }

            var msg = evt == CTFEvent.RETURN ? "{0} RETURNS THE {2} FLAG!" :
                      FlagStates[flag] == FlagState.HOME ? "{0} ({1}) PICKS UP THE {2} FLAG!" :
                      "{0} ({1}) FINDS THE {2} FLAG AMONG SOME DEBRIS!";

            CTF.NotifyAll(evt, string.Format(Loc.LS(msg), player.m_mp_name, MPTeams.TeamName(player.m_mp_team),
                                             MPTeams.TeamName(MPTeams.AllTeams[flag])), player, flag);
            if (FlagReturnTimer[flag] != null)
            {
                GameManager.m_gm.StopCoroutine(FlagReturnTimer[flag]);
                FlagReturnTimer[flag] = null;
            }
            return(true);
        }
Пример #9
0
 private static void Postfix(PlayerShip __instance)
 {
     if (!CTF.IsActiveServer)
     {
         return;
     }
     if (!CTF.PlayerHasFlag.TryGetValue(__instance.c_player.netId, out int flag))
     {
         return;
     }
     CTF.Drop(__instance.c_player);
     CTF.SpewFlag(flag, __instance);
 }
Пример #10
0
        private static void OnCTFPickup(NetworkMessage rawMsg)
        {
            var msg = rawMsg.ReadMessage <PlayerFlagMessage>();

            CTF.FlagStates[msg.m_flag_id] = msg.m_flag_state;
            if (CTF.PlayerHasFlag.ContainsKey(msg.m_player_id))
            {
                return;
            }
            CTF.PlayerHasFlag.Add(msg.m_player_id, msg.m_flag_id);

            // copy flag ring effect to carrier ship
            CTF.PlayerEnableRing(CTF.FindPlayerForEffect(msg.m_player_id), msg.m_flag_id);
        }
Пример #11
0
        private static void Prefix(Vector2 pos, float ___m_alpha, UIElement __instance)
        {
            if (!CTF.IsActive)
            {
                return;
            }
            pos.x -= 4f;
            pos.y -= 5f;
            pos.x -= 100f;
            pos.y -= 20f;

            pos.x -= 110f;
            pos.y += 20f;

            CTF.DrawFlags(__instance, pos, ___m_alpha);
        }
Пример #12
0
        private static void OnCTFLose(NetworkMessage rawMsg)
        {
            var msg = rawMsg.ReadMessage <PlayerFlagMessage>();

            if (CTF.PlayerHasFlag.ContainsKey(msg.m_player_id))
            {
                CTF.PlayerHasFlag.Remove(msg.m_player_id);
            }
            CTF.FlagStates[msg.m_flag_id] = msg.m_flag_state;

            // remove flag ring effect from carrier ship
            CTF.PlayerDisableRing(CTF.FindPlayerForEffect(msg.m_player_id));

            if (msg.m_flag_state == FlagState.LOST)
            {
                CTF.FlagReturnTime[msg.m_flag_id] = Time.time + CTF.ReturnTimeAmount;
            }
        }
Пример #13
0
        public static void SendJoinUpdate(Player player)
        {
            if (!CTF.IsActiveServer)
            {
                return;
            }
            int conn_id = player.connectionToClient.connectionId;

            foreach (var x in CTF.PlayerHasFlag)
            {
                CTF.SendCTFPickup(conn_id, x.Key, x.Value, FlagState.PICKEDUP);
            }
            for (int flag = 0; flag < TeamCount; flag++)
            {
                if (FlagStates[flag] == FlagState.LOST)
                {
                    CTF.SendCTFFlagUpdate(conn_id, NetworkInstanceId.Invalid, flag, FlagStates[flag]);
                }
            }
        }
Пример #14
0
        static bool Prefix(Item __instance, Collider other)
        {
            if (__instance.m_type == ItemType.NONE)
            {
                return(false);
            }

            if (__instance.m_type != ItemType.KEY_SECURITY || !CTF.IsActive)
            {
                return(true);
            }

            if (other.attachedRigidbody == null)
            {
                return(false);
            }

            PlayerShip component = other.attachedRigidbody.GetComponent <PlayerShip>();

            if (component == null)
            {
                return(false);
            }

            Player c_player = component.c_player;

            if (!(bool)_Item_ItemIsReachable_Method.Invoke(__instance, new object[] { other }) || (bool)component.m_dying)
            {
                return(false);
            }

            if (Overload.NetworkManager.IsServer() && !NetworkMatch.m_postgame && !c_player.c_player_ship.m_dying)
            {
                if (!CTF.Pickup(c_player, __instance))
                {
                    return(false);
                }
                c_player.CallRpcPlayItemPickupFX(__instance.m_type, __instance.m_super);
            }
            return(false);
        }
Пример #15
0
        private static void OnCTFPickup(NetworkMessage rawMsg)
        {
            var msg = rawMsg.ReadMessage <PlayerFlagMessage>();

            if (!CTF.IsActiveServer)
            {
                CTF.FlagStates[msg.m_flag_id] = msg.m_flag_state;
                if (CTF.PlayerHasFlag.ContainsKey(msg.m_player_id))
                {
                    return;
                }
                CTF.PlayerHasFlag.Add(msg.m_player_id, msg.m_flag_id);
            }

            if (!CTF.CarrierBoostEnabled && GameManager.m_player_ship.netId == msg.m_player_id)
            {
                GameManager.m_player_ship.m_boosting             = false;
                GameManager.m_player_ship.m_boost_overheat_timer = float.MaxValue;
            }

            // copy flag ring effect to carrier ship
            CTF.PlayerEnableRing(CTF.FindPlayerForEffect(msg.m_player_id), msg.m_flag_id);
        }
Пример #16
0
 static void Postfix(CCInput cc_type, ref bool __result, Player __instance)
 {
     if (!CTF.CarrierBoostEnabled && (!__instance.isLocalPlayer || !uConsole.IsOn()) && __instance.m_input_count[(int)cc_type] >= 1 && cc_type == CCInput.USE_BOOST && GameplayManager.IsMultiplayer && CTF.IsFlagrunner(__instance.c_player_ship))
     {
         __result = false;
     }
     else
     {
         __result = (!__instance.isLocalPlayer || !uConsole.IsOn()) && __instance.m_input_count[(int)cc_type] >= 1;
     }
 }
        private static IEnumerator MatchStart(int connectionId)
        {
            var        newPlayer      = Server.FindPlayerByConnectionId(connectionId);
            MPBanEntry newPlayerEntry = new MPBanEntry(newPlayer);

            // prevent banned players from JIP into our match
            // there is already a delayed Disconnect going on, just
            // prevent this player from entering the JIP code
            if (MPBanPlayers.IsBanned(newPlayerEntry))
            {
                yield break;
            }

            float pregameWait = 3f;

            if (!newPlayer.m_mp_name.StartsWith("OBSERVER"))
            {
                foreach (Player player in Overload.NetworkManager.m_Players)
                {
                    if (MPTweaks.ClientHasTweak(player.connectionToClient.connectionId, "jip"))
                    {
                        NetworkServer.SendToClient(player.connectionToClient.connectionId, MessageTypes.MsgJIPJustJoined, new JIPJustJoinedMessage {
                            playerId = newPlayer.netId, ready = false
                        });
                    }
                }
                MPJoinInProgress.SetReady(newPlayer, false, true); // special case: do not disable the player completely, as this would prevent this player to be sent to new clients joining before we finally switch to ready
            }

            pregameWait = SendPreGame(connectionId, pregameWait);
            yield return(new WaitForSeconds(pregameWait));

            Server.SendLoadoutDataToClients();

            if (newPlayer.m_mp_name.StartsWith("OBSERVER"))
            {
                Debug.LogFormat("Enabling spectator for {0}", newPlayer.m_mp_name);
                newPlayer.Networkm_spectator = true;
                Debug.LogFormat("Enabled spectator for {0}", newPlayer.m_mp_name);

                yield return(null); // make sure spectator change is received before sending MatchStart
            }
            else
            {
                foreach (Player player in Overload.NetworkManager.m_Players)
                {
                    if (MPTweaks.ClientHasTweak(player.connectionToClient.connectionId, "jip"))
                    {
                        NetworkServer.SendToClient(player.connectionToClient.connectionId, MessageTypes.MsgJIPJustJoined, new JIPJustJoinedMessage {
                            playerId = newPlayer.netId, ready = true
                        });
                    }
                }
                MPJoinInProgress.SetReady(newPlayer, true);
            }

            if (NetworkMatch.GetMatchState() != MatchState.PLAYING)
            {
                yield break;
            }

            IntegerMessage modeMsg = new IntegerMessage((int)NetworkMatch.GetMode());

            NetworkServer.SendToClient(connectionId, CustomMsgType.MatchStart, modeMsg);
            SendMatchState(connectionId);

            NetworkSpawnPlayer.Respawn(newPlayer.c_player_ship);
            MPTweaks.Send(connectionId);
            //if (!newPlayer.m_spectator && RearView.MPNetworkMatchEnabled)
            //    newPlayer.CallTargetAddHUDMessage(newPlayer.connectionToClient, "REARVIEW ENABLED", -1, true);
            CTF.SendJoinUpdate(newPlayer);
            Race.SendJoinUpdate(newPlayer);
            foreach (Player player in Overload.NetworkManager.m_Players)
            {
                if (player.connectionToClient.connectionId == connectionId)
                {
                    continue;
                }
                // Resend mode for existing player to move h2h -> anarchy
                NetworkServer.SendToClient(player.connectionToClient.connectionId, CustomMsgType.MatchStart, modeMsg);

                if (!newPlayer.m_spectator)
                {
                    player.CallTargetAddHUDMessage(player.connectionToClient, String.Format(Loc.LS("{0} JOINED MATCH"), newPlayer.m_mp_name), -1, true);
                }

                //Debug.Log("JIP: spawning on new client net " + player.netId + " lobby " + player.connectionToClient.connectionId);
                NetworkServer.SendToClient(connectionId, CustomMsgType.Respawn, new RespawnMessage
                {
                    m_net_id     = player.netId,
                    lobby_id     = player.connectionToClient.connectionId,
                    m_pos        = player.transform.position,
                    m_rotation   = player.transform.rotation,
                    use_loadout1 = player.m_use_loadout1
                });
            }
            ServerStatLog.Connected(newPlayer.m_mp_name);
            MPBanPlayers.ApplyAllBans(); // make sure the newly connected player gets proper treatment if he is BANNED
        }
Пример #18
0
        private static void Postfix()
        {
            // for some reason using entity_item_security_key directly doesn't work well in MP,
            // so take the relatively simple cloak powerup and give it the appearance and type of a security key
            GameObject prefab      = PrefabManager.item_prefabs[(int)ItemPrefab.entity_item_cloak];
            var        prefabkeyA2 = PrefabManager.item_prefabs[(int)ItemPrefab.entity_item_security_key].GetChildByName("keyA2");

            for (int i = 0; i < CTF.TeamCount; i++)
            {
                GameObject flag = UnityEngine.Object.Instantiate(prefab, Vector3.zero, Quaternion.identity);
                UnityEngine.Object.Destroy(flag.GetChildByName("cloak_ball (1)"));
                var      color      = CTF.FlagColor(i);
                var      lightColor = MPTeams.TeamColor(MPTeams.AllTeams[i], 5);
                Material newMat     = null;
                var      keyA2      = UnityEngine.Object.Instantiate(prefabkeyA2, flag.transform);
                foreach (var rend in keyA2.GetComponentsInChildren <MeshRenderer>())
                {
                    if (newMat == null)
                    {
                        newMat = new Material(rend.sharedMaterial.shader);
                        newMat.CopyPropertiesFromMaterial(rend.sharedMaterial);
                        newMat.SetColor("_Color", color);
                        newMat.SetColor("_EmissionColor", color);
                    }
                    rend.sharedMaterial = newMat;
                }
                var light = flag.GetChildByName("_light").GetComponent <Light>();
                light.color = lightColor;
                //light.intensity = 4.455539f;
                light.intensity       = 2f;
                light.range           = 4f;
                light.bounceIntensity = 0f;
                keyA2.GetChildByName("inner_ring001").GetComponent <HighlighterConstant>().color = color;
                var partRend   = keyA2.GetChildByName("outer_ring_004").GetChildByName("_particle1").GetComponent <ParticleSystemRenderer>();
                var newPartMat = new Material(partRend.sharedMaterial.shader);
                newPartMat.CopyPropertiesFromMaterial(partRend.sharedMaterial);
                newPartMat.SetColor("_CoreColor", color);
                newPartMat.SetColor("_TintColor", color);
                partRend.sharedMaterial = newPartMat;

                if (flag == null)
                {
                    Debug.LogWarningFormat("CTF: Failed to instantiate prefab: {0} in RegisterSpawnHandlers", prefab.name);
                    return;
                }
                var assetId = CTF.FlagAssetId(i);
                var netId   = flag.GetComponent <NetworkIdentity>();
                netId.GetType().GetField("m_AssetId", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(netId, assetId);
                UnityEngine.Object.DontDestroyOnLoad(flag);
                flag.SetActive(false);
                var item = flag.GetComponent <Item>();
                //item.m_current_segment = -1;
                //item.m_stationary = false;
                item.m_index = i;
                //item.m_light_flicker = 0;
                item.m_type          = ItemType.KEY_SECURITY;
                item.m_rotate_speed  = 180f;
                item.m_light_flicker = 0.2f;
                //flag.tag = "Item";
                //flag.GetComponent<NetworkIdentity>().a
                CTF.FlagObjs.Add(flag);
                //Debug.Log("Flag " + i + " color " + color + " assetid " + flag.GetComponent<NetworkIdentity>().assetId);
                m_registered_prefabs.Add(assetId, flag);
                ClientScene.RegisterSpawnHandler(assetId, NetworkSpawnItemHandler, NetworkUnspawnItemHandler);
            }
            Debug.Log("CTF: Created " + CTF.FlagObjs.Count + " flag prefabs");
        }
Пример #19
0
 private static void Postfix()
 {
     CTF.InitForMatch();
 }
Пример #20
0
        private static IEnumerator MatchStart(int connectionId)
        {
            var newPlayer = Server.FindPlayerByConnectionId(connectionId);

            float pregameWait = 3f;

            if (!newPlayer.m_mp_name.StartsWith("OBSERVER"))
            {
                foreach (Player player in Overload.NetworkManager.m_Players)
                {
                    if (MPTweaks.ClientHasTweak(player.connectionToClient.connectionId, "jip"))
                    {
                        NetworkServer.SendToClient(player.connectionToClient.connectionId, MessageTypes.MsgJIPJustJoined, new JIPJustJoinedMessage {
                            playerId = newPlayer.netId, ready = false
                        });
                    }
                }
                MPJoinInProgress.SetReady(newPlayer, false);
            }

            pregameWait = SendPreGame(connectionId, pregameWait);
            yield return(new WaitForSeconds(pregameWait));

            Server.SendLoadoutDataToClients();

            if (newPlayer.m_mp_name.StartsWith("OBSERVER"))
            {
                Debug.LogFormat("Enabling spectator for {0}", newPlayer.m_mp_name);
                newPlayer.Networkm_spectator = true;
                Debug.LogFormat("Enabled spectator for {0}", newPlayer.m_mp_name);

                yield return(null); // make sure spectator change is received before sending MatchStart
            }
            else
            {
                foreach (Player player in Overload.NetworkManager.m_Players)
                {
                    if (MPTweaks.ClientHasTweak(player.connectionToClient.connectionId, "jip"))
                    {
                        NetworkServer.SendToClient(player.connectionToClient.connectionId, MessageTypes.MsgJIPJustJoined, new JIPJustJoinedMessage {
                            playerId = newPlayer.netId, ready = true
                        });
                    }
                }
                MPJoinInProgress.SetReady(newPlayer, true);
            }

            if (NetworkMatch.GetMatchState() != MatchState.PLAYING)
            {
                yield break;
            }

            IntegerMessage modeMsg = new IntegerMessage((int)NetworkMatch.GetMode());

            NetworkServer.SendToClient(connectionId, CustomMsgType.MatchStart, modeMsg);
            SendMatchState(connectionId);

            NetworkSpawnPlayer.Respawn(newPlayer.c_player_ship);
            MPTweaks.Send(connectionId);
            //if (!newPlayer.m_spectator && RearView.MPNetworkMatchEnabled)
            //    newPlayer.CallTargetAddHUDMessage(newPlayer.connectionToClient, "REARVIEW ENABLED", -1, true);
            CTF.SendJoinUpdate(newPlayer);
            Race.SendJoinUpdate(newPlayer);
            foreach (Player player in Overload.NetworkManager.m_Players)
            {
                if (player.connectionToClient.connectionId == connectionId)
                {
                    continue;
                }
                // Resend mode for existing player to move h2h -> anarchy
                NetworkServer.SendToClient(player.connectionToClient.connectionId, CustomMsgType.MatchStart, modeMsg);

                if (!newPlayer.m_spectator)
                {
                    player.CallTargetAddHUDMessage(player.connectionToClient, String.Format(Loc.LS("{0} JOINED MATCH"), newPlayer.m_mp_name), -1, true);
                }

                //Debug.Log("JIP: spawning on new client net " + player.netId + " lobby " + player.connectionToClient.connectionId);
                NetworkServer.SendToClient(connectionId, CustomMsgType.Respawn, new RespawnMessage
                {
                    m_net_id     = player.netId,
                    lobby_id     = player.connectionToClient.connectionId,
                    m_pos        = player.transform.position,
                    m_rotation   = player.transform.rotation,
                    use_loadout1 = player.m_use_loadout1
                });
            }
            ServerStatLog.Connected(newPlayer.m_mp_name);
        }
Пример #21
0
        private static IEnumerator MatchStart(int connectionId)
        {
            if (!MPTweaks.ClientHasMod(connectionId) && MPTweaks.MatchNeedsMod())
            {
                yield break;
            }
            var newPlayer = Server.FindPlayerByConnectionId(connectionId);

            if (newPlayer.m_mp_name.StartsWith("OBSERVER"))
            {
                Debug.LogFormat("Enabling spectator for {0}", newPlayer.m_mp_name);
                newPlayer.Networkm_spectator = true;
                Debug.LogFormat("Enabled spectator for {0}", newPlayer.m_mp_name);
            }

            int pregameWait = newPlayer.Networkm_spectator ? 0 : 3;

            //Debug.Log("SendLoadoutDataToClients: " + NetworkMatch.m_player_loadout_data.Join());
            // restore lobby_id which got wiped out in Client.OnSetLoadout
            foreach (var idData in NetworkMatch.m_player_loadout_data)
            {
                idData.Value.lobby_id = idData.Key;
            }
            Server.SendLoadoutDataToClients();
            IntegerMessage durationMsg = new IntegerMessage(pregameWait * 1000);

            NetworkServer.SendToClient(connectionId, CustomMsgType.StartPregameCountdown, durationMsg);
            Debug.Log("JIP: sending start pregame countdown");
            yield return(new WaitForSeconds(pregameWait));

            IntegerMessage modeMsg = new IntegerMessage((int)NetworkMatch.GetMode());

            NetworkServer.SendToClient(connectionId, CustomMsgType.MatchStart, modeMsg);
            SendMatchState(connectionId);
            NetworkSpawnPlayer.Respawn(newPlayer.c_player_ship);
            MPTweaks.Send(connectionId);
            if (!newPlayer.m_spectator && RearView.MPNetworkMatchEnabled)
            {
                newPlayer.CallTargetAddHUDMessage(newPlayer.connectionToClient, "REARVIEW ENABLED", -1, true);
            }
            CTF.SendJoinUpdate(newPlayer);
            Race.SendJoinUpdate(newPlayer);
            foreach (Player player in Overload.NetworkManager.m_Players)
            {
                if (player.connectionToClient.connectionId == connectionId)
                {
                    continue;
                }
                // Resend mode for existing player to move h2h -> anarchy
                NetworkServer.SendToClient(player.connectionToClient.connectionId, CustomMsgType.MatchStart, modeMsg);

                if (!newPlayer.m_spectator)
                {
                    player.CallTargetAddHUDMessage(player.connectionToClient, String.Format(Loc.LS("{0} JOINED MATCH"), newPlayer.m_mp_name), -1, true);
                }

                //Debug.Log("JIP: spawning on new client net " + player.netId + " lobby " + player.connectionToClient.connectionId);
                NetworkServer.SendToClient(connectionId, CustomMsgType.Respawn, new RespawnMessage
                {
                    m_net_id     = player.netId,
                    lobby_id     = player.connectionToClient.connectionId,
                    m_pos        = player.transform.position,
                    m_rotation   = player.transform.rotation,
                    use_loadout1 = player.m_use_loadout1
                });
            }
            ServerStatLog.Connected(newPlayer.m_mp_name);
        }