F1 2019 UDP解码 [英] F1 2019 UDP decoding

查看:253
本文介绍了F1 2019 UDP解码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在为F1方向盘制作显示器。
F1 2019(由代码管理员)通过UDP发送数据。此数据存储在字节数组中。

I am currently working on my own display for an F1 steering wheel. F1 2019 (by codemasters) sends data through UDP. This data is stored in a byte array.

我在解码返回的数组时遇到一些问题。问题是我得到了很多信息,但是我不知道该怎么做。我将按照我的尝试进行操作。

I am having some issues decoding the array being returned. The problem is that I get a lot of information back, but I don't know what to do with it. I will run you through what I have tried.

我通过端口20777(游戏的标准端口)连接到游戏:

I am connecting to the game through port 20777 (standard port for the game):

using System.Net;
using System.Net.Sockets;

var Client = new UdpClient(20777); //Connectionport

在下一段代码中,我从游戏中获取了信息:

In this next piece of code, I get the information from the game:

var RemoteIP = new IPEndPoint(IPAddress.Any, 60240);

byte[] received = Client.EndReceive(res, ref RemoteIP);

如您所见,来自游戏的数据当前存储在字节数组中

As you can see, the data from the game currently gets stored in a byte array.

这是最困难的部分(对我来说)。

Here comes the hard part (for me).

F1 2019发送的数据打包在结构中(据我从他们的网站了解到的信息)。但是我不知道如何从字节数组中获取信息并将其放入正确的变量中(例如,当前速度是多少,或者汽车的档位是什么)。

The data F1 2019 sends is packed in structs (from what I understand from their site). But I have no idea how I get the information out of the byte array and into the correct variables (e.g., what the current speed is, or in what gear the car is).

有关数据包的信息位于网站上的代码管理员:

The information about the packets is on the website from codemasters:

https://forums.codemasters.com/topic/44592-f1-2019-udp-specification/

现在是实际问题:

当我输入以下代码行时:

When I type this line of code:

short game_version = BitConverter.ToInt16(received, 0);

我将其显示在文本框中,变量 game_version 现在是2019年。

And I display it in a textbox, the variable game_version is now 2019.

我不明白为什么,索引号为 0 ,字节将在2019年进行转换。

I don't understand why, with the indexnumber 0, the bytes are converted in 2019.

而且我不知道该使用哪个索引号来获取我想要的每个变量。

And I don't know which index numbers to use to get each of the variables I want.

我希望有人能对此事有所启发。在codemasters论坛上,每个人似乎都知道如何从字节数组中获取数据。

I hope someone can shine some light on this matter. On the codemasters forum everyone seems to know how to get the data from the byte array.

以亲切的问候。

推荐答案

好的,所以我发现(感谢Jeremy)是我需要从字节数组中获取结构。我遵循以下示例:
示例1
Example2

Okay so what I have found (Thanks to Jeremy) is that I need to get a structure out of the byte array. I followed these examples: Example1 Example2

因此,Codemasters(F1 2019的制造商)正在发送包含所有所需信息的字节数组。他们已将结构转换为字节数组。这些结构包含游戏发出的所有信息。因此,需要发生的事情是将字节数组转换回结构。请记住,来自Codemasters的结构布局必须保持不变,否则您将无法在正确的变量中获得正确的信息。

So Codemasters (Makers of F1 2019) are sending a byte array with all the information needed. They have converted structs in to the byte array. These structs contain all the information which the game sends out. So the thing that needs to happen is converting the byte array back to structs. Keep in mind that the structlayout from Codemasters need to stay the same, Else you won't get the right information in the right variable.

PacketHeader packetheader = ByteArrayToPacketHeader(received);

PacketHeader ByteArrayToPacketHeader(byte[] bytes)
{
   GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
   PacketHeader stuff;
   try
   {
     stuff = (PacketHeader)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(PacketHeader));
   }
   finally
   {
   handle.Free();
   }
   return stuff;
   }

当前,以上代码将传入的字节数组(接收到的)转换为struct PacketHeader结构。
结构看起来像这样:

Currently the code above converts the incoming byte array (received) into the struct PacketHeader. The struct looks like this:

public struct PacketHeader
    {
        public ushort m_packetFormat;         // 2019
        public byte m_gameMajorVersion;     // Game major version - "X.00"
        public byte m_gameMinorVersion;     // Game minor version - "1.XX"
        public byte m_packetVersion;        // Version of this packet type, all start from 1
        public byte m_packetId;             // Identifier for the packet type, see below
        public ulong m_sessionUID;           // Unique identifier for the session
        public float m_sessionTime;          // Session timestamp
        public uint m_frameIdentifier;      // Identifier for the frame the data was retrieved on
        public byte m_playerCarIndex;       // Index of player's car in the array
    };

每个包含信息的数据包(结构)都有一个PacketHeader。通过转换每个数据包的标题,您可以在变量中获得相应的信息:stuff。

Every Packet (struct) with information has a PacketHeader. By converting the Header of each Packet you get the corresponding information in the variable: stuff.

在这里您可以在调试时看到PacketHeader的信息

我将尝试解释代码做。我不确定我可以100%解释它,因为我自己不太了解。

I'll try to explain what the code does. I am not sure that I can explain it 100% because I don't understand it fully myself.

PacketHeader ByteArrayToPacketHeader(byte[] bytes)
{

}

首先,我做了一个新方法。此方法会将结构从字节数组中拉出。
然后将所需的变量添加到方法中:

First I made a new method. This method will pull the struct out of the byte array. Then I added the needed variables to the method:

GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
PacketHeader stuff;

我不太了解该句柄,但是如果它是我认为的样子,它会固定下来字节,以便可以正确转换。

I don't really understand the Handle but if it is what I think it is, it pins down the bytes so they can be converted correctly.

我还创建了一个变量:stuff。在该变量中,结构将被存储。
在下一部分中,我添加了转换代码:

I also made a variable: stuff. In this variable the struct will be "stored". In the next part I added the conversion code:

try
{
  stuff = (PacketHeader)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(PacketHeader));
}
finally
{
   handle.Free();
}
return stuff;

此代码已完成转换。
填充PacketHeader后,在代码中将遵循结构布局并填充变量。

The conversion is done is this code. When the PacketHeader is filled in, in the code, the struct layout will be followed and the variables will be filled.

最后一部分需要完成是调用此方法。
我是这样的:

The last part that needs to be done is calling this method. I did this like this:

PacketHeader packetheader = ByteArrayToPacketHeader(received);

在这里,您可以看到我调用了PacketHeader方法并创建了一个名为packetheader的变量。所有信息都将存储在此变量中。

Here you can see that I called the method PacketHeader and created a variable called packetheader. In this variable all the information will be stored.

重要!
填写要在接收的插槽中使用的字节数组。这样,该方法将使用该字节数组。

Important! Fill in the byte array you want to use in the received slot. This way the method will use that byte array.

如果我现在想从PacketHeader结构中调用变量,我只需编写:

If I now want to call a variable out of the PacketHeader struct I simply write this:

packetheader.m_packetFormat (example)

当前,我能够从PacketHeader中获取正确的信息,但仍然无法从其他结构中获取正确的信息。但是,我距离完成我的项目又迈进了一步!

Currently I am able to get the right information out of the PacketHeader but still not out of the other structs. But I am one step closer to completing my project!

如果解释不完全正确,我感到抱歉。 (我还在学习自己)。
如果您对此解释有任何提示或笔记,请与我联系。我想进一步了解这个主题。

I am sorry if the explanation is not entirely correct. (I am still learning myself). Please contact me if you have any tips or notes about this explanation. I would like to know more about this subject.

亲切的问候。

这篇关于F1 2019 UDP解码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆