I'm trying to make client/bot for minecraft server to automatically guard chat and ban spammers. (first achievment)
I found some docs here and I've implemented data types from here (so they look like this - and I'm not finished yet). Now, I'm trying to send inital 0x02
packet, which should look like this:
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
*Fails means that the bukkit server outputs following in the console, and the socket is closed:
11:09:45 [INFO] /127.0.0.1:51256 lost connection
I can see now way, how to test if my data types are correct, but because I seem to send username with no problem, I think I'm sending wrong information, though in correct format.
But anyway, I'm curious if I did everything right. I have class for mc_short
and mc_string
. This is how mc_short
creates 2 bytes of itself:
//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!!)
}
**Refer to http://wiki.vg/Data_Types:
All types in Java (and as such Minecraft) are big-endian, that is, the most significant byte comes first.
Then the string itself uses the mc_short
and std::string
to fill bytes in 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
}
}
I'm aware, that my question is about not very known topic and thus you may not know nor the answer, nor the topic itself. Just ignore the question under such circumstances.
The strings are encoded in big-endian unicode (UTF-16, but big endian). You can't map your characters directly from memory if you aren't using Java (well, you can cheat if you just write a zero between each character and accept that it's a shitty way to do it). There's an example in C# of encoding Minecraft strings here.
As for the contents of that string, it should be the hostname to connect to. If Google ran a Minecraft server, that string might be minecraft.google.com
.
An example of working with this actual packet is here.
So, with your question actually answered, some advice. The Minecraft protocol is terrible and writing a client will take a lot of work. You need to be able to support all packets in the protocol (yes, all of them), and you need to implement basic physics to fall to the ground so you don't get kicked for flying. There are several options, in order from best to worst choice:
So, if you do the first, you'll need to write a plugin in Java. I don't know much about this.
I do know a lot about the latter two options. I'm the maintainer of Craft.Net, which is a bunch of libraries, including a generic networking library, and a client library. You could throw together a client or proxy in a few hours. An example client is in the same repo, and there's a proxy here. These all use C#.
If you still want to totally roll your own, good luck and godspeed.