def send_join_game(self): codec = TagRoot({ '': TagCompound({ 'minecraft:dimension_type': TagCompound({ 'type': TagString("minecraft:dimension_type"), 'value': TagList([ TagCompound(self.dimension) ]), }), 'minecraft:worldgen/biome': self.biomes.root_tag.body }) }) self.protocol.send_packet("join_game", self.protocol.buff_type.pack("i?BB", 0, False, 3, 3), self.protocol.buff_type.pack_varint(2), self.protocol.buff_type.pack_string("rtgame:linking"), self.protocol.buff_type.pack_string("rtgame:reset"), self.protocol.buff_type.pack_nbt(codec), self.protocol.buff_type.pack_nbt(self.current_dimension), self.protocol.buff_type.pack_string("rtgame:linking"), self.protocol.buff_type.pack("q", 0), self.protocol.buff_type.pack_varint(0), self.protocol.buff_type.pack_varint(32), self.protocol.buff_type.pack("????", False, True, False, False))
def send_join_game(self): codec = TagRoot({ '': TagCompound({ 'dimension': TagList([ TagCompound({ 'name': TagString("minecraft:overworld"), 'natural': TagByte(1), 'ambient_light': TagFloat(0.0), 'has_ceiling': TagByte(0), 'has_skylight': TagByte(1), 'shrunk': TagByte(0), 'ultrawarm': TagByte(0), 'has_raids': TagByte(0), 'respawn_anchor_works': TagByte(0), 'bed_works': TagByte(0), 'piglin_safe': TagByte(0), 'logical_height': TagInt(255), 'infiniburn': TagString("minecraft:infiniburn_end"), }) ]) }) }) self.protocol.send_packet("join_game", self.protocol.buff_type.pack("iBB", 0, 3, 3), self.protocol.buff_type.pack_varint(1), self.protocol.buff_type.pack_string("rtgame:linking"), self.protocol.buff_type.pack_nbt(codec), self.protocol.buff_type.pack_string("minecraft:overworld"), self.protocol.buff_type.pack_string("rtgame:linking"), self.protocol.buff_type.pack("qB", 0, 0), self.protocol.buff_type.pack_varint(32), self.protocol.buff_type.pack("????", False, True, False, False)) self.protocol.send_packet("time_update", self.protocol.buff_type.pack("qq", 1, -18000))
def send_reset_world(self): data = [ self.protocol.buff_type.pack_varint(0), b'', self.protocol.buff_type.pack_nbt( TagRoot({ '': TagCompound({ "MOTION_BLOCKING": TagLongArray(PackedArray.empty_height()) }) })), self.protocol.buff_type.pack_varint(1024), ] for i in range(1024): data.append(self.protocol.buff_type.pack_varint(127)) data.append(self.protocol.buff_type.pack_varint(0)) data.append(b'') data.append(self.protocol.buff_type.pack_varint(0)) data.append(b'') for x in range(-8, 8): for y in range(-8, 8): self.protocol.send_packet( "chunk_data", self.protocol.buff_type.pack("ii", x, y), *data)
def send_air_chunk(self, x, z): sections = [] if x == 0 and z == 0: sections = [(BlockArray.empty(self.registry), None) for _ in range(16)] sections[9][0][0] = {"name": "minecraft:bedrock"} sections_data = self.buff_type.pack_chunk(sections) motion_world = PackedArray.empty_height() motion_blocking = TagLongArray(PackedArray.empty_height()) world_surface = TagLongArray(PackedArray.empty_height()) heightmap = TagRoot({ "": TagCompound({ "MOTION_BLOCKING": motion_blocking, "WORLD_SURFACE": world_surface }) }) biomes = [27 for _ in range(1024)] block_entities = [] self.send_packet( "chunk_data", self.buff_type.pack("ii?", x, z, True), self.buff_type.pack_chunk_bitmask(sections), self.buff_type.pack_nbt(heightmap), # added in 1.14 self.buff_type.pack_varint(0), b"", # b"".join(self.buff_type.pack_varint(biome) for biome in biomes), # self.buff_type.pack_array("I", biomes), self.buff_type.pack_varint(len(sections_data)), sections_data, self.buff_type.pack_varint(len(block_entities)), b"" # b"".join(self.buff_type.pack_nbt(entity) for entity in block_entities), )
def __init__(self, protocol: Protocol, bedrock: False): super(Version_1_16_2, self).__init__(protocol, bedrock) self.version_name = '1.16.2' self.dimension_settings = self.get_dimension_settings() self.dimension = { 'name': TagString("minecraft:overworld"), 'id': TagInt(0), 'element': TagCompound(self.dimension_settings), } self.current_dimension = TagRoot({ '': TagCompound(self.dimension_settings), }) self.biomes = NBTFile(TagRoot({})).load(os.path.join(path, 'biomes.nbt'))
def __init__(self, protocol: Protocol, bedrock: False): super(Version_1_16_2, self).__init__(protocol, bedrock) self.version_name = '1.16.2' self.dimension_settings = { 'piglin_safe': TagByte(0), 'natural': TagByte(1), 'ambient_light': TagFloat(0.0), 'infiniburn': TagString("minecraft:infiniburn_overworld"), 'respawn_anchor_works': TagByte(0), 'has_skylight': TagByte(0), 'bed_works': TagByte(0), "effects": TagString("minecraft:overworld") if self.is_bedrock else TagString("minecraft:the_nether"), 'has_raids': TagByte(0), 'logical_height': TagInt(256), 'coordinate_scale': TagFloat(1.0), 'ultrawarm': TagByte(0), 'has_ceiling': TagByte(0), } self.dimension = { 'name': TagString("minecraft:overworld"), 'id': TagInt(0), 'element': TagCompound(self.dimension_settings), } self.current_dimension = TagRoot({ '': TagCompound(self.dimension_settings), }) self.biomes = NBTFile(TagRoot({})).load('biomes.nbt')
def send_chunk(self, x, z): emptyHeight = TagRoot({"": TagCompound({ "MOTION_BLOCKING": TagLongArray(PackedArray.empty_height()) })}) try: cdpacket = ChunkDataPacket(self.protocol.buff_type, x, z, False, emptyHeight, [None]*16, [1]*256, []) self.protocol.send_packet(cdpacket.type_, *cdpacket.datas) except ValueError: pass
def send_world(self): self.send_spawn() # Clear geyser chunk cache from previous server if self.is_bedrock: data = [ self.protocol.buff_type.pack_varint(0), self.protocol.buff_type.pack_nbt(TagRoot({'': TagCompound({})})), self.protocol.buff_type.pack_varint(1024), ] for i in range(0, 1024): data.append(self.protocol.buff_type.pack_varint(127)) data.append(self.protocol.buff_type.pack_varint(0)) data.append(self.protocol.buff_type.pack_varint(0)) for x in range(-8, 8): for y in range(-8, 8): self.protocol.send_packet( "chunk_data", self.protocol.buff_type.pack("ii?", x, y, True), *data) # Chunk packets for packet in self.current_world.packets: self.protocol.send_packet(packet.get('type'), packet.get('packet')) # Start/stop rain as necessary if self.current_world.weather == 'rain': if self.raining is False: self.protocol.send_packet( 'change_game_state', self.protocol.buff_type.pack("Bf", 2, 0)) self.raining = True elif self.raining is True: self.protocol.send_packet('change_game_state', self.protocol.buff_type.pack("Bf", 1, 0)) self.raining = False if self.is_bedrock: # Current versions of geyser seem to ignore the time sometimes. Send repeatedly for now. self.protocol.ticker.add_loop(100, self.send_time) else: self.send_time()
def send_reset_world(self): data = [ self.protocol.buff_type.pack_varint(1), self.protocol.buff_type.pack('l', 0), self.protocol.buff_type.pack_nbt(TagRoot({'': TagCompound({})})), self.protocol.buff_type.pack_varint(1024), ] for i in range(0, 1024): data.append(self.protocol.buff_type.pack_varint(127)) data.append(self.protocol.buff_type.pack_varint(0)) data.append(self.protocol.buff_type.pack_varint(0)) for x in range(-8, 8): for y in range(-8, 8): self.protocol.send_packet( "chunk_data", self.protocol.buff_type.pack("ii", x, y), *data)
def nbt(self, token: str, bedrock: bool): pages = [] if bedrock: for page in self.pages: pages.append(TagString(page.replace("[token]", token))) else: for page in self.pages: pages.append(TagString(page.replace("[token]", token))) return TagRoot({ '': TagCompound({ 'resolved': TagInt(1), 'generation': TagInt(2), 'author': TagString(self.author), 'title': TagString(self.title), 'pages': TagList(pages) }) })
def send_world(self): data = [ self.protocol.buff_type.pack_varint(0), self.protocol.buff_type.pack_nbt(TagRoot({'': TagCompound({})})), self.protocol.buff_type.pack_varint(1024), ] for i in range(0, 1024): data.append(self.protocol.buff_type.pack_varint(127)) data.append(self.protocol.buff_type.pack_varint(0)) data.append(self.protocol.buff_type.pack_varint(0)) if self.is_bedrock: # Clear geyser chunk cache from previous server for x in range(-8, 8): for y in range(-8, 8): self.protocol.send_packet("chunk_data", self.protocol.buff_type.pack("ii?", x, y, True), *data) self.protocol.ticker.add_loop(100, self.send_time)
def player_joined(self): # Call super. This switches us to "play" mode, marks the player as # in-game, and does some logging. ServerProtocol.player_joined(self) print(self.protocol_version) # Send "Join Game" packet dim_name = "minecraft:the_end" if self.protocol_version > 736: # Minecraft 1.16.2 # Send "Join Game" packet biome_codec = TagCompound({ "type": TagString("minecraft:worldgen/biome"), "value": TagList([ TagCompound({ "name": TagString( "minecraft:plains" ), # Client crashes if you do not define plains "id": TagInt(1), "element": TagCompound({ "precipitation": TagString("none"), "effects": TagCompound({ "sky_color": TagInt(0xFFFFFF), "water_fog_color": TagInt(0), "fog_color": TagInt(0xFFFFFF), "water_color": TagInt(0), }), "depth": TagFloat(0.5), "temperature": TagFloat(1), "scale": TagFloat(0.2), "downfall": TagFloat(0.5), "category": TagString("plains"), }), }) ]), }) dim_settings = TagCompound({ "natural": TagByte(1), "ambient_light": TagFloat(1.0), "has_ceiling": TagByte(0), "has_skylight": TagByte(1), "fixed_time": TagLong(9000), "ultrawarm": TagByte(0), "has_raids": TagByte(0), "respawn_anchor_works": TagByte(0), "bed_works": TagByte(0), "piglin_safe": TagByte(0), "logical_height": TagInt(256), "infiniburn": TagString("minecraft:infiniburn_overworld"), "coordinate_scale": TagFloat(1.0), }) dim_codec = TagRoot({ "": TagCompound({ "minecraft:dimension_type": TagCompound({ "type": TagString("minecraft:dimension_type"), "value": TagList([ TagCompound({ "name": TagString(dim_name), "id": TagInt(0), "element": dim_settings, }), ]), }), "minecraft:worldgen/biome": biome_codec, }) }) current_dim = TagRoot({ "": dim_settings, }) self.send_packet( "join_game", self.buff_type.pack( "i?BB", 0, False, 3, 3), # entity id, hardcore, game mode, previous game mode self.buff_type.pack_varint(1), # world count self.buff_type.pack_string(dim_name), # world name(s) self.buff_type.pack_nbt(dim_codec), # dimension registry self.buff_type.pack_nbt(current_dim), # current dimension self.buff_type.pack_string(dim_name), # world name self.buff_type.pack("q", 42), # hashed seed self.buff_type.pack_varint(0), # max players (unused) self.buff_type.pack_varint(2), # view distance self.buff_type.pack("????", True, True, False, True), ) # respawn screen, debug world, flat world # self.send_packet( # "join_game", # self.buff_type.pack( # "i?Bb", # 1, # entity id # False, # 2, # game mode # -1, # previous game mode # ), # self.buff_type.pack_varint(1), # world count # self.buff_type.pack_string("minecraft:the_end"), # world identifiers # # self.buff_type.pack("qiB", ) # self.buff_type.pack_nbt(TagRoot({})), # dimension codec # self.buff_type.pack_nbt(TagRoot({})), # dimension # self.buff_type.pack_string("holdmusic"), # world identifiers # self.buff_type.pack("L", 12345678), # self.buff_type.pack_varint(0), # self.buff_type.pack_varint(3), # view distance # self.buff_type.pack("????", False, True, False, False), # reduced debug info # ) # show respawn screen for x in range(-7, 8): for y in range(-7, 8): self.send_air_chunk(x, y) self.send_air_chunk(1, 1) # Send "Player Position and Look" packet self.send_packet( "player_position_and_look", self.buff_type.pack( "dddff?", *self.pos, self.yaw, self.pitch, 0b00000 # x # y # z # yaw # pitch ), # flags self.buff_type.pack_varint(0), ) # teleport id # Send "Player Abilities" packet self.send_packet( "player_abilities", self.buff_type.pack("bff", 0b01111, 0.2, 0.1), ) # Send "Server Difficulty" packet self.send_packet( "server_difficulty", self.buff_type.pack("B?", 3, False), ) # Send "World Border" packet # self.send_packet( # "world_border", # self.buff_type.pack_varint(0), # self.buff_type.pack("d", 100), # ) # Send "Server Difficulty" packet # self.send_packet( # "chat_message", # self.buff_type.pack_chat(Message({"text": "Playing Stal -- C418", "color": "red"})) + self.buff_type.pack("B", 0), # ) items: List[Optional[str]] = [[ "minecraft:firework_rocket" if random() > 0.5 else "minecraft:pumpkin", int(random() * 127), None, ] for _ in range(46)] items[36] = [ "minecraft:written_book", 1, TagRoot({ "": TagCompound({ "title": TagString("Server Loading"), "author": TagString("Vin Howe"), "pages": TagList([ TagString( "This is a dummy server to keep you distracted while the real server starts running. Hang tight!" ) ]), }) }), ] # items[6] = "minecraft:elytra" # items[36:45] = ["minecraft:firework_rocket" for _ in range(36, 45)] # self.send_packet( # "window_items", # self.buff_type.pack("Bh", 0, 46), # *[self.buff_type.pack_slot(*item) for item in items] # ) # self.send_packet("open_book", self.buff_type.pack_varint(0)) self.update_music(create=True) # for player in self.factory.players: # player.send_packet( # "player_list_item", # self.buff_type.pack_varint(0), # action # self.buff_type.pack_varint(1), # count # self.buff_type.pack_uuid(self.uuid), # uuid # self.buff_type.pack_string(self.display_name), # name # self.buff_type.pack_varint( # 0 # ), # properties count (not really sure what to do with this) # self.buff_type.pack_varint(0), # gamemode (survival = 0) # self.buff_type.pack_varint(0), # ping (in ms) # self.buff_type.pack("?", False), # Has Display Name # ) # Start sending "Keep Alive" packets self.ticker.add_loop(20, self.update_keep_alive) self.ticker.add_loop(2, self.send_position_update)
def player_joined(self): # Call super. This switches us to "play" mode, marks the player as # in-game, and does some logging. ServerProtocol.player_joined(self) if self.protocol_version > 578: # Minecraft 1.16.1 # Send "Join Game" packet dim_name = "minecraft:the_end" dim_codec = TagRoot({ '': TagCompound({ "dimension": TagList([ TagCompound({ "name" : TagString(dim_name), "natural" : TagByte(0), "ambient_light" : TagFloat(0.0), "has_ceiling" : TagByte(0), "has_skylight" : TagByte(0), "fixed_time" : TagLong(6000), "shrunk" : TagByte(0), "ultrawarm" : TagByte(0), "has_raids" : TagByte(1), "respawn_anchor_works": TagByte(0), "bed_works" : TagByte(0), "piglin_safe" : TagByte(0), "logical_height" : TagInt(256), "infiniburn" : TagString("minecraft:infiniburn_end"), }), ]) }) }) self.send_packet("join_game", self.buff_type.pack("iBB", 0, 3, 3), # entity id, game mode, previous game mode self.buff_type.pack_varint(1), # world count self.buff_type.pack_string(dim_name), # world name(s) self.buff_type.pack_nbt(dim_codec), # dimension registry self.buff_type.pack_string(dim_name), # dimension self.buff_type.pack_string(dim_name), # world name self.buff_type.pack("qB", 42, 0), # hashed seed, max players (unused) self.buff_type.pack_varint(2), # view distance self.buff_type.pack("????", True, True, False, True)) # respawn screen, debug world, flat world else: # Minecraft 1.15 # Send "Join Game" packet self.send_packet("join_game", self.buff_type.pack("iBiqB", 0, # entity id 3, # game mode 0, # dimension 0, # hashed seed 0), # max players self.buff_type.pack_string("flat"), # level type self.buff_type.pack_varint(1), # view distance self.buff_type.pack("??", False, # reduced debug info True)) # show respawn screen # Send "Player Position and Look" packet self.send_packet("player_position_and_look", self.buff_type.pack("dddff?", 0, # x 255, # y 0, # z 0, # yaw 0, # pitch 0b00000), # flags self.buff_type.pack_varint(0)) # teleport id # Start sending "Keep Alive" packets self.ticker.add_loop(20, self.update_keep_alive) # Announce player joined self.factory.send_chat(u"\u00a7e%s has joined." % self.display_name)
def player_joined(self): # Call super. This switches us to "play" mode, marks the player as # in-game, and does some logging. ServerProtocol.player_joined(self) dim_name = "minecraft:the_end" if self.protocol_version > 736: # Minecraft 1.16.2 # Send "Join Game" packet biome_codec = TagCompound({ "type": TagString("minecraft:worldgen/biome"), "value": TagList([ TagCompound({ 'name': TagString( "minecraft:plains" ), # Client crashes if you do not define plains 'id': TagInt(1), 'element': TagCompound({ 'precipitation': TagString("none"), 'effects': TagCompound({ 'sky_color': TagInt(0), 'water_fog_color': TagInt(0), 'fog_color': TagInt(0), 'water_color': TagInt(0), }), 'depth': TagFloat(0.1), 'temperature': TagFloat(0.5), 'scale': TagFloat(0.2), 'downfall': TagFloat(0.5), 'category': TagString("plains") }), }) ]) }) dim_settings = TagCompound({ "natural": TagByte(1), "ambient_light": TagFloat(0.0), "has_ceiling": TagByte(0), "has_skylight": TagByte(0), "fixed_time": TagLong(6000), "ultrawarm": TagByte(0), "has_raids": TagByte(0), "respawn_anchor_works": TagByte(0), "bed_works": TagByte(0), "piglin_safe": TagByte(0), "logical_height": TagInt(256), "infiniburn": TagString("minecraft:infiniburn_end"), "coordinate_scale": TagFloat(1.0) }) dim_codec = TagRoot({ '': TagCompound({ "minecraft:dimension_type": TagCompound({ "type": TagString("minecraft:dimension_type"), "value": TagList([ TagCompound({ "name": TagString(dim_name), "id": TagInt(0), "element": dim_settings }), ]), }), "minecraft:worldgen/biome": biome_codec }) }) current_dim = TagRoot({ '': dim_settings, }) self.send_packet( "join_game", self.buff_type.pack( "i?BB", 0, False, 3, 3), # entity id, hardcore, game mode, previous game mode self.buff_type.pack_varint(1), # world count self.buff_type.pack_string(dim_name), # world name(s) self.buff_type.pack_nbt(dim_codec), # dimension registry self.buff_type.pack_nbt(current_dim), # current dimension self.buff_type.pack_string(dim_name), # world name self.buff_type.pack("q", 42), # hashed seed self.buff_type.pack_varint(0), # max players (unused) self.buff_type.pack_varint(2), # view distance self.buff_type.pack( "????", True, True, False, True)) # respawn screen, debug world, flat world elif self.protocol_version > 578: # Minecraft 1.16.1 # Send "Join Game" packet dim_codec = TagRoot({ '': TagCompound({ "dimension": TagList([ TagCompound({ "name": TagString(dim_name), "natural": TagByte(0), "ambient_light": TagFloat(0.0), "has_ceiling": TagByte(0), "has_skylight": TagByte(0), "fixed_time": TagLong(6000), "shrunk": TagByte(0), "ultrawarm": TagByte(0), "has_raids": TagByte(1), "respawn_anchor_works": TagByte(0), "bed_works": TagByte(0), "piglin_safe": TagByte(0), "logical_height": TagInt(256), "infiniburn": TagString("minecraft:infiniburn_end"), }), ]) }) }) self.send_packet( "join_game", self.buff_type.pack( "iBB", 0, 3, 3), # entity id, game mode, previous game mode self.buff_type.pack_varint(1), # world count self.buff_type.pack_string(dim_name), # world name(s) self.buff_type.pack_nbt(dim_codec), # dimension registry self.buff_type.pack_string(dim_name), # dimension self.buff_type.pack_string(dim_name), # world name self.buff_type.pack("qB", 42, 0), # hashed seed, max players (unused) self.buff_type.pack_varint(2), # view distance self.buff_type.pack( "????", True, True, False, True)) # respawn screen, debug world, flat world else: # Minecraft 1.15 # Send "Join Game" packet self.send_packet( "join_game", self.buff_type.pack( "iBiqB", 0, # entity id 3, # game mode 0, # dimension 0, # hashed seed 0), # max players self.buff_type.pack_string("flat"), # level type self.buff_type.pack_varint(1), # view distance self.buff_type.pack( "??", False, # reduced debug info True)) # show respawn screen # Send "Player Position and Look" packet self.send_packet( "player_position_and_look", self.buff_type.pack( "dddff?", 0, # x 255, # y 0, # z 0, # yaw 0, # pitch 0b00000), # flags self.buff_type.pack_varint(0)) # teleport id # Start sending "Keep Alive" packets self.ticker.add_loop(20, self.update_keep_alive) # Announce player joined self.factory.send_chat(u"\u00a7e%s has joined." % self.display_name)