示例#1
0
            public IpPacket(byte[] buffer)
            {
                try
                {
                    var versionAndHeaderLength = buffer[0];
                    Version      = versionAndHeaderLength >> 4 == 4 ? ProtocolFamily.InterNetwork : ProtocolFamily.InterNetworkV6;
                    HeaderLength = (byte)((versionAndHeaderLength & 15) * 4); // 0b1111 = 15

                    Protocol = (ProtocolType)buffer[9];

                    SourceIpAddress      = new IPAddress(BitConverter.ToUInt32(buffer, 12));
                    DestinationIpAddress = new IPAddress(BitConverter.ToUInt32(buffer, 16));

                    Data = buffer.Skip(HeaderLength).ToArray();

                    IsValid = true;
                }
                catch (Exception ex)
                {
                    Version      = ProtocolFamily.Unknown;
                    HeaderLength = 0;

                    Protocol = ProtocolType.Unknown;

                    SourceIpAddress      = null;
                    DestinationIpAddress = null;

                    Data = null;

                    IsValid = false;
                    MsgLog.Exception(ex, "l-packet-error-ip");
                }
            }
示例#2
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);
                }
            }
        }
示例#3
0
            public TcpPacket(byte[] buffer)
            {
                try
                {
                    SourcePort      = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(buffer, 0));
                    DestinationPort = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(buffer, 2));

                    var offsetAndFlags = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(buffer, 12));
                    DataOffset = (byte)((offsetAndFlags >> 12) * 4);
                    Flags      = (TcpFlags)(offsetAndFlags & 511); // 0b111111111 = 511

                    Payload = buffer.Skip(DataOffset).ToArray();

                    IsValid = true;
                }
                catch (Exception ex)
                {
                    SourcePort      = 0;
                    DestinationPort = 0;
                    DataOffset      = 0;
                    Flags           = TcpFlags.NONE;

                    Payload = null;

                    IsValid = false;

                    MsgLog.Exception(ex, "l-packet-error-tcp");
                }
            }
示例#4
0
        private void CboClientVersion_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cboClientVersion.SelectedIndex < 0)
            {
                return;
            }

            try
            {
                var v = GameData.ClientVersions[cboClientVersion.SelectedIndex];
                //MsgLog.S("i-client-version", string.Format("이전={0}, 변경={1}", Settings.ClientVersion, v.Value));

                if (Settings.ClientVersion != v.Value)
                {
                    Settings.ClientVersion = v.Value;
                    txtClientVersion.Text  = v.Value.ToString();

                    PacketWorker.Codes = GameData.PacketCodes[v.Value];

#if true
                    MsgLog.S("i-client-version", $"{v.Name}, {PacketWorker.Codes.FATE:X4}/{PacketWorker.Codes.Duty:X4}/{PacketWorker.Codes.Match:X4}");
#else
                    MsgLog.S("i-client-version", v.Name);
#endif
                    SaveSettings();
                }
            }
            catch
            {
            }
        }
示例#5
0
        private static void Fill(string json)
        {
            try
            {
                var data    = JsonConvert.DeserializeObject <Group>(json);
                var version = data.Version;

                if (version > decimal.Truncate(Version))
                {
                    var fates = new Dictionary <int, Fate>();

                    foreach (var area in data.Areas)
                    {
                        foreach (var fate in area.Value.Fates)
                        {
                            fate.Value.Area = area.Value;
                            fates.Add(fate.Key, fate.Value);
                        }
                    }

                    Areas     = data.Areas;
                    Instances = data.Instances;
                    Roulettes = data.Roulettes;
                    Fates     = fates;
                    Version   = version;
                }
            }
            catch (Exception ex)
            {
                MsgLog.Ex(ex, "l-data-error");
            }
        }
示例#6
0
        //
        public void DeInitPlugin()
        {
            _isPluginEnabled = false;

            _frmOverlay.Hide();
            _frmOverlay = null;

            SaveSettings();

            _actTabPage = null;

            if (_actLabelStatus != null)
            {
                _actLabelStatus.Text = Localization.GetText("l-plugin-stopped");
                _actLabelStatus      = null;
            }

            foreach (var e in _pronets)
            {
                e.Value.Network.StopCapture();
            }

            _timer.Enabled = false;

            MsgLog.SetTextBox(null);
        }
示例#7
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;

                string json;
                switch (lang.Index)
                {
                case 1: json = Properties.Resources.gamedata_ja; break;

                case 2: json = Properties.Resources.gamedata_de; break;

                case 3: json = Properties.Resources.gamedata_fr; break;

                case 4: json = Properties.Resources.gamedata_ko; break;

                default: json = Properties.Resources.gamedata_en; break;
                }
                GameData.Initialize(json);

                MsgLog.I("i-data-version",
                         GameData.Version,
                         GameData.Areas.Count, GameData.Instances.Count,
                         GameData.Roulettes.Count, GameData.Fates.Count);
            }
        }
示例#8
0
        private void RegisterToFirewall()
        {
            try
            {
                var netFwMgr    = GetInstance <INetFwMgr>("HNetCfg.FwMgr");
                var netAuthApps = netFwMgr.LocalPolicy.CurrentProfile.AuthorizedApplications;

                var exists = false;
                foreach (var netAuthAppObject in netAuthApps)
                {
                    if (netAuthAppObject is INetFwAuthorizedApplication netAuthApp && netAuthApp.ProcessImageFileName == _exePath && netAuthApp.Enabled)
                    {
                        exists = true;
                    }
                }

                if (!exists)
                {
                    var networkApp = GetInstance <INetFwAuthorizedApplication>("HNetCfg.FwAuthorizedApplication");

                    networkApp.Enabled = true;
                    networkApp.Name    = "ACT_DFASSIST";
                    networkApp.ProcessImageFileName = _exePath;
                    networkApp.Scope = NET_FW_SCOPE_.NET_FW_SCOPE_ALL;

                    netAuthApps.Add(networkApp);

                    MsgLog.Success("l-firewall-registered");
                }
            }
            catch (Exception ex)
            {
                MsgLog.Exception(ex, "l-firewall-error");
            }
        }
示例#9
0
        private void SaveSettings()
        {
            if (!_isInitSetting)
            {
                return;
            }

            txtOverayLocation.Text = $"{Settings.OverlayLocation.X},{Settings.OverlayLocation.Y}";

            try
            {
                using (var fs = new FileStream(Settings.Path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
                    using (var xw = new XmlTextWriter(fs, Encoding.UTF8)
                    {
                        Formatting = Formatting.Indented, Indentation = 1, IndentChar = '\t'
                    })
                    {
                        xw.WriteStartDocument(true);
                        xw.WriteStartElement("Config");             // <Config>
                        xw.WriteStartElement("SettingsSerializer"); // <Config><SettingsSerializer>
                        _srset.ExportToXml(xw);                     // Fill the SettingsSerializer XML
                        xw.WriteEndElement();                       // </SettingsSerializer>
                        xw.WriteEndElement();                       // </Config>
                        xw.WriteEndDocument();                      // Tie up loose ends (shouldn't be any)
                        xw.Flush();                                 // Flush the file buffer to disk
                        xw.Close();
                    }
            }
            catch (Exception ex)
            {
                MsgLog.Ex(ex, "Exception: save setting failed");
            }
        }
示例#10
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.I("i-selected-color", cboLogBackground.Text);
     }
 }
示例#11
0
        private IPEndPoint GetLobbyEndPoint(Process process)
        {
            IPEndPoint ipep      = null;
            string     lobbyHost = null;
            var        lobbyPort = 0;

            try
            {
                using (var managementObjectSearcher = new ManagementObjectSearcher("SELECT CommandLine FROM Win32_Process WHERE ProcessId = " + process.Id))
                {
                    foreach (var managementBaseObject in managementObjectSearcher.Get())
                    {
                        var commandline = managementBaseObject["CommandLine"].ToString();
                        var args        = commandline.Split(' ');

                        foreach (var arg in args)
                        {
                            var splitted = arg.Split('=');
                            if (splitted.Length != 2)
                            {
                                continue;
                            }

                            switch (splitted[0])
                            {
                            case "DEV.LobbyHost01":
                                lobbyHost = splitted[1];
                                break;

                            case "DEV.LobbyPort01":
                                lobbyPort = int.Parse(splitted[1]);
                                break;
                            }
                        }
                    }
                }

                if (lobbyHost != null && lobbyPort > 0)
                {
                    var address = Dns.GetHostAddresses(lobbyHost)[0];
                    ipep = new IPEndPoint(address, lobbyPort);
                }
            }
            catch (Exception ex)
            {
                MsgLog.Exception(ex, "l-network-error-finding-lobby");
            }

            return(ipep);
        }
示例#12
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);
            }
        }
示例#13
0
        private void FilterAndProcessPacket(byte[] buffer)
        {
            try
            {
                var ipPacket = new IpPacket(buffer);
                if (!ipPacket.IsValid || ipPacket.Protocol != ProtocolType.Tcp)
                {
                    return;
                }

                var tcpPacket = new TcpPacket(ipPacket.Data);
                if (!tcpPacket.IsValid)
                {
                    return;
                }

                if (!tcpPacket.Flags.HasFlag(TcpFlags.ACK | TcpFlags.PSH))
                {
                    return;
                }

                var sourceEndPoint      = new IPEndPoint(ipPacket.SourceIpAddress, tcpPacket.SourcePort);
                var destinationEndPoint = new IPEndPoint(ipPacket.DestinationIpAddress, tcpPacket.DestinationPort);
                var connection          = new Connection {
                    LocalEndPoint = sourceEndPoint, RemoteEndPoint = destinationEndPoint
                };
                var reverseConnection = new Connection {
                    LocalEndPoint = destinationEndPoint, RemoteEndPoint = sourceEndPoint
                };

                if (!(_connections.Contains(connection) || _connections.Contains(reverseConnection)))
                {
                    return;
                }

                if (!_connections.Contains(reverseConnection))
                {
                    return;
                }

                lock (_lockAnalyse)
                    PacketFFXIV.Analyze(_pid, tcpPacket.Payload, ref _state);
            }
            catch (Exception ex)
            {
                MsgLog.Exception(ex, "l-network-error-filtering-packet");
            }
        }
示例#14
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");
                }
            });
        }
示例#15
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");
            }
        }
示例#16
0
        private void OnReceive(IAsyncResult ar)
        {
            try
            {
                var length = _socket.EndReceive(ar);
                var buffer = _recvBuffer.Take(length).ToArray();
                _socket.BeginReceive(_recvBuffer, 0, _recvBuffer.Length, 0, OnReceive, null);

                FilterAndProcessPacket(buffer);
            }
            catch (Exception ex) when(ex is ObjectDisposedException || ex is NullReferenceException)
            {
                IsRunning = false;
                _socket   = null;
                MsgLog.Success("l-network-stopped");
            }
            catch (Exception ex)
            {
                MsgLog.Exception(ex, "l-network-error-receiving-packet");
            }
        }
示例#17
0
        //
        public void DeInitPlugin()
        {
            _isPluginEnabled = false;

            _frmOverlay.Hide();
            _frmOverlay = null;

            SaveSettings();

            _isInitSetting = false;

            _actTabPage = null;

            if (_actLabelStatus != null)
            {
                _actLabelStatus.Text = Localization.GetText("l-plugin-stopped");
                _actLabelStatus      = null;
            }

            PacketWorker.EndMachina();

            MsgLog.SetTextBox(null);
        }
示例#18
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
            }
        }
示例#19
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;
        }
示例#20
0
        //
        private void UpdateProcesses()
        {
            var ps = new List <Process>();

            ps.AddRange(Process.GetProcessesByName("ffxiv"));
            ps.AddRange(Process.GetProcessesByName("ffxiv_dx11"));

            foreach (var p in ps)
            {
                try
                {
                    if (_pronets.ContainsKey(p.Id))
                    {
                        continue;
                    }

                    var pn = new ProNet(p, new Network());
                    PacketFFXIV.OnEventReceived += PacketFFXIV_OnEventReceived;

                    _pronets.TryAdd(p.Id, pn);
                    MsgLog.Success("l-process-set-success", p.Id);
                }
                catch (Exception e)
                {
                    MsgLog.Exception(e, "l-process-set-failed");
                }
            }

            var dels = new List <int>();

            foreach (var e in _pronets)
            {
                if (e.Value.Process.HasExited)
                {
                    e.Value.Network.StopCapture();
                    dels.Add(e.Key);
                }
                else
                {
                    if (e.Value.Network.IsRunning)
                    {
                        e.Value.Network.UpdateGameConnections(e.Value.Process);
                    }
                    else
                    {
                        e.Value.Network.StartCapture(e.Value.Process);
                    }
                }
            }

            foreach (var u in dels)
            {
                try
                {
                    _pronets.TryRemove(u, out var _);
                    PacketFFXIV.OnEventReceived -= PacketFFXIV_OnEventReceived;
                }
                catch (Exception e)
                {
                    MsgLog.Exception(e, "l-process-remove-failed");
                }
            }
        }
示例#21
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 && false
            MsgLog.D("ui-dbg", System.Environment.CurrentDirectory);
            MsgLog.D("ui-dbg", 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";

            cboClientVersion.DataSource    = GameData.ClientVersions.Clone();
            cboClientVersion.DisplayMember = "Name";
            cboClientVersion.ValueMember   = "Value";
            cboClientVersion.SelectedIndex = 0;

            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();

            //
            string tagname = Settings.GetTagNameForUpdate();
            if (!Settings.TagName.Equals(tagname))
            {
                MsgLog.I("i-client-updated", tagname);

                if (!txtUpdateSkip.Text.Equals(tagname))
                {
                    Task.Run(() =>
                    {
                        var res = MessageBox.Show(
                            Localization.GetText("i-visit-updated"),
                            Localization.GetText("app-name"), MessageBoxButtons.YesNo, MessageBoxIcon.Information);
                        if (res == DialogResult.Yes)
                        {
                            Process.Start("https://github.com/purutu/ACT.DFAssist/releases/latest");
                        }
                        else
                        {
                            txtUpdateSkip.Text = tagname;
                            SaveSettings();
                        }
                    });
                }
            }

            //
            PacketWorker.OnEventReceived += PacketWorker_OnEventReceived;
            PacketWorker.BeginMachina();

            _isInActInit = false;
        }
示例#22
0
        // process packet
        private static void PacketFFXIV(string pid, byte[] message)
        {
            var opcode = BitConverter.ToUInt16(message, 18);

#if !DEBUG
            if (opcode != Codes.Instance &&
                opcode != Codes.FATE &&
                opcode != Codes.Duty &&
                opcode != Codes.Match)
            {
                return;
            }
#endif

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

#if false
            if (opcode == Codes.Instance)                       // 인스턴스
            {
                // [2020-01-13] 코드를 찾을 수 없다.
                var code = BitConverter.ToInt16(data, 4);
                var type = data[8];

                if (type == 0x0B)
                {
                    // 들어옴
                    MsgLog.Instance("l-instance-enter", GameData.GetInstanceName(code));
                    FireEvent(pid, GameEvents.InstanceEnter, new int[] { code });
                }
                else if (type == 0x0C)
                {
                    // 나감
                    MsgLog.Instance("l-instance-leave");
                    FireEvent(pid, GameEvents.InstanceLeave, new int[] { code });
                }
            }             // Codes.Instance
            else
#endif
            if (opcode == Codes.FATE)                       // FATE 관련
            {
                var type = data[0];

                if (type == 0x74)                 // FATE 시작! 에이리어 이동해도 진행중인 것도 이걸로 처리됨
                {
                    var code = BitConverter.ToUInt16(data, 4);

                    if (Settings.LoggingWholeFates || Settings.SelectedFates.Contains(code.ToString()))
                    {
                        MsgLog.Fate("l-fate-occured-info", GameData.GetFate(code).Name);
                        FireEvent(pid, GameEvents.FateOccur, new int[] { code });
                    }
                }
            }                              // Codes.FATE
            else if (opcode == Codes.Duty) // 듀티
            {
                var status   = data[0];
                var reason   = data[4];
                var roulette = data[Codes.RouletteCode];

                if (roulette != 0 && (data[15] == 0 || data[15] == 64))                 // 루렛, 한국/글로벌
                {
                    MsgLog.Duty("i-queue-roulette", GameData.GetRouletteName(roulette));
                    FireEvent(pid, GameEvents.MatchQueue, new[] { (int)MatchType.Roulette, roulette });
                }
                else                 // 골라놓은 듀티 큐 (Dungeon/Trial/Raid)
                {
                    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.Duty("i-queue-instance", string.Join(", ", instances.Select(x => GameData.GetInstanceName(x)).ToArray()));
                    FireEvent(pid, GameEvents.MatchQueue, args.ToArray());
                }
            }                               // Codes.Duty
            else if (opcode == Codes.Match) // 매칭
            {
                var roulette = BitConverter.ToUInt16(data, 2);
                var code     = BitConverter.ToUInt16(data, 20);

                MsgLog.Duty("i-matched", GameData.GetInstanceName(code));
                FireEvent(pid, GameEvents.MatchDone, new int[] { roulette, code });
            }             // Codes.Match
        }
示例#23
0
        public static void Analyze(int pid, byte[] payload, ref MatchStatus state)
        {
            try
            {
                while (true)
                {
                    if (payload.Length < 4)
                    {
                        break;
                    }

                    var type = BitConverter.ToUInt16(payload, 0);

                    if (type == 0x0000 || type == 0x5252)
                    {
                        if (payload.Length < 28)
                        {
                            break;
                        }

                        var length = BitConverter.ToInt32(payload, 24);

                        if (length <= 0 || payload.Length < length)
                        {
                            break;
                        }

                        using (var messages = new MemoryStream(payload.Length))
                        {
                            using (var stream = new MemoryStream(payload, 0, length))
                            {
                                stream.Seek(40, SeekOrigin.Begin);

                                if (payload[33] == 0x00)
                                {
                                    stream.CopyTo(messages);
                                }
                                else
                                {
                                    stream.Seek(2, SeekOrigin.Current);                                     // 닷넷 DeflateStream 버그 (앞 2바이트 넘겨야함)

                                    using (var z = new DeflateStream(stream, CompressionMode.Decompress))
                                        z.CopyTo(messages);
                                }
                            }
                            messages.Seek(0, SeekOrigin.Begin);

                            var messageCount = BitConverter.ToUInt16(payload, 30);
                            for (var i = 0; i < messageCount; i++)
                            {
                                try
                                {
                                    var buffer = new byte[4];
                                    var read   = messages.Read(buffer, 0, 4);
                                    if (read < 4)
                                    {
                                        MsgLog.Error("l-analyze-error-length", read, i, messageCount);
                                        break;
                                    }
                                    var messageLength = BitConverter.ToInt32(buffer, 0);

                                    var message = new byte[messageLength];
                                    messages.Seek(-4, SeekOrigin.Current);
                                    messages.Read(message, 0, messageLength);

                                    HandleMessage(pid, message, ref state);
                                }
                                catch (Exception ex)
                                {
                                    MsgLog.Exception(ex, "l-analyze-error-general");
                                }
                            }
                        }

                        if (length < payload.Length)
                        {
                            // 더 처리해야 할 패킷이 남아 있음
                            payload = payload.Skip(length).ToArray();
                            continue;
                        }
                    }
                    else
                    {
                        // 앞쪽이 잘려서 오는 패킷 workaround
                        // 잘린 패킷 1개는 버리고 바로 다음 패킷부터 찾기...
                        // TODO: 버리는 패킷 없게 제대로 수정하기
                        for (var offset = 0; offset < payload.Length - 2; offset++)
                        {
                            var possibleType = BitConverter.ToUInt16(payload, offset);
                            if (possibleType == 0x5252)
                            {
                                payload = payload.Skip(offset).ToArray();
                                Analyze(pid, payload, ref state);
                                break;
                            }
                        }
                    }

                    break;
                }
            }
            catch (Exception ex)
            {
                MsgLog.Exception(ex, "l-analyze-error");
            }
        }