Example #1
0
        /// <summary>A callback raised when sending a network message as the host player.</summary>
        /// <param name="server">The server sending the message.</param>
        /// <param name="connection">The connection to which a message is being sent.</param>
        /// <param name="message">The message being sent.</param>
        /// <param name="resume">Send the underlying message.</param>
        protected void OnServerSendingMessage(SLidgrenServer server, NetConnection connection, OutgoingMessage message, Action resume)
        {
            if (this.Monitor.IsVerbose)
            {
                this.Monitor.Log($"SERVER SEND {(MessageType)message.MessageType} {message.FarmerID}", LogLevel.Trace);
            }

            resume();
        }
Example #2
0
        /// <summary>Process an incoming network message as the host player.</summary>
        /// <param name="server">The server instance that received the connection.</param>
        /// <param name="rawMessage">The raw network message that was received.</param>
        /// <param name="message">The message to process.</param>
        /// <param name="resume">Process the message using the game's default logic.</param>
        public void OnServerProcessingMessage(SLidgrenServer server, NetIncomingMessage rawMessage, IncomingMessage message, Action resume)
        {
            if (this.Monitor.IsVerbose)
            {
                this.Monitor.Log($"SERVER RECV {(MessageType)message.MessageType} {message.FarmerID}", LogLevel.Trace);
            }

            switch (message.MessageType)
            {
            // sync mod context (step 2)
            case (byte)MessageType.ModContext:
            {
                // parse message
                RemoteContextModel model = this.ReadContext(message.Reader);
                this.Monitor.Log($"Received context for farmhand {message.FarmerID} running {(model != null ? $"SMAPI {model.ApiVersion} with {model.Mods.Length} mods" : "vanilla")}.", LogLevel.Trace);

                // store peer
                MultiplayerPeer newPeer = MultiplayerPeer.ForConnectionToFarmhand(message.FarmerID, model, server, rawMessage.SenderConnection);
                if (this.Peers.ContainsKey(message.FarmerID))
                {
                    this.Monitor.Log($"Rejected mod context from farmhand {message.FarmerID}: already received context for that player.", LogLevel.Error);
                    return;
                }
                this.AddPeer(newPeer, canBeHost: false, raiseEvent: false);

                // reply with own context
                this.Monitor.VerboseLog("   Replying with host context...");
                newPeer.SendMessage(new OutgoingMessage((byte)MessageType.ModContext, Game1.player.UniqueMultiplayerID, this.GetContextSyncMessageFields()));

                // reply with other players' context
                foreach (MultiplayerPeer otherPeer in this.Peers.Values.Where(p => p.PlayerID != newPeer.PlayerID))
                {
                    this.Monitor.VerboseLog($"   Replying with context for player {otherPeer.PlayerID}...");
                    newPeer.SendMessage(new OutgoingMessage((byte)MessageType.ModContext, otherPeer.PlayerID, this.GetContextSyncMessageFields(otherPeer)));
                }

                // forward to other peers
                if (this.Peers.Count > 1)
                {
                    object[] fields = this.GetContextSyncMessageFields(newPeer);
                    foreach (MultiplayerPeer otherPeer in this.Peers.Values.Where(p => p.PlayerID != newPeer.PlayerID))
                    {
                        this.Monitor.VerboseLog($"   Forwarding context to player {otherPeer.PlayerID}...");
                        otherPeer.SendMessage(new OutgoingMessage((byte)MessageType.ModContext, newPeer.PlayerID, fields));
                    }
                }

                // raise event
                this.EventManager.PeerContextReceived.Raise(new PeerContextReceivedEventArgs(newPeer));
            }
            break;

            // handle player intro
            case (byte)MessageType.PlayerIntroduction:
                // store peer if new
                if (!this.Peers.ContainsKey(message.FarmerID))
                {
                    this.Monitor.Log($"Received connection for vanilla player {message.FarmerID}.", LogLevel.Trace);
                    MultiplayerPeer peer = MultiplayerPeer.ForConnectionToFarmhand(message.FarmerID, null, server, rawMessage.SenderConnection);
                    this.AddPeer(peer, canBeHost: false);
                }

                resume();
                break;

            // handle mod message
            case (byte)MessageType.ModMessage:
                this.ReceiveModMessage(message);
                break;

            default:
                resume();
                break;
            }
        }