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)
def get_damage_packet(self): """ Make a packet representing the current damage on this chunk. This method is not private, but some care should be taken with it, since it wraps some fairly cryptic internal data structures. If this chunk is currently undamaged, this method will return an empty string, which should be safe to treat as a packet. Please check with `is_damaged()` before doing this if you need to optimize this case. To avoid extra overhead, this method should really be used in conjunction with `Factory.broadcast_for_chunk()`. Do not forget to clear this chunk's damage! Callers are responsible for doing this. >>> packet = chunk.get_damage_packet() >>> factory.broadcast_for_chunk(packet, chunk.x, chunk.z) >>> chunk.clear_damage() :returns: str representing a packet """ if len(self.damaged) == 0: return "" elif len(self.damaged) == 1: # Use a single block update packet. x, y, z = next(iter(self.damaged)) index = triplet_to_index((x, y, z)) x += self.x * 16 z += self.z * 16 return make_packet("block", x=x, y=y, z=z, type=self.blocks[index], meta=self.metadata[index]) else: # Use a batch update. coords = [] types = [] metadata = [] for x, y, z in self.damaged: index = triplet_to_index((x, y, z)) # Coordinates are not quite packed in the same system as the # indices for chunk data structures. # Chunk data structures are ((x * 16) + z) * 128) + y, or in # bit-twiddler's parlance, x << 11 | z << 7 | y. However, for # this, we need x << 12 | z << 8 | y, so repack accordingly. packed = x << 12 | z << 8 | y coords.append(packed) types.append(self.blocks[index]) metadata.append(self.metadata[index]) return make_packet("batch", x=self.x, z=self.z, length=len(coords), coords=coords, types=types, metadata=metadata)
def chat(self, container): if container.message.startswith("/"): coiterate( self.transport.write(make_packet("chat", message=line)) for line in self.factory.run_command(container.message[1:]) ) else: message = "<%s> %s" % (self.username, container.message) print message packet = make_packet("chat", message=message) self.factory.broadcast(packet)
def login(self, protocol, container): protocol.username = container.username packet = make_packet("login", protocol=protocol.entity.id, username="", unused="", unknown1=0, unknown2=0) protocol.transport.write(packet) super(OfflineAuthenticator, self).login(protocol, container)
def give(self, coords, block, quantity): """ Spawn a pickup at the specified coordinates. The coordinates need to be in pixels, not blocks. """ x, y, z = coords entity = self.create_entity(x, y, z, block, quantity) packet = make_packet("spawn-pickup", entity=Container(id=entity.id), item=block, count=quantity, x=x, y=y, z=z, yaw=0, pitch=0, roll=0) self.broadcast(packet) packet = make_packet("create", id=entity.id) self.broadcast(packet)
def save_to_packet(self): tag = self.save_to_tag() sio = StringIO.StringIO() tag._render_buffer(sio) packet = make_packet("tile", x=self.x, y=self.y, z=self.z, nbt=sio.getvalue()) return packet
def save_to_packet(self): """ Returns a position/look/flying packet. """ position = Container(x=self.x, y=self.y, z=self.z, stance=self.stance) look = Container(rotation=degrees(self.theta), pitch=self.pitch) flying = Container(flying=self.midair) packet = make_packet("location", position=position, look=look, flying=flying) return packet
def dispatch(self, factory, parameters): # XXX Do save stuff here # Then let's shutdown! message = "Server shutting down." yield message # Use an error packet to kick clients cleanly. packet = make_packet("error", message=message) factory.broadcast(packet) reactor.stop()
def save_to_packet(self): """ Generate a chunk packet. """ array = [chr(i) for i in self.blocks] array += pack_nibbles(self.metadata) array += pack_nibbles(self.lightmap) array += pack_nibbles(self.skylight) packet = make_packet("chunk", x=self.x * 16, y=0, z=self.z * 16, x_size=15, y_size=127, z_size=15, data="".join(array)) return packet
def authenticated(self): self.state = STATE_AUTHENTICATED self.player = Player() self.factory.players[self.username] = self packet = make_packet("chat", message="%s is joining the game..." % self.username) self.factory.broadcast(packet) spawn = self.factory.world.spawn packet = make_packet("spawn", x=spawn[0], y=spawn[1], z=spawn[2]) self.transport.write(packet) self.player.location.x = spawn[0] self.player.location.y = spawn[1] self.player.location.stance = spawn[1] self.player.location.z = spawn[2] tag = self.factory.world.load_player(self.username) if tag: self.player.load_from_tag(tag) packet = self.player.inventory.save_to_packet() self.transport.write(packet) packet = self.player.crafting.save_to_packet() self.transport.write(packet) packet = self.player.armor.save_to_packet() self.transport.write(packet) self.send_initial_chunk_and_location() self.ping_loop = LoopingCall(self.update_ping) self.ping_loop.start(5) self.time_loop = LoopingCall(self.update_time) self.time_loop.start(10) self.update_chunks()
def save_to_packet(self): lc = ListContainer() for item in self.items: if item is None: lc.append(Container(id=-1)) else: lc.append(Container(id=item[0], damage=item[1], count=item[2])) packet = make_packet("inventory", unknown1=self.unknown1, length=len(lc), items=lc) return packet
def enable_chunk(self, x, z): if (x, z) in self.chunks: return chunk = self.factory.world.load_chunk(x, z) packet = make_packet("prechunk", x=x, z=z, enabled=1) self.transport.write(packet) packet = chunk.save_to_packet() self.transport.write(packet) for entity in chunk.tileentities: packet = entity.save_to_packet() #self.transport.write(packet) self.chunks[x, z] = chunk
def handshake(self, protocol, container): packet = make_packet("handshake", username="******") protocol.transport.write(packet) reactor.callLater(0, protocol.challenged)
def update_time(self): packet = make_packet("time", timestamp=int(self.factory.time)) self.transport.write(packet)
def update_ping(self): packet = make_packet("ping") self.transport.write(packet)
def disable_chunk(self, x, z): del self.chunks[x, z] packet = make_packet("prechunk", x=x, z=z, enabled=0) self.transport.write(packet)
def dispatch(self, factory, parameters): message = "[Server] %s" % parameters yield message packet = make_packet("chat", message=message) factory.broadcast(packet)