与minecraft bukkit服务器握手 - 发送服务器主机字段失败

时间:2013-03-16 10:44:08

标签: c++ minecraft packets

我正在尝试为Minecraft服务器制作客户端/机器人以自动保护聊天并禁止垃圾邮件发送者。 (第一次成就)
我在这里找到了一些文档,我已经实现了数据类型from hereso they look like this - 我还没有完成)。现在,我正在尝试发送初始0x02数据包,它应该是这样的:

我的数据包格式

size    value                comment

1       0x02                 Packet ID
2+?     string               Username (I send "jakub")
2+?     another string       Server host name - here, the program FAILS*
4       25565                Port number

*失败意味着bukkit服务器在控制台中输出以下内容,并且套接字已关闭:

  

11:09:45 [INFO] /127.0.0.1:51256 失去连接

我现在可以看到,如何测试我的数据类型是否正确,但因为我似乎发送用户名没有问题,我想我发送的是错误的信息,但是在格式正确

生成字符串

但无论如何,如果我做的一切都很好,我很好奇。我有mc_shortmc_string的课程。这就是mc_short创建自己2个字节的方式:

//mc_short::val is type of short 
void mc_short::asBytes(char* data) {  
    for (int i = 0; i < 2; i++)
       data[endianity?i:1-i] = (val >> (i * 8));  //Some magic with byteshifting.
       //endianity is set to false, because java uses BigEndian everywhere** (UNFRIENDLY PERSONS!!)
}

**请参阅http://wiki.vg/Data_Types

  

Java中的所有类型(以及类似的Minecraft)都是big-endian,也就是说,最重要的字节是第一个。

然后字符串本身使用mc_shortstd::string来填充char*中的字节。

void mc_string::asBytes(char* data) {
    mc_short size((short)val.length());  //val is std::string
    size.endianity = endianity;          //mc_string::endianity is boolean, and is ony used to determine endianity of the first 2 bytes
    size.asBytes(data);  //Filling 2 bytes in data - length info
    for(short i=0; i<size.value(); i++) {
        data[i+2] = val[i];  //Copying std::string to data
    }
}

问题摘要

  1. 我应该发送什么作为“服务器主机名”,第二个字段0x02?
  2. 我是否正确发送了字符串?是否需要进行任何其他转换?
  3. 我知道,我的问题是关于不是很知名的话题,因此你可能不知道答案,也不知道话题本身。在这种情况下,请忽略这个问题。

1 个答案:

答案 0 :(得分:2)

字符串以big-endian unicode(UTF-16,但是大端)编码。如果你不使用Java,你不能直接从内存中映射你的角色(好吧,如果你只是在每个角色之间写一个零并且接受它是一种糟糕的方式,你可以作弊)。在C#编码的Minecraft字符串here中有一个例子。

对于该字符串的内容,它应该是要连接的主机名。如果Google运行Minecraft服务器,则该字符串可能为minecraft.google.com

使用此实际数据包的示例是here

所以,你的问题得到了实际回答,一些建议。 Minecraft协议很糟糕,写一个客户端需要做很多工作。您需要能够支持协议中的所有数据包(是的,所有数据包),并且您需要实现基本物理设备才能落到地面,这样您就不会因为飞行而被踢。从最好到最差的选择,有几种选择:

  • 使用Bukkit并为此编写插件
  • 编写代理而不是客户端
  • 写一个客户端,就像你现在想要的那样

所以,如果你先做第一个,你需要用Java编写一个插件。我对此并不了解。

我对后两种选择了解很多。我是Craft.Net的维护者,它是一堆库,包括通用网络库和客户端库。您可以在几个小时内将客户端或代理放在一起。示例客户端位于同一个repo中,并且有一个代理here。这些都使用C#。

如果你还想完全自己动手,祝你好运,那就是好吧。