Ejemplo n.º 1
0
    def position_look(self, container):
        oldx, chaff, oldz, chaff = split_coords(self.player.location.x,
            self.player.location.z)

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

        self.player.location.load_from_packet(container)

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

        if oldpos == pos:
            # We haven't actually moved...
            return

        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,
            pos[1] * 32, pos[2] * 32, 2 * 32):
            if entity.name != "Pickup":
                continue

            if self.player.inventory.add(entity.block, entity.quantity):
                packet = self.player.inventory.save_to_packet()
                self.transport.write(packet)

                packet = make_packet("collect", eid=entity.eid,
                    destination=self.player.eid)
                self.transport.write(packet)

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

                self.factory.destroy_entity(entity)

        for entity in self.factory.entities_near(pos[0] * 32,
            pos[1] * 32, pos[2] * 32, 160 * 32):

            if (entity is self.player or
                entity.name != "Player" or
                entity.eid in self.entities):
                continue

            self.entities.add(entity.eid)

            packet = entity.save_to_packet()
            self.transport.write(packet)

            packet = make_packet("create", eid=entity.eid)
            self.transport.write(packet)
Ejemplo n.º 2
0
    def position_changed(self):
        x, chaff, z, chaff = split_coords(self.location.x, self.location.z)

        # Inform everybody of our new location.
        packet = make_packet(
            "teleport",
            eid=self.player.eid,
            x=self.location.x * 32,
            y=self.location.y * 32,
            z=self.location.z * 32,
            yaw=int(self.location.theta * 255 / (2 * pi)) % 256,
            pitch=int(self.location.phi * 255 / (2 * pi)) % 256,
        )
        self.factory.broadcast_for_others(packet, self)

        self.update_chunks()

        for entity in self.entities_near(2):
            if entity.name != "Item":
                continue

            if self.player.inventory.add(entity.item, entity.quantity):
                packet = make_packet("collect",
                                     eid=entity.eid,
                                     destination=self.player.eid)
                self.factory.broadcast(packet)

                packet = make_packet("destroy", eid=entity.eid)
                self.factory.broadcast(packet)

                packet = self.player.inventory.save_to_packet()
                self.transport.write(packet)

                self.factory.destroy_entity(entity)
Ejemplo n.º 3
0
    def sign(self, container):
        bigx, smallx, bigz, smallz = split_coords(container.x, container.z)

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

        if (smallx, container.y, smallz) in chunk.tiles:
            new = False
            s = chunk.tiles[smallx, container.y, smallz]
        else:
            new = True
            s = Sign(smallx, container.y, smallz)
            chunk.tiles[smallx, container.y, smallz] = s

        s.text1 = container.line1
        s.text2 = container.line2
        s.text3 = container.line3
        s.text4 = container.line4

        chunk.dirty = True

        # The best part of a sign isn't making one, it's showing everybody
        # else on the server that you did.
        packet = make_packet("sign", container)
        self.factory.broadcast_for_chunk(packet, bigx, bigz)

        # Run sign hooks.
        for hook in self.sign_hooks:
            hook.sign_hook(self.factory, chunk, container.x, container.y,
                           container.z, [s.text1, s.text2, s.text3, s.text4],
                           new)
Ejemplo n.º 4
0
    def send_initial_chunk_and_location(self):
        bigx, smallx, bigz, smallz = split_coords(self.location.x,
                                                  self.location.z)

        # Spawn the 25 chunks in a square around the spawn, *before* spawning
        # the player. Otherwise, there's a funky Beta 1.2 bug which causes the
        # player to not be able to move.
        d = cooperate(
            self.enable_chunk(i, j)
            for i, j in product(xrange(bigx - 3, bigx +
                                       3), xrange(bigz - 3, bigz +
                                                  3))).whenDone()

        # Don't dare send more chunks beyond the initial one until we've
        # spawned.
        d.addCallback(lambda none: self.update_location())
        d.addCallback(lambda none: self.position_changed())

        # Send the MOTD.
        if self.motd:
            packet = make_packet("chat",
                                 message=self.motd.replace(
                                     "<tagline>", get_motd()))
            d.addCallback(lambda none: self.transport.write(packet))

        # Finally, start the secondary chunk loop.
        d.addCallback(lambda none: self.update_chunks())
Ejemplo n.º 5
0
    def send_initial_chunk_and_location(self):
        bigx, smallx, bigz, smallz = split_coords(self.location.x,
            self.location.z)

        # Spawn the 25 chunks in a square around the spawn, *before* spawning
        # the player. Otherwise, there's a funky Beta 1.2 bug which causes the
        # player to not be able to move.
        d = cooperate(
            self.enable_chunk(i, j)
            for i, j in product(
                xrange(bigx - 3, bigx + 3),
                xrange(bigz - 3, bigz + 3)
            )
        ).whenDone()

        # Don't dare send more chunks beyond the initial one until we've
        # spawned.
        d.addCallback(lambda none: self.update_location())
        d.addCallback(lambda none: self.position_changed())

        # Send the MOTD.
        if self.motd:
            packet = make_packet("chat",
                message=self.motd.replace("<tagline>", get_motd()))
            d.addCallback(lambda none: self.transport.write(packet))

        # Finally, start the secondary chunk loop.
        d.addCallback(lambda none: self.update_chunks())
Ejemplo n.º 6
0
Archivo: beta.py Proyecto: dequis/bravo
    def digging(self, container):
        # XXX several improvements should happen here
        # ~ We should time started and stopped pairs to force clients to
        # slow-break their blocks
        # ~ we should handle "dropped" state packets for item drops
        if container.x == -1 and container.z == -1 and container.y == 255:
            # Lala-land dig packet. Discard it for now.
            return

        if container.state != "stopped":
            # We only care about digs which break blocks.
            return

        if time() - self.last_dig_build_timer < 0.1:
            self.error("You are digging too fast.")

        self.last_dig_build_timer = time()

        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

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

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

        self.factory.flush_chunk(chunk)
Ejemplo n.º 7
0
    def decorated(self, coords, *args, **kwargs):
        x, y, z = coords

        bigx, smallx, bigz, smallz = split_coords(x, z)
        chunk = self.load_chunk(bigx, bigz)

        return f(self, chunk, (smallx, y, smallz), *args, **kwargs)
Ejemplo n.º 8
0
Archivo: beta.py Proyecto: dequis/bravo
    def digging(self, container):
        # XXX several improvements should happen here
        # ~ We should time started and stopped pairs to force clients to
        # slow-break their blocks
        # ~ we should handle "dropped" state packets for item drops
        if container.x == -1 and container.z == -1 and container.y == 255:
            # Lala-land dig packet. Discard it for now.
            return

        if container.state != "stopped":
            # We only care about digs which break blocks.
            return

        if time() - self.last_dig_build_timer < 0.1:
            self.error("You are digging too fast.")

        self.last_dig_build_timer = time()

        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

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

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

        self.factory.flush_chunk(chunk)
Ejemplo n.º 9
0
Archivo: beta.py Proyecto: dequis/bravo
    def sign(self, container):
        bigx, smallx, bigz, smallz = split_coords(container.x, container.z)

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

        if (smallx, container.y, smallz) in chunk.tiles:
            new = False
            s = chunk.tiles[smallx, container.y, smallz]
        else:
            new = True
            s = Sign(smallx, container.y, smallz)
            chunk.tiles[smallx, container.y, smallz] = s

        s.text1 = container.line1
        s.text2 = container.line2
        s.text3 = container.line3
        s.text4 = container.line4

        chunk.dirty = True

        # The best part of a sign isn't making one, it's showing everybody
        # else on the server that you did.
        packet = make_packet("sign", container)
        self.factory.broadcast_for_chunk(packet, bigx, bigz)

        # Run sign hooks.
        for hook in self.sign_hooks:
            hook.sign_hook(self.factory, chunk, container.x, container.y,
                container.z, [s.text1, s.text2, s.text3, s.text4], new)
Ejemplo n.º 10
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)
Ejemplo n.º 11
0
    def sign(self, container):
        bigx, smallx, bigz, smallz = split_coords(container.x, container.z)

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

        if (smallx, container.y, smallz) in chunk.tiles:
            s = chunk.tiles[smallx, container.y, smallz]
        else:
            s = Sign()

        s.x = smallx
        s.y = container.y
        s.z = smallz

        s.text1 = container.line1
        s.text2 = container.line2
        s.text3 = container.line3
        s.text4 = container.line4

        chunk.tiles[smallx, container.y, smallz] = s
        chunk.dirty = True

        # The best part of a sign isn't making one, it's showing everybody
        # else on the server that you did.
        packet = make_packet("sign", container)
        self.factory.broadcast_for_chunk(packet, bigx, bigz)
Ejemplo n.º 12
0
    def decorated(self, coords, *args, **kwargs):
        x, y, z = coords

        bigx, smallx, bigz, smallz = split_coords(x, z)
        chunk = self.load_chunk(bigx, bigz)

        return f(self, chunk, (smallx, y, smallz), *args, **kwargs)
Ejemplo n.º 13
0
    def build_hook(self, factory, player, builddata):
        block, metadata, x, y, z, face = builddata

        # Don't place items as blocks.
        if block.slot not in blocks:
            return True, builddata

        # Make sure we can remove it from the inventory first.
        if not player.inventory.consume((block.slot, 0)):
            return True, builddata

        # Offset coords according to face.
        if face == "-x":
            x -= 1
        elif face == "+x":
            x += 1
        elif face == "-y":
            y -= 1
        elif face == "+y":
            y += 1
        elif face == "-z":
            z -= 1
        elif face == "+z":
            z += 1

        bigx, smallx, bigz, smallz = split_coords(x, z)
        chunk = factory.world.load_chunk(bigx, bigz)

        chunk.set_block((smallx, y, smallz), block.slot)
        if metadata:
            chunk.set_metadata((smallx, y, smallz), metadata)

        return True, builddata
Ejemplo n.º 14
0
    def update_chunks(self):
        x, chaff, z, chaff = split_coords(self.player.location.x,
            self.player.location.z)

        new = set((i + x, j + z) for i, j in circle)
        old = set(self.chunks.iterkeys())
        added = new - old
        discarded = old - new

        # Perhaps some explanation is in order.
        # The cooperate() 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_tasks:
            for task in self.chunk_tasks:
                try:
                    task.stop()
                except (TaskDone, TaskFailed):
                    pass

        self.chunk_tasks = [cooperate(task) for task in
            (
                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)
        ]
Ejemplo n.º 15
0
    def update_chunks(self):
        x, chaff, z, chaff = split_coords(self.location.x, self.location.z)

        new = set((i + x, j + z) for i, j in circle)
        old = set(self.chunks.iterkeys())
        added = new - old
        discarded = old - new

        # Perhaps some explanation is in order.
        # The cooperate() 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_tasks:
            for task in self.chunk_tasks:
                try:
                    task.stop()
                except (TaskDone, TaskFailed):
                    pass

        self.chunk_tasks = [
            cooperate(task)
            for task in (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)
        ]
Ejemplo n.º 16
0
Archivo: beta.py Proyecto: dequis/bravo
    def position_changed(self):
        x, chaff, z, chaff = split_coords(self.location.x, self.location.z)

        # Inform everybody of our new location.
        packet = make_packet("teleport",
            eid=self.player.eid,
            x=self.location.x * 32,
            y=self.location.y * 32,
            z=self.location.z * 32,
            yaw=int(self.location.theta * 255 / (2 * pi)) % 256,
            pitch=int(self.location.phi * 255 / (2 * pi)) % 256,
        )
        self.factory.broadcast_for_others(packet, self)

        self.update_chunks()

        for entity in self.entities_near(2):
            if entity.name != "Item":
                continue

            if self.player.inventory.add(entity.item, entity.quantity):
                packet = make_packet("collect", eid=entity.eid,
                    destination=self.player.eid)
                self.factory.broadcast(packet)

                packet = make_packet("destroy", eid=entity.eid)
                self.factory.broadcast(packet)

                packet = self.player.inventory.save_to_packet()
                self.transport.write(packet)

                self.factory.destroy_entity(entity)
Ejemplo n.º 17
0
    def build_hook(self, factory, player, builddata):
        bigx, smallx, bigz, smallz = split_coords(builddata.x, builddata.z)
        chunk = factory.world.load_chunk(bigx, bigz)
        block = chunk.get_block((smallx, builddata.y, smallz))

        if block == blocks["snow"].slot:
            # Building any block on snow causes snow to get replaced.
            builddata = builddata._replace(face="+y", y=builddata.y - 1)

        return True, builddata
Ejemplo n.º 18
0
    def set_metadata(self, coords, value):
        """
        Set a block's metadata in an unknown chunk.
        """

        x, y, z = coords

        bigx, smallx, bigz, smallz = split_coords(x, z)
        chunk = self.load_chunk(bigx, bigz)
        chunk.set_metadata((smallx, y, smallz), value)
Ejemplo n.º 19
0
    def get_metadata(self, coords):
        """
        Get a block's metadata from an unknown chunk.
        """

        x, y, z = coords

        bigx, smallx, bigz, smallz = split_coords(x, z)
        chunk = self.load_chunk(bigx, bigz)
        return chunk.get_metadata((smallx, y, smallz))
Ejemplo n.º 20
0
    def build_hook(self, factory, player, builddata):
        bigx, smallx, bigz, smallz = split_coords(builddata.x, builddata.z)
        chunk = factory.world.load_chunk(bigx, bigz)
        block = chunk.get_block((smallx, builddata.y, smallz))

        if block == blocks["snow"].slot:
            # Building any block on snow causes snow to get replaced.
            builddata = builddata._replace(face="+y", y=builddata.y - 1)

        return True, builddata
Ejemplo n.º 21
0
    def decorated(self, coords, *args, **kwargs):
        x, y, z = coords

        bigx, smallx, bigz, smallz = split_coords(x, z)
        d = self.request_chunk(bigx, bigz)

        def cb(chunk):
            return f(self, chunk, (smallx, y, smallz), *args, **kwargs)
        d.addCallback(cb)
        return d
Ejemplo n.º 22
0
    def update_location(self):
        bigx, smallx, bigz, smallz = split_coords(self.player.location.x,
            self.player.location.z)

        chunk = self.chunks[bigx, bigz]

        height = chunk.height_at(smallx, smallz) + 2
        self.player.location.y = height

        packet = self.player.location.save_to_packet()
        self.transport.write(packet)
Ejemplo n.º 23
0
    def decorated(self, coords, *args, **kwargs):
        x, y, z = coords

        bigx, smallx, bigz, smallz = split_coords(x, z)
        d = self.request_chunk(bigx, bigz)

        def cb(chunk):
            return f(self, chunk, (smallx, y, smallz), *args, **kwargs)

        d.addCallback(cb)
        return d
Ejemplo n.º 24
0
    def update_location(self):
        bigx, smallx, bigz, smallz = split_coords(self.location.x,
                                                  self.location.z)

        chunk = self.chunks[bigx, bigz]

        height = chunk.height_at(smallx, smallz) + 2
        self.location.y = height

        packet = self.location.save_to_packet()
        self.transport.write(packet)
Ejemplo n.º 25
0
Archivo: beta.py Proyecto: dequis/bravo
    def send_initial_chunk_and_location(self):
        bigx, smallx, bigz, smallz = split_coords(self.location.x,
                                                  self.location.z)

        # Spawn the 25 chunks in a square around the spawn, *before* spawning
        # the player. Otherwise, there's a funky Beta 1.2 bug which causes the
        # player to not be able to move.
        d = cooperate(
            self.enable_chunk(i, j)
            for i, j in product(xrange(bigx - 3, bigx +
                                       3), xrange(bigz - 3, bigz +
                                                  3))).whenDone()

        # Don't dare send more chunks beyond the initial one until we've
        # spawned.
        d.addCallback(lambda none: self.update_location())
        d.addCallback(lambda none: self.position_changed())
        d.addCallback(lambda none: self.update_chunks())
Ejemplo n.º 26
0
    def build_hook(self, factory, 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.
                return False, builddata
            elif face == "+y":
                # Put +Y signs on signposts. We're fancy that way.
                builddata = builddata._replace(block=blocks["signpost"])
                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)
            chunk = factory.world.load_chunk(bigx, bigz)

            # Let's build a sign!
            s = tile_entities["Sign"]()
            s.x = x
            s.y = y
            s.z = z

            chunk.tiles[x, y, z] = s

            # We handled this build correctly, but the signpost still needs to
            # get placed.
            return True, builddata

        return True, builddata
Ejemplo n.º 27
0
    def send_initial_chunk_and_location(self):
        bigx, smallx, bigz, smallz = split_coords(self.player.location.x,
            self.player.location.z)

        # Spawn the 25 chunks in a square around the spawn, *before* spawning
        # the player. Otherwise, there's a funky Beta 1.2 bug which causes the
        # player to not be able to move.
        d = cooperate(
            self.enable_chunk(i, j)
            for i, j in product(
                xrange(bigx - 3, bigx + 3),
                xrange(bigz - 3, bigz + 3)
            )
        ).whenDone()

        # Don't dare send more chunks beyond the initial one until we've
        # spawned.
        d.addCallback(lambda none: self.update_location())
        d.addCallback(lambda none: self.update_chunks())
Ejemplo n.º 28
0
    def entities_near(self, radius):
        """
        Obtain the entities within a radius of this player.

        Radius is measured in blocks.
        """

        chunk_radius = int(radius // 16 + 1)
        chunkx, chaff, chunkz, chaff = split_coords(self.location.x,
            self.location.z)

        minx = chunkx - chunk_radius
        maxx = chunkx + chunk_radius + 1
        minz = chunkz - chunk_radius
        maxz = chunkz + chunk_radius + 1

        for x, z in product(xrange(minx, maxx), xrange(minz, maxz)):
            chunk = self.chunks[x, z]
            yieldables = [entity for entity in chunk.entities
                if self.location.distance(entity.location) <= radius]
            for i in yieldables:
                yield i
Ejemplo n.º 29
0
Archivo: beta.py Proyecto: dequis/bravo
    def entities_near(self, radius):
        """
        Obtain the entities within a radius of this player.

        Radius is measured in blocks.
        """

        chunk_radius = int(radius // 16 + 1)
        chunkx, chaff, chunkz, chaff = split_coords(self.location.x,
            self.location.z)

        minx = chunkx - chunk_radius
        maxx = chunkx + chunk_radius + 1
        minz = chunkz - chunk_radius
        maxz = chunkz + chunk_radius + 1

        for x, z in product(xrange(minx, maxx), xrange(minz, maxz)):
            chunk = self.chunks[x, z]
            yieldables = [entity for entity in chunk.entities
                if self.location.distance(entity.location) <= radius]
            for i in yieldables:
                yield i
Ejemplo n.º 30
0
    def digging(self, container):
        if container.state != 3:
            return

        if time() - self.last_dig_build_timer < 0.2:
            self.error("You are digging too fast.")

        self.last_dig_build_timer = time()

        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

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

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

        self.factory.flush_chunk(chunk)
Ejemplo n.º 31
0
    def build_hook(self, factory, 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.
                return False, builddata
            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)
            chunk = factory.world.load_chunk(bigx, bigz)

            # Let's build a sign!
            s = Sign(smallx, y, smallz)
            chunk.tiles[smallx, y, smallz] = s

        elif item.slot == blocks["chest"].slot:
            if face == "-x":
                x -= 1
            elif face == "+x":
                x += 1
            elif face == "-y":
                y -= 1
            elif face == "+y":
                y += 1
            elif face == "-z":
                z -= 1
            elif face == "+z":
                z += 1

            bigx, smallx, bigz, smallz = split_coords(x, z)
            chunk = factory.world.load_chunk(bigx, bigz)

            # Not much to do, just tell the chunk about this chest.
            c = Chest(smallx, y, smallz)
            chunk.tiles[smallx, y, smallz] = c

        return True, builddata
Ejemplo n.º 32
0
 def build_hook(self, factory, player, builddata):
     bigx, smallx, bigz, smallz = split_coords(builddata.x, builddata.z)
     chunk = yield factory.world.request_chunk(bigx, bigz)
     self.dig_hook(factory, chunk, smallx, builddata.y, smallz, builddata.block)
     returnValue((True, builddata))
Ejemplo n.º 33
0
    def build_hook(self, factory, 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.
                return False, builddata
            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)
            chunk = factory.world.load_chunk(bigx, bigz)

            # Let's build a sign!
            s = Sign(smallx, y, smallz)
            chunk.tiles[smallx, y, smallz] = s

        elif item.slot == blocks["chest"].slot:
            if face == "-x":
                x -= 1
            elif face == "+x":
                x += 1
            elif face == "-y":
                y -= 1
            elif face == "+y":
                y += 1
            elif face == "-z":
                z -= 1
            elif face == "+z":
                z += 1

            bigx, smallx, bigz, smallz = split_coords(x, z)
            chunk = factory.world.load_chunk(bigx, bigz)

            # Not much to do, just tell the chunk about this chest.
            c = Chest(smallx, y, smallz)
            chunk.tiles[smallx, y, smallz] = c

        return True, builddata
Ejemplo n.º 34
0
 def build_hook(self, factory, player, builddata):
     bigx, smallx, bigz, smallz = split_coords(builddata.x, builddata.z)
     chunk = factory.world.load_chunk(bigx, bigz)
     self.dig_hook(factory, chunk, smallx, builddata.y, smallz,
                   builddata.block)
     return True, builddata
Ejemplo n.º 35
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)
Ejemplo n.º 36
0
    def digging(self, container):
        # XXX several improvements should happen here
        # ~ We should time started and stopped pairs to force clients to
        # slow-break their blocks
        if container.x == -1 and container.z == -1 and container.y == 255:
            # Lala-land dig packet. Discard it for now.
            return

        # Player drops currently holding item/block.
        if (container.state == "dropped" and container.face == "-y"
                and container.x == 0 and container.y == 0
                and container.z == 0):
            i = self.player.inventory
            holding = i.holdables[self.player.equipped]
            if holding:
                primary, secondary, count = holding
                if i.consume((primary, secondary), self.player.equipped):
                    dest = self.location.in_front_of(2)
                    dest.y += 1
                    coords = (int(dest.x * 32) + 16, int(dest.y * 32) + 16,
                              int(dest.z * 32) + 16)
                    self.factory.give(coords, (primary, secondary), 1)

                    # Re-send inventory.
                    packet = self.player.inventory.save_to_packet()
                    self.transport.write(packet)

                    # If no items in this slot are left, this player isn't
                    # holding an item anymore.
                    if i.holdables[self.player.equipped] is None:
                        packet = make_packet("entity-equipment",
                                             eid=self.player.eid,
                                             slot=0,
                                             primary=65535,
                                             secondary=0)
                        self.factory.broadcast_for_others(packet, self)
            return

        if container.state != "stopped":
            # We only care about digs which break blocks.
            return

        if time() - self.last_dig_build_timer < 0.1:
            self.error("You are digging too fast.")

        self.last_dig_build_timer = time()

        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

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

        l = []
        for hook in self.dig_hooks:
            l.append(
                maybeDeferred(hook.dig_hook, self.factory, chunk, smallx,
                              container.y, smallz, oldblock))

        dl = DeferredList(l)
        dl.addCallback(lambda none: self.factory.flush_chunk(chunk))
Ejemplo n.º 37
0
    def digging(self, container):
        # XXX several improvements should happen here
        # ~ We should time started and stopped pairs to force clients to
        # slow-break their blocks
        if container.x == -1 and container.z == -1 and container.y == 255:
            # Lala-land dig packet. Discard it for now.
            return

        # Player drops currently holding item/block.
        if (container.state == "dropped" and container.face == "-y" and
            container.x == 0 and container.y == 0 and container.z == 0):
            i = self.player.inventory
            holding = i.holdables[self.player.equipped]
            if holding:
                primary, secondary, count = holding
                if i.consume((primary, secondary), self.player.equipped):
                    dest = self.location.in_front_of(2)
                    dest.y += 1
                    coords = (int(dest.x * 32) + 16, int(dest.y * 32) + 16,
                        int(dest.z * 32) + 16)
                    self.factory.give(coords, (primary, secondary), 1)

                    # Re-send inventory.
                    packet = self.player.inventory.save_to_packet()
                    self.transport.write(packet)

                    # If no items in this slot are left, this player isn't
                    # holding an item anymore.
                    if i.holdables[self.player.equipped] is None:
                        packet = make_packet("entity-equipment",
                            eid=self.player.eid,
                            slot=0,
                            primary=65535,
                            secondary=0
                        )
                        self.factory.broadcast_for_others(packet, self)
            return

        if container.state != "stopped":
            # We only care about digs which break blocks.
            return

        if time() - self.last_dig_build_timer < 0.1:
            self.error("You are digging too fast.")

        self.last_dig_build_timer = time()

        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

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

        l = []
        for hook in self.dig_hooks:
            l.append(maybeDeferred(hook.dig_hook,
                self.factory, chunk, smallx, container.y, smallz, oldblock))

        dl = DeferredList(l)
        dl.addCallback(lambda none: self.factory.flush_chunk(chunk))
Ejemplo n.º 38
0
 def build_hook(self, factory, player, builddata):
     bigx, smallx, bigz, smallz = split_coords(builddata.x, builddata.z)
     chunk = factory.world.load_chunk(bigx, bigz)
     self.dig_hook(factory, chunk, smallx, builddata.y, smallz,
         builddata.block)
     return True, builddata