예제 #1
0
파일: protocol.py 프로젝트: welterde/beta
    def position_look(self, container):
        oldx, chaff, oldz, chaff = split_coords(self.player.location.x,
            self.player.location.z)

        self.player.location.load_from_packet(container)

        pos = (self.player.location.x, self.player.location.y,
            self.player.location.z)

        x, chaff, z, chaff = split_coords(pos[0], pos[2])

        if oldx != x or oldz != z:
            self.update_chunks()

        for entity in self.factory.entities_near(pos[0] * 32,
            self.player.location.y * 32, pos[2] * 32, 64):

            packet = make_packet("pickup", type=entity.entity_type,
                quantity=entity.quantity, wear=0)
            self.transport.write(packet)

            packet = make_packet("destroy", id=entity.id)
            self.transport.write(packet)

            self.factory.destroy_entity(entity)
예제 #2
0
파일: protocol.py 프로젝트: welterde/beta
    def digging(self, container):
        if container.state != 3:
            return

        bigx, smallx, bigz, smallz = split_coords(container.x, container.z)

        try:
            chunk = self.chunks[bigx, bigz]
        except KeyError:
            self.error("Couldn't dig in chunk (%d, %d)!" % (bigx, bigz))
            return

        # XXX something to consider: All of this handler's functionality is
        # based on the chunk, the coords, and the block type, which means that
        # it could all be implemented as IDigHooks. Hmm....

        oldblock = chunk.get_block((smallx, container.y, smallz))
        newblock = blocks[oldblock].replace
        chunk.set_block((smallx, container.y, smallz), newblock)

        dropblock = blocks[oldblock].drop

        if dropblock != 0:
            coords = (container.x * 32 + 16, container.y * 32,
                container.z * 32 + 16)
            self.factory.give(coords, dropblock, 1)

        for hook in self.dig_hooks:
            hook.dig_hook(chunk, smallx, container.y, smallz, oldblock)

        if chunk.is_damaged():
            packet = chunk.get_damage_packet()
            self.factory.broadcast_for_chunk(packet, bigx, bigz)
            chunk.clear_damage()
예제 #3
0
파일: protocol.py 프로젝트: welterde/beta
    def send_initial_chunk_and_location(self):
        bigx, smallx, bigz, smallz = split_coords(self.player.location.x,
            self.player.location.z)

        self.enable_chunk(bigx, bigz)
        chunk = self.chunks[bigx, bigz]

        # This may not play well with recent Alpha clients, which have an
        # unfortunate bug at maximum heights. We have yet to ascertain whether
        # the bug is server-side or client-side.
        height = chunk.height_at(smallx, smallz) + 2
        self.player.location.y = height

        packet = self.player.location.save_to_packet()
        self.transport.write(packet)
예제 #4
0
파일: protocol.py 프로젝트: welterde/beta
    def build(self, container):
        # Ignore clients that think -1 is placeable.
        if container.block == 65535:
            return

        x = container.x
        y = container.y
        z = container.z

        # Special case when face is -1: Update the status of the currently
        # held block rather than placing a new block.
        if container.face == -1:
            return

        # Offset coords according to face.
        if container.face == 0:
            y -= 1
        elif container.face == 1:
            y += 1
        elif container.face == 2:
            z -= 1
        elif container.face == 3:
            z += 1
        elif container.face == 4:
            x -= 1
        elif container.face == 5:
            x += 1

        bigx, smallx, bigz, smallz = split_coords(x, z)

        try:
            chunk = self.chunks[bigx, bigz]
        except KeyError:
            self.error("Couldn't build in chunk (%d, %d)!" % (bigx, bigz))
            return

        chunk.set_block((smallx, y, smallz), container.block)

        if chunk.is_damaged():
            packet = chunk.get_damage_packet()
            self.factory.broadcast_for_chunk(packet, bigx, bigz)
            chunk.clear_damage()
예제 #5
0
파일: protocol.py 프로젝트: welterde/beta
    def update_chunks(self):
        print "Sending chunks..."
        x, chaff, z, chaff = split_coords(self.player.location.x,
            self.player.location.z)

        new = set(product(xrange(x - 10, x + 10), xrange(z - 10, z + 10)))
        old = set(self.chunks.iterkeys())
        added = new - old
        discarded = old - new

        # Perhaps some explanation is in order.
        # The generator expressions are stored in the protocol instance. If we
        # need to cancel them, we can call their close() method, which causes
        # them to become inert. This is incredibly important because we want
        # to cancel all previously pending chunk changes when a new set of
        # chunk changes is requested.
        # The coiterate() function iterates over the iterable it is fed,
        # without tying up the reactor, by yielding after each iteration. The
        # inner part of the generator expression generates all of the chunks
        # around the currently needed chunk, and it sorts them by distance to
        # the current chunk. The end result is that we load chunks one-by-one,
        # nearest to furthest, without stalling other clients.
        if self.chunk_generators:
            for generator in self.chunk_generators:
                generator.close()

        self.chunk_generators = [
            (
                self.enable_chunk(i, j) for i, j in
                sorted(added, key=lambda t: (t[0] - x)**2 + (t[1] - z)**2)
            ),
            (self.disable_chunk(i, j) for i, j in discarded)
        ]

        for generator in self.chunk_generators:
            coiterate(generator)