def __init__(self, template=None, **kwargs): self.name = "" self.to_room_vnum = None self.to_room = None self.exit_info = bit.Bit(flagset_name="exit_flags") self.key = 0 self.keyword = "" self.description = "" self.is_broken = False if template: [ setattr(self, k, copy.deepcopy(v)) for k, v in template.__dict__.items() ] if self.to_room_vnum != -1 and not None and self.to_room_vnum in instance.instances_by_room: self.to_room = instance.instances_by_room[self.to_room_vnum][0] elif self.to_room_vnum == -1 or None: # This is a case where self.to_room = None elif self.to_room_vnum not in instance.instances_by_room: self.is_broken = True comm.notify( "Exit: bad to_room_vnum {}".format(self.to_room_vnum), merc.CONSOLE_ERROR) else: self.to_room = None if self.key <= 0: self.key = None if kwargs: [setattr(self, k, copy.deepcopy(v)) for k, v in kwargs.items()]
def get_weight(self): # noinspection PyUnresolvedReferences weight = self.weight # noinspection PyUnresolvedReferences contents = self.inventory[:] # noinspection PyUnresolvedReferences counted = [self.instance_id] for content_id in contents: content = instance.items[content_id] if content.instance_id in counted: # noinspection PyUnresolvedReferences comm.notify( "get_weight: items contain each other. {} ({}) - {} ({})". format(self.short_descr, self.instance_id, content.short_descr, content.instance_id), merc.CONSOLE_ERROR) break counted.append(content) contents.extend(content.inventory) try: # For items in containers weight += content.weight except AttributeError: pass return weight
def cmd_disconnect(ch, argument): argument, arg = game_utils.read_word(argument) if not arg: ch.send("Disconnect whom?\n") return victim = ch.get_char_world(arg) if not victim: ch.not_here(arg) return if not victim.desc: handler_game.act("$N doesn't have a descriptor.", ch, None, victim, merc.TO_CHAR) return if victim.act.is_set( merc.PLR_GODLESS ) and ch.trust < merc.NO_GODLESS and not ch.extra.is_set( merc.EXTRA_ANTI_GODLESS): ch.send("You failed.\n") return for d in instance.descriptor_list: if d == victim.desc: comm.close_socket(d) ch.send("Ok.\n") return comm.notify("cmd_disconnect: desc not found", merc.CONSOLE_WARNING) ch.send("Descriptor not found!\n")
def get_number(self): try: # if self is an item. noweight = [merc.ITEM_CONTAINER, merc.ITEM_MONEY] # noinspection PyUnresolvedReferences if self.item_type in noweight: number = 0 else: number = 1 except AttributeError: number = 1 # noinspection PyUnresolvedReferences contents = self.inventory[:] # noinspection PyUnresolvedReferences counted = [self.instance_id] for content_id in contents: content = instance.items[content_id] number += 1 if content.instance_id in counted: # noinspection PyUnresolvedReferences comm.notify( "get_number: items contain each other. {} ({}) - {} ({})". format(self.short_descr, self.instance_id, content.short_descr, content.instance_id), merc.CONSOLE_ERROR) break counted.append(content) contents.extend(content.inventory) return number
def cmd_empty(ch, argument): argument, arg = game_utils.read_word(argument) if not arg: ch.send("Empty what?\n") return item = ch.get_item_here(arg) if not item: ch.send("You can't find it.\n") return if item.item_type == merc.ITEM_DRINK_CON: if item.value[1] <= 0: ch.send("It is already empty.\n") return liquid = item.value[2] if liquid not in const.liq_table: comm.notify("cmd_drink: bad liquid number {}".format(liquid), merc.CONSOLE_WARNING) liquid = item.value[2] = "water" handler_game.act("$n empties $T from $p.", ch, item, const.liq_table[liquid].name, merc.TO_ROOM) handler_game.act("You empty $T from $p.", ch, item, const.liq_table[liquid].name, merc.TO_CHAR) item.value[1] = 0 else: ch.send("You cannot empty that.\n")
def load_stub(cls, player_name: str = None, silent=False): if not player_name: raise KeyError("Player name is required to load a player!") pathname = os.path.join(settings.PLAYER_DIR, player_name[0].lower(), player_name.capitalize()) filename = os.path.join(pathname, "login.json") if os.path.isfile(filename): jso = "" with open(filename, "r+") as f: for line in f: jso += line data = json.loads(jso, object_hook=instance.from_json) if isinstance(data, dict): return data else: if not silent: comm.notify( "Could not load player stub file for {}".format( player_name), merc.CONSOLE_ERROR) return None else: if not silent: comm.notify( "Could not open player stub file for {}".format( player_name), merc.CONSOLE_ERROR) return None
def str_cmp(astr, bstr, lower: bool = True): if not astr or not bstr: return False if type(astr) != str: comm.notify("str_cmp: astr:{} must be a type(str), received {}".format(astr, type(astr)), merc.CONSOLE_WARNING) return False if type(bstr) == list: i = 0 while i < len(bstr): if str_cmp(astr, bstr[i]): return True i += 1 return False if len(astr) != len(bstr): return False if lower: astr = astr.lower() bstr = bstr.lower() index = 0 while index < len(astr): if astr[index] != bstr[index]: return False index += 1 return True
def read_int(pstr): if not pstr: return None, None pstr = pstr.lstrip() nstr = "" if pstr.isalpha(): pstr = list_in_dict(pstr, bit.bitvector_table) if not pstr[0].isdigit() and pstr[0] not in ["-", "+"]: comm.notify("read_int: bad format ({})".format(pstr), merc.CONSOLE_CRITICAL) sys.exit(1) for index, c in enumerate(pstr): if c.isdigit() or c in ["-", "|"]: nstr += c elif c in ["+"]: if pstr[index - 1] and pstr[index - 1].isdigit(): break nstr += c else: break pstr = pstr[len(nstr):] nstr = [int(s) for s in nstr.lstrip().split("|")] return pstr, sum(nstr)
def cmd_web(ch, argument): argument, arg = game_utils.read_word(argument) if ch.is_npc(): return if not ch.is_werewolf() or ch.powers[merc.WPOWER_SPIDER] < 2: ch.huh() return victim = ch.get_char_room(arg) if not victim: ch.not_here(arg) return if ch == victim: ch.not_self() return if victim.is_affected(merc.AFF_ETHEREAL): ch.send("You cannot web an ethereal person.\n") return sn = "web" if sn not in const.skill_table: comm.notify("cmd_web: missing sn (web) in skill_table", merc.CONSOLE_WARNING) return spelltype = const.skill_table[sn].target level = ch.spl[spelltype] * 0.25 const.skill_table[sn].spell_fun(sn, level, ch, victim, merc.TARGET_CHAR) ch.wait_state(merc.PULSE_VIOLENCE)
def load(cls, index: int = None, instance_id: int = None): if instance_id: if instance_id in instance.characters: comm.notify( 'Instance {} of npc already loaded!'.format(instance_id), merc.CONSOLE_INFO) return top_dir = settings.INSTANCE_DIR number = instance_id else: top_dir = settings.AREA_DIR number = index target_file = '%d-area%s' % (number, settings.DATA_EXTN) filename = None for a_path, a_directory, i_files in os.walk(top_dir): if target_file in i_files: filename = os.path.join(a_path, target_file) break if not filename: raise ValueError('Cannot find %s' % target_file) jso = '' with open(filename, 'r+') as f: for line in f: jso += line obj = json.loads(jso, object_hook=instance.from_json) if isinstance(obj, Area): return obj else: comm.notify('Could not load area data for {}'.format(number), merc.CONSOLE_ERROR) return None
def load(cls, player_name: str = None, silent=False): if not player_name: raise KeyError("Player name is required to load a player!") pathname = os.path.join(settings.PLAYER_DIR, player_name[0].lower(), player_name.capitalize()) filename = os.path.join(pathname, "player.json") if os.path.isfile(filename): jso = "" with open(filename, "r+") as f: for wline in f: jso += wline obj = json.loads(jso, object_hook=instance.from_json) if isinstance(obj, Pc): obj._last_login = time.time() obj._last_logout = None obj.played = obj.played_fake return obj else: if not silent: comm.notify( "Could not load player file for {}".format( player_name), merc.CONSOLE_ERROR) return None else: if not silent: comm.notify( "Could not open player file for {}".format(player_name), merc.CONSOLE_ERROR) return None
def save(self, force: bool = False): if self.instance_id: top_dir = settings.INSTANCE_DIR number = self.instance_id else: top_dir = settings.AREA_DIR number = self.vnum if self.in_area.instance_id: area_number = self.in_area.instance_id else: area_number = self.in_area.index pathname = os.path.join(top_dir, "%d-%s" % (area_number, self.in_area.name), "rooms") os.makedirs(pathname, 0o755, True) filename = os.path.join(pathname, "%d-room%s" % (number, settings.DATA_EXTN)) comm.notify("Saving {}".format(filename), merc.CONSOLE_INFO) js = json.dumps(self, default=instance.to_json, indent=2, sort_keys=True) md5 = hashlib.md5(js.encode("utf-8")).hexdigest() if self._md5 != md5: self._md5 = md5 with open(filename, "w") as fp: fp.write(js) if self.inventory: for item_id in self.items[:]: if item_id not in instance.items: comm.notify("Item {} is in Room {}'s inventory, but does not exist?".format(item_id, self.instance_id), merc.CONSOLE_ERROR) continue item = instance.items[item_id] item.save(in_inventory=True, force=force)
def p_reset(parea, preset, last, level, npc): if preset.arg1 not in instance.item_templates.keys(): comm.notify("p_reset: 'P': bad vnum {}".format(preset.arg1), merc.CONSOLE_WARNING) return last, level, npc else: item_template = instance.item_templates[preset.arg1] if preset.arg3 not in instance.item_templates.keys(): comm.notify("p_reset: 'P': bad vnum {}".format(preset.arg3), merc.CONSOLE_WARNING) return last, level, npc else: item_to_template = instance.item_templates[preset.arg3] item_to = None item_to_list = instance.instances_by_item.get(item_to_template.vnum, None) if item_to_list: item_to = instance.global_instances[item_to_list[0]] if parea.player_count > 0 or not item_to or not item_to.in_room or handler_item.count_obj_list( item_template, item_to.inventory) > 0: last = False return last, level, npc item = object_creator.create_item(item_template, game_utils.number_range(1, 50)) item_to.put(item) last = True return last, level, npc
def o_reset(parea, preset, last, level, npc): if preset.arg1 not in instance.item_templates.keys(): comm.notify("o_reset: 'O': bad vnum {}".format(preset.arg1), merc.CONSOLE_WARNING) return last, level, npc else: item_template = instance.item_templates[preset.arg1] if preset.arg3 not in instance.room_templates.keys(): comm.notify("o_reset: 'R': bad vnum {}".format(preset.arg3), merc.CONSOLE_WARNING) return last, level, npc else: room_instance_id = instance.instances_by_room[preset.arg3][0] room_instance = instance.global_instances[room_instance_id] if parea.player_count > 0 or handler_item.count_obj_list( item_template, room_instance.items) > 0: last = False return last, level, npc item = object_creator.create_item(item_template, game_utils.number_range(1, 50)) item.cost = 0 room_instance.put(item) last = True return last, level, npc
def cmd_list(ch, argument): argument, arg = game_utils.read_word(argument) buf = [] if ch.in_room.room_flags.is_set(merc.ROOM_PET_SHOP): proomindexnext = None if ch.in_room.vnum + 1 in instance.room_templates: proomindexnext = handler_room.get_room_by_vnum(ch.in_room.vnum + 1) if not proomindexnext: comm.notify("cmd_list: bad pet shop at vnum {}".format(ch.in_room.vnum), merc.CONSOLE_ERROR) ch.send("You can't do that here.\n") return found = False for pet in proomindexnext.people[:]: if pet.act.is_set(merc.ACT_PET): if not found: found = True buf = "Pets for sale:\n" buf += "[{:2}] {:8} - {}\n".format(pet.level, 10 * pet.level * pet.level, pet.short_descr) if not found: buf += "Sorry, we're out of pets right now.\n" ch.send("".join(buf)) return keeper = shop_utils.find_keeper(ch) if not keeper: return items = collections.OrderedDict() for item_id in keeper.inventory[:]: item = instance.items[item_id] cost = shop_utils.get_cost(keeper, item, True) if not item.equipped_to and ch.can_see_item(item) and cost > 0 and (not arg or not game_utils.str_prefix(arg, item.name)): if item.inventory: items[(item.vnum, item.short_descr)] = (item.vnum, -1) else: k = (item.vnum, item.short_descr) if k not in items: items[k] = (item, 1) else: items[k][1] += 1 if not items: if not arg: buf += "You can't buy anything here.\n" else: buf += "You can't buy that here.\n" buf += "[Lv Price] Item\n" for k, p in items.items(): item, count = p cost = shop_utils.get_cost(keeper, item, True) buf += "[{:2} {:5}] {}\n".format(item.level, cost, item.short_descr.capitalize()) ch.send("".join(buf))
def register_spell(entry: skill_type): skill_table[entry.name] = entry spell_lookup_dict[entry.name] = [entry.slot] if settings.DEBUG: comm.notify( " {}:{} registered in skill table".format( entry.slot, entry.name), merc.CONSOLE_BOOT)
def create_room(room_template): if room_template is None: comm.notify("create_room: No roomTemplate given", merc.CONSOLE_CRITICAL) sys.exit(1) room = handler_room.Room(room_template) return room
def cmd_quit(ch, argument): if ch.is_npc(): return if ch.position == merc.POS_FIGHTING: ch.send("No way! You are fighting.\n") return if ch.position < merc.POS_SLEEPING: ch.send("You're not DEAD yet.\n") return mount = ch.mount if mount: ch.cmd_dismount("") # After extract_char the ch is no longer valid! for item_id in ch.equipped.values(): if not item_id: continue item = instance.items[item_id] if not ch.is_npc() and (item.chobj and not item.chobj.is_npc() and item.chobj.obj_vnum != 0) or item.item_type == merc.ITEM_KEY: ch.unequip(item.equipped_to, silent=True, forced=True) ch.save(logout=True, force=True) if ch.obj_vnum != 0: handler_game.act("$n slowly fades out of existance.", ch, None, None, merc.TO_ROOM) else: handler_game.act("$n has left the game.", ch, None, None, merc.TO_ROOM) comm.notify("{} has quit.".format(ch.name), merc.CONSOLE_INFO) if ch.obj_vnum == 0: comm.info("{} has left the God Wars.".format(ch.name)) if ch.chobj: ch.chobj.extract() ch.send("\n I'm a lean dog, a keen dog, a wild dog, and lone;\n" " I'm a rough dog, a tough dog, hunting on my own;\n" " I'm a bad dog, a mad dog, teasing silly sheep;\n" " I love to sit and bay the moon, to keep fat souls from sleep.\n\n") d = ch.desc pid = ch.id ch.extract(True) if d: comm.close_socket(d) # toast evil cheating bastards for d in instance.descriptor_list[:]: tch = handler_ch.ch_desc(d) if tch and tch.id == pid: tch.extract(True) comm.close_socket(d)
def environment(self): # TODO: Remove this once we track down the source. This should never happen. if self._environment == self: # noinspection PyUnresolvedReferences comm.notify("{} environment is set to itself".format(self.name), merc.CONSOLE_ERROR) self._environment = None return instance.global_instances.get(self._environment, None)
def instance_number_save(): if instance.max_instance_id > instance.previous_max_instance_id: instance.previous_max_instance_id = instance.max_instance_id with open(settings.INSTANCE_FILE, "w") as fp: fp.write(str(instance.max_instance_id)) comm.notify( "Saved the current instance number: {}".format( instance.max_instance_id, ), merc.CONSOLE_INFO)
def number_range(a, b): if type(a) != int or type(b) != int: comm.notify("number_range: ({}, {})".format(type(a), type(b)), merc.CONSOLE_WARNING) return -1 if b < a: tmp = b b = a a = tmp return random.randint(a, b)
def load_npcs(area, parea): area, w = game_utils.read_word(area, False) w = w[1:] # strip the pound while w != "0": vnum = int(w) if vnum in instance.npc_templates: comm.notify("load_npcs: vnum {} duplicated.".format(vnum), merc.CONSOLE_CRITICAL) sys.exit(1) npc = handler_npc.Npc() npc.vnum = vnum instance.npc_templates[npc.vnum] = npc npc.area = parea.name area, npc.name = game_utils.read_string(area) npc.name = npc.name.lower() area, npc.short_descr = game_utils.read_string(area) area, npc.long_descr = game_utils.read_string(area) npc.long_descr = miniboa.terminal.escape(npc.long_descr, "ANSI") area, npc.description = game_utils.read_string(area) npc.description = miniboa.terminal.escape(npc.description, "ANSI") area, act = game_utils.read_int(area) npc.act.bits = act | merc.ACT_IS_NPC area, affected_by = game_utils.read_int(area) npc.affected_by.bits = affected_by area, npc.alignment = game_utils.read_int(area) area, letter = game_utils.read_letter(area) area, level = game_utils.read_int(area) npc.level = game_utils.number_fuzzy(level) area, npc.hitroll = game_utils.read_int(area) area, npc.armor = game_utils.read_word(area) area, dummy = game_utils.read_int(area) area = game_utils.read_forward(area) area, dummy = game_utils.read_int(area) area = game_utils.read_forward(area) area, dummy = game_utils.read_int(area) area, dummy = game_utils.read_int(area) area = game_utils.read_forward(area) area, dummy = game_utils.read_int(area) area = game_utils.read_forward(area) area, dummy = game_utils.read_int(area) area, npc.gold = game_utils.read_int(area) area, dummy = game_utils.read_int(area) area, dummy = game_utils.read_int(area) area, dummy = game_utils.read_int(area) area, npc.sex = game_utils.read_int(area) area, w = game_utils.read_word(area, False) w = w[1:] # strip the pound return area
def init_file(path, modules, silent=False, reload=True): # called by init_monitoring to begin tracking a file. modules = [importlib.import_module(m) for m in modules] if reload: tracked_files[path] = [os.path.getmtime(path), modules] else: untrack_files[path] = [os.path.getmtime(path), modules] if not silent: comm.notify(" Tracking {}".format(path), merc.CONSOLE_INFO)
def obj_cast_spell(sn, level, ch, victim, obj): global target_name target = merc.TARGET_NONE if not sn: return if sn not in const.skill_table or not const.skill_table[sn].spell_fun: comm.notify("obj_cast_spell: bad sn {}".format(sn), merc.CONSOLE_ERROR) return sn = const.skill_table[sn] if sn.target == merc.TAR_IGNORE: vo = None elif sn.target == merc.TAR_CHAR_OFFENSIVE: if not victim: victim = ch.fighting if not victim: ch.send("You can't do that.\n") return vo = victim target = merc.TARGET_CHAR elif sn.target == merc.TAR_CHAR_DEFENSIVE: if not victim: victim = ch vo = victim target = merc.TARGET_CHAR elif sn.target == merc.TAR_CHAR_SELF: vo = ch target = merc.TARGET_CHAR elif sn.target == merc.TAR_OBJ_INV: if not obj: ch.send("You can't do that.\n") return vo = obj target = merc.TARGET_ITEM else: comm.notify("obj_cast_spell: bad target for sn {}".format(sn.name), merc.CONSOLE_ERROR) return target_name = "" sn.spell_fun(sn, level, ch, vo, target) if sn.target == merc.TAR_CHAR_OFFENSIVE and victim != ch and instance.characters[ victim.master] != ch: for vch in ch.in_room.people[:]: if victim == vch and not victim.fighting: fight.multi_hit(victim, ch, merc.TYPE_UNDEFINED) break
def pywars(): global server sys.path.append(os.getcwd()) server = TelnetServer(port=PORT) server.on_connect = init_descriptor server.on_disconnect = close_socket init_monitoring() game_loop(server) notify("Termination of game", merc.CONSOLE_CRITICAL)
def add_follower(ch, master): if ch.master: comm.notify("add_follower: non-null master.", merc.CONSOLE_WARNING) return ch.master = master.instance_id ch.leader = None if master.can_see(ch): handler_game.act("$n now follows you.", ch, None, master, merc.TO_VICT) handler_game.act("You now follow $N.", ch, None, master, merc.TO_CHAR)
def init_directory(path, silent=False): ddir = os.listdir(path) files = [f for f in ddir if not f.startswith("__")] if not silent: comm.notify("Tracking {:,} files in {}".format(len(files), path), merc.CONSOLE_INFO) for file in files: full_path = os.path.join(path, file) module = full_path.split(".")[0].replace(os.sep, ".") init_file(full_path, [module], silent)
def __init__(self, port=23, address="", on_connect=_on_connect, on_disconnect=_on_disconnect, max_connections=MAX_CONNECTIONS, timeout=0.05): # Create a new Telnet Server. # # port -- Port to listen for new connection on. On UNIX-like platforms, # you made need root access to use ports under 1025. # # address -- Address of the LOCAL network interface to listen on. You # can usually leave this blank unless you want to restrict traffic # to a specific network device. This will usually NOT be the same # as the Internet address of your server. # # on_connect -- function to call with new telnet connections # # on_disconnect -- function to call when a client's connection dies, # either through a terminated session or client.active being set # to False. # # max_connections -- maximum simultaneous the server will accept at once # # timeout -- amount of time that Poll() will wait from user input # before returning. Also, frees a slice of CPU time. self.port = port self.address = address self.on_connect = on_connect self.on_disconnect = on_disconnect self.max_connections = min(max_connections, MAX_CONNECTIONS) self.timeout = timeout server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) try: server_socket.bind((address, port)) server_socket.listen(5) except socket.error as err: comm.notify( "Unable to create the server socket: {}".format(str(err)), merc.CONSOLE_ERROR) raise self.server_socket = server_socket self.server_fileno = server_socket.fileno() # Dictionary of active clients, # key = file descriptor, value = TelnetClient instance self.clients = {}
def con_get_name(self): argument = self.get_command() name = argument.title() if not check_parse_name(name): self.send("Illegal name, try another.\n" "Name: ") return if not self.character: ch_dummy = CharDummy() ch_dummy.desc = self self.character = ch_dummy ch_dummy.send = self.send else: ch_dummy = self.character ch_dummy.name = name comm.notify("{} trying to connect".format(name), merc.CONSOLE_INFO) ch_dummy.stub = handler_pc.Pc.load_stub(name) if ch_dummy.stub: found = True if ch_dummy.stub["is_banned"]: comm.notify( "Denying access to {}@{}".format(ch_dummy.stub["name"], self.addrport()), merc.CONSOLE_INFO) self.send("You are denied access.\n") comm.close_socket(self) return if settings.WIZLOCK and not ch_dummy.stub["is_immortal"]: self.send("The game is wizlocked.\n") comm.close_socket(self) return if comm.is_reconnecting(self, name): found = True else: found, ch_dummy = save.legacy_load_char_obj(self, name) ch_dummy.send = self.send ch_dummy.desc = self self.character = ch_dummy if found: ch_dummy.send("Please enter password: "******"You want {} engraved on your tombstone (Y/N)? ".format( ch_dummy.name)) self.set_connected(con_confirm_new_name)
def load(cls, instance_id: int = None, vnum: int = None, player_name: str = None): if not vnum and not instance_id: raise ValueError( "You must provide either a vnum or an instance_id!") if vnum and instance_id: raise ValueError( "You must provide either a vnum or an instance_id, not BOTH!") if instance_id and (instance_id in instance.items.keys()): comm.notify( "Instance {} of item already loaded!".format(instance_id), merc.CONSOLE_ERROR) return if not player_name: if instance_id: pathname = settings.INSTANCE_DIR number = instance_id else: pathname = settings.AREA_DIR number = vnum else: pathname = os.path.join(settings.PLAYER_DIR, player_name[0].lower(), player_name.capitalize()) number = instance_id target_file = "{}-item{}".format(number, settings.DATA_EXTN) filename = None for a_path, a_directory, i_files in os.walk(pathname): if target_file in i_files: filename = os.path.join(a_path, target_file) break if not filename: raise ValueError("Cannot find %s" % target_file) jso = "" with open(filename, "r+") as f: for line in f: jso += line obj = json.loads(jso, object_hook=instance.from_json) if not isinstance(obj, Items): raise TypeError("Could not load instance %r!" % number) if obj.inventory: obj.load_inventory(player_name) if obj.environment: if obj.environment.is_room and obj.instance_id not in obj.environment.inventory: obj.environment.put(obj) return obj