#!/usr/bin/python2
# ManaChat simple frontend. Works only on *nix
import asyncore
import logging
import os
import sys
import readline
import thread
import struct
import fcntl
import termios
from collections import deque
from ConfigParser import ConfigParser
try:
import construct
del construct
except ImportError:
import os
sys.path.insert(0, os.path.join(os.getcwd(), "external"))
import net
import net.mapserv as mapserv
import plugins
from utils import extends
from itemdb import load_itemdb
from monsterdb import read_monster_db
from loggers import debuglog
import commands
from logicmanager import logic_manager
PROMPT = '] '
input_buffer = deque()
def input_thread():
while True:
s = raw_input(PROMPT)
input_buffer.append(s)
# ~ time.sleep(0.2) # Attempt to reduce CPU usage on bad connection
class DebugLogHandler(logging.Handler):
def clear_curr_input(self):
# http://stackoverflow.com/questions/2082387/reading-input-from-raw-input-without-having-the-prompt-overwritten-by-other-th?rq=1
_, cols = struct.unpack('hh',
fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ, '1234'))
tl = len(readline.get_line_buffer()) + len(PROMPT)
# ANSI escape sequences (All VT100 except ESC[0G)
sys.stdout.write('\x1b[2K') # Clear current line
sys.stdout.write('\x1b[1A\x1b[2K' * (tl / cols)) # cur up & clr line
sys.stdout.write('\x1b[0G') # to start of line
def emit(self, record):
self.clear_curr_input()
print self.format(record)
sys.stdout.write(PROMPT + readline.get_line_buffer())
sys.stdout.flush()
@extends('smsg_player_warp')
def player_warp(data):
mapserv.cmsg_map_loaded()
m = "[warp] {} ({},{})".format(data.map, data.x, data.y)
debuglog.info(m)
@extends('smsg_map_login_success')
def map_login_success(data):
mapserv.server.raw = True
mapserv.cmsg_map_loaded()
@extends('smsg_whisper_response')
def send_whisper_result(data):
if data.code == 0:
if len(readline.get_line_buffer()) == 0:
last_nick = mapserv.last_whisper['to']
readline.insert_text('/w "{}" '.format(last_nick))
readline.redisplay()
if __name__ == '__main__':
try:
rootLogger = logging.getLogger('')
rootLogger.addHandler(logging.NullHandler())
dbgh = DebugLogHandler()
dbgh.setFormatter(logging.Formatter("[%(asctime)s] %(message)s",
datefmt="%Y-%m-%d %H:%M:%S"))
debuglog.addHandler(dbgh)
debuglog.setLevel(logging.INFO)
config_ini = 'manachat.ini'
if len(sys.argv) > 1:
if sys.argv[1].endswith('.ini') and os.path.isfile(sys.argv[1]):
config_ini = sys.argv[1]
config = ConfigParser()
config.read(config_ini)
if config.getboolean('Other', 'log_network_packets'):
from loggers import netlog
netlog.setLevel(logging.INFO)
fh = logging.FileHandler('/tmp/netlog.txt', mode="w")
fmt = logging.Formatter("[%(asctime)s] %(message)s",
datefmt="%Y-%m-%d %H:%M:%S")
fh.setFormatter(fmt)
netlog.addHandler(fh)
load_itemdb('itemdb.txt')
read_monster_db('monsterdb.txt')
plugins.load_plugins(config)
net.login(host=config.get('Server', 'host'),
port=config.getint('Server', 'port'),
username=config.get('Player', 'username'),
password=config.get('Player', 'password'),
charname=config.get('Player', 'charname'))
thread.start_new_thread(input_thread, ())
while True:
if len(input_buffer) > 0:
for l in input_buffer:
commands.process_line(l)
input_buffer.clear()
asyncore.loop(timeout=0.2, count=5)
logic_manager.tick()
except Exception as e:
print(e) ## Fails on Keyboard interrupt
os._exit(255)
except KeyboardInterrupt:
print("Interrupted by keyboard")
os._exit(255)