You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
4.0 KiB
129 lines
4.0 KiB
from __future__ import division |
|
|
|
import struct |
|
|
|
from minecraft.networking.types.basic import ( |
|
Type, Byte, Short, Integer, Long, Float, Double, |
|
ShortPrefixedByteArray, Boolean, VarInt, TrailingByteArray |
|
) |
|
from minecraft.networking.types.utility import Vector |
|
|
|
|
|
class IntegerPrefixedByteArray(Type): |
|
@staticmethod |
|
def read(file_object): |
|
length = Integer.read(file_object) |
|
return struct.unpack(str(length) + "s", file_object.read(length))[0] |
|
|
|
@staticmethod |
|
def send(value, socket): |
|
Integer.send(len(value), socket) |
|
socket.send(value) |
|
|
|
|
|
TAG_End = 0 |
|
TAG_Byte = 1 |
|
TAG_Short = 2 |
|
TAG_Int = 3 |
|
TAG_Long = 4 |
|
TAG_Float = 5 |
|
TAG_Double = 6 |
|
TAG_Byte_Array = 7 |
|
TAG_String = 8 |
|
TAG_List = 9 |
|
TAG_Compound = 10 |
|
TAG_Int_Array = 11 |
|
TAG_Long_Array = 12 |
|
|
|
class Nbt(Type): |
|
@staticmethod |
|
def read(file_object): |
|
type_id = Byte.read(file_object) |
|
if type_id != TAG_Compound: |
|
raise Exception("Invalid NBT header") |
|
name = ShortPrefixedByteArray.read(file_object).decode('utf-8') |
|
a = Nbt.decode_tag(file_object, TAG_Compound) |
|
a['_name'] = name |
|
return a |
|
|
|
@staticmethod |
|
def decode_tag(file_object, type_id): |
|
if type_id == TAG_Byte: |
|
return Byte.read(file_object) |
|
elif type_id == TAG_Short: |
|
return Short.read(file_object) |
|
elif type_id == TAG_Int: |
|
return Integer.read(file_object) |
|
elif type_id == TAG_Long: |
|
return Long.read(file_object) |
|
elif type_id == TAG_Float: |
|
return Float.read(file_object) |
|
elif type_id == TAG_Double: |
|
return Double.read(file_object) |
|
elif type_id == TAG_Byte_Array: |
|
return IntegerPrefixedByteArray.read(file_object).decode('utf-8') |
|
elif type_id == TAG_String: |
|
return ShortPrefixedByteArray.read(file_object) |
|
elif type_id == TAG_List: |
|
list_type_id = Byte.read(file_object) |
|
size = Integer.read(file_object) |
|
a = [] |
|
for i in range(size): |
|
a.append(Nbt.decode_tag(file_object, list_type_id)) |
|
return a |
|
elif type_id == TAG_Compound: |
|
c = { } |
|
child_type_id = Byte.read(file_object) |
|
while child_type_id != TAG_End: |
|
child_name = ShortPrefixedByteArray.read(file_object).decode('utf-8') |
|
c[child_name] = Nbt.decode_tag(file_object, child_type_id) |
|
child_type_id = Byte.read(file_object) |
|
return c |
|
elif type_id == TAG_Int_Array: |
|
size = Integer.read(file_object) |
|
a = [] |
|
for i in range(size): |
|
a.append(Integer.read(file_object)) |
|
return a |
|
elif type_id == TAG_Long_Array: |
|
size = Integer.read(file_object) |
|
a = [] |
|
for i in range(size): |
|
a.append(Long.read(file_object)) |
|
return a |
|
else: |
|
raise Exception("Invalid NBT tag type") |
|
|
|
@staticmethod |
|
def send(value, socket): |
|
# TODO |
|
pass |
|
|
|
|
|
class Slot(Type): |
|
def __init__(self, present, item_id, item_count, nbt): |
|
self.present = present |
|
self.item_id = item_id |
|
self.item_count = item_count |
|
self.nbt = nbt |
|
|
|
def __str__(self): |
|
return str(self.__dict__) |
|
def __repr__(self): |
|
return 'Slot(present={}, item_id={}, item_count={}, nbt={}'.format( |
|
self.present, self.item_id, self.item_count, self.nbt) |
|
|
|
@staticmethod |
|
def read(file_object): |
|
present = Boolean.read(file_object) |
|
item_id = VarInt.read(file_object) if present else None |
|
item_count = Byte.read(file_object) if present else None |
|
nbt = TrailingByteArray.read(file_object) if present else None |
|
return Slot(present, item_id, item_count, nbt) |
|
|
|
@staticmethod |
|
def send(value, socket): |
|
Boolean.send(value.present, socket) |
|
VarInt.send(value.item_id, socket) |
|
Byte.send(value.item_count, socket) |
|
TrailingByteArray.send(value.nbt, socket)
|
|
|