コード例 #1
0
    def console_command(self, parameters):
        wanted = " ".join(parameters)
        if wanted == "spring":
            season = Spring()
        elif wanted == "winter":
            season = Winter()
        else:
            yield "Couldn't find season %s" % wanted
            return

        msg = "Changing season to %s..." % wanted
        yield msg
        self.factory.day = season.day
        self.factory.update_season()
        yield "Season successfully changed!"
コード例 #2
0
ファイル: test_seasons.py プロジェクト: dkkline/bravo
class TestWinter(unittest.TestCase):

    def setUp(self):
        self.hook = Winter()
        self.c = Chunk(0, 0)

    def test_trivial(self):
        pass

    def test_spring_to_ice(self):
        self.c.set_block((0, 0, 0), blocks["spring"].slot)
        self.hook.transform(self.c)
        self.assertEqual(self.c.get_block((0, 0, 0)), blocks["ice"].slot)

    def test_snow_on_stone(self):
        self.c.set_block((0, 0, 0), blocks["stone"].slot)
        self.hook.transform(self.c)
        self.assertEqual(self.c.get_block((0, 1, 0)), blocks["snow"].slot)

    def test_no_snow_on_snow(self):
        """
        Test whether snow is spawned on top of other snow.
        """

        self.c.set_block((0, 0, 0), blocks["snow"].slot)
        self.hook.transform(self.c)
        self.assertNotEqual(self.c.get_block((0, 1, 0)), blocks["snow"].slot)

    def test_no_floating_snow(self):
        """
        Test whether snow is spawned in the correct y-level over populated
        chunks.
        """

        self.c.set_block((0, 0, 0), blocks["grass"].slot)
        self.c.populated = True
        self.c.dirty = False
        self.c.clear_damage()
        self.hook.transform(self.c)
        self.assertEqual(self.c.get_block((0, 1, 0)), blocks["snow"].slot)
        self.assertNotEqual(self.c.get_block((0, 2, 0)), blocks["snow"].slot)

    def test_bad_heightmap_floating_snow(self):
        """
        Test whether snow is spawned in the correct y-level over populated
        chunks, if the heightmap is incorrect.
        """

        self.c.set_block((0, 0, 0), blocks["grass"].slot)
        self.c.populated = True
        self.c.dirty = False
        self.c.clear_damage()
        self.c.heightmap[0 * 16 + 0] = 2
        self.hook.transform(self.c)
        self.assertEqual(self.c.get_block((0, 1, 0)), blocks["snow"].slot)
        self.assertNotEqual(self.c.get_block((0, 2, 0)), blocks["snow"].slot)

    def test_top_of_world_snow(self):
        """
        Blocks at the top of the world should not cause exceptions when snow
        is placed on them.
        """

        self.c.set_block((0, 127, 0), blocks["stone"].slot)
        self.hook.transform(self.c)
コード例 #3
0
ファイル: test_seasons.py プロジェクト: dkkline/bravo
 def setUp(self):
     self.hook = Winter()
     self.c = Chunk(0, 0)
コード例 #4
0
ファイル: factory.py プロジェクト: tazjel/bravo
class BravoFactory(Factory):
    """
    A ``Factory`` that creates ``BravoProtocol`` objects when connected to.
    """

    implements(IPushProducer)

    protocol = BravoProtocol

    timestamp = None
    time = 0
    day = 0
    eid = 1

    interfaces = []

    def __init__(self, config, name):
        """
        Create a factory and world.

        ``name`` is the string used to look up factory-specific settings from
        the configuration.

        :param str name: internal name of this factory
        """

        self.name = name
        self.config = config
        self.config_name = "world %s" % name

        self.world = World(self.config, self.name)
        self.world.factory = self

        self.protocols = dict()
        self.connectedIPs = defaultdict(int)

        self.mode = self.config.get(self.config_name, "mode")
        if self.mode not in ("creative", "survival"):
            raise Exception("Unsupported mode %s" % self.mode)

        self.limitConnections = self.config.getintdefault(
            self.config_name, "limitConnections", 0)
        self.limitPerIP = self.config.getintdefault(self.config_name,
                                                    "limitPerIP", 0)

        self.vane = WeatherVane(self)

    def startFactory(self):
        log.msg("Initializing factory for world '%s'..." % self.name)

        # Get our plugins set up.
        self.register_plugins()

        log.msg("Starting world...")
        self.world.start()

        # Start up the permanent cache.
        # has_option() is not exactly desirable, but it's appropriate here
        # because we don't want to take any action if the key is unset.
        if self.config.has_option(self.config_name, "perm_cache"):
            cache_level = self.config.getint(self.config_name, "perm_cache")
            self.world.enable_cache(cache_level)

        log.msg("Starting timekeeping...")
        self.timestamp = reactor.seconds()
        self.time = self.world.level.time
        self.update_season()
        self.time_loop = LoopingCall(self.update_time)
        self.time_loop.start(2)

        log.msg("Starting entity updates...")

        # Start automatons.
        for automaton in self.automatons:
            automaton.start()

        self.chat_consumers = set()

        log.msg("Factory successfully initialized for world '%s'!" % self.name)

    def stopFactory(self):
        """
        Called before factory stops listening on ports. Used to perform
        shutdown tasks.
        """

        log.msg("Shutting down world...")

        # Stop automatons. Technically, they may not actually halt until their
        # next iteration, but that is close enough for us, probably.
        # Automatons are contracted to not access the world after stop() is
        # called.
        for automaton in self.automatons:
            automaton.stop()

        # Evict plugins as soon as possible. Can't be done before stopping
        # automatons.
        self.unregister_plugins()

        self.time_loop.stop()

        # Write back current world time. This must be done before stopping the
        # world.
        self.world.time = self.time

        # And now stop the world.
        self.world.stop()

        log.msg("World data saved!")

    def buildProtocol(self, addr):
        """
        Create a protocol.

        This overriden method provides early player entity registration, as a
        solution to the username/entity race that occurs on login.
        """

        banned = self.world.serializer.load_plugin_data("banned_ips")

        # Do IP bans first.
        for ip in banned.split():
            if addr.host == ip:
                # Use KickedProtocol with extreme prejudice.
                log.msg("Kicking banned IP %s" % addr.host)
                p = KickedProtocol("Sorry, but your IP address is banned.")
                p.factory = self
                return p

        # We are ignoring values less that 1, but making sure not to go over
        # the connection limit.
        if (self.limitConnections
                and len(self.protocols) >= self.limitConnections):
            log.msg("Reached maximum players, turning %s away." % addr.host)
            p = KickedProtocol("The player limit has already been reached."
                               " Please try again later.")
            p.factory = self
            return p

        # Do our connection-per-IP check.
        if (self.limitPerIP
                and self.connectedIPs[addr.host] >= self.limitPerIP):
            log.msg("At maximum connections for %s already, dropping." %
                    addr.host)
            p = KickedProtocol(
                "There are too many players connected from this IP.")
            p.factory = self
            return p
        else:
            self.connectedIPs[addr.host] += 1

        # If the player wasn't kicked, let's continue!
        log.msg("Starting connection for %s" % addr)
        p = self.protocol(self.config, self.name)
        p.host = addr.host
        p.factory = self

        self.register_entity(p)

        # Copy our hooks to the protocol.
        p.register_hooks()

        return p

    def teardown_protocol(self, protocol):
        """
        Do internal bookkeeping on behalf of a protocol which has been
        disconnected.

        Did you know that "bookkeeping" is one of the few words in English
        which has three pairs of double letters in a row?
        """

        username = protocol.username
        host = protocol.host

        if username in self.protocols:
            del self.protocols[username]

        self.connectedIPs[host] -= 1

    def set_username(self, protocol, username):
        """
        Attempt to set a new username for a protocol.

        :returns: whether the username was changed
        """

        # If the username's already taken, refuse it.
        if username in self.protocols:
            return False

        if protocol.username in self.protocols:
            # This protocol's known under another name, so remove it.
            del self.protocols[protocol.username]

        # Set the username.
        self.protocols[username] = protocol
        protocol.username = username

        return True

    def register_plugins(self):
        """
        Setup plugin hooks.
        """

        log.msg("Registering client plugin hooks...")

        plugin_types = {
            "automatons": IAutomaton,
            "generators": ITerrainGenerator,
            "open_hooks": IWindowOpenHook,
            "click_hooks": IWindowClickHook,
            "close_hooks": IWindowCloseHook,
            "pre_build_hooks": IPreBuildHook,
            "post_build_hooks": IPostBuildHook,
            "pre_dig_hooks": IPreDigHook,
            "dig_hooks": IDigHook,
            "sign_hooks": ISignHook,
            "use_hooks": IUseHook,
        }

        packs = self.config.getlistdefault(self.config_name, "packs", [])
        try:
            packs = [available_packs[pack] for pack in packs]
        except KeyError, e:
            raise Exception("Couldn't find plugin pack %s" % e.args)

        for t, interface in plugin_types.iteritems():
            l = self.config.getlistdefault(self.config_name, t, [])

            # Grab extra plugins from the pack. Order doesn't really matter
            # since the plugin loader sorts things anyway.
            for pack in packs:
                if t in pack:
                    l += pack[t]

            # Hax. :T
            if t == "generators":
                plugins = retrieve_sorted_plugins(interface, l)
            elif issubclass(interface, ISortedPlugin):
                plugins = retrieve_sorted_plugins(interface, l, factory=self)
            else:
                plugins = retrieve_named_plugins(interface, l, factory=self)
            log.msg("Using %s: %s" %
                    (t.replace("_", " "), ", ".join(plugin.name
                                                    for plugin in plugins)))
            setattr(self, t, plugins)

        # Deal with seasons.
        seasons = self.config.getlistdefault(self.config_name, "seasons", [])
        for pack in packs:
            if "seasons" in pack:
                seasons += pack["seasons"]
        self.seasons = []
        if "spring" in seasons:
            self.seasons.append(Spring())
        if "winter" in seasons:
            self.seasons.append(Winter())

        # Assign generators to the world pipeline.
        self.world.pipeline = self.generators

        # Use hooks have special funkiness.
        uh = self.use_hooks
        self.use_hooks = defaultdict(list)
        for plugin in uh:
            for target in plugin.targets:
                self.use_hooks[target].append(plugin)
コード例 #5
0
class TestWinter(unittest.TestCase):

    def setUp(self):
        self.hook = Winter()
        self.c = Chunk(0, 0)

    def test_trivial(self):
        pass

    def test_spring_to_ice(self):
        self.c.set_block((0, 0, 0), blocks["spring"].slot)
        self.hook.transform(self.c)
        self.assertEqual(self.c.get_block((0, 0, 0)), blocks["ice"].slot)

    def test_snow_on_stone(self):
        self.c.set_block((0, 0, 0), blocks["stone"].slot)
        self.hook.transform(self.c)
        self.assertEqual(self.c.get_block((0, 1, 0)), blocks["snow"].slot)

    def test_no_snow_on_snow(self):
        """
        Test whether snow is spawned on top of other snow.
        """

        self.c.set_block((0, 0, 0), blocks["snow"].slot)
        self.hook.transform(self.c)
        self.assertNotEqual(self.c.get_block((0, 1, 0)), blocks["snow"].slot)

    def test_no_floating_snow(self):
        """
        Test whether snow is spawned in the correct y-level over populated
        chunks.
        """

        self.c.set_block((0, 0, 0), blocks["grass"].slot)
        self.c.populated = True
        self.c.dirty = False
        self.c.clear_damage()
        self.hook.transform(self.c)
        self.assertEqual(self.c.get_block((0, 1, 0)), blocks["snow"].slot)
        self.assertNotEqual(self.c.get_block((0, 2, 0)), blocks["snow"].slot)

    def test_bad_heightmap_floating_snow(self):
        """
        Test whether snow is spawned in the correct y-level over populated
        chunks, if the heightmap is incorrect.
        """

        self.c.set_block((0, 0, 0), blocks["grass"].slot)
        self.c.populated = True
        self.c.dirty = False
        self.c.clear_damage()
        self.c.heightmap[0 * 16 + 0] = 2
        self.hook.transform(self.c)
        self.assertEqual(self.c.get_block((0, 1, 0)), blocks["snow"].slot)
        self.assertNotEqual(self.c.get_block((0, 2, 0)), blocks["snow"].slot)

    def test_top_of_world_snow(self):
        """
        Blocks at the top of the world should not cause exceptions when snow
        is placed on them.
        """

        self.c.set_block((0, 127, 0), blocks["stone"].slot)
        self.hook.transform(self.c)
コード例 #6
0
 def setUp(self):
     self.hook = Winter()
     self.c = Chunk(0, 0)