Exemplo n.º 1
0
        public override void Handle(ByteReader data)
        {
            object target = null;

            if (targetType != null)
            {
                target = Sync.ReadSyncObject(data, targetType);
                if (target == null)
                {
                    return;
                }
            }

            object value = Sync.ReadSyncObject(data, fieldType);

            if (cancelIfValueNull && value == null)
            {
                return;
            }

            object index = null;

            if (indexType != null)
            {
                index = Sync.ReadSyncObject(data, indexType);
            }

            preApply?.Invoke(target, value);

            MpLog.Log($"Set {memberPath} in {target} to {value}, map {data.MpContext().map}, index {index}");
            MpReflection.SetValue(target, memberPath, value, index);

            postApply?.Invoke(target, value);
        }
Exemplo n.º 2
0
        public static void TryConnect(IPAddress address, int port)
        {
            EventBasedNetListener listener = new EventBasedNetListener();

            Multiplayer.session = new MultiplayerSession();
            NetManager netClient = new NetManager(listener);

            netClient.Start();
            netClient.ReconnectDelay     = 300;
            netClient.MaxConnectAttempts = 8;

            listener.PeerConnectedEvent += peer =>
            {
                IConnection conn = new MpNetConnection(peer);
                conn.username = Multiplayer.username;
                conn.State    = ConnectionStateEnum.ClientJoining;
                Multiplayer.session.client = conn;

                MpLog.Log("Net client connected");
            };

            listener.PeerDisconnectedEvent += (peer, info) =>
            {
                string reason;

                if (info.AdditionalData.AvailableBytes > 0)
                {
                    reason = info.AdditionalData.GetString();
                }
                else
                {
                    reason = DisconnectReasonString(info.Reason);
                    if (info.SocketErrorCode != SocketError.Success)
                    {
                        reason += ": " + info.SocketErrorCode;
                    }
                }

                Multiplayer.session.disconnectNetReason = reason;

                ConnectionStatusListeners.TryNotifyAll_Disconnected();

                OnMainThread.StopMultiplayer();
                MpLog.Log("Net client disconnected");
            };

            listener.NetworkReceiveEvent += (peer, reader, method) =>
            {
                byte[] data = reader.GetRemainingBytes();
                Multiplayer.HandleReceive(new ByteReader(data), method == DeliveryMethod.ReliableOrdered);
            };

            listener.NetworkErrorEvent += (endpoint, error) =>
            {
                Log.Warning($"Net client error {error}");
            };

            Multiplayer.session.netClient = netClient;
            netClient.Connect(address.ToString(), port, "");
        }
Exemplo n.º 3
0
        public override void Handle(ByteReader data)
        {
            object target = Activator.CreateInstance(delegateType);

            for (int i = 0; i < fieldPaths.Length; i++)
            {
                string path       = fieldPaths[i];
                string noTypePath = MpReflection.RemoveType(path);
                Type   fieldType  = fieldTypes[i];
                object value;

                if (fieldType.IsCompilerGenerated())
                {
                    value = Activator.CreateInstance(fieldType);
                }
                else
                {
                    value = Sync.ReadSyncObject(data, fieldType);
                }

                if (value == null)
                {
                    if (cancelIfAnyNullBlacklist != null && !cancelIfAnyNullBlacklist.Contains(noTypePath))
                    {
                        return;
                    }

                    if (path.EndsWith("$this"))
                    {
                        return;
                    }

                    if (cancelIfNull != null && cancelIfNull.Contains(noTypePath))
                    {
                        return;
                    }
                }

                if (removeNullsFromLists != null && removeNullsFromLists.Contains(noTypePath) && value is IList list)
                {
                    list.RemoveNulls();
                }

                MpReflection.SetValue(target, path, value);
            }

            if (context.HasFlag(SyncContext.MapSelected) && cancelIfNoSelectedObjects && Find.Selector.selected.Count == 0)
            {
                return;
            }

            object[] parameters = Sync.ReadSyncObjects(data, argTypes);

            MpLog.Log("Invoked delegate method " + method + " " + delegateType);
            method.Invoke(target, parameters);
        }
        public void OnPeerConnected(NetPeer peer)
        {
            IConnection conn = new MpNetConnection(peer);

            conn.username = Multiplayer.username;
            conn.State    = ConnectionStateEnum.ClientJoining;
            Multiplayer.session.client = conn;

            MpLog.Log("Net client connected");
        }
Exemplo n.º 5
0
        public void Add(SyncInfo info)
        {
            if (Multiplayer.session.desynced)
            {
                return;
            }
            if (TickPatch.Skipping)
            {
                return;
            }

            if (buffer.Count == 0)
            {
                buffer.Add(info);
                return;
            }

            if (buffer[0].local == info.local)
            {
                buffer.Add(info);
                if (buffer.Count > 30)
                {
                    buffer.RemoveAt(0);
                }
            }
            else
            {
                while (buffer.Count > 0 && buffer[0].startTick < info.startTick)
                {
                    buffer.RemoveAt(0);
                }

                if (buffer.Count == 0)
                {
                    buffer.Add(info);
                }
                else if (buffer.First().startTick == info.startTick)
                {
                    var first = buffer.RemoveFirst();
                    var error = first.Compare(info);

                    if (error != null)
                    {
                        MpLog.Log($"Desynced {lastValidTick}: {error}");
                        Multiplayer.session.desynced = true;
                        OnMainThread.Enqueue(() => OnDesynced(first, info, error));
                    }
                    else
                    {
                        lastValidTick    = first.startTick;
                        lastValidArbiter = Multiplayer.session.ArbiterPlaying;
                    }
                }
            }
        }
Exemplo n.º 6
0
        public void OnPeerDisconnected(NetPeer peer, DisconnectInfo info)
        {
            var reader = new ByteReader(info.AdditionalData.GetRemainingBytes());

            Multiplayer.session.HandleDisconnectReason((MpDisconnectReason)reader.ReadByte(), reader.ReadPrefixedBytes());

            ConnectionStatusListeners.TryNotifyAll_Disconnected();

            OnMainThread.StopMultiplayer();
            MpLog.Log("Net client disconnected");
        }
Exemplo n.º 7
0
        public void OnPeerConnected(NetPeer peer)
        {
            ConnectionBase conn = new LiteNetConnection(peer);

            conn.username = Multiplayer.username;
            conn.State    = ConnectionStateEnum.ClientJoining;
            conn.StateObj.StartState();

            Multiplayer.session.client = conn;
            Multiplayer.session.ReapplyPrefs();

            MpLog.Log("Net client connected");
        }
Exemplo n.º 8
0
        public override void Handle(ByteReader data)
        {
            object target = null;

            if (targetType != null)
            {
                target = Sync.ReadSyncObject(data, targetType);
                if (target == null)
                {
                    return;
                }
            }

            if (!instancePath.NullOrEmpty())
            {
                target = target.GetPropertyOrField(instancePath);
            }

            object[] args = null;
            if (argTypes != null)
            {
                args = Sync.ReadSyncObjects(data, argTypes);
                if (cancelIfAnyArgNull && args.Any(a => a == null))
                {
                    return;
                }
            }

            if (context.HasFlag(SyncContext.MapSelected) && cancelIfNoSelectedMapObjects && Find.Selector.selected.Count == 0)
            {
                return;
            }

            if (context.HasFlag(SyncContext.WorldSelected) && cancelIfNoSelectedWorldObjects && Find.WorldSelector.selected.Count == 0)
            {
                return;
            }

            beforeCall?.Invoke(target, args);

            MpLog.Log("Invoked " + method + " on " + target + " with " + args.Length + " params " + args.ToStringSafeEnumerable());
            method.Invoke(target, args);

            afterCall?.Invoke(target, args);
        }
Exemplo n.º 9
0
        public static void ScheduleCommand(ScheduledCommand cmd)
        {
            MpLog.Log($"Cmd: {cmd.type}, faction: {cmd.factionId}, map: {cmd.mapId}, ticks: {cmd.ticks}");
            cachedMapCmds.GetOrAddNew(cmd.mapId).Add(cmd);

            if (Current.ProgramState != ProgramState.Playing)
            {
                return;
            }

            if (cmd.mapId == ScheduledCommand.Global)
            {
                Multiplayer.WorldComp.cmds.Enqueue(cmd);
            }
            else
            {
                cmd.GetMap()?.AsyncTime().cmds.Enqueue(cmd);
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Adds a client opinion to the <see cref="knownClientOpinions"/> list and checks that it matches the most recent currently in there. If not, a desync event is fired.
        /// </summary>
        /// <param name="newOpinion">The <see cref="ClientSyncOpinion"/> to add and check.</param>
        public void AddClientOpinionAndCheckDesync(ClientSyncOpinion newOpinion)
        {
            //If we've already desynced, don't even bother
            if (Multiplayer.session.desynced)
            {
                return;
            }

            //If we're skipping ticks, again, don't bother
            if (TickPatch.Skipping)
            {
                return;
            }

            //If this is the first client opinion we have nothing to compare it with, so just add it
            if (knownClientOpinions.Count == 0)
            {
                knownClientOpinions.Add(newOpinion);
                return;
            }

            if (knownClientOpinions[0].isLocalClientsOpinion == newOpinion.isLocalClientsOpinion)
            {
                knownClientOpinions.Add(newOpinion);
                if (knownClientOpinions.Count > 30)
                {
                    knownClientOpinions.RemoveAt(0);
                }
            }
            else
            {
                //Remove all opinions that started before this one, as it's the most up to date one
                while (knownClientOpinions.Count > 0 && knownClientOpinions[0].startTick < newOpinion.startTick)
                {
                    knownClientOpinions.RemoveAt(0);
                }

                //If there are none left, we don't need to compare this new one
                if (knownClientOpinions.Count == 0)
                {
                    knownClientOpinions.Add(newOpinion);
                }
                else if (knownClientOpinions.First().startTick == newOpinion.startTick)
                {
                    //If these two contain the same tick range - i.e. they start at the same time, cause they should continue to the current tick, then do a comparison.

                    var oldOpinion = knownClientOpinions.RemoveFirst();

                    //Actually do the comparison to find any desync
                    var desyncMessage = oldOpinion.CheckForDesync(newOpinion);

                    if (desyncMessage != null)
                    {
                        MpLog.Log($"Desynced after tick {lastValidTick}: {desyncMessage}");
                        Multiplayer.session.desynced = true;
                        OnMainThread.Enqueue(() => HandleDesync(oldOpinion, newOpinion, desyncMessage));
                    }
                    else
                    {
                        //Update fields
                        lastValidTick = oldOpinion.startTick;
                        arbiterWasPlayingOnLastValidTick = Multiplayer.session.ArbiterPlaying;
                    }
                }
            }
        }