diff --git a/src/protocol/generate_protocol.py b/src/protocol/generate_protocol.py index 41a2860..5b8be36 100644 --- a/src/protocol/generate_protocol.py +++ b/src/protocol/generate_protocol.py @@ -64,6 +64,25 @@ def get_type_info(types, typename): return tp +def resolve_name(types, name, typename, decl=False): + tp = get_type_info(types, typename) + no_array = 'size' in tp and tp['size'] == 'count' + + + idx = name.find('(') + if idx > 0: + name = name[:idx] + elif idx == 0: + warn('ERROR: Invalid variable name "{}"'.format(name)) + exit(1) + + if decl: + count = extract_array_count(typename) + if count != None and not no_array: + name += '[' + str(count) + ']' + + return name + def resolve_type(types, typename): tp = get_type_info(types, typename) if 'type' in tp: @@ -117,6 +136,35 @@ def get_rw_func(types, typename, read): return method +def print_rw_logic(types, typename, name, read): + resolved_name = resolve_name(types, name, typename) + start = name.find('(') + local_indent = 0 + if start != -1: + end = name.rfind(')') + if end == -1 or end < start: + warn('ERROR: Invalid variable name syntax "{}"'.format(name)) + exit(1) + # conditional + if name[end - 1] == '?': + add_text('if ({})'.format(name[start+1:end-1])) + indent() + local_indent += 1 + if read: + add_text('{} = reader.{}();', + resolved_name, + get_rw_func(types, typename, True) + ) + else: + add_text('msg.{}({});', + get_rw_func(types, typename, False), + resolved_name + ) + + for i in range(local_indent): + unindent() + + def get_enum_type(dict, fallback = 'int32'): return dict['.type'] if '.type' in dict else fallback @@ -181,10 +229,7 @@ def print_messages(list, globalTypes): add_text('{{') indent() for name, typename in message['vars'].items(): - add_text('{} = reader.{}();', - name, - get_rw_func(types, typename, True) - ) + print_rw_logic(types, typename, name, True) unindent() add_text('}}') newline() @@ -195,10 +240,7 @@ def print_messages(list, globalTypes): add_text('NetworkMessage msg(MaxSize);') add_text('msg.WriteVarInt(PacketId);') for name, typename in message['vars'].items(): - add_text('msg.{}({});', - get_rw_func(types, typename, False), - name - ) + print_rw_logic(types, typename, name, False) add_text('msg.Finalize();') add_text('return msg;') unindent() @@ -206,10 +248,11 @@ def print_messages(list, globalTypes): for name, typename in message['vars'].items(): resolved_type = resolve_type(types, extract_array_type(typename)) + resolved_name = resolve_name(types, name, typename, decl=True) if not serverbound and resolved_type == 'std::string': - add_text('const {}& {};', resolved_type, name) + add_text('const {}& {};', resolved_type, resolved_name) else: - add_text('{} {};', resolved_type, name) + add_text('{} {};', resolved_type, resolved_name) unindent() add_text('}};') diff --git a/src/protocol/protocol.hjson b/src/protocol/protocol.hjson index 7d21b8b..b9d85b9 100644 --- a/src/protocol/protocol.hjson +++ b/src/protocol/protocol.hjson @@ -23,6 +23,7 @@ type: std::string method: String // requires count: e.g. string[256] + // generated C type will not be an array size: count } @@ -228,7 +229,7 @@ } } - /*ChunkData: + ChunkData: { id: 0x22 vars: { @@ -238,20 +239,20 @@ // bitmask for each 16x16x16 chunk section // LSB: section at y=0, bits for up to y=15 chunkSections: varint - heightmaps: nbt + //heightmaps: nbt // only if fullChunk == true - biomes: int32[1024] + biomes(fullChunk?): int32[1024] - dataSize: varint - data: byte[dataSize] + //dataSize: varint + //data: byte[dataSize] - numBlockEntities: varint - blockEntities: nbt[numBlockEntities] + //numBlockEntities: varint + //blockEntities: nbt[numBlockEntities] } - }*/ - + } + PlayerPositionAndLook: { id: 0x36