import net.mapserv as mapserv from net.inventory import get_item_index from net.common import distance import itemdb from utils import preprocess_argument from textutils import expand_links from loggers import debuglog import walkto from actor import find_nearest_being import status import chat import badge __all__ = [ 'commands', 'must_have_arg', 'parse_player_name', 'process_line' ] def must_have_arg(func): def wrapper(cmd, arg): if len(arg) > 0: return func(cmd, arg) wrapper.__doc__ = func.__doc__ return wrapper @preprocess_argument(expand_links) def general_chat(msg): '''Send message to #General chat''' chat.general_chat(msg) @must_have_arg def send_whisper(_, arg): '''Send whisper to player /w "Player Name" Message... /w NameWithourSpaces Message''' nick, message = parse_player_name(arg) if len(nick) > 0 and len(message) > 0: chat.send_whisper(nick, message) @must_have_arg def send_party_message(_, msg): '''Sent message to party''' mapserv.cmsg_party_message(msg) @must_have_arg def set_direction(_, dir_str): '''/turn down|up|left|right''' d = {"down": 1, "left": 2, "up": 4, "right": 8} dir_num = d.get(dir_str.lower(), -1) if dir_num > 0: mapserv.cmsg_player_change_dir(dir_num) def sit_or_stand(cmd, _): '''Use /sit or /stand for corresponding action''' a = {"sit": 2, "stand": 3} try: action = a[cmd] mapserv.cmsg_player_change_act(0, action) except KeyError: pass @must_have_arg def set_destination(_, xy): '''/goto x y -- walk to given coordinates''' try: x, y = map(int, xy.split()) mapserv.cmsg_player_change_dest(x, y) except ValueError: pass @must_have_arg def show_emote(_, emote): '''Smile! /emote ID''' try: mapserv.cmsg_player_emote(int(emote)) except ValueError: pass @must_have_arg def attack(_, arg): '''Attack being (ID or Name)''' try: target = mapserv.beings_cache[int(arg)] except (ValueError, KeyError): target = find_nearest_being(name=arg, ignored_ids=walkto.unreachable_ids) if target is not None: walkto.walkto_and_action(target, 'attack') else: debuglog.warning("Being %s not found", arg) @must_have_arg def me_action(_, arg): '''You can guess :-)''' general_chat("*{}*".format(arg)) @must_have_arg def item_action(cmd, name_or_id): '''/use /equip /unequip item can be either item name or ID''' item_id = -10 item_db = itemdb.item_names try: item_id = int(name_or_id) except ValueError: for id_, name in item_db.iteritems(): if name == name_or_id: item_id = id_ if item_id < 0: debuglog.warning("Unknown item: %s", name_or_id) return index = get_item_index(item_id) if index > 0: if cmd == 'use': mapserv.cmsg_player_inventory_use(index, item_id) elif cmd == 'equip': mapserv.cmsg_player_equip(index) elif cmd == 'unequip': mapserv.cmsg_player_unequip(index) else: debuglog.error("You don't have %s", name_or_id) @must_have_arg def drop_item(_, arg): '''/drop ''' s = arg.split(None, 1) try: amount = int(s[0]) except ValueError: debuglog.warning('Usage: /drop ') return item_id = -10 item_db = itemdb.item_names try: item_id = int(s[1]) except ValueError: for id_, name in item_db.iteritems(): if name == s[1]: item_id = id_ if item_id < 0: debuglog.warning("Unknown item: %s", s[1]) return index = get_item_index(item_id) if index > 0: mapserv.cmsg_player_inventory_drop(index, amount) else: debuglog.error("You don't have %s", s[1]) def show_inventory(*unused): '''Show inventory''' inv = {} for itemId, amount in mapserv.player_inventory.values(): inv[itemId] = inv.setdefault(itemId, 0) + amount s = [] for itemId, amount in inv.items(): if amount > 1: s.append('{} [{}]'.format(amount, itemdb.item_name(itemId))) else: s.append('[{}]'.format(itemdb.item_name(itemId))) debuglog.info(', '.join(s)) def show_zeny(*unused): '''Show player money''' debuglog.info('You have {} GP'.format(mapserv.player_money)) def print_beings(cmd, btype): '''Show nearby beings /beings -- show all beings /beings player|npc|portal|monster --show only given being type''' for l in status.nearby(btype): debuglog.info(l) def player_position(*unused): '''Show player position''' debuglog.info(status.player_position()) def respawn(*unused): '''Respawn''' mapserv.cmsg_player_respawn() def pickup(*unused): '''Pickup nearby item, if any''' px = mapserv.player_pos['x'] py = mapserv.player_pos['y'] for item in mapserv.floor_items.values(): if distance(px, py, item.x, item.y) < 2: mapserv.cmsg_item_pickup(item.id) def show_status(_, arg): '''Show various stats''' if arg: all_stats = arg.split() else: all_stats = ('stats', 'hpmp', 'weight', 'points', 'zeny', 'attack', 'skills') sr = status.stats_repr(*all_stats) debuglog.info(' | '.join(sr.values())) def cmd_afk(_, arg): '''Become AFK''' if arg: chat.afk_message = '*AFK* ' + arg badge.is_afk = True debuglog.info(chat.afk_message) def cmd_back(*unused): '''Disable AFK''' badge.is_afk = False def print_help(_, hcmd): '''Show help /help -- show all commands /help CMD -- show help on CMD''' s = ' '.join(commands.keys()) if hcmd in commands: docstring = commands[hcmd].__doc__ if docstring: debuglog.info(docstring) else: debuglog.info('No help available for command /{}'.format(hcmd)) else: debuglog.info("[help] commands: %s", s) def cmd_exec(_, arg): try: exec arg except Exception, e: debuglog.error(e.message) def command_not_found(cmd): debuglog.warning("[warning] command not found: %s. Try /help.", cmd) def parse_player_name(line): line = line.lstrip() if len(line) < 2: return "", "" if line[0] == '"': end = line[1:].find('"') if end < 0: return line[1:], "" else: return line[1:end + 1], line[end + 3:] else: end = line.find(" ") if end < 0: return line, "" else: return line[:end], line[end + 1:] commands = { "w" : send_whisper, "whisper" : send_whisper, "p" : send_party_message, "party" : send_party_message, "e" : show_emote, "emote" : show_emote, "dir" : set_direction, "direction" : set_direction, "turn" : set_direction, "sit" : sit_or_stand, "stand" : sit_or_stand, "goto" : set_destination, "nav" : set_destination, "dest" : set_destination, "me" : me_action, "use" : item_action, "equip" : item_action, "unequip" : item_action, "attack" : attack, "beings" : print_beings, "inv" : show_inventory, "zeny" : show_zeny, "where" : player_position, "respawn" : respawn, "pickup" : pickup, "drop" : drop_item, "status" : show_status, "afk" : cmd_afk, "back" : cmd_back, "help" : print_help, "exec" : cmd_exec, } def process_line(line): if line == "": return elif line[0] == "/": end = line.find(" ") if end < 0: cmd = line[1:] arg = "" else: cmd = line[1:end] arg = line[end + 1:] if cmd in commands: func = commands[cmd] func(cmd, arg) else: command_not_found(cmd) else: general_chat(line)