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)
def make_packet(self): if self.weather == "rainy": return make_packet("state", state="start_rain") elif self.weather == "sunny": return make_packet("state", state="stop_rain") else: return ""
def chat(self, container): if container.message.startswith("/"): commands = retrieve_plugins(IChatCommand) # Register aliases. for plugin in commands.values(): for alias in plugin.aliases: commands[alias] = plugin params = container.message[1:].split(" ") command = params.pop(0).lower() if command and command in commands: try: for line in commands[command].chat_command(self.factory, self.username, params): self.transport.write( make_packet("chat", message=line) ) except Exception, e: self.transport.write( make_packet("chat", message="Error: %s" % e) ) else: self.transport.write( make_packet("chat", message="Unknown command: %s" % command) )
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)
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() :rtype: str :returns: String representation of the packet. """ if self.all_damaged: # Resend the entire chunk! return self.save_to_packet() elif not self.damaged.any(): return "" elif self.damaged.sum() == 1: # Use a single block update packet. x, z, y = [int(i) for i in zip(*self.damaged.nonzero())[0]] return make_packet("block", x=x + self.x * 16, y=y, z=z + self.z * 16, type=int(self.blocks[x, z, y]), meta=int(self.metadata[x, z, y])) else: # Use a batch update. damaged = self.damaged.nonzero() # 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. coords = [int(x << 12 | z << 8 | y) for x, z, y in zip(*damaged)] types = [int(i) for i in self.blocks[damaged]] metadata = [int(i) for i in self.metadata[damaged]] return make_packet("batch", x=self.x, z=self.z, length=len(coords), coords=coords, types=types, metadata=metadata)
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() :rtype: str :returns: String representation of the packet. """ if self.all_damaged: # Resend the entire chunk! return self.save_to_packet() elif not self.damaged.any(): return "" elif self.damaged.sum() == 1: # Use a single block update packet. x, z, y = [int(i) for i in zip(*self.damaged.nonzero())[0]] return make_packet( "block", x=x + self.x * 16, y=y, z=z + self.z * 16, type=int(self.blocks[x, z, y]), meta=int(self.metadata[x, z, y]), ) else: # Use a batch update. damaged = self.damaged.nonzero() # 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. coords = [int(x << 12 | z << 8 | y) for x, z, y in zip(*damaged)] types = [int(i) for i in self.blocks[damaged]] metadata = [int(i) for i in self.metadata[damaged]] return make_packet( "batch", x=self.x, z=self.z, length=len(coords), coords=coords, types=types, metadata=metadata )
def disable_chunk(self, x, z): # Remove the chunk from cache. chunk = self.chunks.pop(x, z) for entity in chunk.entities: packet = make_packet("destroy", eid=entity.eid) self.transport.write(packet) packet = make_packet("prechunk", x=x, z=z, enabled=0) self.transport.write(packet)
def chat_command(self, username, parameters): from bravo.packets.beta import make_packet arg = "".join(parameters) if arg == "start": factory.broadcast(make_packet("state", state="start_rain")) elif arg == "stop": factory.broadcast(make_packet("state", state="stop_rain")) else: return ("Couldn't understand you!",) return ("*%s did the rain dance*" % (username),)
def packets_for_dirty(self, dirty_slots): """ Generate update packets for dirty usually privided by another window (sic!) """ packets = "" for slot, item in dirty_slots.iteritems(): if item is None: packets += make_packet("window-slot", wid=self.wid, slot=slot, primary=-1) else: packets += make_packet("window-slot", wid=self.wid, slot=slot, primary=item.primary, secondary=item.secondary, count=item.quantity) return packets
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())
def use_hook(self, factory, player, target, button): # Block coordinates. x, y, z = target.location.x, target.location.y, target.location.z # Offset coords according to direction. A painting does not # occupy a block, therefore we drop the pickup right in front of the # block it is attached to. face = direction_to_face[target.direction] if face == "-x": x -= 1 elif face == "+x": x += 1 elif face == "-z": z -= 1 elif face == "+z": z += 1 # Pixel coordinates. coords = (x * 32 + 16, y * 32, z * 32 + 16) factory.destroy_entity(target) factory.give(coords, (items["paintings"].slot, 0), 1) packet = make_packet("destroy", eid=target.eid) factory.broadcast(packet) # Force the chunk (with its entities) to be saved to disk. factory.world.mark_dirty((x, y, z))
def save_to_packet(self): """ Create a "player" packet representing this entity. """ yaw = int(self.location.theta * 255 / (2 * pi)) % 256 pitch = int(self.location.phi * 255 / (2 * pi)) % 256 item = self.inventory.holdables[self.equipped] if item is None: item = 0 else: item = item[0] return make_packet( "player", eid=self.eid, username=self.username, x=self.location.x, y=self.location.y, z=self.location.z, yaw=yaw, pitch=pitch, item=item, )
def connectionLost(self, reason): if self.time_loop: self.time_loop.stop() if self.chunk_tasks: for task in self.chunk_tasks: try: task.stop() except (TaskDone, TaskFailed): pass if self.player: self.factory.world.save_player(self.username, self.player) self.factory.destroy_entity(self.player) packet = make_packet("destroy", eid=self.player.eid) self.factory.broadcast(packet) self.factory.chat("%s has left the game." % self.username) if self.username in self.factory.protocols: del self.factory.protocols[self.username] self.factory.connectedIPs[self.host] -= 1 if self.factory.connectedIPs[self.host] <= 0: del self.factory.connectedIPs[self.host]
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)
def chat(self, container): if container.message.startswith("/"): pp = {"factory": self.factory} commands = retrieve_plugins(IChatCommand, parameters=pp) # Register aliases. for plugin in commands.values(): for alias in plugin.aliases: commands[alias] = plugin params = container.message[1:].split(" ") command = params.pop(0).lower() if command and command in commands: def cb(iterable): for line in iterable: self.transport.write(make_packet("chat", message=line)) def eb(error): self.transport.write(make_packet("chat", message="Error: %s" % error.getErrorMessage())) d = maybeDeferred(commands[command].chat_command, self.username, params) d.addCallback(cb) d.addErrback(eb) else: self.transport.write(make_packet("chat", message="Unknown command: %s" % command)) else: # Send the message up to the factory to be chatified. message = "<%s> %s" % (self.username, container.message) self.factory.chat(message)
def update_ping(self): """ Send a keepalive to the client. """ packet = make_packet("ping") self.transport.write(packet)
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())
def give(self, coords, block, quantity): """ Spawn a pickup at the specified coordinates. The coordinates need to be in pixels, not blocks. If the size of the stack is too big, multiple stacks will be dropped. :param tuple coords: coordinates, in pixels :param tuple block: key of block or item to drop :param int quantity: number of blocks to drop in the stack """ x, y, z = coords while quantity > 0: entity = self.create_entity(x // 32, y // 32, z // 32, "Item", item=block, quantity=min(quantity, 64)) packet = entity.save_to_packet() packet += make_packet("create", eid=entity.eid) self.broadcast(packet) quantity -= 64
def animate(self, container): # Broadcast the animation of the entity to everyone else. Only swing # arm is send by notchian clients. packet = make_packet("animate", eid=self.player.eid, animation=container.animation) self.factory.broadcast_for_others(packet, self)
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 orientation_changed(self): # Bang your head! packet = make_packet("entity-orientation", eid=self.player.eid, 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)
def animate(self, container): # Broadcast the animation of the entity to everyone else. Only swing # arm is send by notchian clients. packet = make_packet("animate", eid=self.player.eid, animation=container.animation ) self.factory.broadcast_for_others(packet, self)
def waction(self, container): if container.wid == 0: # Inventory. i = self.player.inventory elif container.wid in self.windows: i = self.windows[container.wid] else: self.error("Couldn't find window %d" % container.wid) selected = i.select(container.slot, bool(container.button), bool(container.shift)) if selected: # XXX should be if there's any damage to the inventory packet = i.save_to_packet() self.transport.write(packet) # Inform other players about changes to this player's equipment. if container.wid == 0 and (container.slot in range(5, 9) or container.slot == 36): # Armor changes. if container.slot in range(5, 9): item = i.armor[container.slot - 5] # Order of slots is reversed in the equipment package. slot = 4 - (container.slot - 5) # Currently equipped item changes. elif container.slot == 36: item = i.holdables[0] slot = 0 if item is None: primary, secondary = 65535, 0 else: primary, secondary, count = item packet = make_packet("entity-equipment", eid=self.player.eid, slot=slot, primary=primary, secondary=secondary ) self.factory.broadcast_for_others(packet, self) packet = make_packet("window-token", wid=0, token=container.token, acknowledged=selected) self.transport.write(packet)
def waction(self, container): if container.wid == 0: # Inventory. i = self.player.inventory elif container.wid in self.windows: i = self.windows[container.wid] else: self.error("Couldn't find window %d" % container.wid) selected = i.select(container.slot, bool(container.button)) if selected: # XXX should be if there's any damage to the inventory packet = i.save_to_packet() self.transport.write(packet) # Inform other players about changes to this player's equipment. if container.wid == 0 and (container.slot in range(5, 9) or container.slot == 36): # Armor changes. if container.slot in range(5, 9): item = i.armor[container.slot - 5] # Order of slots is reversed in the equipment package. slot = 4 - (container.slot - 5) # Currently equipped item changes. elif container.slot == 36: item = i.holdables[0] slot = 0 if item is None: primary, secondary = 65535, 0 else: primary, secondary, count = item packet = make_packet("entity-equipment", eid=self.player.eid, slot=slot, primary=primary, secondary=secondary) self.factory.broadcast_for_others(packet, self) packet = make_packet("window-token", wid=0, token=container.token, acknowledged=selected) self.transport.write(packet)
def authenticated(self): BetaServerProtocol.authenticated(self) # Init player, and copy data into it. self.player = yield self.factory.world.load_player(self.username) self.player.eid = self.eid self.location = self.player.location # Init players' inventory window. self.inventory = InventoryWindow(self.player.inventory) # Announce our presence. packet = make_packet("chat", message="%s is joining the game..." % self.username) self.factory.broadcast(packet) # Craft our avatar and send it to already-connected other players. packet = self.player.save_to_packet() packet += make_packet("create", eid=self.player.eid) self.factory.broadcast_for_others(packet, self) # And of course spawn all of those players' avatars in our client as # well. Note that, at this point, we are not listed in the factory's # list of protocols, so we won't accidentally send one of these to # ourselves. for protocol in self.factory.protocols.itervalues(): packet = protocol.player.save_to_packet() packet += protocol.player.save_equipment_to_packet() self.transport.write(packet) self.write_packet("create", eid=protocol.player.eid) self.factory.protocols[self.username] = self # Send spawn and inventory. spawn = self.factory.world.spawn packet = make_packet("spawn", x=spawn[0], y=spawn[1], z=spawn[2]) packet += self.inventory.save_to_packet() self.transport.write(packet) # Send weather. self.transport.write(self.factory.vane.make_packet()) self.send_initial_chunk_and_location() self.time_loop = LoopingCall(self.update_time) self.time_loop.start(10)
def login(self, protocol, container): protocol.username = container.username packet = make_packet("login", protocol=protocol.eid, username="", seed=protocol.factory.world.seed, dimension=protocol.factory.world.dimension) protocol.transport.write(packet) return succeed(None)
def login(self, container): self.username = container.username packet = make_packet("login", protocol=0, username="", seed=0, dimension="earth") self.transport.write(packet) url = urlunparse(("http", self.gateway, "/node/0/0/", None, None, None)) d = getPage(url) d.addCallback(self.start_proxy)
def save_to_packet(self): return make_packet("painting", eid=self.eid, title=self.motive, x=self.location.x, y=self.location.y, z=self.location.z, direction=self.direction )
def orientation_changed(self): # Bang your head! packet = make_packet( "entity-orientation", eid=self.player.eid, 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)
def dispatch(self, factory, parameters): player = parse_player(factory, parameters[0]) if len(parameters) == 1: msg = "%s has been kicked." % parameters[0] elif len(parameters) > 1: reason = " ".join(parameters[1:]) msg = "%s has been kicked for %s" % (parameters[0],reason) packet = make_packet("error", message=msg) player.transport.write(packet) yield msg
def success(self, response, protocol, container): if response != "YES": protocol.error("Authentication server didn't like you.") return packet = make_packet("login", protocol=protocol.eid, username="", seed=protocol.factory.world.seed, dimension=protocol.factory.world.dimension) protocol.transport.write(packet)
def dispatch(self, factory, parameters): player = parse_player(factory, parameters[0]) if len(parameters) == 1: msg = "%s has been kicked." % parameters[0] elif len(parameters) > 1: reason = " ".join(parameters[1:]) msg = "%s has been kicked for %s" % (parameters[0], reason) packet = make_packet("error", message=msg) player.transport.write(packet) yield msg
def save_to_packet(self): """ Generate a chunk packet. """ array = self.blocks.tostring() array += pack_nibbles(self.metadata) array += pack_nibbles(self.blocklight) 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=array) return packet
def save_to_packet(self): return make_packet("mob", eid=self.eid, type=self.type, x=self.location.x * 32 + 16, y=self.location.y * 32, z=self.location.z * 32 + 16, yaw=0, pitch=0, metadata=self.metadata )
def save_to_packet(self): lc = ListContainer() for item in chain(*self.metalist): if item is None: lc.append(Container(primary=-1)) else: lc.append(Container(primary=item.primary, secondary=item.secondary, count=item.quantity)) packet = make_packet("inventory", wid=self.wid, length=len(lc), items=lc) return packet
def authenticated(self): BetaServerProtocol.authenticated(self) # Init player, and copy data into it. self.player = yield self.factory.world.load_player(self.username) self.player.eid = self.eid self.location = self.player.location # Announce our presence. packet = make_packet("chat", message="%s is joining the game..." % self.username) self.factory.broadcast(packet) # Craft our avatar and send it to already-connected other players. packet = self.player.save_to_packet() packet += make_packet("create", eid=self.player.eid) self.factory.broadcast_for_others(packet, self) # And of course spawn all of those players' avatars in our client as # well. Note that, at this point, we are not listed in the factory's # list of protocols, so we won't accidentally send one of these to # ourselves. for protocol in self.factory.protocols.itervalues(): packet = protocol.player.save_to_packet() packet += protocol.player.save_equipment_to_packet() packet += make_packet("create", eid=protocol.player.eid) self.transport.write(packet) self.factory.protocols[self.username] = self # Send spawn and inventory. spawn = self.factory.world.spawn packet = make_packet("spawn", x=spawn[0], y=spawn[1], z=spawn[2]) packet += self.player.inventory.save_to_packet() self.transport.write(packet) self.send_initial_chunk_and_location() self.time_loop = LoopingCall(self.update_time) self.time_loop.start(10)
def equip(self, container): self.player.equipped = container.item # Inform everyone about the item the player is holding now. item = self.player.inventory.holdables[self.player.equipped] if item is None: # Empty slot. Use signed short -1 == unsigned 65535. primary, secondary = 65535, 0 else: primary, secondary, count = item packet = make_packet("entity-equipment", eid=self.player.eid, slot=0, primary=primary, secondary=secondary) self.factory.broadcast_for_others(packet, self)
def save_to_packet(self): """ Create a "painting" packet representing this entity. """ return make_packet("painting", eid=self.eid, title=self.motive, x=self.location.x, y=self.location.y, z=self.location.z, direction=self.direction )
def save_to_packet(self): return make_packet("pickup", eid=self.eid, primary=self.item[0], secondary=self.item[1], count=self.quantity, x=self.location.x * 32 + 16, y=self.location.y * 32, z=self.location.z * 32 + 16, yaw=0, pitch=0, roll=0 )
def login(self, container): self.username = container.username packet = make_packet("login", protocol=0, username="", seed=0, dimension=0) self.transport.write(packet) url = urlunparse( ("http", self.gateway, "/node/0/0/", None, None, None)) d = getPage(url) d.addCallback(self.start_proxy)
def handshake(self, protocol, container): """ Handle a handshake with an online challenge. """ challenge = "%x" % random.randint(0, sys.maxint) self.challenges[protocol] = challenge packet = make_packet("handshake", username=challenge) d = deferLater(reactor, 0, protocol.challenged) d.addCallback(lambda none: protocol.transport.write(packet)) return True
def console_command(self, factory, parameters): # 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) yield "Saving all chunks to disk..." for chunk in factory.world.dirty_chunk_cache.itervalues(): factory.world.save_chunk(chunk) yield "Halting." reactor.stop()
def login(self, protocol, container): if container.password != configuration.get("bravo", "password"): protocol.error("Wrong password.") return fail() protocol.username = container.username packet = make_packet("login", protocol=protocol.eid, username="", seed=protocol.factory.world.seed, dimension=protocol.factory.world.dimension) protocol.transport.write(packet) return succeed(None)
def chat(self, container): if container.message.startswith("/"): commands = retrieve_plugins(IChatCommand) # Register aliases. for plugin in commands.values(): for alias in plugin.aliases: commands[alias] = plugin params = container.message[1:].split(" ") command = params.pop(0).lower() if command and command in commands: try: for line in commands[command].chat_command( self.factory, self.username, params): self.transport.write(make_packet("chat", message=line)) except Exception, e: self.transport.write( make_packet("chat", message="Error: %s" % e)) else: self.transport.write( make_packet("chat", message="Unknown command: %s" % command))
def save_to_packet(self): """ Returns a position/look/grounded packet. """ position = Container(x=self.x, y=self.stance, z=self.z, stance=self.y) orientation = Container(rotation=self.yaw, pitch=self.pitch) grounded = Container(grounded=self.grounded) packet = make_packet("location", position=position, orientation=orientation, grounded=grounded) return packet
def save_to_packet(self): # Prepare metadata. metadata = self.metadata.copy() metadata[16] = "byte", self.size return make_packet("mob", eid=self.eid, type="slime", x=self.location.x * 32 + 16, y=self.location.y * 32, z=self.location.z * 32 + 16, yaw=0, pitch=0, metadata=self.metadata )
def handshake(self, protocol, container): """ Handle a handshake with a server-specific password. This doesn't work with Notchian clients. """ packet = make_packet("handshake", username="******") # Order is important here; the challenged callback *must* fire before # we send anything back to the client, because otherwise we won't have # a valid entity ready to use. d = deferLater(reactor, 0, protocol.challenged) d.addCallback(lambda none: protocol.transport.write(packet)) return True
def handshake(self, protocol, container): """ Handle a handshake with an offline challenge. This will authenticate just about anybody. """ packet = make_packet("handshake", username="******") # Order is important here; the challenged callback *must* fire before # we send anything back to the client, because otherwise we won't have # a valid entity ready to use. d = deferLater(reactor, 0, protocol.challenged) d.addCallback(lambda none: protocol.transport.write(packet)) return True
def send_chunk(self, chunk): packet = make_packet("prechunk", x=chunk.x, z=chunk.z, enabled=1) self.transport.write(packet) packet = chunk.save_to_packet() self.transport.write(packet) for entity in chunk.entities: packet = entity.save_to_packet() self.transport.write(packet) for entity in chunk.tiles.itervalues(): if entity.name == "Sign": packet = entity.save_to_packet() self.transport.write(packet) self.chunks[chunk.x, chunk.z] = chunk
def chat(self, message): """ Relay chat messages. Chat messages are sent to all connected clients, as well as to anybody consuming this factory. """ for consumer in self.chat_consumers: consumer.write((self, message)) # Prepare the message for chat packeting. for user in self.protocols: message = message.replace(user, chat_name(user)) message = sanitize_chat(message) packet = make_packet("chat", message=message) self.broadcast(packet)