1 /*
2  * This file was automatically generated by sel-utils and
3  * released under the MIT License.
4  * 
5  * License: https://github.com/sel-project/sel-utils/blob/master/LICENSE
6  * Repository: https://github.com/sel-project/sel-utils
7  * Generated from https://github.com/sel-project/sel-utils/blob/master/xml/protocol/pocket112.xml
8  */
9 module sul.protocol.pocket112.types;
10 
11 import std.bitmanip : write, peek;
12 static import std.conv;
13 import std.system : Endian;
14 import std.typecons : Tuple;
15 import std.uuid : UUID;
16 
17 import sul.utils.buffer;
18 import sul.utils.var;
19 
20 static if(__traits(compiles, { import sul.metadata.pocket112; })) import sul.metadata.pocket112;
21 
22 struct LoginBody {
23 
24 	public enum string[] FIELDS = ["chain", "clientData"];
25 
26 	public ubyte[] chain;
27 	public ubyte[] clientData;
28 
29 	public pure nothrow @safe void encode(Buffer o_buffer) {
30 		Buffer buffer = new Buffer();
31 		with(buffer) {
32 			writeLittleEndianUint(cast(uint)chain.length); writeBytes(chain);
33 			writeLittleEndianUint(cast(uint)clientData.length); writeBytes(clientData);
34 		}
35 		with(o_buffer){ writeBytes(varuint.encode(cast(uint)buffer._buffer.length)); }
36 		o_buffer.writeBytes(buffer._buffer);
37 	}
38 
39 	public pure nothrow @safe void decode(Buffer o_buffer) {
40 		Buffer buffer = new Buffer();
41 		with(o_buffer) {
42 			immutable _length=varuint.decode(_buffer, &_index);
43 			buffer._buffer = readBytes(_length);
44 		}
45 		with(buffer) {
46 			chain.length=readLittleEndianUint(); if(_buffer.length>=_index+chain.length){ chain=_buffer[_index.._index+chain.length].dup; _index+=chain.length; }
47 			clientData.length=readLittleEndianUint(); if(_buffer.length>=_index+clientData.length){ clientData=_buffer[_index.._index+clientData.length].dup; _index+=clientData.length; }
48 		}
49 	}
50 
51 	public string toString() {
52 		return "LoginBody(chain: " ~ std.conv.to!string(this.chain) ~ ", clientData: " ~ std.conv.to!string(this.clientData) ~ ")";
53 	}
54 
55 }
56 
57 struct PackWithSize {
58 
59 	public enum string[] FIELDS = ["id", "vers", "size"];
60 
61 	public string id;
62 	public string vers;
63 	public ulong size;
64 
65 	public pure nothrow @safe void encode(Buffer buffer) {
66 		with(buffer) {
67 			writeBytes(varuint.encode(cast(uint)id.length)); writeString(id);
68 			writeBytes(varuint.encode(cast(uint)vers.length)); writeString(vers);
69 			writeBytes(varulong.encode(size));
70 		}
71 	}
72 
73 	public pure nothrow @safe void decode(Buffer buffer) {
74 		with(buffer) {
75 			uint aq=varuint.decode(_buffer, &_index); id=readString(aq);
76 			uint dvc=varuint.decode(_buffer, &_index); vers=readString(dvc);
77 			size=varulong.decode(_buffer, &_index);
78 		}
79 	}
80 
81 	public string toString() {
82 		return "PackWithSize(id: " ~ std.conv.to!string(this.id) ~ ", vers: " ~ std.conv.to!string(this.vers) ~ ", size: " ~ std.conv.to!string(this.size) ~ ")";
83 	}
84 
85 }
86 
87 struct Pack {
88 
89 	public enum string[] FIELDS = ["id", "vers"];
90 
91 	public string id;
92 	public string vers;
93 
94 	public pure nothrow @safe void encode(Buffer buffer) {
95 		with(buffer) {
96 			writeBytes(varuint.encode(cast(uint)id.length)); writeString(id);
97 			writeBytes(varuint.encode(cast(uint)vers.length)); writeString(vers);
98 		}
99 	}
100 
101 	public pure nothrow @safe void decode(Buffer buffer) {
102 		with(buffer) {
103 			uint aq=varuint.decode(_buffer, &_index); id=readString(aq);
104 			uint dvc=varuint.decode(_buffer, &_index); vers=readString(dvc);
105 		}
106 	}
107 
108 	public string toString() {
109 		return "Pack(id: " ~ std.conv.to!string(this.id) ~ ", vers: " ~ std.conv.to!string(this.vers) ~ ")";
110 	}
111 
112 }
113 
114 /**
115  * Informations about a slot, that, if not empty, contains an item id and meta, the
116  * count (0-255) and, optionally, an nbt tag for enchantments, custom name, colours
117  * and more.
118  */
119 struct Slot {
120 
121 	public enum string[] FIELDS = ["id", "metaAndCount", "nbt", "canPlaceOn", "canDestroy"];
122 
123 	/**
124 	 * Item's id or 0 if the slot is empty.
125 	 */
126 	public int id;
127 
128 	/**
129 	 * Item's meta or uses (unsigned short) left-shifted 8 times and the count (unisgned
130 	 * byte).
131 	 * Examples:
132 	 * ---
133 	 * var encoded = item.meta << 8 | item.count
134 	 * var meta = encoded >> 8
135 	 * var count = count & 255
136 	 * ---
137 	 */
138 	public int metaAndCount;
139 
140 	/**
141 	 * Optional nbt data encoded as a nameless little-endian compound tag.
142 	 */
143 	public ubyte[] nbt;
144 	public string[] canPlaceOn;
145 	public string[] canDestroy;
146 
147 	public pure nothrow @safe void encode(Buffer buffer) {
148 		with(buffer) {
149 			writeBytes(varint.encode(id));
150 			if(id>0){ writeBytes(varint.encode(metaAndCount)); }
151 			if(id>0){ writeLittleEndianUshort(cast(ushort)nbt.length); writeBytes(nbt); }
152 			writeBytes(varuint.encode(cast(uint)canPlaceOn.length)); foreach(yfuxyvb;canPlaceOn){ writeBytes(varuint.encode(cast(uint)yfuxyvb.length)); writeString(yfuxyvb); }
153 			writeBytes(varuint.encode(cast(uint)canDestroy.length)); foreach(yfrvdje;canDestroy){ writeBytes(varuint.encode(cast(uint)yfrvdje.length)); writeString(yfrvdje); }
154 		}
155 	}
156 
157 	public pure nothrow @safe void decode(Buffer buffer) {
158 		with(buffer) {
159 			id=varint.decode(_buffer, &_index);
160 			if(id>0){ metaAndCount=varint.decode(_buffer, &_index); }
161 			if(id>0){ nbt.length=readLittleEndianUshort(); if(_buffer.length>=_index+nbt.length){ nbt=_buffer[_index.._index+nbt.length].dup; _index+=nbt.length; } }
162 			canPlaceOn.length=varuint.decode(_buffer, &_index); foreach(ref yfuxyvb;canPlaceOn){ uint ezely=varuint.decode(_buffer, &_index); yfuxyvb=readString(ezely); }
163 			canDestroy.length=varuint.decode(_buffer, &_index); foreach(ref yfrvdje;canDestroy){ uint ezdrz=varuint.decode(_buffer, &_index); yfrvdje=readString(ezdrz); }
164 		}
165 	}
166 
167 	public string toString() {
168 		return "Slot(id: " ~ std.conv.to!string(this.id) ~ ", metaAndCount: " ~ std.conv.to!string(this.metaAndCount) ~ ", nbt: " ~ std.conv.to!string(this.nbt) ~ ", canPlaceOn: " ~ std.conv.to!string(this.canPlaceOn) ~ ", canDestroy: " ~ std.conv.to!string(this.canDestroy) ~ ")";
169 	}
170 
171 }
172 
173 struct Attribute {
174 
175 	public enum string[] FIELDS = ["min", "max", "value", "def", "name"];
176 
177 	public float min;
178 	public float max;
179 	public float value;
180 	public float def;
181 	public string name;
182 
183 	public pure nothrow @safe void encode(Buffer buffer) {
184 		with(buffer) {
185 			writeLittleEndianFloat(min);
186 			writeLittleEndianFloat(max);
187 			writeLittleEndianFloat(value);
188 			writeLittleEndianFloat(def);
189 			writeBytes(varuint.encode(cast(uint)name.length)); writeString(name);
190 		}
191 	}
192 
193 	public pure nothrow @safe void decode(Buffer buffer) {
194 		with(buffer) {
195 			min=readLittleEndianFloat();
196 			max=readLittleEndianFloat();
197 			value=readLittleEndianFloat();
198 			def=readLittleEndianFloat();
199 			uint bfz=varuint.decode(_buffer, &_index); name=readString(bfz);
200 		}
201 	}
202 
203 	public string toString() {
204 		return "Attribute(min: " ~ std.conv.to!string(this.min) ~ ", max: " ~ std.conv.to!string(this.max) ~ ", value: " ~ std.conv.to!string(this.value) ~ ", def: " ~ std.conv.to!string(this.def) ~ ", name: " ~ std.conv.to!string(this.name) ~ ")";
205 	}
206 
207 }
208 
209 /**
210  * Position of a block, where x and z are signed and y is always positive (as blocks
211  * cannot be placed under 0).
212  */
213 struct BlockPosition {
214 
215 	public enum string[] FIELDS = ["x", "y", "z"];
216 
217 	public int x;
218 	public uint y;
219 	public int z;
220 
221 	public pure nothrow @safe void encode(Buffer buffer) {
222 		with(buffer) {
223 			writeBytes(varint.encode(x));
224 			writeBytes(varuint.encode(y));
225 			writeBytes(varint.encode(z));
226 		}
227 	}
228 
229 	public pure nothrow @safe void decode(Buffer buffer) {
230 		with(buffer) {
231 			x=varint.decode(_buffer, &_index);
232 			y=varuint.decode(_buffer, &_index);
233 			z=varint.decode(_buffer, &_index);
234 		}
235 	}
236 
237 	public string toString() {
238 		return "BlockPosition(x: " ~ std.conv.to!string(this.x) ~ ", y: " ~ std.conv.to!string(this.y) ~ ", z: " ~ std.conv.to!string(this.z) ~ ")";
239 	}
240 
241 }
242 
243 struct McpeUuid {
244 
245 	public enum string[] FIELDS = ["mostSignificantBits", "leastSignificantBits"];
246 
247 	public long mostSignificantBits;
248 	public long leastSignificantBits;
249 
250 	public pure nothrow @safe void encode(Buffer buffer) {
251 		with(buffer) {
252 			writeLittleEndianLong(mostSignificantBits);
253 			writeLittleEndianLong(leastSignificantBits);
254 		}
255 	}
256 
257 	public pure nothrow @safe void decode(Buffer buffer) {
258 		with(buffer) {
259 			mostSignificantBits=readLittleEndianLong();
260 			leastSignificantBits=readLittleEndianLong();
261 		}
262 	}
263 
264 	public string toString() {
265 		return "McpeUuid(mostSignificantBits: " ~ std.conv.to!string(this.mostSignificantBits) ~ ", leastSignificantBits: " ~ std.conv.to!string(this.leastSignificantBits) ~ ")";
266 	}
267 
268 }
269 
270 /**
271  * Player's skin.
272  */
273 struct Skin {
274 
275 	public enum string[] FIELDS = ["name", "data"];
276 
277 	/**
278 	 * Name of the skin. It's used to render the shape of the skin correctly.
279 	 */
280 	public string name;
281 
282 	/**
283 	 * Bytes of the skin in format RGBA. The length should be 8192 or 16382.
284 	 */
285 	public ubyte[] data;
286 
287 	public pure nothrow @safe void encode(Buffer buffer) {
288 		with(buffer) {
289 			writeBytes(varuint.encode(cast(uint)name.length)); writeString(name);
290 			writeBytes(varuint.encode(cast(uint)data.length)); writeBytes(data);
291 		}
292 	}
293 
294 	public pure nothrow @safe void decode(Buffer buffer) {
295 		with(buffer) {
296 			uint bfz=varuint.decode(_buffer, &_index); name=readString(bfz);
297 			data.length=varuint.decode(_buffer, &_index); if(_buffer.length>=_index+data.length){ data=_buffer[_index.._index+data.length].dup; _index+=data.length; }
298 		}
299 	}
300 
301 	public string toString() {
302 		return "Skin(name: " ~ std.conv.to!string(this.name) ~ ", data: " ~ std.conv.to!string(this.data) ~ ")";
303 	}
304 
305 }
306 
307 /**
308  * Informations about a player that will be added to the player's list in the pause
309  * menu.
310  */
311 struct PlayerList {
312 
313 	public enum string[] FIELDS = ["uuid", "entityId", "displayName", "skin"];
314 
315 	/**
316 	 * UUID of the player. If it's associated with an XBOX Live account the player's profile
317 	 * will also be available in pause menu.
318 	 */
319 	public sul.protocol.pocket112.types.McpeUuid uuid;
320 
321 	/**
322 	 * Player's id, used to associate the skin with the game's entity spawned with AddPlayer.
323 	 */
324 	public long entityId;
325 
326 	/**
327 	 * Player's display name, that can contain Minecraft's formatting codes. It shouldn't
328 	 * contain suffixes nor prefixes.
329 	 */
330 	public string displayName;
331 
332 	/**
333 	 * Player's skin usually given in the Login's packet body.
334 	 */
335 	public sul.protocol.pocket112.types.Skin skin;
336 
337 	public pure nothrow @safe void encode(Buffer buffer) {
338 		with(buffer) {
339 			uuid.encode(bufferInstance);
340 			writeBytes(varlong.encode(entityId));
341 			writeBytes(varuint.encode(cast(uint)displayName.length)); writeString(displayName);
342 			skin.encode(bufferInstance);
343 		}
344 	}
345 
346 	public pure nothrow @safe void decode(Buffer buffer) {
347 		with(buffer) {
348 			uuid.decode(bufferInstance);
349 			entityId=varlong.decode(_buffer, &_index);
350 			uint zlcxe5bu=varuint.decode(_buffer, &_index); displayName=readString(zlcxe5bu);
351 			skin.decode(bufferInstance);
352 		}
353 	}
354 
355 	public string toString() {
356 		return "PlayerList(uuid: " ~ std.conv.to!string(this.uuid) ~ ", entityId: " ~ std.conv.to!string(this.entityId) ~ ", displayName: " ~ std.conv.to!string(this.displayName) ~ ", skin: " ~ std.conv.to!string(this.skin) ~ ")";
357 	}
358 
359 }
360 
361 struct Link {
362 
363 	// action
364 	public enum ubyte ADD = 0;
365 	public enum ubyte RIDE = 1;
366 	public enum ubyte REMOVE = 2;
367 
368 	public enum string[] FIELDS = ["from", "to", "action"];
369 
370 	public long from;
371 	public long to;
372 	public ubyte action;
373 
374 	public pure nothrow @safe void encode(Buffer buffer) {
375 		with(buffer) {
376 			writeBytes(varlong.encode(from));
377 			writeBytes(varlong.encode(to));
378 			writeBigEndianUbyte(action);
379 		}
380 	}
381 
382 	public pure nothrow @safe void decode(Buffer buffer) {
383 		with(buffer) {
384 			from=varlong.decode(_buffer, &_index);
385 			to=varlong.decode(_buffer, &_index);
386 			action=readBigEndianUbyte();
387 		}
388 	}
389 
390 	public string toString() {
391 		return "Link(from: " ~ std.conv.to!string(this.from) ~ ", to: " ~ std.conv.to!string(this.to) ~ ", action: " ~ std.conv.to!string(this.action) ~ ")";
392 	}
393 
394 }
395 
396 struct Recipe {
397 
398 	// type
399 	public enum int SHAPELESS = 0;
400 	public enum int SHAPED = 1;
401 	public enum int FURNACE = 2;
402 	public enum int FURNACE_DATA = 3;
403 	public enum int MULTI = 4;
404 
405 	public enum string[] FIELDS = ["type", "data"];
406 
407 	public int type;
408 	public ubyte[] data;
409 
410 	public pure nothrow @safe void encode(Buffer buffer) {
411 		with(buffer) {
412 			writeBytes(varint.encode(type));
413 			writeBytes(data);
414 		}
415 	}
416 
417 	public pure nothrow @safe void decode(Buffer buffer) {
418 		with(buffer) {
419 			type=varint.decode(_buffer, &_index);
420 			data=_buffer[_index..$].dup; _index=_buffer.length;
421 		}
422 	}
423 
424 	public string toString() {
425 		return "Recipe(type: " ~ std.conv.to!string(this.type) ~ ", data: " ~ std.conv.to!string(this.data) ~ ")";
426 	}
427 
428 }
429 
430 /**
431  * Chunk's blocks, lights and other immutable data.
432  */
433 struct ChunkData {
434 
435 	public enum string[] FIELDS = ["sections", "heights", "biomes", "borders", "extraData", "blockEntities"];
436 
437 	/**
438 	 * 16x16x16 section of the chunk. The array's keys also indicate the section's height
439 	 * (the 3rd element of the array will be the 3rd section from bottom, starting at `y=24`).
440 	 * The amount of sections should be in a range from 0 (empty chunk) to 16.
441 	 */
442 	public sul.protocol.pocket112.types.Section[] sections;
443 
444 	/**
445 	 * Coordinates of the highest block in the column that receives sky light (order `xz`).
446 	 * It is used to increase the speed when calculating the block's light level.
447 	 */
448 	public ushort[256] heights;
449 
450 	/**
451 	 * Biomes in order `xz`.
452 	 */
453 	public ubyte[256] biomes;
454 
455 	/**
456 	 * Colums where there are world borders (in format `xz`). This feature hasn't been
457 	 * implemented in the game yet and crashes the client.
458 	 */
459 	public ubyte[] borders;
460 	public sul.protocol.pocket112.types.ExtraData[] extraData;
461 
462 	/**
463 	 * Additional data for the chunk's block entities (tiles), encoded in the same way
464 	 * as BlockEntityData.nbt is. The position is given by the `Int` tags `x`, `y`, `z`
465 	 * which are added to the block's compound tag together with the `String` tag `id`
466 	 * that contains the name of the tile in pascal case.
467 	 * Wrong encoding or missing tags may result in the block becoming invisible.
468 	 */
469 	public ubyte[] blockEntities;
470 
471 	public pure nothrow @safe void encode(Buffer o_buffer) {
472 		Buffer buffer = new Buffer();
473 		with(buffer) {
474 			writeBytes(varuint.encode(cast(uint)sections.length)); foreach(cvdlbm;sections){ cvdlbm.encode(bufferInstance); }
475 			foreach(avzhc;heights){ writeBigEndianUshort(avzhc); }
476 			writeBytes(biomes);
477 			writeBytes(varuint.encode(cast(uint)borders.length)); writeBytes(borders);
478 			writeBytes(varuint.encode(cast(uint)extraData.length)); foreach(zhcfyr;extraData){ zhcfyr.encode(bufferInstance); }
479 			writeBytes(blockEntities);
480 		}
481 		with(o_buffer){ writeBytes(varuint.encode(cast(uint)buffer._buffer.length)); }
482 		o_buffer.writeBytes(buffer._buffer);
483 	}
484 
485 	public pure nothrow @safe void decode(Buffer o_buffer) {
486 		Buffer buffer = new Buffer();
487 		with(o_buffer) {
488 			immutable _length=varuint.decode(_buffer, &_index);
489 			buffer._buffer = readBytes(_length);
490 		}
491 		with(buffer) {
492 			sections.length=varuint.decode(_buffer, &_index); foreach(ref cvdlbm;sections){ cvdlbm.decode(bufferInstance); }
493 			foreach(ref avzhc;heights){ avzhc=readBigEndianUshort(); }
494 			if(_buffer.length>=_index+biomes.length){ biomes=_buffer[_index.._index+biomes.length].dup; _index+=biomes.length; }
495 			borders.length=varuint.decode(_buffer, &_index); if(_buffer.length>=_index+borders.length){ borders=_buffer[_index.._index+borders.length].dup; _index+=borders.length; }
496 			extraData.length=varuint.decode(_buffer, &_index); foreach(ref zhcfyr;extraData){ zhcfyr.decode(bufferInstance); }
497 			blockEntities=_buffer[_index..$].dup; _index=_buffer.length;
498 		}
499 	}
500 
501 	public string toString() {
502 		return "ChunkData(sections: " ~ std.conv.to!string(this.sections) ~ ", heights: " ~ std.conv.to!string(this.heights) ~ ", biomes: " ~ std.conv.to!string(this.biomes) ~ ", borders: " ~ std.conv.to!string(this.borders) ~ ", extraData: " ~ std.conv.to!string(this.extraData) ~ ", blockEntities: " ~ std.conv.to!string(this.blockEntities) ~ ")";
503 	}
504 
505 }
506 
507 /**
508  * Section of a chunk with informations about blocks and lights. The array of bytes
509  * are always ordered `xzy`.
510  */
511 struct Section {
512 
513 	public enum string[] FIELDS = ["storageVersion", "blockIds", "blockMetas", "skyLight", "blockLight"];
514 
515 	public ubyte storageVersion = 0;
516 	public ubyte[4096] blockIds;
517 	public ubyte[2048] blockMetas;
518 	public ubyte[2048] skyLight;
519 	public ubyte[2048] blockLight;
520 
521 	public pure nothrow @safe void encode(Buffer buffer) {
522 		with(buffer) {
523 			writeBigEndianUbyte(storageVersion);
524 			writeBytes(blockIds);
525 			writeBytes(blockMetas);
526 			writeBytes(skyLight);
527 			writeBytes(blockLight);
528 		}
529 	}
530 
531 	public pure nothrow @safe void decode(Buffer buffer) {
532 		with(buffer) {
533 			storageVersion=readBigEndianUbyte();
534 			if(_buffer.length>=_index+blockIds.length){ blockIds=_buffer[_index.._index+blockIds.length].dup; _index+=blockIds.length; }
535 			if(_buffer.length>=_index+blockMetas.length){ blockMetas=_buffer[_index.._index+blockMetas.length].dup; _index+=blockMetas.length; }
536 			if(_buffer.length>=_index+skyLight.length){ skyLight=_buffer[_index.._index+skyLight.length].dup; _index+=skyLight.length; }
537 			if(_buffer.length>=_index+blockLight.length){ blockLight=_buffer[_index.._index+blockLight.length].dup; _index+=blockLight.length; }
538 		}
539 	}
540 
541 	public string toString() {
542 		return "Section(storageVersion: " ~ std.conv.to!string(this.storageVersion) ~ ", blockIds: " ~ std.conv.to!string(this.blockIds) ~ ", blockMetas: " ~ std.conv.to!string(this.blockMetas) ~ ", skyLight: " ~ std.conv.to!string(this.skyLight) ~ ", blockLight: " ~ std.conv.to!string(this.blockLight) ~ ")";
543 	}
544 
545 }
546 
547 struct ExtraData {
548 
549 	public enum string[] FIELDS = ["key", "value"];
550 
551 	public uint key;
552 	public ushort value;
553 
554 	public pure nothrow @safe void encode(Buffer buffer) {
555 		with(buffer) {
556 			writeBytes(varuint.encode(key));
557 			writeLittleEndianUshort(value);
558 		}
559 	}
560 
561 	public pure nothrow @safe void decode(Buffer buffer) {
562 		with(buffer) {
563 			key=varuint.decode(_buffer, &_index);
564 			value=readLittleEndianUshort();
565 		}
566 	}
567 
568 	public string toString() {
569 		return "ExtraData(key: " ~ std.conv.to!string(this.key) ~ ", value: " ~ std.conv.to!string(this.value) ~ ")";
570 	}
571 
572 }
573 
574 struct Decoration {
575 
576 	public enum string[] FIELDS = ["rotationAndIcon", "position", "label", "color"];
577 
578 	public int rotationAndIcon;
579 	public Tuple!(ubyte, "x", ubyte, "z") position;
580 	public string label;
581 
582 	/**
583 	 * ARGB colour.
584 	 */
585 	public uint color;
586 
587 	public pure nothrow @safe void encode(Buffer buffer) {
588 		with(buffer) {
589 			writeBytes(varint.encode(rotationAndIcon));
590 			writeBigEndianUbyte(position.x); writeBigEndianUbyte(position.z);
591 			writeBytes(varuint.encode(cast(uint)label.length)); writeString(label);
592 			writeLittleEndianUint(color);
593 		}
594 	}
595 
596 	public pure nothrow @safe void decode(Buffer buffer) {
597 		with(buffer) {
598 			rotationAndIcon=varint.decode(_buffer, &_index);
599 			position.x=readBigEndianUbyte(); position.z=readBigEndianUbyte();
600 			uint bfzw=varuint.decode(_buffer, &_index); label=readString(bfzw);
601 			color=readLittleEndianUint();
602 		}
603 	}
604 
605 	public string toString() {
606 		return "Decoration(rotationAndIcon: " ~ std.conv.to!string(this.rotationAndIcon) ~ ", position: " ~ std.conv.to!string(this.position) ~ ", label: " ~ std.conv.to!string(this.label) ~ ", color: " ~ std.conv.to!string(this.color) ~ ")";
607 	}
608 
609 }
610 
611 /**
612  * A game rule that prevents the client from doing client-side actions and animations.
613  */
614 struct Rule {
615 
616 	// name
617 	public enum string COMMAND_BLOCK_OUTPUT = "commandblockoutput";
618 	public enum string DO_DAYLIGHT_CYCLE = "dodaylightcycle";
619 	public enum string DO_ENTITY_DROPS = "doentitydrops";
620 	public enum string DO_FIRE_TICK = "dofiretick";
621 	public enum string DO_MOB_LOOT = "domobloot";
622 	public enum string DO_MOB_SPAWNING = "domobspawning";
623 	public enum string DO_TILE_DROPS = "dotiledrops";
624 	public enum string DO_WEATHER_CYCLE = "doweathercycle";
625 	public enum string DROWNING_DAMAGE = "drowningdamage";
626 	public enum string FALL_DAMAGE = "falldamage";
627 	public enum string FIRE_DAMAGE = "firedamage";
628 	public enum string KEEP_INVENTORY = "keepinventory";
629 	public enum string MOB_GRIEFING = "mobgriefing";
630 	public enum string PVP = "pvp";
631 	public enum string SEND_COMMAND_FEEDBACK = "sendcommandfeedback";
632 
633 	public enum string[] FIELDS = ["name", "value", "unknown2"];
634 
635 	/**
636 	 * Name of the rule. Same of the `gamerule` command's field in the game.
637 	 * The behaviours indicated in the following constants' descriptions is enabled or
638 	 * disabled.
639 	 */
640 	public string name;
641 
642 	/**
643 	 * Indicates whether the game rule is enabled.
644 	 */
645 	public bool value;
646 	public bool unknown2;
647 
648 	public pure nothrow @safe void encode(Buffer buffer) {
649 		with(buffer) {
650 			writeBytes(varuint.encode(cast(uint)name.length)); writeString(name);
651 			writeBigEndianBool(value);
652 			writeBigEndianBool(unknown2);
653 		}
654 	}
655 
656 	public pure nothrow @safe void decode(Buffer buffer) {
657 		with(buffer) {
658 			uint bfz=varuint.decode(_buffer, &_index); name=readString(bfz);
659 			value=readBigEndianBool();
660 			unknown2=readBigEndianBool();
661 		}
662 	}
663 
664 	public string toString() {
665 		return "Rule(name: " ~ std.conv.to!string(this.name) ~ ", value: " ~ std.conv.to!string(this.value) ~ ", unknown2: " ~ std.conv.to!string(this.unknown2) ~ ")";
666 	}
667 
668 }
669