from lampost.server.user import User from lampost.context.resource import m_requires from lampost.context.config import m_configured from lampost.util.lputil import ClientError m_requires(__name__, 'datastore', 'dispatcher', 'session_manager', 'user_manager', 'email_sender', 'perm') m_configured(__name__, 'lampost_title') _REQUEST_KEY = "friend_requests" _FRIEND_EMAIL_KEY = "friend_email_notifies" _ALL_EMAIL_KEY = "all_email_notifies" class FriendService(): def _post_init(self): register('player_login', self._check_friends) register('player_deleted', self._delete_player) def friend_request(self, source, target): req_key = ':'.join([source.dbo_id, target.dbo_id]) if set_key_exists(_REQUEST_KEY, req_key): raise ClientError("You already have a friend request to {} outstanding.".format(target.name)) dispatch('player_message', 'friend_req', {'friend_id': source.dbo_id, 'friend_name': source.name}, target.dbo_id, source.dbo_id) add_set_key(_REQUEST_KEY, req_key) def remove_request(self, source_id, target_id): delete_set_key('friend_requests', ':'.join([source_id, target_id])) def add_friend(self, source_id, target_id):
import time from datetime import datetime, timedelta from os import urandom from base64 import b64encode from lampost.context.resource import m_requires, requires, provides from lampost.model.player import Player from lampost.client.user import User LINK_DEAD_INTERVAL = timedelta(seconds=15) LINK_DEAD_PRUNE = timedelta(minutes=2) LINK_IDLE_REFRESH = timedelta(seconds=45) m_requires("log", __name__) @provides("sm") @requires("dispatcher", "user_manager", "config_manager") class SessionManager(object): def __init__(self): self.session_map = {} self.player_info_map = {} self.player_session_map = {} self.register_p(self._refresh_link_status, seconds=5) self.register_p(self._push_player_list, seconds=30) def get_session(self, session_id): return self.session_map.get(session_id, None)
from lampost.comm.channel import Channel from lampost.context.config import m_configured from lampost.context.resource import m_requires from lampost.env.room import Room, safe_room from lampost.gameops.action import ActionError from lampost.mud.action import mud_action, imm_actions m_requires(__name__, 'log', 'datastore', 'dispatcher', 'perm', 'user_manager', 'instance_manager', 'message_service', 'friend_service') m_configured(__name__, 'default_start_room') _init_priority = 5000 def _post_init(): global shout_channel, imm_channel shout_channel = Channel('shout', general=True) imm_channel = Channel('imm') register('player_create', _player_create) register('player_baptise', _baptise, priority=-100) register('imm_baptise', _imm_baptise, priority=-100) register('missing_env', _start_env) def _player_create(player, user): if len(user.player_ids) == 1 and not player.imm_level: player.imm_level = perm_level('builder') update_immortal_list(player) dispatch('imm_level_change', player, 0) message_service.add_message('system', "Welcome! Your first player has been given immortal powers. Check out the 'Editor' window on the top menu.", player.dbo_id)
from lampost.gameops.display import * from lampost.gameops.action import ActionError from lampost.context.resource import m_requires from lampost.mud.action import mud_action m_requires('sm', __name__) @mud_action(('t', 'tell')) def tell(source, args, command, **ignored): if not args: raise ActionError("Tell who?") tell_message(source, args[0], command.partition(args[0])[2][1:]) def tell_message(source, player_id, statement): session = sm.player_session(player_id) if not session: return source.display_line("Cannot find " + player_id) player = session.player if not statement: return source.display_line("Say what to " + player.name + "?") player.last_tell = source.dbo_id player.display_line(source.name + " tells you, `" + statement + "'", TELL_FROM_COLOR) source.display_line("You tell " + player.name + ", `" + statement + "'", TELL_TO_COLOR) @mud_action(('r', 'reply')) def reply(source, verb, command, **ignored): if not source.last_tell: raise ActionError("You have not received a tell recently.")
from lampost.context.resource import m_requires from lampost.datastore.dbofield import DBOField, DBOTField from lampost.datastore.auto import TemplateField from lampost.lpflavor.archetype import Archetype from lampost.lpflavor.attributes import fill_pools from lampost.lpflavor.entity import EntityLP from lampost.lpflavor.skill import add_skill from lampost.model.mobile import MobileTemplate from lampost.model.race import base_attr_value m_requires(__name__, 'log', 'context', 'datastore', 'dispatcher') affinities = {'player': {'enemies': ['monster']}, 'neutral': {'enemies': []}, 'monster': {'enemies': ['player']}} def _post_init(): context.set('affinities', affinities) class MobileTemplateLP(MobileTemplate): class_id = 'mobile' default_skills = DBOField([], 'default_skill') def on_loaded(self): if self.archetype: arch = load_object(self.archetype, Archetype) for attr_name, start_value in arch.base_attrs.items(): setattr(self.instance_cls, attr_name, start_value) self.desc = arch.desc
import time from datetime import datetime, timedelta from os import urandom from base64 import b64encode from lampost.context.resource import m_requires, requires from lampost.context.config import m_configured from lampost.util.lputil import ClientError m_requires(__name__, 'log', 'dispatcher', 'user_manager') m_configured(__name__, 'refresh_link_interval', 'broadcast_interval', 'link_dead_prune', 'link_dead_interval', 'link_idle_refresh') class SessionManager(): def __init__(self): self.session_map = {} self.player_info_map = {} self.player_session_map = {} def _post_init(self): register_p(self._refresh_link_status, seconds=refresh_link_interval) register_p(self._broadcast_status, seconds=broadcast_interval) self.link_dead_prune = timedelta(seconds=link_dead_prune) self.link_dead_interval = timedelta(seconds=link_dead_interval) self.link_idle_refresh = timedelta(seconds=link_idle_refresh) register('player_logout', self._player_logout) def get_session(self, session_id): return self.session_map.get(session_id)
from collections import defaultdict from random import randint from tornado.ioloop import PeriodicCallback from lampost.context.resource import m_requires from lampost.context.config import m_configured m_requires(__name__, 'log', 'datastore') _registrations = defaultdict(set) _pulse_map = defaultdict(set) _owner_map = defaultdict(set) _pulse_count = 0 pulses_per_second = 0 pulse_lc = None maintenance_lc = None def register(event_type, callback, owner=None, priority=0): return _add_registration(Registration(event_type, callback, owner, priority)) def unregister(registration): registration.cancel() owner_registrations = _owner_map[registration.owner] owner_registrations.remove(registration) if not owner_registrations: del _owner_map[registration.owner]
from twisted.web.resource import Resource from lampost.client.resources import request from lampost.context.resource import m_requires, requires m_requires('perm', __name__) class ConfigResource(Resource): def __init__(self): Resource.__init__(self) self.putChild('get', ConfigGet()) self.putChild('update', ConfigUpdate()) @requires('config_manager') class ConfigGet(Resource): @request def render_POST(self, content, session): check_perm(session, 'supreme') return self.config_manager.config_json @requires('config_manager', 'dispatcher') class ConfigUpdate(Resource): @request def render_POST(self, content, session): check_perm(session, 'supreme') self.config_manager.update_config(content.config) return self.config_manager.config_json
import time from lampost.context.resource import m_requires from lampost.datastore import classes from lampost.datastore.classes import get_dbo_class from lampost.editor.admin import admin_op from lampost.model.player import Player m_requires(__name__, 'log', 'datastore', 'perm', 'config_manager') @admin_op def rebuild_indexes(dbo_cls): for ix_name in dbo_cls.dbo_indexes: delete_key('ix:{}:{}'.format(dbo_cls.dbo_key_type, ix_name)) for dbo_id in fetch_set_keys(dbo_cls.dbo_set_key): try: dbo_key = '{}:{}'.format(dbo_cls.dbo_key_type, dbo_id) dbo_dict = load_raw(dbo_key) for ix_name in dbo_cls.dbo_indexes: ix_value = dbo_dict.get(ix_name) if ix_value is not None and ix_value != '': set_index('ix:{}:{}'.format(dbo_cls.dbo_key_type, ix_name), ix_value, dbo_id) except (ValueError, TypeError): warn("Missing dbo object {} from set key {}", dbo_id, dbo_cls.dbo_set_key) @admin_op def rebuild_owner_refs(): # Yes, we're abusing the keys command. If we required a later version of Redis (2.8) we could use SCAN for owned_key in datastore.redis.keys('owned:*'): delete_key(owned_key)
from lampost.context.resource import m_requires m_requires(__name__, 'session_manager') def recursive_targets(target_list, target_key): for target in target_list: if target_key in getattr(target, 'target_keys', ()): yield target for sub_target in recursive_targets(getattr(target, 'target_providers', ()), target_key): yield sub_target def self(target_key, entity, *_): if target_key == ('self',) or target_key in entity.target_keys: yield entity def func_owner(target_key, entity, action, *_): return recursive_targets([action.__self__], target_key) def func_providers(target_key, entity, action, *_): for target in action.__self__.target_providers: if target_key in getattr(target, 'target_keys', ()): yield target def action(target_key, entity, action): return recursive_targets([action], target_key)
from lampost.context.resource import m_requires from lampost.datastore.exceptions import DataError from lampost.editor.editor import Editor from lampost.comm.broadcast import BroadcastMap, Broadcast, broadcast_types from lampost.mud.socials import Social m_requires(__name__, "mud_actions") class SocialsEditor(Editor): def initialize(self): super().initialize(Social) def preview(self): content = self._content() broadcast = Broadcast( BroadcastMap(**content.b_map), content.source, content.source if content.self_source else content.target ) return {broadcast_type["id"]: broadcast.substitute(broadcast_type["id"]) for broadcast_type in broadcast_types} def _pre_create(self): if (self.raw["dbo_id"],) in mud_actions: raise DataError("Verb already in use") def _post_delete(self, social): del mud_actions[(social.dbo_id,)] class SkillEditor(Editor): def _pre_create(self): self._ensure_name()
import time from lampost.context.resource import requires, provides, m_requires from lampost.datastore.dbo import RootDBO from lampost.model.player import Player m_requires('log', 'datastore', __name__) class User(RootDBO): dbo_key_type = "user" dbo_fields = "user_name", "email", "password", "player_ids", "toolbar" dbo_set_key = "users" dbo_indexes = "user_name" user_name = "" password = unicode("password") email = "" def __init__(self, dbo_id): self.dbo_id = unicode(dbo_id) self.player_ids = [] self.toolbar = [] self.colors = {} @requires('config_manager', 'nature') @provides('user_manager') class UserManager(object): def validate_user(self, user_name, password): user = self.find_user(user_name)
from lampost.comm.broadcast import BroadcastMap from lampost.context.config import m_configured from lampost.context.resource import m_requires, requires from lampost.datastore.dbofield import DBOField from lampost.env.movement import Direction from lampost.env.room import Room from lampost.gameops import target_gen from lampost.gameops.action import convert_verbs, ActionError from lampost.model.item import BaseItem m_requires(__name__, 'datastore', 'dispatcher') m_configured(__name__, 'instance_preserve_hours') instance_map = {} class InstanceManager(): def _post_init(self): register('maintenance', self.remove_old) def next_instance(self): instance_id = db_counter('instance_id') area_instance = AreaInstance(instance_id) instance_map[instance_id] = area_instance return area_instance def remove_old(self): stale_pulse = future_pulse(instance_preserve_hours * 60 * 60) for instance_id, instance in instance_map.copy().items(): if instance.pulse_stamp < stale_pulse and not [entity for entity in instance.entities
from lampost.context.resource import m_requires from lampost.gameops.action import action_handler, ActionError from lampost.lpflavor.fight import Fight from lampost.lpflavor.attributes import need_refresh, POOL_KEYS from lampost.lpflavor.combat import calc_consider from lampost.model.entity import Entity m_requires(__name__, "log", "tools", "dispatcher") def _post_init(): register("game_settings", update_settings) def update_settings(game_settings): EntityLP._refresh_interval = game_settings.get("refresh_interval", 12) EntityLP._refresher["stamina"] = game_settings.get("stamina_refresh", 8) EntityLP._refresher["health"] = game_settings.get("health_refresh", 1) EntityLP._refresher["mental"] = game_settings.get("mental_refresh", 1) EntityLP._refresher["action"] = game_settings.get("action_refresh", 40) class EntityLP(Entity): health = 0 stamina = 0 mental = 0 action = 0 auto_fight = True weapon = None last_opponent = None
from twisted.web.resource import Resource from lampost.client.resources import request from lampost.context.resource import m_requires, requires from lampost.model.player import Player from lampost.client.user import User from lampost.util.lmutil import DataError m_requires('datastore', 'perm', 'user_manager',__name__) class PlayerResource(Resource): def __init__(self): Resource.__init__(self) self.putChild('list', PlayerList()) self.putChild('delete', PlayerDelete()) class PlayerList(Resource): @request def render_POST(self, content, session): return [player_dto(key.split(':')[1]) for key in fetch_set_keys("players")] @requires('user_manager') class PlayerDelete(Resource): @request def render_POST(self, content, session): player = load_object(Player, content.player_id) if not player: raise DataError("Player no longer exists.") if player.imm_level >= perm_level('supreme'):
import cgi from datetime import datetime from twisted.web.resource import Resource, NoResource from twisted.web.server import NOT_DONE_YET from lampost.util.lmlog import logged from lampost.context.resource import m_requires from lampost.util.lmutil import build_object, PermError, DataError, StateError m_requires('sm', 'json_decode', 'json_encode', 'log', __name__) def find_session_id(request): session_headers = request.requestHeaders.getRawHeaders('X-Lampost-Session') if session_headers: return session_headers[0] def request(func): @logged def wrapper(self, request): content = build_object(json_decode(request.content.getvalue())) session = sm.get_session(find_session_id(request)) if not session: return json_encode({'link_status': 'session_not_found'}) try: result = func(self, content, session) if result is None: request.setResponseCode(204) return ''
from smtplib import SMTPHeloError, SMTP, SMTPRecipientsRefused, SMTPSenderRefused, SMTPDataError from threading import Thread from lampost.context.resource import requires, m_requires m_requires(__name__, 'log') class EmailSender(): def __init__(self): try: info_file = open('data/email_info') except IOError: warn("No email info available") self.available = False return email_info = info_file.readlines() self.email_name = email_info[0].strip self.email_address = email_info[1].strip() self.email_password = email_info[2].strip() info_file.close() self.available = True def send_targeted_email(self, subject, text, users): if not self.available: return "Email not available" wrappers = [] for user in users: if user.email: wrappers.append(EmailWrapper(user.email, "\From: {}\nTo: {}\nSubject:{}\n\n{}".format(self.email_name, user.user_name, subject, text)))
import random import string from lampost.server.handlers import MethodHandler from lampost.server.user import User from lampost.context.resource import m_requires, requires from lampost.datastore.exceptions import DataError from lampost.context.config import m_configured from lampost.model.player import Player from lampost.util.encrypt import make_hash from lampost.util.lputil import ClientError m_requires(__name__, 'datastore', 'dispatcher', 'user_manager', 'perm', 'email_sender', 'friend_service') m_configured(__name__, 'lampost_title') @requires('session_manager') class Settings(MethodHandler): def get_account(self): user_id = self.raw['user_id'] if self.session.user.dbo_id != user_id: check_perm(self.player, 'admin') return load_object(user_id, User).edit_dto def create_account(self): account_name = self.raw['account_name'].lower() if get_index("ix:user:name", account_name) or object_exists('player', account_name) or\ account_name in perm.system_accounts or object_exists('area', account_name): raise DataError("InUse: {}".format(account_name))
from tornado.web import RequestHandler from lampost.server.handlers import SessionHandler from lampost.context.resource import m_requires from lampost.model.player import Player from lampost.util.lputil import ClientError m_requires( __name__, "log", "session_manager", "user_manager", "datastore", "json_decode", "json_encode", "perm", "edit_notify_service", ) def editor_login(session): edit_perms = [] player = session.player if has_perm(player, "builder"): edit_perms.extend(["build", "mud"]) if has_perm(player, "admin"): edit_perms.extend(["player"]) if has_perm(player, "supreme"): edit_perms.extend(["admin", "config"]) session.append( {
from lampost.context.resource import m_requires from lampost.gameops.action import ActionError from lampost.util.lputil import timestamp m_requires(__name__, 'log', 'datastore', 'dispatcher', 'session_manager', 'user_manager') class MessageService(): def _post_init(self): register("player_deleted", self._remove_player_messages) register("player_connect", self._player_connect) register("player_message", self.add_message) def get_messages(self, player_id): return get_all_db_hash(_message_key(player_id)) def add_message(self, msg_type, content, player_id, source_id=None): if self.is_blocked(player_id, source_id): raise ActionError("You are blocked from sending messages to that player.") msg_id = db_counter("message_id") message = {'msg_type': msg_type, 'msg_id': msg_id, 'content': content, 'source': user_manager.id_to_name(source_id)} timestamp(message) set_db_hash(_message_key(player_id), msg_id, message) try: session_manager.player_session(player_id).append({'new_message': message}) except AttributeError: pass def remove_message(self, player_id, msg_id): remove_db_hash(_message_key(player_id), msg_id)
from twisted.web.resource import Resource from lampost.client.resources import request from lampost.context.resource import m_requires, requires from lampost.model.area import Area m_requires('datastore', 'mud', 'perm', __name__) class AreaResource(Resource): def __init__(self): Resource.__init__(self) self.putChild('list', AreaList()) self.putChild('new', AreaNew()) self.putChild('delete', AreaDelete()) self.putChild('update', AreaUpdate()) class AreaList(Resource): @request def render_POST(self, content, session): return [area_dto(area, has_perm(session.player, area)) for area in mud.area_map.itervalues()] @requires('mud', 'cls_registry') class AreaNew(Resource): @request def render_POST(self, content, session): area_id = content.id.lower() if datastore.load_object(Area, area_id): return "AREA_EXISTS" area = self.cls_registry(Area)(area_id)
import math import itertools from lampost.gameops.action import ActionError from lampost.comm.broadcast import Broadcast, SingleBroadcast from lampost.context.resource import m_requires, requires from lampost.model.item import BaseItem from lampost.util.lmutil import PermError m_requires('log', __name__) @requires('mud_actions') class Entity(BaseItem): dbo_fields = BaseItem.dbo_fields + ("size", "sex") env = None status = 'awake' sex = 'none' size = 'medium' living = True entry_msg = Broadcast(e="{n} arrives.", silent=True) exit_msg = Broadcast(e="{n} leaves.", silent=True) current_target = None def baptise(self, soul): self.registrations = set() self.soul = soul self.target_map = {} self.target_key_map = {} self.actions = {}
import hashlib from lampost.editor.editor import ChildrenEditor from lampost.context.resource import m_requires from lampost.datastore.exceptions import DataError from lampost.gameops.script import compile_script, ShadowScript m_requires(__name__, 'perm') def validate(script_dict): code, err_str = compile_script(script_dict['text'], script_dict['name']) if err_str: raise DataError(err_str) return code class ScriptEditor(ChildrenEditor): def initialize(self): super().initialize(ShadowScript) def validate(self): validate(self.raw)
import itertools from lampost.gameops import target_gen from lampost.context.resource import m_requires from lampost.gameops.action import find_actions from lampost.util.lputil import find_extra, ClientError m_requires(__name__, 'log', 'mud_actions') MISSING_VERB = "Unrecognized command '{verb}'. Perhaps you should try 'help'?" EXTRA_WORDS = "'{extra}' does not make sense with '{verb}'." MISSING_TARGET = "'{command}' what? or whom?" ABSENT_TARGET = "'{target}' is not here." ABSENT_OBJECT = "'{object}' is not here." MISSING_PREP = "'{prep}' missing from command." INVALID_TARGET = "You can't {verb} {target}." INVALID_OBJECT = "You can't {verb} {target} {prep} {object}." INSUFFICIENT_QUANTITY = "Not enough there to {verb} {quantity}." AMBIGUOUS_COMMAND = "Ambiguous command" def all_actions(entity, verb): actions = {action for action in itertools.chain.from_iterable( actions.get(verb, []) for actions in (entity.soul, entity.inven_actions))} try: actions.add(mud_actions[verb]) except KeyError: pass actions.update(find_actions(verb, entity.env.action_providers)) return actions
from lampost.datastore.classes import get_dbo_class from lampost.context.resource import m_requires from lampost.datastore.exceptions import DataError from lampost.editor.editor import Editor, ChildrenEditor from lampost.env.movement import Direction from lampost.env.room import Room from lampost.context.config import m_configured from lampost.model.area import Area m_requires(__name__, 'datastore', 'log', 'perm', 'dispatcher', 'edit_notify_service') m_configured(__name__, 'root_area_id', 'default_start_room') class AreaEditor(Editor): def initialize(self): super().initialize(Area) def _pre_create(self): if object_exists('player', self.raw['dbo_id']): raise DataError("Area name should not match any player name.") def _pre_delete(self, del_obj): if del_obj.dbo_id == root_area_id: raise DataError("Cannot delete root area.") for room in load_object_set(Room, 'area_rooms:{}'.format(del_obj.dbo_id)): room_clean_up(room, self.session, del_obj.dbo_id) class RoomEditor(ChildrenEditor): def initialize(self):
from lampost.context.resource import m_requires from lampost.datastore.dbofield import DBOField, DBOLField from lampost.env.room import Room from lampost.gameops.action import ActionError from lampost.gameops.display import SYSTEM_DISPLAY, COMBAT_DISPLAY from lampost.lpflavor.entity import EntityLP from lampost.model.item import BaseItem from lampost.model.player import Player m_requires(__name__, 'dispatcher', 'datastore', 'config_manager') class PlayerLP(Player, EntityLP, BaseItem): dbo_key_type = 'player' race = DBOLField(dbo_class_id='race') affinity = 'player' skills = DBOField({}, 'untyped') touchstone = DBOField() can_die = True size = DBOField('medium') def __init(self): super().__init__() self.auto_fight = False def on_loaded(self): for skill in self.skills.values(): self._apply_skill(skill)
from lampost.context.resource import m_requires m_requires(__name__, "log", "session_manager", "dispatcher", "perm") class ClientService: def __init__(self): self.sessions = set() def _post_init(self): register("session_disconnect", self.unregister) def register(self, session, data=None): self.sessions.add(session) def unregister(self, session): try: self.sessions.remove(session) except KeyError: pass def _session_dispatch(self, event): for session in self.sessions: session.append(event) class PlayerListService(ClientService): def _post_init(self): super()._post_init() register("player_list", self._process_list)
from lampost.gameops.action import ActionError from lampost.context.resource import m_requires, get_resource from lampost.mud.action import imm_action from lampost.model.player import Player from lampost.util.lmutil import find_extra, patch_object, PatchError m_requires('sm', 'mud', 'datastore', 'perm', 'nature', __name__) @imm_action('edit') def edit(source, **ignored): check_perm(source, mud.get_area(source.env.area_id)) return {'start_room_edit': source.env.dbo_id} @imm_action(('cmds', 'commands')) def cmds(source, **ignored): soul_actions = [action for action in source.soul if getattr(action, 'imm_level', None)] verb_lists = ["/".join([" ".join(list(verb)) for verb in action.verbs]) for action in soul_actions] return ", ".join(sorted(verb_lists)) @imm_action('goto') def goto(source, args, **ignored): if not args: raise ActionError("Go to whom? or to where?") dest = args[0].lower() if dest == 'area' and len(args) > 1: area = mud.get_area(args[1]) if not area: raise ActionError("Area does not exist") if not area.rooms:
from lampost.context.resource import m_requires from lampost.datastore.auto import AutoField from lampost.datastore.dbo import KeyDBO from lampost.datastore.dbofield import DBOField from lampost.model.item import Connected m_requires(__name__, 'log', 'dispatcher') class Player(KeyDBO, Connected): dbo_key_type = "player" dbo_set_key = "players" user_id = DBOField(0) created = DBOField(0) imm_level = DBOField(0) last_login = DBOField(0) last_logout = DBOField(0) age = DBOField(0) room_id = DBOField() home_room = DBOField() instance_id = DBOField(0) instance_room_id = DBOField() group = AutoField() is_player = True can_die = True @property def edit_dto(self): dto = super().edit_dto
from lampost.context.resource import m_requires m_requires('cls_registry', __name__) class TemplateException(Exception): pass class Template(object): dbo_fields = ("dbo_rev", "instance_class", "world_max") class_map = {} template_fields = [] instance_count = 0 instance_class = None world_max = 1000000 dbo_rev = 0 def __init__(self, dbo_id): self.dbo_id = unicode(dbo_id) def config_instance(self, instance): pass def get_class(self): clazz = self.class_map.get(self.instance_class) if clazz: return clazz split_path = self.instance_class.split(".") module_name = ".".join(split_path[:-1]) class_name = split_path[-1]