def build(self, container): # Is the target being selected? bigx, smallx, bigz, smallz = split_coords(container.x, container.z) try: chunk = self.chunks[bigx, bigz] except KeyError: self.error("Couldn't select in chunk (%d, %d)!" % (bigx, bigz)) return if (chunk.get_block((smallx, container.y, smallz)) == blocks["workbench"].slot): i = Workbench() sync_inventories(self.player.inventory, i) self.windows[self.wid] = i packet = make_packet("window-open", wid=self.wid, type="workbench", title="Hurp", slots=2) self.wid += 1 self.transport.write(packet) return # Ignore clients that think -1 is placeable. if container.primary == -1: return # Special case when face is "noop": Update the status of the currently # held block rather than placing a new block. if container.face == "noop": return if container.primary in blocks: block = blocks[container.primary] elif container.primary in items: block = items[container.primary] else: log.err("Ignoring request to place unknown block %d" % container.primary) return if time() - self.last_dig_build_timer < 0.2: self.error("You are building too fast.") self.last_dig_build_timer = time() builddata = BuildData(block, 0x0, container.x, container.y, container.z, container.face) for hook in self.build_hooks: cont, builddata = hook.build_hook(self.factory, self.player, builddata) if not cont: break # Re-send inventory. # XXX this could be optimized if/when inventories track damage. packet = self.player.inventory.save_to_packet() self.transport.write(packet) # Flush damaged chunks. for chunk in self.chunks.itervalues(): self.factory.flush_chunk(chunk)
def wclose(self, container): top = self.windows.pop() # If the requested WID is on top of the stack, go ahead and close the # window. Otherwise, ignore it. # XXX should/can we nak requests for closing windows? if container.wid == top.wid: if top.identifier == "workbench": # Closing the workbench. dest = self.location.in_front_of(1) dest.y += 1 coords = (int(dest.x * 32) + 16, int(dest.y * 32) + 16, int(dest.z * 32) + 16) # Loop over items left in workbench, and drop all of them # in front of the player. for item in top.crafting: if item is None: continue self.factory.give(coords, (item[0], item[1]), item[2]) sync_inventories(i, self.player.inventory) # All done! return elif container.wid == 0: # XXX Why does this happen? What should we do? pass else: log.msg("Ignoring request to close non-current window %d" % container.wid)
def build(self, container): if container.x == -1 and container.z == -1 and container.y == 255: # Lala-land build packet. Discard it for now. return # Is the target being selected? bigx, smallx, bigz, smallz = split_coords(container.x, container.z) try: chunk = self.chunks[bigx, bigz] except KeyError: self.error("Couldn't select in chunk (%d, %d)!" % (bigx, bigz)) return if chunk.get_block((smallx, container.y, smallz)) == blocks["workbench"].slot: i = Workbench() sync_inventories(self.player.inventory, i) self.windows[self.wid] = i packet = make_packet("window-open", wid=self.wid, type="workbench", title="Hurp", slots=2) self.wid += 1 self.transport.write(packet) return # Ignore clients that think -1 is placeable. if container.primary == -1: return # Special case when face is "noop": Update the status of the currently # held block rather than placing a new block. if container.face == "noop": return if container.primary in blocks: block = blocks[container.primary] elif container.primary in items: block = items[container.primary] else: log.err("Ignoring request to place unknown block %d" % container.primary) return # it's the top of the world, you can't build here if container.y == 127 and container.face == "+y": return # Run pre-build hooks. These hooks are able to interrupt the build # process. builddata = BuildData(block, 0x0, container.x, container.y, container.z, container.face) for hook in self.pre_build_hooks: cont, builddata = yield maybeDeferred(hook.pre_build_hook, self.player, builddata) if not cont: break # Run the build. try: builddata = self.prepare_build(builddata) yield maybeDeferred(self.run_build, builddata) except BuildError, e: print e return
def wclose(self, container): if container.wid in self.windows: i = self.windows[container.wid] del self.windows[container.wid] sync_inventories(i, self.player.inventory) elif container.wid == 0: pass else: self.error("Can't close non-existent window %d!" % container.wid)
def wclose(self, container): if container.wid in self.windows: i = self.windows[container.wid] if i.identifier == 1: # Closing the workbench. dest = self.location.in_front_of(1) dest.y += 1 coords = (int(dest.x * 32) + 16, int(dest.y * 32) + 16, int(dest.z * 32) + 16) # loop over items left in workbench for item in i.crafting: if item is None: continue self.factory.give(coords, (item[0], item[1]), item[2]) del self.windows[container.wid] sync_inventories(i, self.player.inventory) elif container.wid == 0: pass else: self.error("Can't close non-existent window %d!" % container.wid)
def select_for_inventory(self, block): """ Perform a custom block selection to open an inventory window. Returns whether the selection was successful. """ if block == blocks["workbench"].slot: i = Workbench() i.wid = self.wid self.wid += 1 sync_inventories(self.player.inventory, i) self.windows.append(i) self.write_packet("window-open", wid=i.wid, type="workbench", title="Hurp", slots=2) return True return False
def wclose(self, container): # Handle windows getting closed. First, a special case for inventory # windows, then the generic case for other opened windows. # Notchian client will open its inventory window without telling the # server about it, so it can request an inventory window close # *without* an open, and the window wouldn't be on our window stack. # To properly handle it, special-case it here. if container.wid == 0: # Kick items out of the crafting table. self.drop_items(self.player.inventory.crafting) # And vacate the corresponding slots on the client. # XXX we should really have a method for automating this in the # inventory. for i in xrange(0, 4): if self.player.inventory.crafting[i] is not None: self.write_packet( "window-slot", wid = 0, slot = i+1, primary = -1 ) self.player.inventory.crafting[i] = None # XXX huh? self.drop_selected(self.player.inventory) return top = self.windows.pop() # If the requested WID is on top of the stack, go ahead and close the # window. Otherwise, ignore it. # XXX should/can we nak requests for closing windows? if container.wid == top.wid: if top.identifier == "workbench": # Closing the workbench. self.drop_items(top.crafting) self.drop_selected(top) sync_inventories(top, self.player.inventory) # All done! return else: log.msg("Ignoring request to close non-current window %d" % container.wid)
def wclose(self, container): if container.wid in self.windows: i = self.windows[container.wid] if i.identifier == 1: # closing workbench # XXX: this should be re-factored into an extra utility function # Do some trig to put the pickup one block ahead of the player # in the direction they are facing. l = self.location x = l.x - sin(l.theta) y = l.y + 1 z = l.z + cos(l.theta) coords = (int(x * 32) + 16, int(y * 32) + 16, int(z * 32) + 16) # loop over items left in workbench for item in i.crafting: if item is None: continue self.factory.give(coords, (item[0], item[1]), item[2]) del self.windows[container.wid] sync_inventories(i, self.player.inventory) elif container.wid == 0: pass else: self.error("Can't close non-existent window %d!" % container.wid)
def wclose(self, container): if container.wid in self.windows: i = self.windows[container.wid] if i.identifier == 1: # closing workbench # XXX: this should be re-factored into an extra utility function # Do some trig to put the pickup one block ahead of the player # in the direction they are facing. l = self.player.location x = l.x - math.sin(l.theta) y = l.y + 1 z = l.z + math.cos(l.theta) coords = (int(x * 32) + 16, int(y * 32) + 16, int(z * 32) + 16) # loop over items left in workbench for item in i.crafting: if item is None: continue self.factory.give(coords, (item[0], item[1]), item[2]) del self.windows[container.wid] sync_inventories(i, self.player.inventory) elif container.wid == 0: pass else: self.error("Can't close non-existent window %d!" % container.wid)
def build(self, container): if container.x == -1 and container.z == -1 and container.y == 255: # Lala-land build packet. Discard it for now. return # Is the target being selected? bigx, smallx, bigz, smallz = split_coords(container.x, container.z) try: chunk = self.chunks[bigx, bigz] except KeyError: self.error("Couldn't select in chunk (%d, %d)!" % (bigx, bigz)) return if (chunk.get_block( (smallx, container.y, smallz)) == blocks["workbench"].slot): i = Workbench() sync_inventories(self.player.inventory, i) self.windows[self.wid] = i packet = make_packet("window-open", wid=self.wid, type="workbench", title="Hurp", slots=2) self.wid += 1 self.transport.write(packet) return # Ignore clients that think -1 is placeable. if container.primary == -1: return # Special case when face is "noop": Update the status of the currently # held block rather than placing a new block. if container.face == "noop": return if container.primary in blocks: block = blocks[container.primary] elif container.primary in items: block = items[container.primary] else: log.err("Ignoring request to place unknown block %d" % container.primary) return if time() - self.last_dig_build_timer < 0.05: self.error("You are building too fast.") self.last_dig_build_timer = time() # it's the top of the world, you can't build here if container.y == 127 and container.face == '+y': return builddata = BuildData(block, 0x0, container.x, container.y, container.z, container.face) for hook in self.build_hooks: cont, builddata = yield maybeDeferred(hook.build_hook, self.factory, self.player, builddata) if not cont: break newblock = builddata.block.slot # Feed automatons. for automaton in self.factory.automatons: if newblock in automaton.blocks: automaton.feed(self.factory, (builddata.x, builddata.y, builddata.z)) # Re-send inventory. # XXX this could be optimized if/when inventories track damage. packet = self.player.inventory.save_to_packet() self.transport.write(packet) # Flush damaged chunks. for chunk in self.chunks.itervalues(): self.factory.flush_chunk(chunk)
def build(self, container): if container.x == -1 and container.z == -1 and container.y == 255: # Lala-land build packet. Discard it for now. return # Is the target being selected? bigx, smallx, bigz, smallz = split_coords(container.x, container.z) try: chunk = self.chunks[bigx, bigz] except KeyError: self.error("Couldn't select in chunk (%d, %d)!" % (bigx, bigz)) return if (chunk.get_block((smallx, container.y, smallz)) == blocks["workbench"].slot): i = Workbench() sync_inventories(self.player.inventory, i) self.windows[self.wid] = i packet = make_packet("window-open", wid=self.wid, type="workbench", title="Hurp", slots=2) self.wid += 1 self.transport.write(packet) return # Ignore clients that think -1 is placeable. if container.primary == -1: return # Special case when face is "noop": Update the status of the currently # held block rather than placing a new block. if container.face == "noop": return if container.primary in blocks: block = blocks[container.primary] elif container.primary in items: block = items[container.primary] else: log.err("Ignoring request to place unknown block %d" % container.primary) return # it's the top of the world, you can't build here if container.y == 127 and container.face == '+y': return # Run pre-build hooks. These hooks are able to interrupt the build # process. builddata = BuildData(block, 0x0, container.x, container.y, container.z, container.face) for hook in self.pre_build_hooks: cont, builddata = yield maybeDeferred(hook.pre_build_hook, self.player, builddata) if not cont: break # Run the build. try: yield maybeDeferred(self.run_build, builddata) except BuildError: return newblock = builddata.block.slot coords = builddata.x, builddata.y, builddata.z # Run post-build hooks. These are merely callbacks which cannot # interfere with the build process, largely because the build process # already happened. for hook in self.post_build_hooks: yield maybeDeferred(hook.post_build_hook, self.player, coords, builddata.block) # Feed automatons. for automaton in self.factory.automatons: if newblock in automaton.blocks: automaton.feed((builddata.x, builddata.y, builddata.z)) # Re-send inventory. # XXX this could be optimized if/when inventories track damage. packet = self.player.inventory.save_to_packet() self.transport.write(packet) # Flush damaged chunks. for chunk in self.chunks.itervalues(): self.factory.flush_chunk(chunk)