from asyncore import dispatcher from asynchat import async_chat import socket, asyncore, time, sys from login import * from admin import * ## # GLOBAL PARAMETERS - Change them to what you need. ## PORT = 4000 LOGFILE = "mainlog" # Change to where the logfile should go. ## # Nothing to edit below this, unless you know what you're doing. ## # ANSI is turned off by default. # I am not using the other ANSI possibilities on purpose. If you want to add # backgrounds and blinking, you're on your own. BLACK = '' RED = '' GREEN = '' YELLOW = '' BLUE = '' MAGENTA = '' CYAN = '' WHITE = '' RESET = '' BOLD = '' # Global dictionaries holding the player's ID, socket and IP address. sessions = {} ipsessions = {} logger = open(LOGFILE, 'a') def Log(line): "Just call Log('text') to log to a file." timer = '' timer = time.asctime() logger.write(line + " " + timer + "\n") logger.flush() class Handler: "Command parser, where all player commands go." def unknown(self, session, cmd): session.push('Unknown command: %s\r\n' % cmd) def handle(self, session, line): self.checkbit = 0 #Time of last command executed. Will be used for external timeout cleanup. cu.execute("update pnames set last_command = %s where p_id = %s", time.time(), session.p_id) if not line.strip(): session.push("> ") parts = line.split(' ', 1) cmd = parts[0] if cmd == '': pass else: try: line = parts[1].strip() except IndexError: line = '' admincmd = AdminCmds(sessions, ipsessions) meth = getattr(self, 'do_'+cmd, None) # Normal commands methadm = getattr(admincmd, 'do_'+cmd, None) # Admin commands, admin.py for i in self.coders: # SECURITY CHECK if i == session.pname: self.checkbit = 1 else: pass if (self.checkbit == 1) & (callable(methadm)): # Is a coder methadm(session, line) session.push("> ") elif callable(meth): # Is a player, do not let them use AdminCmds() meth(session, line) session.push("> ") else: self.unknown(session, cmd) session.push("> ") def RoomBroadcast(self, session, inroom, line): "By calling this method, 'line' is sent to all players in 'inroom'." cu.execute("select p_id from pnames where is_in = %s", inroom) self.local = cu.fetchall() self.pnamer = BOLD+WHITE + session.pname + RESET if line == '': pass else: for i in self.local: self.tmpses = sessions.get(i[0]) # sessions dict if self.tmpses == '': # Player is not logged in pass elif self.tmpses.p_id == session.p_id: # Is the player pass else: self.tmpses.push(self.pnamer + line+"\r\n> ") def do_look(self, session, line): #Check if looked-at player is there cu.execute("select p_id,description,is_in,names from pnames where names = %s and is_in = %s", line.lower(), session.is_in) self.peeps = cu.fetchall() #Get list of items possessed by player. cu.execute("select instances.parent_id,instances.is_owned,instances.is_in,objects.obj_id,objects.name,objects.description\ from instances,objects where instances.parent_id = objects.obj_id\ and instances.is_owned = %s and objects.name = %s", session.p_id, line.lower()) self.foo = cu.fetchall() #Get list of mobs in the room. cu.execute("select instances.parent_id,instances.sub_id,instances.is_owned,instances.is_in,\ npcs.npc_id,npcs.name,npcs.description,instances.id\ from instances,npcs where instances.sub_id = 2 and instances.is_owned = 0 and instances.parent_id = npcs.npc_id\ and instances.is_in = %s and npcs.name = %s", session.is_in, line.lower()) self.mobonfloor = cu.fetchall() #Get list of objects in the room. cu.execute("select instances.parent_id,instances.sub_id,instances.is_owned,instances.is_in,\ objects.obj_id,objects.name,objects.description,objects.alias\ from instances,objects where instances.sub_id = 1 and instances.is_owned = 0 and instances.parent_id = objects.obj_id\ and instances.is_in = %s", session.is_in) self.obj = cu.fetchall() if line != '': # Not looking at the room try: if self.peeps != []: #Looking at a player self.descri = self.peeps[0][1].split('\\n') for i in self.descri: session.push(str(i) + "\r\n") session.push("Inventory:\r\n") cu.execute("select parent_id,is_owned from instances where is_owned = %s", self.peeps[0][0]) self.invent = cu.fetchall() if self.invent != []: for i in self.invent: cu.execute("select obj_id,name from objects where obj_id = %s", i[0]) self.has = cu.fetchall() session.push(str(self.has[0][1]) + "\r\n") else: session.push("Empty.\r\n") self.RoomBroadcast(session, session.is_in, " looks at " + line) elif self.foo != []: #An object in your inventory self.descri = self.foo[0][5].split('\\n') for i in self.descri: session.push(str(i) + "\r\n") elif self.mobonfloor != []: #A mob/NPC cu.execute("select instances.parent_id,instances.sub_id,instances.is_owned,instances.is_in,\ objects.obj_id,objects.name,instances.npc_own\ from instances,objects where instances.sub_id = 1 and instances.is_owned = 0 and instances.parent_id = objects.obj_id\ and instances.is_in = 0 and instances.npc_own = %s", self.mobonfloor[0][7]) self.mobinv = cu.fetchall() self.descri = self.mobonfloor[0][6].split('\\n') # Print the description for i in self.descri: session.push(str(i) + "\r\n") if self.mobinv != []: # Print the mob's inventory self.stuff = [] self.stufa = {} session.push(BOLD+WHITE+"Inventory:\r\n"+RESET) for i in self.mobinv: self.stuff.append(i[5]) self.stufa[i[5]] = self.stuff.count(i[5]) for i in self.stufa: if self.stufa[i] > 1: session.push(str(i) + " ("+str(self.stufa[i])+")" + "\r\n") else: session.push(str(i) + "\r\n") else: pass elif self.obj != []: #An item on the floor for i in self.obj: if i[5] == line.lower(): self.descri = i[6].split('\\n') for y in self.descri: session.push(str(y) + "\r\n") else: # Check if an alias is defined. try: self.objalias = i[7].split(':') self.ind = self.objalias.count(line.lower()) if self.ind > 0: self.descri = i[6].split('\\n') for y in self.descri: session.push(str(y) + "\r\n") self.action = 1 else: session.push("You do not see that here.\r\n") except: pass else: session.push("You do not see that here.\r\n") except: session.push("ERROR - You do not see that here.\r\n") else: #No argument, look at room cu.execute("select short_desc,long_desc from rooms where r_id = %s", session.is_in) self.descr = cu.fetchone() session.push(CYAN+str(self.descr[0]) + RESET + "\r\n") self.descri = self.descr[1].split('\\n') for i in self.descri: session.push(str(i) + "\r\n") cu.execute("select names from pnames where is_in = %s", session.is_in) self.look_com = cu.fetchall() session.push("\r\n" + BOLD + RED) for i in self.look_com: session.push(str(i[0].capitalize()) + "\r\n") session.push(RESET + "\r\n") #Get list of mobs in the room. cu.execute("select instances.parent_id,instances.sub_id,instances.is_owned,instances.is_in,\ npcs.npc_id,npcs.name\ from instances,npcs where instances.sub_id = 2 and instances.is_owned = 0 and instances.parent_id = npcs.npc_id\ and instances.is_in = %s", session.is_in) self.mobonfloor = cu.fetchall() #Get list of objects in the room. cu.execute("select instances.parent_id,instances.sub_id,instances.is_owned,instances.is_in,\ objects.obj_id,objects.name\ from instances,objects where instances.sub_id = 1 and instances.is_owned = 0 and instances.parent_id = objects.obj_id\ and instances.is_in = %s", session.is_in) self.objonfloor = cu.fetchall() if self.mobonfloor == []: pass #If there's nobody don't print a newline else: for i in self.mobonfloor: session.push(BOLD+MAGENTA + str(i[5]) + " " + RESET) session.push("\r\n") if self.objonfloor == []: pass #If there's nothing don't print a newline else: self.flo = [] self.fla = {} for i in self.objonfloor: self.flo.append(i[5]) self.fla[i[5]] = self.flo.count(i[5]) for i in self.fla: if self.fla[i] > 1: session.push(BOLD+GREEN+str(i)+RESET+" ("+str(self.fla[i])+")"+" ") else: session.push(BOLD+GREEN+str(i)+RESET+" ") session.push("\r\n") # List exits session.push(BOLD+CYAN + "Exits: ") cu.execute("select direction from links where room_id = %s", session.is_in) self.tmpgoto = cu.fetchall() for i in self.tmpgoto: session.push(i[0] + " ") session.push(RESET + "\r\n") def do_drop(self, session, line): try: cu.execute("select instances.id,instances.is_owned,objects.obj_id,objects.name\ from instances,objects where instances.parent_id = objects.obj_id\ and instances.is_owned = %s and objects.name = %s", session.p_id, line.lower()) self.drop = cu.fetchone() cu.execute("update instances set is_owned = 0 where id = %s", self.drop[0]) cu.execute("update instances set is_in = %s where id = %s", session.is_in, self.drop[0]) session.push(str(self.drop[3])+" dropped.\r\n") except: session.push("You cannot drop this.\r\n") def do_go(self, session, line): if not line: session.push("You don't go anywhere.\r\n") else: try: cu.execute("select direction, exit from links where room_id = %s and direction = %s", session.is_in, line) self.isexit = cu.fetchone() except: session.push("No exit this way.\r\n") try: cu.execute("select tor from exits where exit_id = %s", self.isexit[1]) self.goto = cu.fetchone() # Actually move self.movemsg = " leaves " + str(self.isexit[0]) + "." self.RoomBroadcast(session, session.is_in, self.movemsg) cu.execute("update pnames set is_in = %s where p_id = %s", self.goto[0], session.p_id) session.is_in = self.goto[0] self.RoomBroadcast(session, session.is_in, " enters the room.") self.do_look(session, '') # Force a look, to be replaced by something nicer. except: session.push("You can't move that way.\r\n") def do_say(self, session, line): self.says = " says: " + line session.push("You say: " + line + "\r\n") self.RoomBroadcast(session, session.is_in, self.says) def do_chat(self, session, line): cu.execute("select p_id from pnames where is_in > 0") self.everybody = cu.fetchall() self.talker = BOLD+WHITE + session.pname + RESET for i in self.everybody: self.listen = sessions.get(i[0]) if self.listen == None: pass else: self.listen.push(BOLD+GREEN+"["+RESET+ self.talker +BOLD+GREEN+"] "+RESET + line + "\r\n") def do_logout(self, session, line): raise EndSession def do_who(self, session, line): session.push("The following players are logged on:\r\n") cu.execute("select names from pnames where is_in > 0") self.whoin = cu.fetchall() for i in self.whoin: session.push(BOLD + RED + str(i[0].capitalize() + RESET) + "\r\n") session.push("\r\n") def do_help(self, session, line): if line == '': # help command alone cu.execute("select command from helps") self.allh = cu.fetchall() self.allhelp = [] for i in self.allh: self.allhelp.append(i[0]) self.allhelp.sort() self.counter = 0 for i in self.allhelp: self.counter += 1 #Make 2 columns of help files self.counter = self.counter / 2 self.counter = int(self.counter) self.first = self.allhelp[:self.counter] self.second = self.allhelp[self.counter:] session.push("The following help topics exist:\r\n") for x, y in map(None, self.first, self.second): if x == None: x = ' ' session.push(str(x).ljust(15) + str(y).ljust(10) + "\r\n") else: session.push(str(x).ljust(15) + str(y).ljust(10) + "\r\n") else: #If help <foo> try: cu.execute("select command, doc from helps where command = %s", line) self.helper = cu.fetchone() session.push("Help for " + line + ":\r\n") self.docu = self.helper[1].split('\\n') for i in self.docu: session.push(i + "\r\n") session.push("\r\n") except: session.push("Help is not available on this topic.\r\n") def do_description(self, session, line): cu.execute("update pnames set description = %s where p_id = %s", line, session.p_id) session.push("Description set.\r\n") def do_inv(self, session, line): cu.execute("select instances.id,instances.is_owned,objects.obj_id,objects.name\ from instances,objects where instances.parent_id = objects.obj_id\ and instances.is_owned = %s", session.p_id) self.owned = cu.fetchall() self.stuff = [] self.stufa = {} session.push(BOLD + WHITE + "Inventory:\r\n" + RESET) for i in self.owned: self.stuff.append(i[3]) self.stufa[i[3]] = self.stuff.count(i[3]) for i in self.stufa: if self.stufa[i] > 1: session.push(BOLD+GREEN+str(i)+RESET+" ("+str(self.stufa[i])+")"+"\r\n") else: session.push(BOLD+GREEN+str(i)+RESET+"\r\n") def do_get(self, session, line): cu.execute("select instances.parent_id,instances.sub_id,instances.is_owned,instances.is_in,instances.id,\ objects.obj_id,objects.name,objects.description\ from instances,objects where instances.sub_id = 1 and instances.is_owned = 0 and instances.parent_id = objects.obj_id\ and instances.is_in = %s", session.is_in) self.objonfloor = cu.fetchall() self.iterfloor = iter(self.objonfloor) self.action = 0 for i in self.iterfloor: if (i[6] == line.lower()) & (self.action == 0): session.push("You get "+line+".\r\n") cu.execute("update instances set is_in = 0 where sub_id = 1 and id = %s", i[4]) cu.execute("update instances set is_owned = %s where sub_id = 1 and id = %s", session.p_id, i[4]) self.action = 1 elif self.action == 1: pass if self.action == 0: session.push("This is not here.\r\n") def do_emote(self, session, line): self.emote = " " + line self.RoomBroadcast(session, session.is_in, self.emote) session.push("Emote: " + session.pname + self.emote + "\r\n") def do_give(self, session, line): if line == '' : session.push("Correct syntax is:\r\ngive <item> to <player>\r\n") else: self.argu = line.lower() if not self.argu.strip(): session.push("> ") self.parts = line.split(' ', 3) if self.parts[1] == "to": try: cu.execute("select instances.id,instances.is_owned,objects.obj_id,objects.name\ from instances,objects where instances.parent_id = objects.obj_id\ and instances.is_owned = %s and objects.name = %s", session.p_id, self.parts[0].lower()) self.itom = cu.fetchall() # Given item info cu.execute("select p_id, names, is_in from pnames where names = %s and is_in = %s", self.parts[2].lower(), session.is_in) self.transf = cu.fetchall() # Receiver's info # Check if given to a mob. cu.execute("select instances.parent_id,instances.sub_id,instances.is_owned,instances.is_in,\ npcs.npc_id,npcs.name,instances.id\ from instances,npcs where instances.sub_id = 2 and instances.is_owned = 0 and instances.parent_id = npcs.npc_id\ and instances.is_in = %s and npcs.name = %s", session.is_in, self.parts[2]) self.mob = cu.fetchall() if self.transf != []: cu.execute("update instances set is_owned = %s where id = %s", self.transf[0][0], self.itom[0][0]) session.push("You give "+self.parts[0]+" to "+self.parts[2]+".\r\n") self.give = " gives " + self.parts[0] + " to " + self.parts[2] self.RoomBroadcast(session, session.is_in, self.give) elif self.mob != []: cu.execute("update instances set npc_own = %s where id = %s", self.mob[0][6], self.itom[0][0]) cu.execute("update instances set is_owned = 0 where id = %s", self.itom[0][0]) session.push("You give "+self.parts[0]+" to "+self.parts[2]+".\r\n") self.give = " gives " + self.parts[0] + " to " + self.parts[2] self.RoomBroadcast(session, session.is_in, self.give) else: session.push("This somehow fails.\r\n") except: session.push("Correct syntax is:\r\ngive <item> to <player>\r\n") else: session.push("Correct syntax is:\r\ngive <item> to <player>\r\n") def do_stats(self, session, line): cu.execute("select names,str,dex,wis,p_id from pnames where p_id = %s", session.p_id) self.stats = cu.fetchone() session.push(BOLD+WHITE+"Stats for " + str(self.stats[0].capitalize()) +RESET+"\r\n") session.push("STR: " + str(self.stats[1]) + "\r\n") session.push("DEX: " + str(self.stats[2]) + "\r\n") session.push("WIS: " + str(self.stats[3]) + "\r\n") def do_setansi(self, session, arg): global BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET, BOLD if arg == "on": BLACK, RED, GREEN = '\033[30m', '\033[31m', '\033[32m' YELLOW, BLUE, MAGENTA = '\033[33m', '\033[34m', '\033[35m' CYAN, WHITE = '\033[36m', '\033[37m' RESET, BOLD = '\033[0;0m', '\033[1m' cu.execute("update pnames set colors = %s where p_id = %s", arg, session.p_id) elif arg == "off": BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET, BOLD = '','','','','','','','','','' cu.execute("update pnames set colors = %s where p_id = %s", arg, session.p_id) else: session.push("Syntax:\r\nsetansi [off|on]\r\n") # Shortcuts def do_n(self, session, line): self.do_go(session, 'north') def do_s(self, session, line): self.do_go(session, 'south') def do_w(self, session, line): self.do_go(session, 'west') def do_e(self, session, line): self.do_go(session, 'east') def do_u(self, session, line): self.do_go(session, 'up') def do_d(self, session, line): self.do_go(session, 'down') def do_se(self, session, line): self.do_go(session, 'southeast') def do_sw(self, session, line): self.do_go(session, 'southwest') def do_nw(self, session, line): self.do_go(session, 'northwest') def do_ne(self, session, line): self.do_go(session, 'northeast') do_north = do_n do_south = do_s do_west = do_w do_east = do_e do_up = do_u do_down = do_d do_quit = do_logout do_exit = do_logout do_i = do_inv do_l = do_look class EndSession(Exception): pass class EnterGame(Handler): def __init__(self, session): self.session = session self.admin = [] self.coders = [] # Initialize the permissions from the "arch" and "coders" files # Arch file, uncomment if needed. For the sysadmin. #self.arch = open('arch', 'r') #self.iarch = iter(self.arch) #for line in self.iarch: # self.admin.append(line.strip('\n')) #self.arch.close() #Coders file, for in-game creators/wizards/builders self.coder = open('coders', 'r') self.icoder = iter(self.coder) for line in self.icoder: self.coders.append(line.strip('\n')) self.coder.close() def enter(self, room): self.room = room room.add(self, self.session) def found_terminator(self): line = (''.join(self.data)) self.data = [] if line == '': session.push("> ") else: try: self.handle(self, line) except: raise EndSession def add(self, session): self.ival = ipsessions.items() for i in self.ival: if session.ipaddr == "127.0.0.1": pass elif session.ipaddr == i[1]: session.push("You are already connected!\r\n\r\n") raise EndSession else: pass cu.execute("update pnames set is_in = 1 where p_id = %s", session.p_id) sessions[session.p_id] = session ipsessions[session.p_id] = session.ipaddr cu.execute("update pnames set ip_addr = %s where p_id = %s", session.ipaddr, session.p_id) #Store the player's starting location in the socket object. session.is_in = 1 cu.execute("select p_id from pnames where is_in > 0") self.locala = cu.fetchall() cu.execute("select names from pnames where p_id = %s", session.p_id) self.pnamera = cu.fetchall() # Initialize ANSI colors cu.execute("select colors from pnames where p_id = %s", session.p_id) self.colorize = cu.fetchone() self.colorize = self.colorize[0].strip() if self.colorize == "on": self.do_setansi(session, "on") else: self.do_setansi(session, "off") self.pnamera = BOLD+WHITE + self.pnamera[0][0].capitalize() + RESET for i in self.locala: self.tmpsess = sessions.get(i[0]) if self.tmpsess == None: pass else: self.tmpsess.push(self.pnamera + " enters the game.\r\n") self.tmpsess.push("\r\n> ") print self.pnamera + " logged in." Log(session.pname + " logged in from " + session.ipaddr) self.do_look(session, '') # To be replaced with something nicer. session.push("> ") class SecondServSock(async_chat): #The chat server def __init__(self, server, sock, addr): async_chat.__init__(self, sock) self.server = server self.ipaddr = addr self.set_terminator("\n") self.name = None self.data = [] self.sock = sock self.enter(FirstLogin(server, self.ipaddr)) #Call the login procedure before anything. def collect_incoming_data(self, data): self.data.append(data) def found_terminator(self): line = (''.join(self.data)) line = line.strip('\r') self.data = [] try: self.room.handle(self, line) except EndSession: self.handle_close() def handle_close(self): self.ival = ipsessions.items() for i in self.ival: self.sockobj = sessions[i[0]] self.test = str(self.sockobj) self.tesb = str(self.sock) try: if (self.ipaddr == i[1]) & (self.test == self.tesb): cu.execute("select names from pnames where p_id = %s", i[0]) self.leaver = cu.fetchone() #In any case, if the player exits, remove him. cu.execute("update pnames set is_in = 0 where p_id = %s", i[0]) cu.execute("update pnames set ip_addr = NULL where p_id = %s", i[0]) Log("Disconnected from " + self.ipaddr) sessions[i[0]] = '' ipsessions[i[0]] = '' cu.execute("select p_id from pnames where is_in > 0") self.locali = cu.fetchall() self.leaver = BOLD+WHITE + self.leaver[0].capitalize() + RESET print self.leaver + " logged out." for i in self.locali: self.tmpsec = sessions[i[0]] if self.tmpsec == None: pass else: self.tmpsec.push(self.leaver + " leaves the game.\r\n") self.tmpsec.push("\r\n> ") async_chat.handle_close(self) else: pass except: pass def handle_error(self): self.handle_close() def enter(self, room): self.room = room room.add(self) class MainServSock(dispatcher): # The Server def __init__(self, port): dispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_addr() self.bind(('', port)) self.listen(10) self.enterg = EnterGame(self) def handle_accept(self): conn, addr = self.accept() SecondServSock(self, conn, addr) if __name__ == '__main__': s = MainServSock(PORT) # Everybody at room #0 when we start, obvious. cu.execute("update pnames set is_in = 0") try: asyncore.loop() except KeyboardInterrupt: print