TL;DR
I'm trying to talk to a Minecraft server with a client written in Scala, using Akka I/O over TCP, and would like to know if Minecraft uses an official, standardised protocol in it's network communication?
Minecraft's own documentation covers the contents of each packet, but fails to explain how the packets themselves are encoded, or even how they should be formed.
A little back story
As part of a personal project that I'm working on, written in Scala, I need to create an interface capable of mocking a Minecraft client, and performing actions against a Minecraft server. After weeks of research, I came across a lot of Java libraries that were almost what I was looking for, but none that quite suited my exact needs; long story short, I did the classic, "Oh well, why not write it myself and enjoy the learning curve"...
The issue
The Minecraft protocol documentation is thorough in some respects, but lacking in others, many assumptions are made throughout and a lot of key information is missing or even incorrect; a detailed network specification being the most notable in my case.
One attempt to talk to the Minecraft server had me playing around with Google's protocol buffers, using ScalaPB to compile them to usable case classes, but the data types were a pain to resolve between Google's own documentation and Minecraft's.
message Handshake {
<type?> protocolVersion = 1;
<type?> host = 2;
<type?> port = 3;
<type?> nextState = 4;
}
The host is a string, so that's an easy win, but both the protocolVersion and nextState are variable integers, which are not encoded as expected when I compared them with valid packets generated by another client with identical contents (I've been using a third-party library to compare the hexadecimal output of encoded packets).
My hacky solution
In a ditch attempt to achieve my goals, I've simply written methods like the one below (this is also a first iteration, so be kind!) to generate the desired encoding for each of the types declared in Minecraft's documentation that are not supported natively in Scala, and although this works, it just smells like I'm missing something potentially obvious that others might know about.
def toVarint(x: Int): Array[Byte] = {
var number = x
var output = ArrayBuffer[Int]()
while (number >= Math.pow(2, 31)) {
output += number & 0xFF | 0x80
number /= 128
}
while ((number & ~0x7F) > 0) {
output += number 0xFF | 0x80
number >>>= 7
}
output += number | 0
output.map(_.toByte).toArray
}
This is old, but I'll answer anyway! The wiki you referenced has (at least now) a section on the packet format (both before & after compression), as well as explanations including example code for how to handle their varint & varlong types!
To summarise, each packet is length prefixed with a varint (in both compression modes), so you just need to read a varint from the stream, allocate that much space & read that many bytes from the stream to the buffer.
Each byte of Minecraft varints have a "another byte to follow?" flag bit, followed by 7 bits of actual data. Where those 7 bits are just the bits from a standard int (so on receive, you essentially just omit those flag bits & write the rest to a standard int type)
Related
I am currently refactoring a large chunk of old code and have finally dove into the HLSL section where my knowledge is minimal due to being out of practice. I've come across some documentation online that specifies which registers are to be used for which purposes:
t – for shader resource views (SRV)
s – for samplers
u – for unordered access views (UAV)
b – for constant buffer views (CBV)
This part is pretty self explanatory. If I want to create a constant buffer, I can just declare as:
cbuffer LightBuffer: register(b0) { };
cbuffer CameraBuffer: register(b1) { };
cbuffer MaterialBuffer: register(b2) { };
cbuffer ViewBuffer: register(b3) { };
However, originating from the world of MIPS Assembly I can't help but wonder if there are finite and restricted ranges on these. For example, temporary registers are restricted to a range of t0 - t7 in MIPS Assembly. In the case of HLSL I haven't been able to find any documentation surrounding this topic as everything seems to point to assembly languages and microprocessors (such as the 8051 if you'd like a random topic to read up on).
Is there a set range for the four register types in HLSL or do I just continue as much as needed in a sequential fashion and let the underlying assembly handle the messy details?
Note
I have answered this question partially, as I am unable to find a range for u currently; however, if someone has a better, more detailed answer than what I've given through testing, then feel free to post it and I will mark that as the correct answer. I will leave this question open until December 1st, 2018 to give others a chance to give a better answer for future readers.
Resource slot count (for d3d11, indeed d3d12 case expands that) are specified in Resource Limit msdn page.
The ones which are of interest for you here are :
D3D11_COMMONSHADER_INPUT_RESOURCE_REGISTER_COUNT (which is t) = 128
D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT (which is s) = 16
D3D11_COMMONSHADER_CONSTANT_BUFFER_HW_SLOT_COUNT (which is b) = 15 but one is reserved to eventually store some constant data from shaders (if you have a static const large array for example)
The u case is different, as it depends on Feature Level (and tbh is a vendor/os version mess) :
D3D11_FEATURE_LEVEL_11_1 or greater, this is 64 slots
D3D11_FEATURE_LEVEL_11 : It will always be 8 (but some cards/driver eventually support 64, you need at least windows 8 for it (It might also be available in windows 7 with some platform update too). I do not recall a way to test if 64 is supported (many nvidia in their 700 range do for example).
D3D11_FEATURE_LEVEL_10_1 : either 0 or 1, there's a way to check is compute is supported
You need to perform a feature check:
D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS checkData;
d3dDevice->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &checkData);
BOOL computeSupport = checkData.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x
Please note that for some OS/Driver version I had this flag returning TRUE while not supported (Intel was doing that on win7/8), so in that case the only valid solution was to try to either create a small Raw / Byte Address buffer or a Structured Buffer and check the HRESULT
As a side note feature feature level 10 or below are for for quite old configurations nowadays, so except for rare scenarios you can probably safely ignore it (I just leave it for information purpose).
Since it's usually a long wait time for these types of questions I tested the b register by attempting to create a cbuffer in register b51. This failed as I expected and luckily SharpDX spit out an exception that stated it has a maximum of 14. So for the sake of future readers I am testing all four register types and posting back the ranges I find successful.
b has a range of b0 - b13.
s has a range of s0 - s15.
t has a range of t0 - t127.
u has a range of .
At the current moment, I am unable to find a range for the u register as I have no examples of it in my code, and haven't actually ever used it. If someone comes along that does have an example usage then feel free to test it and update this post for future readers.
I did find a contradiction to my findings above in the documentation linked in my question; they have an example using a t register above the noted range in this answer:
Texture2D a[10000] : register(t0);
Texture2D b[10000] : register(t10000);
ConstantBuffer<myConstants> c[10000] : register(b0);
Note
I would like to point out that I am using the SharpDX version of the HLSL compiler and so I am unsure if these ranges vary from compiler to compiler; I heavily doubt that they do, but you can never be too sure until you try to exceed them. GLSL may be the same due to being similar to HLSL, but it could also be very different.
I see that there are many ways to serialize/deserialize Haskell objects:
Data.Serialize -> encode, decode functions
Data.Binary http://code.haskell.org/binary/
MsgPack, JSON, BSON, etc
In my application, I want to setup a simple TCP client-server, where client may send serialized Haskell record objects. How does one decide between these serialization alternatives?
Additionally, when objects serialized into strings are sent over the network using Network.Socket, strings are returned. Is there a slightly higher level library, that works at the level of whole TCP messages? In other words, is there a way to avoid writing parsing code on the receive end that:
collects results of a sequence of recv() calls,
detect that a whole object has been received, and
then parse it into a haskell type?
In my application, the objects are not expected to be too large (maybe about ~1MB max).
As for the second part of your question, two things are required:
An incremental parser that doesn't need to have the whole document in memory to start parsing, and which can be fed with the partial chunks of data arriving from the wire. Also, when the parsing succeeds it must return any "leftover data" along with the parsed value.
A source of data with "pushback capabilities", that allows you to "unread" any leftovers so that they are available to the next parsing attempt.
The most popular library providing (1) is attoparsec. As for (2), all the three main streaming libraries (conduit, io-streams, and pipes) offer some kind of pushback functionality (the latter using the auxiliary pipes-parse package). All three libraries can integrate with attoparsec parsers as well (see here, here and here).
(Another option, of course, is to prepend each message with its lenght are read only the exact number of bytes.)
To answer the first part of your question (about data serialization), I would say that everything you listed sounds fine. Since you are dealing with pretty big (1MB) serializations, I think that the most important thing is laziness. There is another serialization library, called cereal that has strict serializations, and you wouldn't want that because you'd need to build it up in memory before sending in out. I'll give a shout out to aeson (http://hackage.haskell.org/package/aeson-0.8.0.2/docs/Data-Aeson.html) which you can use GHC Generics with to get something simple like this:
data Shape = Rect Int Int | Circle Double | Other String Int
deriving (Generic)
instance FromJSON Shape -- uses a default
instance ToJSON Shape -- uses a default
And then, bam!, you've got access to the encode and decode methods. I don't know about a higher level TCP library. Hopefully, someone else will have more insight on that.
I am making an iphone app that will transmit data via sound. It takes a binary string and plays a tone for each 1 and silence for each 0.
(String example)
NSString* asciiString = #"www.google.com";
NSString* binaryString = AsciiToBinaryString(asciiString);
// binaryString == #"01110111 01110111 01110111 00101110 01100111 01101111 01101111 01100111 01101100 01100101 00101110 01100011 01101111 01101101"
Howver, this simple tone method is prone to errors and I think I need to use binary phase shift keying.
I would like to know how to apply binary phase shift keying to my binary string.
I'm not sure how to implement this. Any suggestions or code samples would be appreciated.
PS:
I did do a search on stack overflow and google and was not satisfied with what I found.
I looked at the GNU Radio project but don't understand python.
PSK is not gonna be easy if possible at all on iPhone. Frequency Shift Keying (FSK) should be possible. But I think what you need first is a higher level protocol that breaks up the data stream in bytes for example, and includes some checks. Think of the good old RS-232 serial protocol with start/stop bits and parity.
On the other hand, there are various apps that use the iPhone's audio port for data transfer. I did not look, but I can imagine that people must have written about this. And I would not be surprised if there're open source or commercial projects that give you this functionality out-of-the-box.
Good luck & enjoy, it sounds like a fun project!
I'm using an open-source networking framework that makes it easy for developers to communicate over a service found using Bonjour in Objective-C.
There are a few lines that have had me on edge for a while now, even though they never seem to have caused any problems on any machines I've tested, regardless of whether I'm running the 32-bit of 64-bit version of my application:
int packetLength = [rawPacketData length];
[outgoingBuffer appendBytes:&packetLength length:sizeof(int)];
[outgoingBuffer appendData:rawPacketData];
[self writeToStream];
Note that the first piece of information sent is the length of the data packet, which is pretty standard, and then the data itself is sent. What scares me is the length of the length. Will one machine ever assume an int is 4 bytes, while the other machine believes an int to be 8 bytes?
If the two sizes could be different on different machines, what would cause this? Is it dependent on my compiler, or the end-user's machine architecture? And finally, if it is a problem, how can I take an 8-byte int and scrunch it down to 4-bytes to ensure backwards compatibility? (Since I'll never need more than 4 bytes to represent the size of the data packet.)
You can't assume that sizeof(int) will always be four bytes. If the size matters, you should either hard-code a size of 4 (and write code to serialize values into four-byte arrays with the proper endianness), or use types like int32_t defined in <stdint.h>.
(However, as a practical matter, most compiler vendors have decided that int should stay four bytes, so you probably don't need to worry about everything breaking tomorrow. Then again, it wasn't so long ago that many compiler vendors let an int be two bytes, leading to many problems when ints became four bytes, so you really ought to do things the right way so guard against future changes.)
It could be different, but this depends on the compiler more than the machine. A different compiler might redeclare int to be 8 bytes.
Size of int depends on machine architecture; size of int will be the size of the data bus almost always, unless your C compiler does something special and changes it.
That means size of int is not 4 bytes when you compile your program in a 8-bit, 16-bit or 64-bit machine/architecture.
I would define a constant for the buffer size instead of using size of int.
Hope this answers your question.
Recently, while reading a Socket Programming HOWTO the following section jumped out at me:
But if you plan to reuse your socket for further transfers, you need to realize that there is no "EOT" (End of Transfer) on a socket. I repeat: if a socket send or recv returns after handling 0 bytes, the connection has been broken. If the connection has not been broken, you may wait on a recv forever, because the socket will not tell you that there's nothing more to read (for now). Now if you think about that a bit, you'll come to realize a fundamental truth of sockets: messages must either be fixed length (yuck), or be delimited (shrug), or indicate how long they are (much better), or end by shutting down the connection. The choice is entirely yours, (but some ways are righter than others).
This section highlights 4 possibilities for how a socket "protocol" may be written to pass messages. My question is, what is the preferred method to use for real applications?
Is it generally best to include message size with each message (presumably in a header), as the article more or less asserts? Are there any situations where another method would be preferable?
The common protocols either specify length in the header, or are delimited (like HTTP, for instance).
Keep in mind that this also depends on whether you use TCP or UDP sockets. Since TCP sockets are reliable you can be sure that you get everything you shoved into them. With UDP the story is different and more complex.
These are indeed our choices with TCP. HTTP, for example, uses a mix of second, third, and forth option (double new-line ends request/response headers, which might contain the Content-Length header or indicate chunked encoding, or it might say Connection: close and not give you the content length but expect you to rely on reading EOF.)
I prefer the third option, i.e. self-describing messages, though fixed-length is plain easy when suitable.
If you're designing your own protocol then look at other people's work first; there might already be something similar out there that you could either use 'as is' or repurpose and adjust. For example; ISO-8583 for financial txns, HTTP or POP3 all do things differently but in ways that are proven to work... In fact it's worth looking at these things anyway as you'll learn a lot about how real world protocols are put together.
If you need to write your own protocol then, IMHO, prefer length prefixed messages where possible. They're easy and efficient to parse for the receiver but possibly harder to generate if it is costly to determine the length of the data before you begin sending it.
The decision should depend on the data you want to send (what it is, how is it gathered). If the data is fixed length, then fixed length packets will probably be the best. If data can be easily (no escaping needed) split into delimited entities then delimiting may be good. If you know the data size when you start sending the data piece, then len-prefixing may be even better. If the data sent is always single characters, or even single bits (e.g. "on"/"off") then anything different than fixed size one character messages will be too much.
Also think how the protocol may evolve. EOL-delimited strings are good as long as they do not contain EOL characters themselves. Fixed length may be good until the data may be extended with some optional parts, etc.
I do not know if there is a preferred option. In our real-world situation (client-server application), we use the option of sending the total message length as one of the first pieces of data. It is simple and works for both our TCP and UDP implementations. It makes the logic reasonably "simple" when reading data in both situations. With TCP, the amount of code is fairly small (by comparison). The UDP version is a bit (understatement) more complex but still relies on the size that is passed in the initial packet to know when all data has been sent.