import zlib _imports = ["lib_markup"] _parents = [] _version = 1 #The avatar object handles negotiation of mud client protocols and formatting of the the text between server and #client to fit those protocols. Once that is done, it's derived classes handle input and output between the client. ANSIColorMapping = {"-c":"\x1B[0m", "b+":"\x1B[1m", "b-":"\x1B[22m", "i+":"\x1B[3m", "i-":"\x1B[23m", "u+":"\x1B[4m", "u-":"\x1B[24m", "n+":"\x1B[7m", "n-":"\x1B[27m", "s+":"\x1B[9m", "s-":"\x1B[29m", "fz":"\x1B[30m", "fr":"\x1B[31m", "fg":"\x1B[32m", "fy":"\x1B[33m", "fb":"\x1B[34m", "fp":"\x1B[35m", "fc":"\x1B[36m", "fw":"\x1B[37m", "fd":"\x1B[39m", "fZ":"\x1B[1m\x1B[30m", "fR":"\x1B[1m\x1B[31m", "fG":"\x1B[1m\x1B[32m", "fY":"\x1B[1m\x1B[33m", "fB":"\x1B[1m\x1B[34m", "fP":"\x1B[1m\x1B[35m", "fC":"\x1B[1m\x1B[36m", "fW":"\x1B[1m\x1B[37m", "b0":"\x1B[40m", "br":"\x1B[41m", "bg":"\x1B[42m", "by":"\x1B[43m", "bb":"\x1B[44m", "bp":"\x1B[45m", "bc":"\x1B[46m", "bw":"\x1B[47m", "bd":"\x1B[49m"} MXPMapping = {"xo":"\x1B[0z","xs":"\x1B[1z","xl":"\x1B[2z", "xr":"\x1B[3z", "xn":"\x1B[4z", "lo":"\x1B[5z", "ls":"\x1B[6z", "ll":"\x1B[7z"} ansiTypes = ["zmud", "vt100", "ansi"] def _Sys_Create(self, client): self._persist = True self.client = client self.useMXP = False self.useMXPSound = False self.useMSP = False self.useMCCP = False self.useMCCP2 = False self.useANSI = False self.sendBuffer = "" self.MXPOnly = False self.notMXPOnly = False self.terminalType = "" self.permissions = {} def Avatar_Connect(self): #IAC WILL TERMINALTYPE, IAC WILL MXP, IAC WILL MSP, IAC WILL COMPRESS2, IAC WILL COMPRESS sendString = "\xFF\xFB\x18\xFF\xFB\x5B\xFF\xFB\x5A\xFF\xFB\x56\xFF\xFB\x55" self.Avatar_RawSend(sendString) #Abstract: called upon client going linkdead. def Avatar_Linkdeath(self): pass #Abstract: called upon client being disconnected by the game, IE by a quit command. def Avatar_Disconnect(self): pass def _Sys_TelnetDO(self, doType): #DO MXP if doType == "\x5B": self.useMXP = True self.useMXPSound = True #DO MSP elif doType == "\x5A": self.useMSP = True #DO COMPRESS2 elif doType == "\x56": if self.useMCCP == True: self.useMCCP = False #Send the client our compression stream notice. #IAC SB COMPRESS2 IAC SE self.Avatar_RawSend("\xFF\xFA\x56\xFF\xF0") self.useMCCP2 = True self.compressObj = zlib.compressobj() #DO COMPRESS elif doType == "\x55": #If we're already using MCCP2, no need to use MCCP. if self.useMCCP2 == False: #Same as above. #IAC SB COMPRESS WILL SE - Note that the SE is not prefixed by WILL, not IAC self.Avatar_RawSend("\xFF\xFA\x56\xFB\xF0") self.useMCCP = True self.compressObj = zlib.compressobj() #DO TERMINALTYPE elif doType == "\x18": #IAC SB TERMINALTYPE SEND IAC SE self.Avatar_RawSend("\xFF\xFA\x18\x01\xFF\xF0") def _Sys_TelnetDONT(self, dontType): #DONT MXP if dontType == "\x5B": self.useMXP = False self.useMXPSound = False #DONT MSP elif dontType == "\x5A": self.useMSP = False #DONT COMPRESS2 elif dontType == "\x56": if self.useMCCP2: self.client.Send(self.compressObj.flush(zlib.Z_FINISH)) self.useMCCP2 = False self.compressObj = None #DONT COMPRESS elif dontType == "\x55": if self.useMCCP: self.client.Send(self.compressObj.flush(zlib.Z_FINISH)) self.useMCCP = False self.compressObj = None def _Sys_ReceiveCommand(self, command): pass def _Sys_TelnetSB(self, subCommand): #TERMINALTYPE IS if subCommand.startswith("\x18\x00"): terminalType = subCommand[2:] self.terminalType = terminalType if terminalType in ansiTypes: self.useANSI = True def Avatar_Send(self, message): self.sendBuffer = "" #Deal with escaped characters. escIndex = message.find(lib_markup.cEsc) newMessage = "" while escIndex != -1: escape = message[escIndex+1:escIndex+3] newMessage = "".join((newMessage, self.Parse(message[:escIndex]))) message = message[(escIndex+3):] if escape in ANSIColorMapping: if self.useANSI: newMessage = "".join((newMessage, ANSIColorMapping[escape])) elif escape in MXPMapping: if self.useMXP: newMessage = "".join((newMessage, MXPMapping[escape])) elif escape == "--": self.MXPOnly = False self.notMXPOnly = False newMessage = "".join((newMessage, ANSIColorMapping["-c"])) elif escape == "-x": self.MXPOnly = False self.notMXPOnly = False elif escape == "x+": self.MXPOnly = True self.notMXPOnly = False elif escape == "x-": self.MXPOnly = False elif escape == "o+": self.notMXPOnly = True self.MXPOnly = False elif escape == "o-": self.notMXPOnly = False elif escape == "t+": if self.useMXP: newMessage = "".join((newMessage, "<")) searchIndex = message.find("".join((lib_markup.cEsc, "t-"))) if searchIndex != -1: if self.useMXP: newMessage = "".join((newMessage, "".join((message[:searchIndex], ">")))) message = message[(searchIndex + 3):] else: mudWorld.logs["mud"].error("Unclosed MXP tag.") elif escape == "sd": searchIndex = message.find(">") if searchIndex != -1: #MXP takes precedence. if self.useMXPSound: newMessage = "".join((newMessage, MXP("SOUND " + message[1:searchIndex]))) message = message[(searchIndex + 1):] elif self.useMSP: newMessage = "".join(("!!SOUND(", message[1:searchIndex], ")")) message = message[(searchIndex + 1):] else: mudWorld.logs["mud"].error("Sound string improperly ended, can not parse.") elif escape == "ms": searchIndex = message.find(">") if searchIndex != -1: #MXP takes precedence. if obj["useMXPSound"]: newMessage = "".join((newMessage, MXP("MUSIC ", message[1:searchIndex]))) message = message[(searchIndex + 1):] elif obj["useMSP"]: newMessage = "".join(("!!MUSIC(", message[1:searchIndex], ")")) message = message[(searchIndex + 1):] else: mudWorld.logs["mud"].error("Music string improperly ended, can not parse.") else: mudWorld.logs["mud"].error("Unrecognized escape %s" % escape) escIndex = message.find(lib_markup.cEsc) newMessage = "".join((newMessage, self.Parse(message))) if self.useMCCP or self.useMCCP2: newMessage = self.compressObj.compress(newMessage) newMessage = "".join((newMessage, self.compressObj.flush(zlib.Z_SYNC_FLUSH))) self.client.Send(newMessage) def Avatar_RawSend(self, sendString): if self.useMCCP or self.useMCCP2: sendString = self.compressObj.compress(sendString) sendString = "".join((sendString, self.compressObj.flush(zlib.Z_SYNC_FLUSH))) self.client.Send(sendString) #Private function section. def Parse(self, message): if self.MXPOnly: if self.useMXP: message = self.ParseMXP(message) else: message = "" elif self.notMXPOnly: if self.useMXP: message = "" elif self.useMXP: message = self.ParseMXP(message) return message def ParseMXP(self, message): message.replace("<", "<") message.replace(">", ">") message.replace("&", "&") message.replace("\"", """) return message