public static Profile JoinLocalDuck(InputProfile input)
        {
            int num = 1;

            foreach (Profile profile in DuckNetwork.profiles)
            {
                if (profile.connection == DuckNetwork.localConnection)
                {
                    ++num;
                }
            }
            string name = Network.activeNetwork.core.GetLocalName();

            if (num > 1)
            {
                name = name + "(" + num.ToString() + ")";
            }

            //Invoke the private method. Hope its not too slow
            Profile profile1 = (Profile)createProfile.Invoke(null, new object[] { DuckNetwork.localConnection, name, -1, input, false, false, true });

            if (profile1 == null)
            {
                return((Profile)null);
            }
            profile1.networkStatus = !Network.isClient ? DuckNetStatus.Connected : DuckNetStatus.Connecting;

            // Our new OnNetworkConnecting which should bloody work
            TeamSelect2Edits.OnNetworkConnecting(profile1);

            DuckNetwork.SendNewProfile(profile1, DuckNetwork.localConnection, false);
            return(profile1);
        }
Пример #2
0
        // This function is run before all mods are finished loading.
        protected override void OnPreInitialize()
        {
            // The order of these is important for some things, others not. I'll document what each one does eventually.

            // Load the embedded DLL which has unsafe code. Allows duck game to compile this source and still use unsafe code.
            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);

            // Get the profile core. Its not supposed to be accessed outside the main thread but I won't tell if you won't.
            ProfilesCore profilecore = typeof(Profiles).GetField("_core", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public).GetValue(null) as ProfilesCore;

            // Normally generates 4 MPPlayer profiles, now does 8
            Injection.install(2, "InitDefaultProfiles", "InitDefaultProfiles");

            // Add our extra personas to the table
            PersonaEdits._personas();

            // Replace the get_defaultProfiles() with one that handles the extra 4 player teams
            InputProfileCoreEdits.defaultProfiles();

            // Duck Game would just check which profiles were past the first 4 and decide they were custom, changed to skip the first 8
            ProfilesCoreEdits.allCustomProfiles();

            // Generates the default Player1-Player8 Profiles now
            Injection.install(5, "Initialize", "Initialize");

            // Returns the first 8 profiles as defaults
            Injection.install(5, "IsDefault", "IsDefault");

            // Generates the extra 4 GenericControllers for the added players
            InputEdits.Initialize();

            // Invokes the new InitDefaultProfiles(). This may not be needed as it may get injected before it gets run the first time. I'll check
            InputEdits.InitDefaultProfiles();

            // Generates 8 Netduck profiles instead of the default 4
            Injection.install(1, "RecreateProfiles", "RecreateProfiles");

            // Allows the host to select between 2 and 8 players maximum for their lobby
            TeamSelect2Edits.OnlineSettings();

            // Add the extra 4 default teams that will be used for the extra players
            TeamsCoreEdits.Initialize();

            // Generate new profile boxes for the lobby level. Also tweaks the camera for it. Will make it not stretched at some point
            Injection.install(4, "UpdateModifierStatus", "UpdateModifierStatus");

            // DoInvite would call Host(4, LobbyType.FriendsOnly) so we change it to 8 max players
            Injection.install(4, "DoInvite", "DoInvite");

            // Would only purge the first 4 boxes by default. Now purges all 8
            Injection.install(4, "FillMatchmakingProfiles", "FillMatchmakingProfiles");

            // ClearTeam() would return if the index was >=4. We need it to be >=8 for the extra teams
            Injection.install(4, "ClearTeam", "ClearTeam");

            // Return the extra inputprofiles for the extra teams
            Injection.install(6, "ControllerNumber", "ControllerNumber");

            // Trying to detour ConfirmTeamSelection was proving a nightmare so I did this garbage solution.
            // A check at the bottom of ConfirmTeamSelection was returning incorrectly due to the extra teams and crashing
            // When I tried injecting my new method, it was never called for some reason. Not sure why, probably due to instancing
            // To deal with this I edited FilterTeam which gets called at the start of ConfirmTeamSelection and did a check where
            // if the _desiredteamselection was <= 7 then set it to 0. This meant the check that was crashing returned correctly
            // and as far as I can tell there aren't any noticeable side effects. Will find better method eventually.
            Injection.install(6, "FilterTeam", "FilterTeam");

            // Because inline removes TeamSelect2.OnNetworkConnecting, I have to inject the methods that called it to change them
            Injection.install(3, "JoinLocalDuck", "JoinLocalDuck");
            Injection.install(3, "OnMessageFromNewClient", "OnMessageFromNewClient");
            Injection.install(3, "OnMessage", "OnMessage");

            // New NMChangeSlot net message as the old one only handled 4 parameters and we need 8.
            Injection.install(3, "ChangeSlotSettings", "ChangeSlotSettings");

            // DuckNetwork.Update calls Host( 4, LobbyType.FriendsOnly ) on inviting someone. Since performance would be garbage reflecting all
            // the private variables, we detour host instead.
            Injection.install(3, "Host", "Host");

            // Only would clear custom data for the first 4 profiles so now it clears all 8
            Injection.install(3, "Join", "Join");

            // Adds our new netmessage to the list of netmessage types so that the game doesn't crash when it encounters it
            DuckNetworkEdits.UpdateNetmessageTypes();

            // netProfileIndex determines how many bits are used to store it. Since we need to store up to the value of seven, we need 3 bits
            // rather than the default 2. Best way I thought would be change it when the ducks get added but idk.
            Injection.install(8, "Add", "AddReplace");

            // Method to inject a call into LevelUpdateChange so that it calls our varient which then checks for rock scoreboard
            // then calls our patched Initialize.
            LevelEdits.UpdateLevelChange();

            // NMVoteToSkip checks whether the player index is greater than 3 and discards it if it is. We want it to be discarded when greater
            // than 7.
            NMVoteToSkipEdits.Activate();

            // Change the get method for determining if a room if on the right or left to Value % 2. Will return 1 if on the right.
            // We inject pure assembly so THIS WILL BREAK EVENTUALLY.
            ProfileBox2Edits.rightRoomCorrection();

            // Injection.install(0, "UpdateQuack", "injectionMethod1"); // Disables quack to check everything loaded right

            // Base
            base.OnPreInitialize();
        }
        public static void OnMessage(NetMessage m)
        {
            if (m is NMJoinDuckNetwork)
            {
//                DevConsole.Log(DCSection.DuckNet, "|DGYELLOW|Join message", -1);
                if (DuckNetwork.status == DuckNetStatus.Disconnected)
                {
                    return;
                }
            }
            if (m == null)
            {
                Main.codeNumber = 13371;
            }
            UIMatchmakingBox.pulseNetwork = true;
            if (DuckNetwork.GetProfiles(m.connection).Count == 0 && m.connection != Network.host)
            {
                Main.codeNumber = 13372;
                NetMessage msg = DuckNetwork.OnMessageFromNewClient(m);
                if (msg == null)
                {
                    return;
                }
                Send.Message(msg, m.connection);
            }
            else
            {
                if (DuckNetwork.HandleCoreConnectionMessages(m) || DuckNetwork.status == DuckNetStatus.Disconnecting)
                {
                    return;
                }
                Main.codeNumber = 13373;
                foreach (Profile profile in DuckNetwork.GetProfiles(m.connection))
                {
                    if (profile.networkStatus == DuckNetStatus.Disconnecting || profile.networkStatus == DuckNetStatus.Disconnected || profile.networkStatus == DuckNetStatus.Failure)
                    {
                        return;
                    }
                }
                Main.codeNumber = m.typeIndex;
                if (Network.isServer)
                {
                    if (m is NMLateJoinDuckNetwork)
                    {
                        if (!(Level.current is TeamSelect2))
                        {
                            Send.Message(new NMGameInProgress(), NetMessagePriority.ReliableOrdered, m.connection);
                        }
                        else
                        {
                            NMLateJoinDuckNetwork lateJoinDuckNetwork = m as NMLateJoinDuckNetwork;
//                            DevConsole.Log(DCSection.DuckNet, "|DGYELLOW|Late join attempt from " + lateJoinDuckNetwork.name, -1);
//                            Profile profile = DuckNetwork.CreateProfile(m.connection, lateJoinDuckNetwork.name, (int)lateJoinDuckNetwork.duckIndex, (InputProfile)null, false, false, false);
                            Profile profile = (Profile)createProfile.Invoke(null, new object[] { m.connection, lateJoinDuckNetwork.name, (int)lateJoinDuckNetwork.duckIndex, null, false, false, false });
                            if (profile != null)
                            {
                                profile.networkStatus = DuckNetStatus.Connected;
                                TeamSelect2Edits.OnNetworkConnecting(profile);
                                DuckNetwork.SendNewProfile(profile, m.connection, true);
                            }
                            else
                            {
                                Send.Message(new NMServerFull(), NetMessagePriority.ReliableOrdered, m.connection);
                            }
                        }
                    }
                    else if (m is NMJoinedDuckNetwork)
                    {
                        foreach (Profile profile in DuckNetwork.GetProfiles(m.connection))
                        {
//                            DevConsole.Log(DCSection.DuckNet, "|LIME|" + profile.name + " Has joined the DuckNet", -1);
                            Send.Message(new NMSwitchLevel("@TEAMSELECT", DuckNetwork.levelIndex, (ushort)0, false, 0U), m.connection);
                        }
                    }
                    else if (m is NMClientLoadedLevel)
                    {
                        if ((m as NMClientLoadedLevel).levelIndex == DuckNetwork.levelIndex)
                        {
                            m.connection.wantsGhostData = (m as NMClientLoadedLevel).levelIndex;
                        }
                        else
                        {
                            ;// DevConsole.Log(DCSection.DuckNet, "|DGRED|" + m.connection.identifier + " LOADED WRONG LEVEL! (" + DuckNetwork.levelIndex + " VS " + (m as NMClientLoadedLevel).levelIndex + ")", -1);
                        }
                    }
                    else if (m is NMSetTeam)
                    {
                        NMSetTeam nmSetTeam = m as NMSetTeam;
                        if (nmSetTeam.duck < 0 || nmSetTeam.duck >= 8)
                        {
                            return;
                        }
                        Profile profile = DuckNetwork.profiles[nmSetTeam.duck];
                        if (profile.connection == null || profile.team == null)
                        {
                            return;
                        }
                        profile.team = Teams.all[nmSetTeam.team];
                        if (!DuckNetwork.OnTeamSwitch(profile))
                        {
                            return;
                        }
                        Send.MessageToAllBut(new NMSetTeam(nmSetTeam.duck, nmSetTeam.team), NetMessagePriority.ReliableOrdered, m.connection);
                    }
                    else
                    {
                        if (!(m is NMSpecialHat))
                        {
                            return;
                        }
                        NMSpecialHat nmSpecialHat = m as NMSpecialHat;
                        Team         t            = Team.Deserialize(nmSpecialHat.GetData());
                        foreach (Profile profile in DuckNetwork.profiles)
                        {
                            if ((long)profile.steamID == (long)nmSpecialHat.link)
                            {
                                if (t != null)
                                {
                                    Team.MapFacade(profile.steamID, t);
                                }
                                else
                                {
                                    Team.ClearFacade(profile.steamID);
                                }
                                Send.MessageToAllBut(new NMSpecialHat(t, profile.steamID), NetMessagePriority.ReliableOrdered, m.connection);
                            }
                        }
                    }
                }
                else if (m is NMSpecialHat)
                {
                    NMSpecialHat nmSpecialHat = m as NMSpecialHat;
                    Team         t            = Team.Deserialize(nmSpecialHat.GetData());
                    foreach (Profile profile in DuckNetwork.profiles)
                    {
                        if ((long)profile.steamID == (long)nmSpecialHat.link)
                        {
                            if (t != null)
                            {
                                Team.MapFacade(profile.steamID, t);
                            }
                            else
                            {
                                Team.ClearFacade(profile.steamID);
                            }
                        }
                    }
                }
                else if (m is NMJoinDuckNetwork)
                {
                    NMRemoteJoinDuckNetwork remoteJoinDuckNetwork = m as NMRemoteJoinDuckNetwork;
                    if (remoteJoinDuckNetwork == null)
                    {
//                        DevConsole.Log(DCSection.DuckNet, "|LIME|Connection with host was established!", -1);
                        NMJoinDuckNetwork nmJoinDuckNetwork = m as NMJoinDuckNetwork;
                        _core.status = DuckNetStatus.Connected;
                        if (DuckNetwork.profiles[nmJoinDuckNetwork.duckIndex].connection == DuckNetwork.localConnection)
                        {
                            DuckNetwork.profiles[nmJoinDuckNetwork.duckIndex].networkStatus = DuckNetStatus.Connected;
                        }
                        else
                        {
//                            Profile profile = DuckNetwork.CreateProfile(DuckNetwork.localConnection, Network.activeNetwork.core.GetLocalName(), (int)nmJoinDuckNetwork.duckIndex, UIMatchmakingBox.matchmakingProfiles.Count > 0 ? UIMatchmakingBox.matchmakingProfiles[0].inputProfile : InputProfile.DefaultPlayer1, Teams.core.extraTeams.Count > 0, false, false);
                            Profile profile = (Profile)createProfile.Invoke(null, new object[] { DuckNetwork.localConnection, Network.activeNetwork.core.GetLocalName(), (int)nmJoinDuckNetwork.duckIndex, UIMatchmakingBox.matchmakingProfiles.Count > 0 ? UIMatchmakingBox.matchmakingProfiles[0].inputProfile : InputProfile.DefaultPlayer1, Teams.core.extraTeams.Count > 0, false, false });

                            _core.localDuckIndex  = nmJoinDuckNetwork.duckIndex;
                            profile.flippers      = Profile.CalculateLocalFlippers();
                            profile.networkStatus = DuckNetStatus.WaitingForLoadingToBeFinished;
                        }
                    }
                    else
                    {
                        NetworkConnection networkConnection = remoteJoinDuckNetwork.connection;
                        Main.codeNumber = 133701;
                        if (remoteJoinDuckNetwork.identifier == "SERVER")
                        {
                            Main.codeNumber = 133702;
//                            Profile profile1 = DuckNetwork.CreateProfile(networkConnection, remoteJoinDuckNetwork.name, (int)remoteJoinDuckNetwork.duckIndex, (InputProfile)null, remoteJoinDuckNetwork.hasCustomHats, false, false);
                            Profile profile1 = (Profile)createProfile.Invoke(null, new object[] { networkConnection, remoteJoinDuckNetwork.name, (int)remoteJoinDuckNetwork.duckIndex, null, remoteJoinDuckNetwork.hasCustomHats, false, false });
                            profile1.flippers = remoteJoinDuckNetwork.flippers;
                            profile1.team     = Teams.all[remoteJoinDuckNetwork.team];
                            if (_core.hostDuckIndex == -1)
                            {
                                _core.hostDuckIndex = remoteJoinDuckNetwork.duckIndex;
                            }
                            Main.codeNumber = 133703;
                            bool flag = false;
                            foreach (Profile profile2 in DuckNetwork.GetProfiles(networkConnection))
                            {
                                if (profile2 != profile1)
                                {
                                    profile1.networkStatus = profile2.networkStatus;
                                    flag = true;
                                    break;
                                }
                            }
                            Main.codeNumber = 133704;
                            if (flag)
                            {
                                return;
                            }
                            profile1.networkStatus = DuckNetStatus.WaitingForLoadingToBeFinished;
                        }
                        else
                        {
                            Main.codeNumber = 133705;
                            bool          flag          = false;
                            DuckNetStatus duckNetStatus = DuckNetStatus.NeedsNotificationWhenReadyForData;
                            foreach (Profile profile in DuckNetwork.GetProfiles(networkConnection))
                            {
                                if (profile.connection.identifier == remoteJoinDuckNetwork.identifier)
                                {
                                    networkConnection = profile.connection;
                                    flag          = true;
                                    duckNetStatus = profile.networkStatus;
                                    break;
                                }
                            }
                            Main.codeNumber = 133706;
                            if (!flag)
                            {
                                networkConnection = Network.activeNetwork.core.AttemptConnection(remoteJoinDuckNetwork.identifier);
                                if (networkConnection == null)
                                {
                                    DuckNetwork.RaiseError(new DuckNetErrorInfo()
                                    {
                                        error   = DuckNetError.InvalidConnectionInformation,
                                        message = "Invalid connection information (" + remoteJoinDuckNetwork.identifier + ")"
                                    });
                                    return;
                                }
                            }
                            Main.codeNumber = 133707;
//                            Profile profile1 = DuckNetwork.CreateProfile(networkConnection, remoteJoinDuckNetwork.name, remoteJoinDuckNetwork.duckIndex, (InputProfile)null, remoteJoinDuckNetwork.hasCustomHats, false, false);
                            Profile profile1 = (Profile)createProfile.Invoke(null, new object[] { networkConnection, remoteJoinDuckNetwork.name, remoteJoinDuckNetwork.duckIndex, (InputProfile)null, remoteJoinDuckNetwork.hasCustomHats, false, false });
                            profile1.team          = Teams.all[remoteJoinDuckNetwork.team];
                            profile1.networkStatus = duckNetStatus;
                            profile1.flippers      = remoteJoinDuckNetwork.flippers;
                        }
                    }
                }
                else if (m is NMEndOfDuckNetworkData)
                {
                    Send.Message(new NMJoinedDuckNetwork(), m.connection);
                    foreach (Profile profile in DuckNetwork.profiles)
                    {
                        if (profile.connection == DuckNetwork.localConnection)
                        {
                            Send.Message(new NMProfileInfo(profile.networkIndex, profile.stats.unloyalFans, profile.stats.loyalFans));
                        }
                    }
                }
                else if (m is NMEndOfGhostData)
                {
                    if ((m as NMEndOfGhostData).levelIndex == DuckNetwork.levelIndex)
                    {
                        //                        DevConsole.Log(DCSection.DuckNet, "|DGGREEN|Received Host Level Information (" + (m as NMEndOfGhostData).levelIndex + ").", -1);
                        Level.current.TransferComplete(m.connection);
                        DuckNetwork.SendToEveryone(new NMLevelDataReady(DuckNetwork.levelIndex));
                        foreach (Profile profile in DuckNetwork.GetProfiles(DuckNetwork.localConnection))
                        {
                            profile.connection.loadingStatus = (m as NMEndOfGhostData).levelIndex;
                        }
                    }
                    else
                    {
                        ;// DevConsole.Log(DCSection.DuckNet, "|DGRED|Recieved data for wrong level.", -1);
                    }
                }
                else if (m is NMSetTeam)
                {
                    NMSetTeam nmSetTeam = m as NMSetTeam;
                    if (nmSetTeam.duck < 0 || nmSetTeam.duck >= 8)
                    {
                        return;
                    }
                    Profile profile = DuckNetwork.profiles[nmSetTeam.duck];
                    if (profile.connection == null || profile.team == null)
                    {
                        return;
                    }
                    profile.team = Teams.all[nmSetTeam.team];
                }
                else
                {
                    if (!(m is NMTeamSetDenied))
                    {
                        return;
                    }
                    NMTeamSetDenied nmTeamSetDenied = m as NMTeamSetDenied;
                    if (nmTeamSetDenied.duck < 0 || nmTeamSetDenied.duck >= 8)
                    {
                        return;
                    }
                    Profile profile = DuckNetwork.profiles[nmTeamSetDenied.duck];
                    if (profile.connection != DuckNetwork.localConnection || profile.team == null || Teams.all.IndexOf(profile.team) != nmTeamSetDenied.team)
                    {
                        return;
                    }
                    openTeamSwitchDialogue.Invoke(null, new[] { profile });
                }
            }
        }
        public static NetMessage OnMessageFromNewClient(NetMessage m)
        {
            if (Network.isServer)
            {
                if (m is NMRequestJoin)
                {
                    if (DuckNetwork.inGame)
                    {
                        return((NetMessage) new NMGameInProgress());
                    }
                    NMRequestJoin nmRequestJoin = m as NMRequestJoin;
//                    DevConsole.Log(DCSection.DuckNet, "|DGYELLOW|Join attempt from " + nmRequestJoin.name, -1);
                    NMVersionMismatch.Type code = DuckNetwork.CheckVersion(nmRequestJoin.id);
                    if (code != NMVersionMismatch.Type.Match)
                    {
//                        DevConsole.Log(DCSection.DuckNet, "|DGYELLOW|" + nmRequestJoin.name + " had a version mismatch.", -1);
//                        return (NetMessage)new NMVersionMismatch(code, DG.version);
                        return((NetMessage) new NMVersionMismatch(code, Assembly.GetEntryAssembly().GetName().Version.ToString()));
                    }
                    Type       methodtype    = typeof(DuckNetwork);
                    MethodInfo createProfile = methodtype.GetMethod("CreateProfile", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);

//                    Profile profile = DuckNetwork.CreateProfile(m.connection, nmRequestJoin.name, -1, (InputProfile)null, nmRequestJoin.hasCustomHats, nmRequestJoin.wasInvited, false);
                    Profile profile = (Profile)createProfile.Invoke(null, new object[] { m.connection, nmRequestJoin.name, -1, (InputProfile)null, nmRequestJoin.hasCustomHats, nmRequestJoin.wasInvited, false });

                    if (profile == null)
                    {
//                        DevConsole.Log(DCSection.DuckNet, "|DGYELLOW|" + nmRequestJoin.name + " could not join, server is full.", -1);
                        return((NetMessage) new NMServerFull());
                    }
                    profile.flippers      = nmRequestJoin.flippers;
                    profile.networkStatus = DuckNetStatus.WaitingForLoadingToBeFinished;
                    _core.status          = DuckNetStatus.Connected;

                    TeamSelect2Edits.OnNetworkConnecting(profile);

                    DuckNetwork.SendNewProfile(profile, m.connection, false);

                    // More slots so we need bigger method to handle them
                    Send.Message(new NMChangeSlotsEdits((byte)DuckNetwork.profiles[0].slotType, (byte)DuckNetwork.profiles[1].slotType, (byte)DuckNetwork.profiles[2].slotType, (byte)DuckNetwork.profiles[3].slotType, (byte)DuckNetwork.profiles[4].slotType, (byte)DuckNetwork.profiles[5].slotType, (byte)DuckNetwork.profiles[6].slotType, (byte)DuckNetwork.profiles[7].slotType), m.connection);
                    TeamSelect2.SendMatchSettings(m.connection, true);
                    return((NetMessage)null);
                }
                if (m is NMMessageIgnored)
                {
                    return((NetMessage)null);
                }
            }
            else
            {
                if (m is NMRequestJoin)
                {
//                    DevConsole.Log(DCSection.DuckNet, "|DGYELLOW|Another computer has requested a matchmaking connection.", -1);
                    return((NetMessage) new NMGameInProgress());
                }
                if (m is NMMessageIgnored)
                {
                    return((NetMessage)null);
                }
            }
            return((NetMessage) new NMMessageIgnored());
        }