def __init__(self): BetaServerProtocol.__init__(self) log.msg("Registering client hooks...") names = configuration.getlist("bravo", "build_hooks") self.build_hooks = retrieve_named_plugins(IBuildHook, names) names = configuration.getlist("bravo", "dig_hooks") self.dig_hooks = retrieve_named_plugins(IDigHook, names) self.last_dig_build_timer = time()
def __init__(self, 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 """ log.msg("Initializing factory for world '%s'..." % name) self.name = name self.port = configuration.getint("world %s" % name, "port") if configuration.has_option("world %s" % name, "host"): self.interface = configuration.get("world %s" % name, "host") world_folder = configuration.get("world %s" % name, "path") self.world = World(world_folder) self.world.factory = self if configuration.has_option("world %s" % name, "perm_cache"): cache_level = configuration.getint("world %s" % name, "perm_cache") self.world.enable_cache(cache_level) self.protocols = dict() self.eid = 1 self.entities = set() self.time_loop = LoopingCall(self.update_time) self.time_loop.start(2) authenticator = configuration.get("world %s" % name, "authenticator") selected = retrieve_named_plugins(IAuthenticator, [authenticator])[0] log.msg("Using authenticator %s" % selected.name) self.handshake_hook = selected.handshake self.login_hook = selected.login generators = configuration.getlist("bravo", "generators") generators = retrieve_named_plugins(ITerrainGenerator, generators) log.msg("Using generators %s" % ", ".join(i.name for i in generators)) self.world.pipeline = generators self.chat_consumers = set() log.msg("Factory successfully initialized for world '%s'!" % name)
def __init__(self, config): self.channels = config['channels'] self.nickname = config['nickname'] self.config = config self.history = {} self.plugins = { 'base_plugin': [], 'presence': [], 'chat': [], 'population': [], } if 'db' in config: print('Loading db from config: ' + config['db']) self.db_engine = sqlalchemy.create_engine(config['db']) else: print('Using in-memory db') self.db_engine = sqlalchemy.create_engine('sqlite:///:memory:') DBSession = orm.sessionmaker(self.db_engine) self.db = DBSession() # Load all plugins mentioned in the configuration. Allow globbing. plugins = retrieve_named_plugins(IPlugin, config['plugins'], 'hamper.plugins') for plugin in plugins: self.registerPlugin(plugin)
def startFactory(self): log.msg("Initializing factory for world '%s'..." % self.name) authenticator = configuration.get(self.config_name, "authenticator") selected = retrieve_named_plugins(IAuthenticator, [authenticator])[0] log.msg("Using authenticator %s" % selected.name) self.handshake_hook = selected.handshake self.login_hook = selected.login # Get our plugins set up. self.register_plugins() log.msg("Starting world...") self.world.start() if configuration.has_option(self.config_name, "perm_cache"): cache_level = configuration.getint(self.config_name, "perm_cache") self.world.enable_cache(cache_level) log.msg("Starting timekeeping...") self.timestamp = reactor.seconds() self.time = self.world.time self.update_season() self.time_loop = LoopingCall(self.update_time) self.time_loop.start(2) # Start automatons. for automaton in self.automatons: automaton.start() self.chat_consumers = set() log.msg("Factory successfully initialized for world '%s'!" % self.name)
def __init__(self, name): """ Load a world from disk. :Parameters: name : str The configuration key to use to look up configuration data. """ world_url = configuration.get("world %s" % name, "url") world_sf_name = configuration.get("world %s" % name, "serializer") sf = retrieve_named_plugins(ISerializerFactory, [world_sf_name])[0] self.serializer = sf(world_url) verifyObject(ISerializer, self.serializer) self.chunk_cache = weakref.WeakValueDictionary() self.dirty_chunk_cache = dict() self._pending_chunks = dict() self.spawn = (0, 0, 0) self.seed = random.randint(0, sys.maxint) self.serializer.load_level(self) self.serializer.save_level(self) self.chunk_management_loop = LoopingCall(self.sort_chunks) self.chunk_management_loop.start(1) log.msg("World started on %s, using serializer %s" % (world_url, self.serializer.name)) log.msg("Using Ampoule: %s" % async)
def __init__(self, name): BetaServerProtocol.__init__(self) self.config_name = "world %s" % name log.msg("Registering client hooks...") names = configuration.getlistdefault(self.config_name, "build_hooks", []) self.build_hooks = retrieve_sorted_plugins(IBuildHook, names) names = configuration.getlistdefault(self.config_name, "dig_hooks", []) self.dig_hooks = retrieve_sorted_plugins(IDigHook, names) names = configuration.getlistdefault(self.config_name, "sign_hooks", []) self.sign_hooks = retrieve_sorted_plugins(ISignHook, names) names = configuration.getlistdefault(self.config_name, "use_hooks", []) self.use_hooks = defaultdict(list) for plugin in retrieve_named_plugins(IUseHook, names): for target in plugin.targets: self.use_hooks[target].append(plugin) # Retrieve the MOTD. Only needs to be done once. self.motd = configuration.getdefault(self.config_name, "motd", None) self.last_dig_build_timer = time()
def __init__(self, name): BetaServerProtocol.__init__(self) self.config_name = "world %s" % name log.msg("Registering client hooks...") names = configuration.getlistdefault(self.config_name, "pre_build_hooks", []) self.pre_build_hooks = retrieve_sorted_plugins(IPreBuildHook, names) names = configuration.getlistdefault(self.config_name, "post_build_hooks", []) self.post_build_hooks = retrieve_sorted_plugins(IPostBuildHook, names) names = configuration.getlistdefault(self.config_name, "dig_hooks", []) self.dig_hooks = retrieve_sorted_plugins(IDigHook, names) names = configuration.getlistdefault(self.config_name, "sign_hooks", []) self.sign_hooks = retrieve_sorted_plugins(ISignHook, names) names = configuration.getlistdefault(self.config_name, "use_hooks", []) self.use_hooks = defaultdict(list) for plugin in retrieve_named_plugins(IUseHook, names): for target in plugin.targets: self.use_hooks[target].append(plugin) log.msg("Registering policies...") self.dig_policy = dig_policies["notchy"] # Retrieve the MOTD. Only needs to be done once. self.motd = configuration.getdefault(self.config_name, "motd", None)
def update_season(self): """ Update the world's season. """ plugins = configuration.getlistdefault(self.config_name, "seasons", []) for plugin in retrieve_named_plugins(ISeason, plugins): if plugin.day == self.day: self.world.season = plugin
def startFactory(self): log.msg("Initializing factory for world '%s'..." % self.name) self.world = World(self.name) self.world.factory = self if configuration.has_option(self.config_name, "perm_cache"): cache_level = configuration.getint(self.config_name, "perm_cache") self.world.enable_cache(cache_level) self.protocols = dict() log.msg("Starting timekeeping...") self.timestamp = time() self.time = self.world.time self.update_season() self.time_loop = LoopingCall(self.update_time) self.time_loop.start(2) authenticator = configuration.get(self.config_name, "authenticator") selected = retrieve_named_plugins(IAuthenticator, [authenticator])[0] log.msg("Using authenticator %s" % selected.name) self.handshake_hook = selected.handshake self.login_hook = selected.login generators = configuration.getlist(self.config_name, "generators") generators = retrieve_sorted_plugins(ITerrainGenerator, generators) log.msg("Using generators %s" % ", ".join(i.name for i in generators)) self.world.pipeline = generators automatons = configuration.getlist(self.config_name, "automatons") automatons = retrieve_named_plugins(IAutomaton, automatons) log.msg("Using automatons %s" % ", ".join(i.name for i in automatons)) self.automatons = automatons self.chat_consumers = set() log.msg("Factory successfully initialized for world '%s'!" % self.name)
def __init__(self, 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.port = configuration.getint(name, "port") world_folder = configuration.get(name, "world") self.world = World(world_folder) self.world.factory = self self.protocols = dict() self.eid = 1 self.entities = set() self.time_loop = LoopingCall(self.update_time) self.time_loop.start(2) authenticator = configuration.get("bravo", "authenticator") selected = retrieve_named_plugins(IAuthenticator, [authenticator])[0] print "Using authenticator %s" % selected.name self.handshake_hook = selected.handshake self.login_hook = selected.login generators = configuration.get("bravo", "generators").split(",") generators = retrieve_named_plugins(ITerrainGenerator, generators) print "Using generators %s" % ", ".join(i.name for i in generators) self.world.pipeline = generators print "Factory init'd"
def console_command(self, factory, parameters): wanted = " ".join(parameters) try: season = retrieve_named_plugins(ISeason, [wanted])[0] except PluginException: yield "Couldn't find season %s" % wanted return msg = "Changing season to %s..." % wanted yield msg factory.day = season.day factory.update_season() yield "Season successfully changed!"
def start(self): """ Load a world from disk. """ world_url = self.config.get(self.config_name, "url") world_sf_name = self.config.get(self.config_name, "serializer") # Get the current serializer list, and attempt to connect our # serializer of choice to our resource. # This could fail. Each of these lines (well, only the first and # third) could raise a variety of exceptions. They should *all* be # fatal. serializers = retrieve_named_plugins(ISerializer, [world_sf_name]) self.serializer = serializers[0] self.serializer.connect(world_url) self.seed = random.randint(0, sys.maxint) # Check if we should offload chunk requests to ampoule. if self.config.getbooleandefault("bravo", "ampoule", False): try: import ampoule if ampoule: self. async = True except ImportError: pass # First, try loading the level, to see if there's any data out there # which we can use. If not, don't worry about it. d = maybeDeferred(self.serializer.load_level, self) d.addCallback(lambda chaff: log.msg("Loaded level data!")) @d.addErrback def sre(failure): failure.trap(SerializerReadException) log.msg("Had issues loading level data, continuing anyway...") # And now save our level. if self.saving: self.serializer.save_level(self) self.chunk_management_loop = LoopingCall(self.sort_chunks) self.chunk_management_loop.start(1) log.msg("World started on %s, using serializer %s" % (world_url, self.serializer.name)) log.msg("Using Ampoule: %s" % self. async) self.mob_manager = MobManager() # XXX Put this in init or here? self.mob_manager.world = self # XXX Put this in the managers constructor?
def start(self): """ Load a world from disk. """ world_url = configuration.get(self.config_name, "url") world_sf_name = configuration.get(self.config_name, "serializer") try: sf = retrieve_named_plugins(ISerializerFactory, [world_sf_name])[0] self.serializer = verify_plugin(ISerializer, sf(world_url)) except PluginException, pe: log.msg(pe) raise RuntimeError("Fatal error: Couldn't set up serializer!")
def __init__(self, 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 """ log.msg("Initializing factory for world '%s'..." % name) self.name = name self.config_name = "world %s" % name self.port = configuration.getint(self.config_name, "port") self.interface = configuration.getdefault(self.config_name, "host", "") self.world = World(name) self.world.factory = self if configuration.has_option(self.config_name, "perm_cache"): cache_level = configuration.getint(self.config_name, "perm_cache") self.world.enable_cache(cache_level) self.protocols = dict() self.eid = 1 self.time = self.world.time self.time_loop = LoopingCall(self.update_time) self.time_loop.start(2) authenticator = configuration.get(self.config_name, "authenticator") selected = retrieve_named_plugins(IAuthenticator, [authenticator])[0] log.msg("Using authenticator %s" % selected.name) self.handshake_hook = selected.handshake self.login_hook = selected.login generators = configuration.getlist(self.config_name, "generators") generators = retrieve_sorted_plugins(ITerrainGenerator, generators) log.msg("Using generators %s" % ", ".join(i.name for i in generators)) self.world.pipeline = generators self.chat_consumers = set() log.msg("Factory successfully initialized for world '%s'!" % name)
def pipeline(): generators = configuration.getlist("bravo", "generators") generators = retrieve_named_plugins(ITerrainGenerator, generators) before = time.time() for i in range(10): chunk = Chunk(i, i) for generator in generators: generator.populate(chunk, 0) after = time.time() return after - before
def pipeline(): generators = beta["generators"] generators = retrieve_named_plugins(ITerrainGenerator, generators) before = time.time() for i in range(10): chunk = Chunk(i, i) for generator in generators: generator.populate(chunk, 0) after = time.time() return after - before
def command(self, bot, comm, groups): """Load a named plugin.""" name = groups[0] plugins = PluginUtils.get_plugins(bot) matched_plugins = [p for p in plugins if p.name == name] if len(matched_plugins) != 0: bot.reply(comm, "%s is already loaded." % name) return False # Fun fact: the fresh thing is just a dummy. It just can't be None new_plugin = plugin.retrieve_named_plugins(IPlugin, [name], 'hamper.plugins', {'fresh': True})[0] bot.addPlugin(new_plugin) bot.reply(comm, 'Loading {0}.'.format(new_plugin)) return True
def register_plugins(self): """ Setup plugin hooks. """ log.msg("Registering client plugin hooks...") plugin_types = { "automatons": IAutomaton, "generators": ITerrainGenerator, "seasons": ISeason, "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, } pp = {"factory": self, "furnaces": self.furnace_manager} for t, interface in plugin_types.iteritems(): l = configuration.getlistdefault(self.config_name, t, []) if issubclass(interface, ISortedPlugin): plugins = retrieve_sorted_plugins(interface, l, parameters=pp) else: plugins = retrieve_named_plugins(interface, l, parameters=pp) log.msg("Using %s: %s" % (t.replace("_", " "), ", ".join(plugin.name for plugin in plugins))) setattr(self, t, plugins) # 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)
def __init__(self, name): """ Load a world from disk. :Parameters: name : str The configuration key to use to look up configuration data. """ self.config_name = "world %s" % name world_url = configuration.get(self.config_name, "url") world_sf_name = configuration.get(self.config_name, "serializer") try: sf = retrieve_named_plugins(ISerializerFactory, [world_sf_name])[0] self.serializer = verify_plugin(ISerializer, sf(world_url)) except PluginException, pe: log.msg(pe) raise RuntimeError("Fatal error: Couldn't set up serializer!")
def connect(self): """ Connect to the world. """ world_url = self.config.get(self.config_name, "url") world_sf_name = self.config.get(self.config_name, "serializer") # Get the current serializer list, and attempt to connect our # serializer of choice to our resource. # This could fail. Each of these lines (well, only the first and # third) could raise a variety of exceptions. They should *all* be # fatal. serializers = retrieve_named_plugins(ISerializer, [world_sf_name]) self.serializer = serializers[0] self.serializer.connect(world_url) log.msg("World started on %s, using serializer %s" % (world_url, self.serializer.name))
def command(self, bot, comm, groups): """Reload a named plugin.""" name = groups[0] plugins = PluginUtils.get_plugins(bot) matched_plugins = [p for p in plugins if p.name == name] if len(matched_plugins) == 0: bot.reply(comm, "I can't find a plugin named {0}!" .format(name)) return False target_plugin = matched_plugins[0] # Fun fact: the fresh thing is just a dummy. It just can't be None new_plugin = plugin.retrieve_named_plugins(IPlugin, [name], 'hamper.plugins', {'fresh': True})[0] bot.removePlugin(target_plugin) bot.addPlugin(new_plugin) bot.reply(comm, 'Reloading {0}.'.format(new_plugin)) return True
def startFactory(self): log.msg("Initializing factory for world '%s'..." % self.name) authenticator = self.config.get(self.config_name, "authenticator") selected = retrieve_named_plugins(IAuthenticator, [authenticator])[0] log.msg("Using authenticator %s" % selected.name) self.handshake_hook = selected.handshake self.login_hook = selected.login # 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.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 update_season(self): """ Update the world's season. """ # Get a sorted list of all the seasons plugins = configuration.getlistdefault(self.config_name, "seasons", []) all_seasons = list(retrieve_named_plugins(ISeason, plugins)) all_seasons.sort(key=lambda s: s.day) # Get all the seasons that we have past the start date of this year. # We are looking for the season which is closest to our current day, # without going over; I call this the Price-is-Right style of season # handling. :3 past_seasons = [s for s in all_seasons if s.day <= self.day] if past_seasons: # The most recent one is the one we are in self.world.season = past_seasons[-1] else: # We haven't past any seasons yet this year, so grab the last one # from 'last year' self.world.season = all_seasons[-1]
class BravoFactory(Factory): """ A ``Factory`` that creates ``BravoProtocol`` objects when connected to. """ implements(IPushProducer) protocol = BravoProtocol timestamp = None time = 0 day = 0 eid = 1 handshake_hook = None login_hook = None 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) authenticator = self.config.get(self.config_name, "authenticator") selected = retrieve_named_plugins(IAuthenticator, [authenticator])[0] log.msg("Using authenticator %s" % selected.name) self.handshake_hook = selected.handshake self.login_hook = selected.login # 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.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, "seasons": ISeason, "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, } pp = {"factory": self} 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] if issubclass(interface, ISortedPlugin): plugins = retrieve_sorted_plugins(interface, l, parameters=pp) else: plugins = retrieve_named_plugins(interface, l, parameters=pp) log.msg("Using %s: %s" % (t.replace("_", " "), ", ".join(plugin.name for plugin in plugins))) setattr(self, t, plugins) # 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)