示例#1
0
        public void UpdateGameConnections(Process process)
        {
            var update             = _connections.Count < 2;
            var currentConnections = GetConnections(process);

            foreach (var connection in _connections)
            {
                if (!currentConnections.Contains(connection))
                {
                    // 기존 연결 끊겨 있음, 새로 해야함
                    update = true;
                    MsgLog.Error("l-network-detected-connection-closing");
                    break;
                }
            }

            if (update)
            {
                var lobbyEndPoint = GetLobbyEndPoint(process);

                _connections = currentConnections.Where(x => !x.RemoteEndPoint.Equals(lobbyEndPoint)).ToList();

                foreach (var connection in _connections)
                {
                    MsgLog.Info("l-network-detected-connection", connection);
                }
            }
        }
示例#2
0
 //
 private void CboLogBackground_SelectedValueChanged(object sender, EventArgs e)
 {
     if (!string.IsNullOrWhiteSpace(cboLogBackground.Text) && !cboLogBackground.Text.Equals(Color.Transparent.Name))
     {
         rtxLogger.BackColor = Color.FromName(cboLogBackground.Text);
         MsgLog.Info("l-info-back-color", cboLogBackground.Text);
     }
 }
示例#3
0
        //
        private void ReadGameData(Localization.Locale gamelang = null)
        {
            Localization.Locale lang = gamelang ?? (Localization.Locale)cboGameLanguage.SelectedItem;

            if (_localeGame == null || !lang.Code.Equals(_localeGame.Code))
            {
                _localeGame = lang;
                GameData.Initialize(Settings.PluginPath, lang.Code);

                MsgLog.Info("l-info-version",
                            GameData.Version,
                            GameData.Areas.Count, GameData.Instances.Count,
                            GameData.Roulettes.Count, GameData.Fates.Count);
            }
        }
示例#4
0
        public void StartCapture(Process process)
        {
            _pid = process.Id;

            Task.Factory.StartNew(() =>
            {
                try
                {
                    MsgLog.Info("l-network-starting");

                    if (IsRunning)
                    {
                        MsgLog.Error("l-network-error-already-started");
                        return;
                    }

                    UpdateGameConnections(process);

                    if (_connections.Count < 2)
                    {
                        MsgLog.Error("l-network-error-no-connection");
                        return;
                    }

                    var localAddress = _connections[0].LocalEndPoint.Address;

                    RegisterToFirewall();

                    _socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
                    _socket.Bind(new IPEndPoint(localAddress, 0));
                    _socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, true);
                    _socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AcceptConnection, true);
                    _socket.IOControl(IOControlCode.ReceiveAll, RcvAllIpLevel, null);
                    _socket.ReceiveBufferSize = _recvBuffer.Length * 4;

                    _socket.BeginReceive(_recvBuffer, 0, _recvBuffer.Length, 0, OnReceive, null);
                    IsRunning = true;

                    MsgLog.Success("l-network-started");
                }
                catch (Exception ex)
                {
                    MsgLog.Exception(ex, "l-network-error-starting");
                }
            });
        }
示例#5
0
        public void StopCapture()
        {
            try
            {
                if (!IsRunning)
                {
                    MsgLog.Error("l-network-error-already-stopped");
                    return;
                }

                _socket.Close();
                _connections.Clear();

                MsgLog.Info("l-network-stopping");
            }
            catch (Exception ex)
            {
                MsgLog.Exception(ex, "l-network-error-stopping");
            }
        }
示例#6
0
        //
        private void ActInitialize()
        {
            if (_isInActInit)
            {
                return;
            }

            _isInActInit = true;

            MsgLog.SetTextBox(rtxLogger);
            ActGlobals.oFormActMain.Shown -= OFormActMain_Shown;

            Localization.Locale defaultlocale = Localization.DefaultLocale;
            ReadLocale(defaultlocale);

#if DEBUG
            MsgLog.Info("ui-dbg-msg", System.Environment.CurrentDirectory);
            MsgLog.Info("ui-dbg-msg", Settings.PluginPath);
#endif

            ReadGameData(defaultlocale);

            _isPluginEnabled = true;

            cboUiLanguage.DataSource    = Localization.Locales.Clone();
            cboUiLanguage.DisplayMember = "Name";
            cboUiLanguage.ValueMember   = "Code";

            cboGameLanguage.DataSource    = Localization.Locales.Clone();
            cboGameLanguage.DisplayMember = "Name";
            cboGameLanguage.ValueMember   = "Code";

            Dock = DockStyle.Fill;

            _actLabelStatus.Text = "Initializing...";

            UpdateUiLanguage();

            _actLabelStatus.Text = Localization.GetText("l-plugin-started");
            _actTabPage.Text     = Localization.GetText("app-name");
            _actTabPage.Controls.Add(this);

            _srset = new SettingsSerializer(this);
            ReadSettings();

            UpdateFates();

            UpdateProcesses();

            if (_timer == null)
            {
                _timer = new Timer {
                    Interval = 10000
                };
                _timer.Tick += _timer_Tick;
            }

            _timer.Enabled = true;

            _isInActInit = false;
        }
示例#7
0
        private static void HandleMessage(int pid, byte[] message, ref MatchStatus state)
        {
            try
            {
                if (message.Length < 32)
                {
                    // type == 0x0000 이였던 메시지는 여기서 걸러짐
                    return;
                }

                var opcode = BitConverter.ToUInt16(message, 18);

#if !DEBUG
                if (
                    opcode != 0x006F &&
                    opcode != 0x0078 &&
                    opcode != 0x0079 &&
                    opcode != 0x0080 &&
                    opcode != 0x0121 &&
                    opcode != 0x0143 &&
                    opcode != 0x022F &&
                    // 5.1
                    opcode != 0x008F &&
                    opcode != 0x00AE &&
                    opcode != 0x00B3 &&
                    opcode != 0x015E &&
                    opcode != 0x0304 &&
                    // 5.11
                    opcode != 0x0002 &&
                    opcode != 0x0164 &&
                    opcode != 0x0339 &&
                    opcode != 0x032D &&
                    opcode != 0x032F &&
                    opcode != 0x03CF)
                {
                    return;
                }
#endif

                var data = message.Skip(32).ToArray();

                if (opcode == 0x022F)                 // 인스턴스 들어오고 나가기
                {
                    var code = BitConverter.ToInt16(data, 4);

                    if (code == 0)
                    {
                        return;
                    }

                    var type = data[8];

                    if (type == 0x0B)
                    {
                        // 들어옴
                        MsgLog.Info("l-field-instance-entered", GameData.GetInstanceName(code));
                        FireEvent(pid, GameEvents.InstanceEnter, new int[] { code });
                    }
                    else if (type == 0x0C)
                    {
                        // 나감
                        MsgLog.Info("l-field-instance-left");
                        FireEvent(pid, GameEvents.InstanceLeave, new int[] { code });
                    }
                }                          // 22F
                else if (opcode == 0x0143) // FATE 관련
                {
#if false
                    // FATE 막음 2019-11-01
                    var type = data[0];

                    if (type == 0x9B)
                    {
                        var code     = BitConverter.ToUInt16(data, 4);
                        var progress = data[8];
                        FireEvent(pid, GameEvents.FateProgress, new int[] { code, progress });
                    }
                    else if (type == 0x79) // FATE 끗
                    {
                        var code   = BitConverter.ToUInt16(data, 4);
                        var status = BitConverter.ToUInt16(data, 28);
                        FireEvent(pid, GameEvents.FateEnd, new int[] { code, status });
                    }
                    else if (type == 0x74) // FATE 시작! 에이리어 이동해도 진행중인 것도 이걸로 처리됨
                    {
                        var code = BitConverter.ToUInt16(data, 4);

                        if (Settings.LoggingWholeFates || Settings.SelectedFates.Contains(code.ToString()))
                        {
                            MsgLog.Info("l-fate-occured-info", GameData.GetFate(code).Name);
                            FireEvent(pid, GameEvents.FateBegin, new int[] { code });
                        }
                    }
#endif
                }                          // 143
                else if (opcode == 0x0078) // 5.1이전 듀티
                {
                    var status = data[0];
                    var reason = data[4];

                    if (status == 0)                     // 듀티 큐
                    {
                        state = MatchStatus.Queued;

                        _rouletteCode = data[20];

                        if (_rouletteCode != 0 && (data[15] == 0 || data[15] == 64))                         // 루렛, 한국/글로벌
                        {
                            MsgLog.Info("l-queue-started-roulette", GameData.GetRouletteName(_rouletteCode));
                            FireEvent(pid, GameEvents.MatchBegin, new[] { (int)MatchType.Roulette, _rouletteCode });
                        }
                        else                         // 듀티 지정 큐 (Dungeon/Trial/Raid)
                        {
                            _rouletteCode = 0;

                            var instances = new List <int>();

                            for (var i = 0; i < 5; i++)
                            {
                                var code = BitConverter.ToUInt16(data, 22 + i * 2);
                                if (code == 0)
                                {
                                    break;
                                }

                                instances.Add(code);
                            }

                            if (!instances.Any())
                            {
                                return;
                            }

                            var args = new List <int> {
                                (int)MatchType.Assignment, instances.Count
                            };
                            foreach (var item in instances)
                            {
                                args.Add(item);
                            }

                            MsgLog.Info("l-queue-started-general", string.Join(", ", instances.Select(x => GameData.GetInstanceName(x)).ToArray()));
                            FireEvent(pid, GameEvents.MatchBegin, args.ToArray());
                        }
                    }
                    else if (status == 3)                     // 취소
                    {
                        state = reason == 8 ? MatchStatus.Queued : MatchStatus.Idle;
                        MsgLog.Info("l-queue-stopped");
                        FireEvent(pid, GameEvents.MatchEnd, new[] { (int)MatchResult.Cancel });
                    }
                    else if (status == 6)                     // 들어가기
                    {
                        state = MatchStatus.Idle;
                        MsgLog.Info("l-queue-entered");
                        FireEvent(pid, GameEvents.MatchEnd, new[] { (int)MatchResult.Enter });
                    }
                    else if (status == 4)                     // 매치
                    {
                        var roulette = data[20];
                        var code     = BitConverter.ToUInt16(data, 22);

                        state = MatchStatus.Matched;

                        MsgLog.Info("l-queue-matched", GameData.GetInstanceName(code));
                        FireEvent(pid, GameEvents.MatchDone, new int[] { roulette, code });
                    }
                }                 // 78
                else if (opcode == 0x006F)
                {
                    var status = data[0];

                    if (status == 0)
                    {
                        // 플레이어가 매칭 참가 확인 창에서 취소를 누르거나 참가 확인 제한 시간이 초과됨
                        // 매칭 중단을 알리기 위해 상단 2DB status 3 패킷이 연이어 옴
                    }
                    if (status == 1)
                    {
                        // 플레이어가 매칭 참가 확인 창에서 확인을 누름
                        // 다른 매칭 인원들도 전부 확인을 눌렀을 경우 입장을 위해 상단 2DB status 6 패킷이 옴
                        FireEvent(pid, GameEvents.MatchCancel, new int[] { -1 });
                    }
                }                          // 6F
                else if (opcode == 0x0121) // 글로벌 깜빡
                {
                    var status = data[5];

                    if (status == 128)
                    {
                        // 매칭 참가 신청 확인 창에서 확인을 누름, 그러니깐 표시 안하도됨
                        FireEvent(pid, GameEvents.MatchCancel, new int[] { -1 });
                    }
                }                          // 121
                else if (opcode == 0x0079) // 매치 상태
                {
                    var code     = BitConverter.ToUInt16(data, 0);
                    var order    = data[4];
                    var status   = data[8];
                    var tank     = data[9];
                    var dps      = data[10];
                    var healer   = data[11];
                    var member   = tank * 10000 + healer * 100 + dps;
                    var instance = GameData.GetInstance(code);

                    if (status == 1)
                    {
                        if (state == MatchStatus.Matched && _lastMember != member)
                        {
                            // 마지막 정보와 다름, 다른 사람에 의한 취소... 인데 이거 되나??!!!
                            state = MatchStatus.Queued;
                            FireEvent(pid, GameEvents.MatchCancel, new int[] { -1 });
                        }
                        else if (state == MatchStatus.Idle || state == MatchStatus.Queued)
                        {
                            if (state == MatchStatus.Idle)
                            {
                                // 매칭 중간에 플러그인이 시작됨
                                state = MatchStatus.Queued;
                            }

                            if (_rouletteCode > 0 || (tank == 0 && healer == 0 && dps == 0))
                            {
                                FireEvent(pid, GameEvents.MatchOrder, new int[] { order });
                            }
                            else
                            {
                                FireEvent(pid, GameEvents.MatchStatus, new int[] { (int)MatchType.ShortStatus, code, status, tank, healer, dps });
                            }
                        }

                        _lastMember = member;
                        _lastOrder  = order;
                    }
                    else if (status == 2)
                    {
                        // 매칭 파티의 인원 정보
                        FireEvent(pid, GameEvents.MatchStatus, new int[] { (int)MatchType.ShortStatus, code, status, tank, healer, dps });
                        return;              // 이건 로그를 안뿌린다
                    }
                    else                     //if (status == 4)
                    {
                        // 매칭하고 파티 인원 상태
                        // 추가로: 다른거땜에 오버레이가 지워질 수도 있음... ㅠㅠ
                        FireEvent(pid, GameEvents.MatchStatus, new int[] { (int)MatchType.ShortStatus, code, status, tank, healer, dps });

                        if (status != 4)
                        {
                            // 기타면 로그 출력X
                            // ....그러고보니 status == 2일때도 여기서 처리해도 되는데 지면이 부족하여 패-_-스
                            return;
                        }
                    }

                    var memberinfo = $"{order} | {tank}/{instance.Tank}, {healer}/{instance.Healer}, {dps}/{instance.Dps} | {member}";
                    MsgLog.Info("l-queue-updated", instance.Name, status, memberinfo);
                }                 // 79
                else if (opcode == 0x0080)
                {
                    var roulette = data[2];
                    var code     = BitConverter.ToUInt16(data, 4);

                    state = MatchStatus.Matched;
                    FireEvent(pid, GameEvents.MatchDone, new int[] { roulette, code });

                    MsgLog.Success("l-queue-matched ", code);
                }                          // 80
                #region 5.1 추가
                else if (opcode == 0x008F) // 5.1 큐 (opcode = 0x0078, status = 0)
                {
                    var status = data[0];
                    var reason = data[4];

                    state = MatchStatus.Queued;

                    _rouletteCode = data[8];

                    if (_rouletteCode != 0 && (data[15] == 0 || data[15] == 64))                     // 루렛, 한국/글로벌
                    {
                        MsgLog.Info("l-queue-started-roulette", GameData.GetRouletteName(_rouletteCode));
                        FireEvent(pid, GameEvents.MatchBegin, new[] { (int)MatchType.Roulette, _rouletteCode });
                    }
                    else                     // 듀티 지정 큐 (Dungeon/Trial/Raid)
                    {
                        _rouletteCode = 0;

                        var instances = new List <int>();

                        for (var i = 0; i < 5; i++)
                        {
                            var code = BitConverter.ToUInt16(data, 12 + (i * 4));
                            if (code == 0)
                            {
                                break;
                            }
                        }

                        if (!instances.Any())
                        {
                            return;
                        }

                        var args = new List <int> {
                            (int)MatchType.Assignment, instances.Count
                        };
                        foreach (var item in instances)
                        {
                            args.Add(item);
                        }

                        MsgLog.Info("l-queue-started-general", string.Join(", ", instances.Select(x => GameData.GetInstanceName(x)).ToArray()));
                        FireEvent(pid, GameEvents.MatchBegin, args.ToArray());
                    }
                }                          // 8F
                else if (opcode == 0x00B3) // 5.1 매칭 (opcode = 0x0078, status = 4)
                {
                    var code = BitConverter.ToUInt16(data, 20);

                    state = MatchStatus.Matched;

                    MsgLog.Info("l-queue-matched", GameData.GetInstanceName(code));
                    FireEvent(pid, GameEvents.MatchDone, new int[] { _rouletteCode, code });
                }                          // B3
                else if (opcode == 0x015E) // 5.1 캔슬 (opcode = 0x0078, status = 3)
                {
                    var status = data[3];

                    if (status == 8)                        // 0이아님
                    {
                        state = MatchStatus.Idle;
                        MsgLog.Info("l-queue-stopped");
                        FireEvent(pid, GameEvents.MatchEnd, new[] { (int)MatchResult.Cancel });
                    }
                }                          // 15E
                else if (opcode == 0x0304) // 5.1, 5.11 상태 (opcode = 0x0078, status = 1)
                {
                    var order     = data[6];
                    var wait      = data[7];
                    var tank      = data[8];
                    var maxtank   = data[9];
                    var healer    = data[10];
                    var maxhealer = data[11];
                    var dps       = data[12];
                    var maxdps    = data[13];
                    var member    = tank * 10000 + healer * 100 + dps;

                    if (state == MatchStatus.Matched && _lastMember != member)
                    {
                        // 마지막 정보와 다름, 다른 사람에 의한 취소... 인데 이거 되나??!!!
                        state = MatchStatus.Queued;
                        FireEvent(pid, GameEvents.MatchCancel, new int[] { -1 });
                    }
                    else if (state == MatchStatus.Idle || state == MatchStatus.Queued)
                    {
                        if (state == MatchStatus.Idle)
                        {
                            // 매칭 중간에 플러그인 시작
                            state = MatchStatus.Queued;
                        }

                        if (_rouletteCode > 0 ||
                            (tank == 0 && healer == 0 && dps == 0) ||
                            (tank > maxtank || healer > maxhealer || dps > maxdps))
                        {
                            FireEvent(pid, GameEvents.MatchOrder, new int[] { order });
                        }
                        else
                        {
                            FireEvent(pid, GameEvents.MatchStatus, new int[] { (int)MatchType.LongStatus, 0, order, tank, healer, dps, maxtank, maxhealer, maxdps });
                        }
                    }

                    _lastMember = member;
                    _lastOrder  = order;

                    var memberinfo = $"{tank}/{maxtank}, {healer}/{maxhealer}, {dps}/{maxdps}";
                    MsgLog.Info("l-queue-updated", $"#{order}", wait, memberinfo);
                }                          // 304
                else if (opcode == 0x00AE) // 5.1 매칭하고 파티 인원 (opcode = 0x0078, status = 4)
                {
                    var code   = BitConverter.ToUInt16(data, 8);
                    var tank   = data[12];
                    var healer = data[14];
                    var dps    = data[16];

                    FireEvent(pid, GameEvents.MatchStatus, new int[] { (int)MatchType.ShortStatus, code, 0, tank, healer, dps });
                }                          // AE
                #endregion                 // 5.1 추가
                #region 5.11 추가
                else if (opcode == 0x0339) // 5.11 인스턴스 들어오고 나가기
                {
                    var code = BitConverter.ToInt16(data, 4);

                    if (code == 0)
                    {
                        return;
                    }

                    var type = data[8];

                    if (type == 0x0B)
                    {
                        // 들어옴
                        MsgLog.Info("l-field-instance-entered", GameData.GetInstanceName(code));
                        FireEvent(pid, GameEvents.InstanceEnter, new int[] { code });
                    }
                    else if (type == 0x0C)
                    {
                        // 나감
                        MsgLog.Info("l-field-instance-left");
                        FireEvent(pid, GameEvents.InstanceLeave, new int[] { code });
                    }
                }                          // 339
                else if (opcode == 0x0164) // 5.11 큐
                {
                    var status = data[0];
                    var reason = data[4];

                    state = MatchStatus.Queued;

                    _rouletteCode = data[8];

                    if (_rouletteCode != 0 && (data[15] == 0 || data[15] == 64))
                    {
                        MsgLog.Info("l-queue-started-roulette", GameData.GetRouletteName(_rouletteCode));
                        FireEvent(pid, GameEvents.MatchBegin, new[] { (int)MatchType.Roulette, _rouletteCode });
                    }
                    else                     // 듀티 지정 큐 (Dungeon/Trial/Raid)
                    {
                        _rouletteCode = 0;

                        var instances = new List <int>();

                        for (var i = 0; i < 5; i++)
                        {
                            var code = BitConverter.ToUInt16(data, 12 + (i * 4));
                            if (code == 0)
                            {
                                break;
                            }
                        }

                        if (!instances.Any())
                        {
                            return;
                        }

                        var args = new List <int> {
                            (int)MatchType.Assignment, instances.Count
                        };
                        foreach (var item in instances)
                        {
                            args.Add(item);
                        }

                        MsgLog.Info("l-queue-started-general", string.Join(", ", instances.Select(x => GameData.GetInstanceName(x)).ToArray()));
                        FireEvent(pid, GameEvents.MatchBegin, args.ToArray());
                    }
                }                          // 164
                else if (opcode == 0x032D) // 5.11 매칭
                {
                    //var roulette = BitConverter.ToUInt16(data, 2);
                    var code = BitConverter.ToUInt16(data, 20);

                    state = MatchStatus.Matched;

                    MsgLog.Info("l-queue-matched", GameData.GetInstanceName(code));
                    FireEvent(pid, GameEvents.MatchDone, new int[] { _rouletteCode, code });
                }                          // 32D
                else if (opcode == 0x03CF) // 5.11 듀티 상태
                {
                    var status = data[0];

                    if (status == 0x73)                     // 매칭 취소
                    {
                        state = MatchStatus.Idle;
                        MsgLog.Info("l-queue-stopped");
                        FireEvent(pid, GameEvents.MatchEnd, new[] { (int)MatchResult.Cancel });
                    }
                    else if (status == 0x81)                        // 매칭 넣었음
                    {
                        //state = MatchStatus.Idle;
                        //FireEvent(pid, GameEvents.MatchEnd, new[] { (int)MatchResult.Enter });
                    }
                }                          // 3CF
                else if (opcode == 0x032F) // 5.11 매칭하고 파티 인원
                {
                    var code      = BitConverter.ToUInt16(data, 8);
                    var tank      = data[12];
                    var maxtank   = data[13];
                    var healer    = data[14];
                    var maxhealer = data[15];
                    var dps       = data[16];
                    var maxdps    = data[17];

                    if (tank > maxtank || healer > maxhealer || dps > maxdps)
                    {
                        FireEvent(pid, GameEvents.MatchDone, new int[] { _rouletteCode, code });
                    }
                    else
                    {
                        //FireEvent(pid, GameEvents.MatchStatus, new int[] { (int)MatchType.ShortStatus, code, 0, tank, healer, dps });
                        FireEvent(pid, GameEvents.MatchStatus, new int[] { (int)MatchType.LongStatus, code, 0, tank, healer, dps, maxtank, maxhealer, maxdps });
                    }
                }                          // 32F
                else if (opcode == 0x0002) // 5.11 매칭 완료
                {
                    // 딱히 할건없음
                    //FireEvent(pid, GameEvents.MatchCancel, new int[] { -1 });
                }                 // 2
                #endregion        // 5.11 추가
            }
            catch (Exception ex)
            {
#if false
                MsgLog.Exception(ex, "l-analyze-error-handle");
#else
                // 에이리어 이동할때만 나타난다. 메시지를 출력하지 말자
                // DFASSIST에서는 안나는데 플러그인은 이동만 하면 난다
                var fmt = Localization.GetText("l-analyze-error-handle");
                var msg = MsgLog.Escape(ex.Message);
                System.Diagnostics.Debug.WriteLine($"{fmt}: {msg}");

                // 오버레이는 지워버리는게 좋겠다
                //FireEvent(pid, GameEvents.MatchEnd, new[] { (int)MatchResult.Cancel });
#endif
            }
        }