def pre_build_hook(self, player, builddata): item, metadata, x, y, z, face = builddata if item.slot != blocks["chest"].slot: returnValue((True, builddata, False)) x, y, z = adjust_coords_for_face((x, y, z), face) bigx, smallx, bigz, smallz = split_coords(x, z) # chest orientation according to players position if face == "-y" or face == "+y": orientation = ('+x', '+z', '-x', '-z')[((int(player.location.yaw) \ - 45 + 360) % 360) / 90] else: orientation = face # Chests have some restrictions on building: # you cannot connect more than two chests. (notchian) ccs = chestsAround(self.factory, (x, y, z)) ccn = len(ccs) if ccn > 1: # cannot build three or more connected chests returnValue((False, builddata, True)) chunk = yield self.factory.world.request_chunk(bigx, bigz) if ccn == 0: metadata = blocks["chest"].orientation(orientation) elif ccn == 1: # check gonna-be-connected chest is not connected already n = len(chestsAround(self.factory, ccs[0])) if n != 0: returnValue((False, builddata, True)) # align both blocks correctly (since 1.8) # get second block x2, y2, z2 = ccs[0] bigx2, smallx2, bigz2, smallz2 = split_coords(x2, z2) # new chests orientation axis according to blocks position pair = x - x2, z - z2 ornt = {(0, 1): "x", (0, -1): "x", (1, 0): "z", (-1, 0): "z"}[pair] # if player is faced another direction, fix it if orientation[1] != ornt: # same sign with proper orientation # XXX Probably notchian logic is different here # but this one works well enough orientation = orientation[0] + ornt metadata = blocks["chest"].orientation(orientation) # update second block's metadata if bigx == bigx2 and bigz == bigz2: # both blocks are in same chunk chunk2 = chunk else: chunk2 = yield self.factory.world.request_chunk(bigx2, bigz2) chunk2.set_metadata((smallx2, y2, smallz2), metadata) # Not much to do, just tell the chunk about this tile. chunk.tiles[smallx, y, smallz] = ChestTile(smallx, y, smallz) builddata = builddata._replace(metadata=metadata) returnValue((True, builddata, False))
def open_hook(self, player, container, block): """ The ``player`` is a Player's protocol The ``container`` is a 0x64 message The ``block`` is a block we trying to open :returns: None or window object """ if block != blocks["chest"].slot: returnValue(None) bigx, smallx, bigz, smallz = split_coords(container.x, container.z) chunk = yield self.factory.world.request_chunk(bigx, bigz) chests_around = chestsAround(self.factory, (container.x, container.y, container.z)) chests_around_num = len(chests_around) if chests_around_num == 0: # small chest chest = self.get_chest_tile(chunk, (smallx, container.y, smallz)) if chest is None: returnValue(None) coords = bigx, smallx, bigz, smallz, container.y window = ChestWindow(player.wid, player.player.inventory, chest.inventory, coords) elif chests_around_num == 1: # large chest # process second chest coordinates x2, y2, z2 = chests_around[0] bigx2, smallx2, bigz2, smallz2 = split_coords(x2, z2) if bigx == bigx2 and bigz == bigz2: # both chest blocks are in same chunk chunk2 = chunk else: chunk2 = yield self.factory.world.request_chunk(bigx2, bigz2) chest1 = self.get_chest_tile(chunk, (smallx, container.y, smallz)) chest2 = self.get_chest_tile(chunk2, (smallx2, container.y, smallz2)) if chest1 is None or chest2 is None: returnValue(None) c1 = bigx, smallx, bigz, smallz, container.y c2 = bigx2, smallx2, bigz2, smallz2, container.y # We shall properly order chest inventories if c1 < c2: window = LargeChestWindow(player.wid, player.player.inventory, chest1.inventory, chest2.inventory, c1) else: window = LargeChestWindow(player.wid, player.player.inventory, chest2.inventory, chest1.inventory, c2) else: log.msg("Chest at (%d, %d, %d) have three chests connected" % (container.x, container.y, container.z)) returnValue(None) player.windows.append(window) returnValue(window)
def pre_build_hook(self, player, builddata): item, metadata, x, y, z, face = builddata if item.slot == items["sign"].slot: # Buildin' a sign, puttin' it on a wall... builddata = builddata._replace(block=blocks["wall-sign"]) # Offset coords according to face. if face == "-x": builddata = builddata._replace(metadata=0x4) x -= 1 elif face == "+x": builddata = builddata._replace(metadata=0x5) x += 1 elif face == "-y": # Ceiling Sign is watching you read. returnValue((False, builddata, False)) elif face == "+y": # Put +Y signs on signposts. We're fancy that way. Also, # calculate the proper orientation based on player # orientation. # 180 degrees around to orient the signs correctly, and then # 23 degrees to get the sign to midpoint correctly. metadata = ((player.location.yaw + 180) * 16 // 360) % 0xf builddata = builddata._replace(block=blocks["signpost"], metadata=metadata) y += 1 elif face == "-z": builddata = builddata._replace(metadata=0x2) z -= 1 elif face == "+z": builddata = builddata._replace(metadata=0x3) z += 1 bigx, smallx, bigz, smallz = split_coords(x, z) # Let's build a sign! chunk = yield factory.world.request_chunk(bigx, bigz) s = Sign(smallx, y, smallz) chunk.tiles[smallx, y, smallz] = s elif item.slot in self.block_to_tile: x, y, z = adjust_coords_for_face((x, y, z), face) bigx, smallx, bigz, smallz = split_coords(x, z) if item.slot == blocks["chest"].slot: # Chests have some restrictions on building: # you cannot connect more than two chests. # (notchian) ccs = chestsAround(factory, (x, y, z)) ccn = len(ccs) if ccn == 1: # check gonna-be-connected chest is not connected already n = len(chestsAround(factory, ccs[0])) if n != 0: returnValue((False, builddata, True)) elif ccn > 1: # cannot build three or more connected chests returnValue((False, builddata, True)) elif item.slot == blocks["furnace"].slot: # the furnace cannot be oriented up or down if face == "-y" or face == "+y": orientation = ('+x', '+z', '-x', '-z')[((int(player.location.yaw) \ - 45 + 360) % 360) / 90] metadata = blocks["furnace"].orientation(orientation) builddata = builddata._replace(metadata=metadata) chunk = yield factory.world.request_chunk(bigx, bigz) # Not much to do, just tell the chunk about this tile. tileClass = self.block_to_tile[item.slot] tile = tileClass(smallx, y, smallz) chunk.tiles[smallx, y, smallz] = tile returnValue((True, builddata, False))