Beispiel #1
0
    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)
Beispiel #2
0
    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)
Beispiel #3
0
    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
Beispiel #4
0
 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)
Beispiel #5
0
 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)
Beispiel #6
0
 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)
Beispiel #7
0
    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
Beispiel #8
0
    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)
Beispiel #9
0
 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)
Beispiel #10
0
 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)
Beispiel #11
0
    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)
Beispiel #12
0
    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)