def test_heading_negative(self): """ Headings shouldn't be negative. Well, they can be, technically, but in Bravo, they should be clamped to the unit circle. """ first = Position(0, 0, 0) second = Position(-1, 0, 0) self.assertTrue(first.heading(second) >= 0)
def test_heading(self): """ The positive Z heading points towards a heading of zero, and the positive X heading points towards three-halves pi. """ first = Position(0, 0, 0) second = Position(0, 0, 1) third = Position(1, 0, 0) self.assertAlmostEqual(first.heading(second), 0) self.assertAlmostEqual(first.heading(third), 3 * math.pi / 2) # Just for fun, this should point between pi and 3pi/2, or 5pi/4. self.assertAlmostEqual(second.heading(third), 5 * math.pi / 4)
def load_player(self, username): fp = self.folder.child("players").child("%s.dat" % username) if not fp.exists(): raise SerializerReadException("%r doesn't exist!" % username) tag = self._read_tag(fp) if not tag: raise SerializerReadException("%r (in %s) is corrupt!" % (username, fp.path)) try: player = Player(username=username) x, y, z = [i.value for i in tag["Pos"].tags] player.location.pos = Position(x, y, z) yaw = tag["Rotation"].tags[0].value pitch = tag["Rotation"].tags[1].value player.location.ori = Orientation.from_degs(yaw, pitch) if "Inventory" in tag: self._load_inventory_from_tag(player.inventory, tag["Inventory"]) except KeyError, e: raise SerializerReadException("%r couldn't be loaded: %s" % (player, e))
def _load_painting_from_tag(self, painting, tag): painting.direction = tag["Dir"].value painting.motive = tag["Motive"].value # Overwrite position with absolute block coordinates of image's # center. Original position seems to be unused. painting.location.pos = Position(tag["TileX"].value, tag["TileY"].value, tag["TileZ"].value)
def chat_command(self, username, parameters): data = self.factory.world.serializer.load_plugin_data("warps") warps = get_locations(data) if len(parameters) == 0: yield "Usage: /warp <warpname>" return location = parameters[0] if location in warps: yield "Teleporting you to %s" % location protocol = self.factory.protocols[username] # An explanation might be necessary. # We are changing the location of the player, but we must # immediately send a new location packet in order to force the # player to appear at the new location. However, before we can do # that, we need to get the chunk loaded for them. This ends up # being the same sequence of events as the initial chunk and # location setup, so we call send_initial_chunk_and_location() # instead of update_location(). l = protocol.player.location x, y, z, yaw, pitch = warps[location] l.pos = Position.from_player(x, y, z) l.ori = Orientation.from_degs(yaw, pitch) protocol.send_initial_chunk_and_location() yield "Teleportation successful!" else: yield "No warp location %s available" % parameters
def test_clamp_void(self): """ Locations in the Void should be clamped to above bedrock. """ self.l.pos = Position(0, -32, 0) self.assertTrue(self.l.clamp()) self.assertEqual(self.l.pos.y, 32)
def test_clamp_stance(self): """ Clamped stance should be 1.62 blocks above the current block. """ self.l.pos = Position(0, 32, 0) self.l.clamp() self.assertAlmostEqual(self.l.stance, 2.62)
def _load_entity_from_tag(self, tag): position = tag["Pos"].tags rotation = tag["Rotation"].tags location = Location() location.pos = Position(position[0].value, position[1].value, position[2].value) location.ori = Orientation.from_degs(rotation[0].value, rotation[1].value) location.grounded = bool(tag["OnGround"]) entity = entities[tag["id"].value](location=location) self._entity_loaders[entity.name](entity, tag) return entity
def chat_command(self, username, parameters): data = self.factory.world.serializer.load_plugin_data("homes") homes = get_locations(data) protocol = self.factory.protocols[username] l = protocol.player.location if username in homes: yield "Teleporting %s home" % username x, y, z, yaw, pitch = homes[username] else: yield "Teleporting %s to spawn" % username x, y, z = self.factory.world.level.spawn yaw, pitch = 0, 0 l.pos = Position.from_player(x, y, z) l.ori = Orientation.from_degs(yaw, pitch) protocol.send_initial_chunk_and_location() yield "Teleportation successful!"
def position(self, container): """ Hook for position packets. """ old_position = self.location.pos position = Position.from_player(container.position.x, container.position.y, container.position.z) self.location.pos = position # Stance is the current jumping position, plus a small offset of # around 0.1. In the Alpha server, it must between 0.1 and 1.65, # or the anti-grounded code kicks the client. self.location.stance = container.position.stance self.grounded(container.grounded) if old_position != position: self.position_changed()
def position(self, container): """ Hook for position packets. """ # Refuse to handle any new position information while we are # relocating. Clients mess this up frequently, and it's fairly racy, # so don't consider this to be exceptional. Just ignore this one # packet and continue. if self.state != STATE_LOCATED: return self.grounded(container.grounded) old_position = self.location.pos position = Position.from_player(container.position.x, container.position.y, container.position.z) altered = False dx, dy, dz = old_position - position if any(abs(d) >= 64 for d in (dx, dy, dz)): # Whoa, slow down there, cowboy. You're moving too fast. We're # gonna ignore this position change completely, because it's # either bogus or ignoring a recent teleport. altered = True else: self.location.pos = position self.location.stance = container.position.stance # Santitize location. This handles safety boundaries, illegal stance, # etc. altered = self.location.clamp() or altered # If, for any reason, our opinion on where the client should be # located is different than theirs, force them to conform to our point # of view. if altered: log.msg("Not updating bogus position!") self.update_location() # If our position actually changed, fire the position change hook. if old_position != position: self.position_changed()
def test_to_player(self): p = Position(-32, 32, 48) self.assertEqual(p.to_player(), (-1.0, 1.0, 1.5))
def test_distance(self): first = Position(0, 0, 0) second = Position(2, 3, 6) self.assertEqual(first.distance(second), 7)
def test_from_player(self): p = Position.from_player(2.5, 3.0, -1.0) self.assertEqual(p, (80, 96, -32))
def test_add_in_place(self): p = Position(1, 2, 3) p += Position(4, 5, 6) self.assertEqual(p, Position(5, 7, 9))
def test_to_block(self): p = Position(-32, 32, 48) self.assertEqual(p.to_block(), (-1, 1, 1))
def test_add(self): first = Position(1, 2, 3) second = Position(4, 5, 6) self.assertEqual(first + second, Position(5, 7, 9))