From c72e45fbc469b22937009d4d371109185a1147bf Mon Sep 17 00:00:00 2001 From: Loudrob Date: Tue, 31 Mar 2015 07:59:36 -0400 Subject: [PATCH 01/14] Added staff chat channels. --- astron/dclass/united.dc | 6 +- otp/chat/ChatAgent.py | 36 ++++- otp/chat/ChatAgentUD.py | 140 +++++++++++++++++--- otp/chat/SequenceList.py | 15 +++ otp/chat/WhiteList.py | 45 ++++++- otp/distributed/DCClassImports.py | 2 +- otp/distributed/OtpDoGlobals.py | 4 +- toontown/ai/ServiceStart.py | 1 + toontown/uberdog/ClientServicesManagerUD.py | 27 +++- 9 files changed, 243 insertions(+), 33 deletions(-) create mode 100644 otp/chat/SequenceList.py diff --git a/astron/dclass/united.dc b/astron/dclass/united.dc index 3f3ee41c..655b2477 100644 --- a/astron/dclass/united.dc +++ b/astron/dclass/united.dc @@ -255,8 +255,10 @@ dclass MagicWordManager : DistributedObject { }; dclass ChatAgent : DistributedObject { - adminChat(uint32, string); - chatMessage(string(0-256)) clsend; + adminChat(uint32 aboutId, string message); + chatMessage(string(0-256) message, uint8 chatMode) clsend; + whisperMessage(uint32 receiverAvId, string(0-256) message) clsend; + sfWhisperMessage(uint32 receiverAvId, string(0-256) message) clsend; }; dclass FriendManager : DistributedObject { diff --git a/otp/chat/ChatAgent.py b/otp/chat/ChatAgent.py index 1b9f8889..32a84a24 100644 --- a/otp/chat/ChatAgent.py +++ b/otp/chat/ChatAgent.py @@ -1,14 +1,17 @@ from direct.distributed.DistributedObjectGlobal import DistributedObjectGlobal from pandac.PandaModules import * from otp.otpbase import OTPGlobals +from otp.ai.MagicWordGlobal import * class ChatAgent(DistributedObjectGlobal): def __init__(self, cr): DistributedObjectGlobal.__init__(self, cr) + self.chatMode = 0 def delete(self): self.ignoreAll() self.cr.chatManager = None + self.cr.chatAgent = None DistributedObjectGlobal.delete(self) return @@ -17,4 +20,35 @@ class ChatAgent(DistributedObjectGlobal): messenger.send('adminChat', [aboutId, message]) def sendChatMessage(self, message): - self.sendUpdate('chatMessage', [message]) + self.sendUpdate('chatMessage', [message, self.chatMode]) + + def sendWhisperMessage(self, receiverAvId, message): + self.sendUpdate('whisperMessage', [receiverAvId, message]) + + def sendSFWhisperMessage(self, receiverAvId, message): + self.sendUpdate('sfWhisperMessage', [receiverAvId, message]) + +@magicWord(category=CATEGORY_MODERATOR, types=[int]) +def chatmode(mode=-1): + """ Set the chat mode of the current avatar. """ + mode2name = { + 0 : "user", + 1 : "moderator", + 2 : "administrator", + 3 : "system administrator", + } + if base.cr.chatAgent is None: + return "No ChatAgent found." + if mode == -1: + return "You are currently talking in the %s chat mode." % mode2name.get(base.cr.chatAgent.chatMode, "N/A") + if not 0 <= mode <= 3: + return "Invalid chat mode specified." + if mode == 3 and spellbook.getInvoker().getAdminAccess() < 500: + return "Chat mode 3 is reserved for system administrators." + if mode == 2 and spellbook.getInvoker().getAdminAccess() < 400: + return "Chat mode 2 is reserved for administrators." + if mode == 1 and spellbook.getInvoker().getAdminAccess() < 200: + # Like this will ever happen, but whatever. + return "Chat mode 1 is reserved for moderators." + base.cr.chatAgent.chatMode = mode + return "You are now talking in the %s chat mode." % mode2name.get(mode, "N/A") diff --git a/otp/chat/ChatAgentUD.py b/otp/chat/ChatAgentUD.py index b90b782d..389678fe 100644 --- a/otp/chat/ChatAgentUD.py +++ b/otp/chat/ChatAgentUD.py @@ -2,41 +2,151 @@ from direct.directnotify import DirectNotifyGlobal from direct.distributed.DistributedObjectGlobalUD import DistributedObjectGlobalUD # TODO: OTP should not depend on Toontown... Hrrm. from toontown.chat.TTWhiteList import TTWhiteList +from toontown.chat.TTSequenceList import TTSequenceList +from otp.distributed import OtpDoGlobals +import time class ChatAgentUD(DistributedObjectGlobalUD): notify = DirectNotifyGlobal.directNotify.newCategory("ChatAgentUD") def announceGenerate(self): DistributedObjectGlobalUD.announceGenerate(self) + self.wantBlacklistSequence = config.GetBool('want-blacklist-sequence', True) + self.wantWhitelist = config.GetBool('want-whitelist', True) + if self.wantWhitelist: + self.whiteList = TTWhiteList() + if self.wantBlacklistSequence: + self.sequenceList = TTSequenceList() + self.chatMode2channel = { + 1 : OtpDoGlobals.OTP_MOD_CHANNEL, + 2 : OtpDoGlobals.OTP_ADMIN_CHANNEL, + 3 : OtpDoGlobals.OTP_SYSADMIN_CHANNEL, + } + self.chatMode2prefix = { + 1 : "[MOD] ", + 2 : "[ADMIN] ", + 3 : "[SYSADMIN] ", + } + + self.muted = {} - self.whiteList = TTWhiteList() + def muteAccount(self, account, howLong): + print ['muteAccount', account, howLong] + self.muted[account] = int(time.time()/60) + howLong - def chatMessage(self, message): + def unmuteAccount(self, account): + print ['unmuteAccount', account] + if account in self.muted: + del self.muted[account] + # Open chat + def chatMessage(self, message, chatMode): sender = self.air.getAvatarIdFromSender() if sender == 0: - self.air.writeServerEvent('suspicious', self.air.getAccountIdFromSender(), - 'Account sent chat without an avatar', message) + self.air.writeServerEvent('suspicious', accId=self.air.getAccountIdFromSender(), + issue='Account sent chat without an avatar', message=message) + return + + if sender in self.muted and int(time.time()/60) < self.muted[sender]: + return + + if self.wantWhitelist: + cleanMessage, modifications = self.cleanWhitelist(message) + else: + cleanMessage, modifications = message, [] + self.air.writeServerEvent('chat-said', avId=sender, chatMode=chatMode, msg=message, cleanMsg=cleanMessage) + + # TODO: The above is probably a little too ugly for my taste... Maybe AIR + # should be given an API for sending updates for unknown objects? + if chatMode != 0: + # Staff messages do not need to be cleaned. [TODO: Blacklist this?] + if message.startswith('.'): + # This is a thought bubble, move the point to the start. + cleanMessage = '.' + self.chatMode2prefix.get(chatMode, "") + message[1:] + else: + cleanMessage = self.chatMode2prefix.get(chatMode, "") + message + modifications = [] + DistributedAvatar = self.air.dclassesByName['DistributedAvatarUD'] + dg = DistributedAvatar.aiFormatUpdate('setTalk', sender, self.chatMode2channel.get(chatMode, sender), + self.air.ourChannel, + [0, 0, '', cleanMessage, modifications, 0]) + self.air.send(dg) + self.air.csm.accountDB.persistChat(sender, message, self.air.ourChannel) + + # Regular filtered chat + def whisperMessage(self, receiverAvId, message): + sender = self.air.getAvatarIdFromSender() + if sender == 0: + self.air.writeServerEvent('suspicious', accId=self.air.getAccountIdFromSender(), + issue='Account sent chat without an avatar', message=message) return + cleanMessage, modifications = self.cleanWhitelist(message) + # Maybe a better "cleaner" way of doing this, but it works + self.air.writeServerEvent('whisper-said', avId=sender, reciever=receiverAvId, msg=message, cleanMsg=cleanMessage) + DistributedAvatar = self.air.dclassesByName['DistributedAvatarUD'] + dg = DistributedAvatar.aiFormatUpdate('setTalkWhisper', receiverAvId, receiverAvId, self.air.ourChannel, + [sender, sender, '', cleanMessage, modifications, 0]) + self.air.send(dg) + + # True friend unfiltered chat + def sfWhisperMessage(self, receiverAvId, message): + sender = self.air.getAvatarIdFromSender() + if sender == 0: + self.air.writeServerEvent('suspicious', accId=self.air.getAccountIdFromSender(), + issue='Account sent chat without an avatar', message=message) + return + + cleanMessage = self.cleanBlacklist(message) + + self.air.writeServerEvent('sf-whisper-said', avId=sender, reciever=receiverAvId, msg=message, cleanMsg=cleanMessage) + DistributedAvatar = self.air.dclassesByName['DistributedAvatarUD'] + dg = DistributedAvatar.aiFormatUpdate('setTalkWhisper', receiverAvId, receiverAvId, self.air.ourChannel, + [sender, sender, '', cleanMessage, [], 0]) + self.air.send(dg) + + # Filter the chat message + def cleanWhitelist(self, message): modifications = [] words = message.split(' ') offset = 0 - WantWhitelist = config.GetBool('want-whitelist', 1) for word in words: - if word and not self.whiteList.isWord(word) and WantWhitelist: + if word and not self.whiteList.isWord(word): modifications.append((offset, offset+len(word)-1)) offset += len(word) + 1 cleanMessage = message + if self.wantBlacklistSequence: + modifications += self.cleanSequences(cleanMessage) + for modStart, modStop in modifications: - cleanMessage = cleanMessage[:modStart] + '*'*(modStop-modStart+1) + cleanMessage[modStop+1:] + # Traverse through modification list and replace the characters of non-whitelisted words and/or blacklisted sequences with asterisks. + cleanMessage = cleanMessage[:modStart] + '*' * (modStop - modStart + 1) + cleanMessage[modStop + 1:] - self.air.writeServerEvent('chat-said', sender, message, cleanMessage) + return (cleanMessage, modifications) - # TODO: The above is probably a little too ugly for my taste... Maybe AIR - # should be given an API for sending updates for unknown objects? - DistributedAvatar = self.air.dclassesByName['DistributedAvatarUD'] - dg = DistributedAvatar.aiFormatUpdate('setTalk', sender, sender, - self.air.ourChannel, - [0, 0, '', cleanMessage, modifications, 0]) - self.air.send(dg) \ No newline at end of file + # Check the black list for black-listed words + def cleanBlacklist(self, message): + # We don't have a black list so we just return the full message + return message + + # Check for black-listed word sequences and scrub accordingly. + def cleanSequences(self, message): + modifications = [] + offset = 0 + words = message.split() + for wordit in xrange(len(words)): + word = words[wordit].lower() + seqlist = self.sequenceList.getList(word) + if len(seqlist) > 0: + for seqit in xrange(len(seqlist)): + sequence = seqlist[seqit] + splitseq = sequence.split() + if len(words) - (wordit + 1) >= len(splitseq): + cmplist = words[wordit + 1:] + del cmplist[len(splitseq):] + cmplist = [word.lower() for word in cmplist] + if cmp(cmplist, splitseq) == 0: + modifications.append((offset, offset + len(word) + len(sequence) - 1)) + offset += len(word) + 1 + + return modifications diff --git a/otp/chat/SequenceList.py b/otp/chat/SequenceList.py new file mode 100644 index 00000000..0021efd3 --- /dev/null +++ b/otp/chat/SequenceList.py @@ -0,0 +1,15 @@ +class SequenceList: + + def __init__(self, wordlist): + self.list = {} + for line in wordlist: + if line is '': + continue + split = line.split(':') + self.list[split[0].lower()] = [word.rstrip('\r\n').lower() for word in split[1].split(',')] + + def getList(self, word): + if word in self.list: + return self.list[word] + else: + return [] \ No newline at end of file diff --git a/otp/chat/WhiteList.py b/otp/chat/WhiteList.py index 8be965a6..0011183e 100644 --- a/otp/chat/WhiteList.py +++ b/otp/chat/WhiteList.py @@ -1,22 +1,55 @@ from bisect import bisect_left +import string +import sys +import os class WhiteList: - def __init__(self, words): - self.words = words + + def __init__(self, wordlist): + self.words = [] + for line in wordlist: + self.words.append(line.strip('\n\r').lower()) + + self.words.sort() self.numWords = len(self.words) def cleanText(self, text): text = text.strip('.,?!') - return text.lower() + text = text.lower() + return text def isWord(self, text): - return self.cleanText(text) in self.words + try: + text = self.cleanText(text) + i = bisect_left(self.words, text) + if i == self.numWords: + return False + return self.words[i] == text + except UnicodeDecodeError: + return False # Lets not open ourselves up to obscure keyboards... + def isPrefix(self, text): text = self.cleanText(text) i = bisect_left(self.words, text) - if i == self.numWords: return False + return self.words[i].startswith(text) - return self.words[i].startswith(text) \ No newline at end of file + def prefixCount(self, text): + text = self.cleanText(text) + i = bisect_left(self.words, text) + j = i + while j < self.numWords and self.words[j].startswith(text): + j += 1 + + return j - i + + def prefixList(self, text): + text = self.cleanText(text) + i = bisect_left(self.words, text) + j = i + while j < self.numWords and self.words[j].startswith(text): + j += 1 + + return self.words[i:j] diff --git a/otp/distributed/DCClassImports.py b/otp/distributed/DCClassImports.py index 8b6c09a8..08fd1b8b 100644 --- a/otp/distributed/DCClassImports.py +++ b/otp/distributed/DCClassImports.py @@ -2,7 +2,7 @@ from pandac.PandaModules import * -hashVal = 598642574 +hashVal = 4270694562L from toontown.coghq import DistributedCashbotBossSafe, DistributedCashbotBossCrane, DistributedBattleFactory, DistributedCashbotBossTreasure, DistributedCogHQDoor, DistributedSellbotHQDoor, DistributedFactoryElevatorExt, DistributedMintElevatorExt, DistributedLawOfficeElevatorExt, DistributedLawOfficeElevatorInt, LobbyManager, DistributedMegaCorp, DistributedFactory, DistributedLawOffice, DistributedLawOfficeFloor, DistributedLift, DistributedDoorEntity, DistributedSwitch, DistributedButton, DistributedTrigger, DistributedCrushableEntity, DistributedCrusherEntity, DistributedStomper, DistributedStomperPair, DistributedLaserField, DistributedGolfGreenGame, DistributedSecurityCamera, DistributedMover, DistributedElevatorMarker, DistributedBarrelBase, DistributedGagBarrel, DistributedBeanBarrel, DistributedHealBarrel, DistributedGrid, ActiveCell, DirectionalCell, CrusherCell, DistributedCrate, DistributedSinkingPlatform, BattleBlocker, DistributedMint, DistributedMintRoom, DistributedMintBattle, DistributedStage, DistributedStageRoom, DistributedStageBattle, DistributedLawbotBossGavel, DistributedLawbotCannon, DistributedLawbotChair, DistributedCogKart, DistributedCountryClub, DistributedCountryClubRoom, DistributedMoleField, DistributedCountryClubBattle, DistributedMaze, DistributedFoodBelt, DistributedBanquetTable, DistributedGolfSpot diff --git a/otp/distributed/OtpDoGlobals.py b/otp/distributed/OtpDoGlobals.py index f665ced4..1371df4a 100644 --- a/otp/distributed/OtpDoGlobals.py +++ b/otp/distributed/OtpDoGlobals.py @@ -88,4 +88,6 @@ OTP_ZONE_ID_DISTRICTS = 3 OTP_ZONE_ID_DISTRICTS_STATS = 4 OTP_ZONE_ID_ELEMENTS = 5 OTP_NET_MESSENGER_CHANNEL = (OTP_DO_ID_UBER_DOG << 32) + OTP_ZONE_ID_MANAGEMENT -OTP_STAFF_CHANNEL = 6200 +OTP_MOD_CHANNEL = 6200 +OTP_ADMIN_CHANNEL = 6400 +OTP_SYSADMIN_CHANNEL = 6500 diff --git a/toontown/ai/ServiceStart.py b/toontown/ai/ServiceStart.py index 4850f968..02df1a35 100644 --- a/toontown/ai/ServiceStart.py +++ b/toontown/ai/ServiceStart.py @@ -35,6 +35,7 @@ if args.astron_ip: localconfig += 'air-connect %s\n' % args.astron_ip if args.eventlogger_ip: localconfig += 'eventlog-host %s\n' % args.eventlogger_ip loadPrcFileData('Command-line', localconfig) + from otp.ai.AIBaseGlobal import * from toontown.ai.ToontownAIRepository import ToontownAIRepository diff --git a/toontown/uberdog/ClientServicesManagerUD.py b/toontown/uberdog/ClientServicesManagerUD.py index c8b3e188..98b25865 100644 --- a/toontown/uberdog/ClientServicesManagerUD.py +++ b/toontown/uberdog/ClientServicesManagerUD.py @@ -422,13 +422,26 @@ class LoginAccountFSM(OperationFSM): datagram.addChannel(self.csm.GetAccountConnectionChannel(self.accountId)) self.csm.air.send(datagram) - # Add this connection to extra channels which may be useful: - if self.accessLevel > 100: - datagram = PyDatagram() - datagram.addServerHeader(self.target, self.csm.air.ourChannel, - CLIENTAGENT_OPEN_CHANNEL) - datagram.addChannel(OtpDoGlobals.OTP_STAFF_CHANNEL) - self.csm.air.send(datagram) + # Subscribe to any "staff" channels that the account has access to. + access = self.account.get('ADMIN_ACCESS', 0) + if access >= 200: + # Subscribe to the moderator channel. + dg = PyDatagram() + dg.addServerHeader(self.target, self.csm.air.ourChannel, CLIENTAGENT_OPEN_CHANNEL) + dg.addChannel(OtpDoGlobals.OTP_MOD_CHANNEL) + self.csm.air.send(dg) + if access >= 400: + # Subscribe to the administrator channel. + dg = PyDatagram() + dg.addServerHeader(self.target, self.csm.air.ourChannel, CLIENTAGENT_OPEN_CHANNEL) + dg.addChannel(OtpDoGlobals.OTP_ADMIN_CHANNEL) + self.csm.air.send(dg) + if access >= 500: + # Subscribe to the system administrator channel. + dg = PyDatagram() + dg.addServerHeader(self.target, self.csm.air.ourChannel, CLIENTAGENT_OPEN_CHANNEL) + dg.addChannel(OtpDoGlobals.OTP_SYSADMIN_CHANNEL) + self.csm.air.send(dg) # Now set their sender channel to represent their account affiliation: datagram = PyDatagram() From 260e5af56f690f8724fd0fbabb9ff83ba5115b44 Mon Sep 17 00:00:00 2001 From: Loudrob Date: Tue, 31 Mar 2015 08:16:01 -0400 Subject: [PATCH 02/14] oo[pssieisss --- config/release/dev.prc | 1 + toontown/chat/TTSequenceList.py | 36 ++++++++++++++++++++++++++ toontown/suit/DistributedSuitBaseAI.py | 3 ++- 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 toontown/chat/TTSequenceList.py diff --git a/config/release/dev.prc b/config/release/dev.prc index 7ac6a986..48c30c26 100644 --- a/config/release/dev.prc +++ b/config/release/dev.prc @@ -27,6 +27,7 @@ want-achievements #f # Chat: want-whitelist #f +want-blacklist-sequence #f # Cashbot boss: want-resistance-toonup #t diff --git a/toontown/chat/TTSequenceList.py b/toontown/chat/TTSequenceList.py new file mode 100644 index 00000000..bf467501 --- /dev/null +++ b/toontown/chat/TTSequenceList.py @@ -0,0 +1,36 @@ +from pandac.PandaModules import * +from otp.chat.SequenceList import SequenceList +from direct.directnotify import DirectNotifyGlobal + +class TTSequenceList(SequenceList): + + def __init__(self): + self.notify = DirectNotifyGlobal.directNotify.newCategory('TTSequenceList') + sequenceListURL = config.GetString('blacklist-sequence-url', '') + if sequenceListURL == '': + self.notify.warning('No Sequence BL URL specified! Continuing with local sequence.') + SequenceList.__init__(self, self.loadSquencesLocally()) + else: + SequenceList.__init__(self, self.downloadSequences(sequenceListURL)) + + def downloadSequences(self, url): + fs = Ramfile() + http = HTTPClient.getGlobalPtr() + self.ch = http.makeChannel(True) + self.ch.getHeader(DocumentSpec(url)) + doc = self.ch.getDocumentSpec() + self.ch.getDocument(doc) + self.ch.downloadToRam(fs) + return fs.getData().split('\r\n') + + def loadSquencesLocally(self): + vfs = VirtualFileSystem.getGlobalPtr() + filename = Filename('tsequence.dat') + searchPath = DSearchPath() + searchPath.appendDirectory(Filename('/server')) + found = vfs.resolveFilename(filename, searchPath) + if not found: + self.notify.warning("Couldn't find blacklist sequence data file!") + return + data = vfs.readFile(filename, True) + return data.split('\n') diff --git a/toontown/suit/DistributedSuitBaseAI.py b/toontown/suit/DistributedSuitBaseAI.py index 687bdc91..f11d1d6d 100644 --- a/toontown/suit/DistributedSuitBaseAI.py +++ b/toontown/suit/DistributedSuitBaseAI.py @@ -117,6 +117,7 @@ class DistributedSuitBaseAI(DistributedAvatarAI.DistributedAvatarAI, SuitBase.Su def useSkeleRevive(self): self.skeleRevives -= 1 self.currHP = self.maxHP + self.d_setHP(self.currHP) self.reviveFlag = 1 def reviveCheckAndClear(self): @@ -195,4 +196,4 @@ class DistributedSuitBaseAI(DistributedAvatarAI.DistributedAvatarAI, SuitBase.Su self.d_setWaiter(flag) def getWaiter(self): - return self.waiter \ No newline at end of file + return self.waiter From a2a1ea6fa76fc145de240faf6c4587c12125a2f8 Mon Sep 17 00:00:00 2001 From: Loudrob Date: Tue, 31 Mar 2015 19:12:18 -0400 Subject: [PATCH 03/14] Started Rock-A-Bye road stuff. --- astron/databases/.gitignore | 1 + toontown/toonbase/TTLocalizerEnglish.py | 1 + toontown/toonbase/ToontownGlobals.py | 1 + 3 files changed, 3 insertions(+) diff --git a/astron/databases/.gitignore b/astron/databases/.gitignore index 98e6ef67..c65d9535 100644 --- a/astron/databases/.gitignore +++ b/astron/databases/.gitignore @@ -1 +1,2 @@ *.db +air_cache/ diff --git a/toontown/toonbase/TTLocalizerEnglish.py b/toontown/toonbase/TTLocalizerEnglish.py index c49b4be3..63d8fca3 100644 --- a/toontown/toonbase/TTLocalizerEnglish.py +++ b/toontown/toonbase/TTLocalizerEnglish.py @@ -93,6 +93,7 @@ GlobalStreetNames = {20000: ('to', 'on', 'Tutorial Terrace'), 9000: ('to the', 'in the', 'Playground'), 9100: ('to', 'on', 'Lullaby Lane'), 9200: ('to', 'on', 'Pajama Place'), + 9300: ('to', 'on', 'Rock-A-Bye Road'), 10000: ('to', 'in', 'Bossbot HQ Country Club'), 10100: ('to the', 'in the', 'Bossbot HQ Lobby'), 10200: ('to the', 'in the', 'The Clubhouse'), diff --git a/toontown/toonbase/ToontownGlobals.py b/toontown/toonbase/ToontownGlobals.py index bc9c45ae..cfad1f72 100644 --- a/toontown/toonbase/ToontownGlobals.py +++ b/toontown/toonbase/ToontownGlobals.py @@ -171,6 +171,7 @@ MapleStreet = 5200 OakStreet = 5300 LullabyLane = 9100 PajamaPlace = 9200 +RockAByeRoad = 9300 ToonHall = 2513 HoodHierarchy = {ToontownCentral: (SillyStreet, LoopyLane, PunchlinePlace), DonaldsDock: (BarnacleBoulevard, SeaweedStreet, LighthouseLane), From 976de78682aac50be662fdc648d8cf62e0d185a3 Mon Sep 17 00:00:00 2001 From: Loudrob Date: Tue, 31 Mar 2015 23:07:13 -0400 Subject: [PATCH 04/14] Removed some of the TTI-ish features from Loading Screen and added globals for new street. --- .../databases/air_cache/pets_401000001.pets | 72 +++++++++---------- toontown/building/SuitBuildingGlobals.py | 3 + toontown/toontowngui/ToontownLoadingScreen.py | 68 +----------------- 3 files changed, 40 insertions(+), 103 deletions(-) diff --git a/astron/databases/air_cache/pets_401000001.pets b/astron/databases/air_cache/pets_401000001.pets index c2a7eda8..e1f5f382 100644 --- a/astron/databases/air_cache/pets_401000001.pets +++ b/astron/databases/air_cache/pets_401000001.pets @@ -1,54 +1,54 @@ (dp1 I4000 (lp2 -I44 -aI170 -aI242 -aI222 -aI111 +I8 +aI25 +aI166 +aI149 +aI59 asI1000 (lp3 -I162 -aI246 -aI230 -aI9 -aI130 +I20 +aI156 +aI148 +aI67 +aI107 asI9000 (lp4 -I238 -aI160 -aI252 -aI128 -aI55 +I144 +aI49 +aI71 +aI198 +aI134 asI2000 (lp5 -I134 -aI234 -aI185 -aI178 -aI237 +I145 +aI195 +aI42 +aI10 +aI65 asI5000 (lp6 -I227 -aI61 -aI35 -aI72 -aI121 +I238 +aI37 +aI127 +aI207 +aI232 asI7000 (lp7 -I152 -aI250 -aI12 -aI249 -aI42 +I183 +aI112 +aI190 +aI222 +aI14 asI3000 (lp8 -I34 -aI75 -aI197 -aI112 -aI54 +I80 +aI160 +aI214 +aI38 +aI241 asS'day' p9 -I16524 +I16526 s. \ No newline at end of file diff --git a/toontown/building/SuitBuildingGlobals.py b/toontown/building/SuitBuildingGlobals.py index 61fd40dc..96da0e99 100644 --- a/toontown/building/SuitBuildingGlobals.py +++ b/toontown/building/SuitBuildingGlobals.py @@ -200,6 +200,8 @@ buildingMinMax = { config.GetInt('lullaby-lane-building-max', 12)], ToontownGlobals.PajamaPlace: [config.GetInt('pajama-place-building-min', 6), config.GetInt('pajama-place-building-max', 12)], + ToontownGlobals.RockAByeRoad: [config.GetInt('rock-a-bye-road-building-min', 6), + config.GetInt('rock-a-bye-road-building-max', 12)], ToontownGlobals.SellbotHQ: [0, 0], ToontownGlobals.SellbotFactoryExt: [0, 0], ToontownGlobals.CashbotHQ: [0, 0], @@ -225,6 +227,7 @@ buildingChance = { ToontownGlobals.PolarPlace: config.GetFloat('polar-place-building-chance', 100.0), ToontownGlobals.LullabyLane: config.GetFloat('lullaby-lane-building-chance', 100.0), ToontownGlobals.PajamaPlace: config.GetFloat('pajama-place-building-chance', 100.0), + ToontownGlobals.RockAByeRoad: config.GetFloat('rock-a-bye-road-building-chance', 100.0), ToontownGlobals.SellbotHQ: 0.0, ToontownGlobals.SellbotFactoryExt: 0.0, ToontownGlobals.CashbotHQ: 0.0, diff --git a/toontown/toontowngui/ToontownLoadingScreen.py b/toontown/toontowngui/ToontownLoadingScreen.py index cc4fadb5..0fcfe085 100644 --- a/toontown/toontowngui/ToontownLoadingScreen.py +++ b/toontown/toontowngui/ToontownLoadingScreen.py @@ -12,53 +12,6 @@ LOADING_SCREEN_SORT_INDEX = 4000 class ToontownLoadingScreen: defaultTex = 'phase_3.5/maps/loading/default.jpg' - zone2picture = { - ToontownGlobals.GoofySpeedway : 'phase_3.5/maps/loading/gs.jpg', - ToontownGlobals.ToontownCentral : 'phase_3.5/maps/loading/ttc.jpg', - ToontownGlobals.SillyStreet : 'phase_3.5/maps/loading/ttc_ss.jpg', - ToontownGlobals.LoopyLane : 'phase_3.5/maps/loading/ttc_ll.jpg', - ToontownGlobals.PunchlinePlace : 'phase_3.5/maps/loading/ttc_pp.jpg', - ToontownGlobals.DonaldsDock : 'phase_3.5/maps/loading/dd.jpg', - ToontownGlobals.BarnacleBoulevard : 'phase_3.5/maps/loading/dd_bb.jpg', - ToontownGlobals.SeaweedStreet : 'phase_3.5/maps/loading/dd_ss.jpg', - ToontownGlobals.LighthouseLane : 'phase_3.5/maps/loading/dd_ll.jpg', - ToontownGlobals.DaisyGardens : 'phase_3.5/maps/loading/dg.jpg', - ToontownGlobals.ElmStreet : 'phase_3.5/maps/loading/dg_es.jpg', - ToontownGlobals.MapleStreet : 'phase_3.5/maps/loading/dg_ms.jpg', - ToontownGlobals.OakStreet : 'phase_3.5/maps/loading/dg_os.jpg', - ToontownGlobals.MinniesMelodyland : 'phase_3.5/maps/loading/mml.jpg', - ToontownGlobals.AltoAvenue : 'phase_3.5/maps/loading/mml_aa.jpg', - ToontownGlobals.BaritoneBoulevard : 'phase_3.5/maps/loading/mml_bb.jpg', - ToontownGlobals.TenorTerrace : 'phase_3.5/maps/loading/mml_tt.jpg', - ToontownGlobals.TheBrrrgh : 'phase_3.5/maps/loading/tb.jpg', - ToontownGlobals.WalrusWay : 'phase_3.5/maps/loading/tb_ww.jpg', - ToontownGlobals.SleetStreet : 'phase_3.5/maps/loading/tb_ss.jpg', - ToontownGlobals.PolarPlace : 'phase_3.5/maps/loading/tb_pp.jpg', - ToontownGlobals.DonaldsDreamland : 'phase_3.5/maps/loading/ddl.jpg', - ToontownGlobals.LullabyLane : 'phase_3.5/maps/loading/ddl_ll.jpg', - ToontownGlobals.PajamaPlace : 'phase_3.5/maps/loading/ddl_pp.jpg', - ToontownGlobals.OutdoorZone : 'phase_3.5/maps/loading/oz.jpg', - ToontownGlobals.GolfZone : 'phase_3.5/maps/loading/gz.jpg', - ToontownGlobals.SellbotHQ : 'phase_3.5/maps/loading/sbhq.jpg', - ToontownGlobals.CashbotHQ : 'phase_3.5/maps/loading/cbhq.jpg', - ToontownGlobals.LawbotHQ : 'phase_3.5/maps/loading/lbhq.jpg', - ToontownGlobals.BossbotHQ : 'phase_3.5/maps/loading/bbhq.jpg' - } - emotes = [ - {'emote': 'bored', 'frame': 135}, - {'emote': 'run', 'frame': 7}, - {'emote': 'victory', 'frame': 10}, - {'emote': 'applause', 'frame': 23}, - {'emote': 'sprinkle-dust', 'frame': 40}, - {'emote': 'hypnotize', 'frame': 25}, - {'emote': 'cringe', 'frame': 25}, - {'emote': 'wave', 'frame': 25}, - {'emote': 'shrug', 'frame': 30}, - {'emote': 'duck', 'frame': 40}, - {'emote': 'up', 'frame': 60}, - {'emote': 'down', 'frame': 23}, - {'emote': 'bow', 'frame': 45} - ] def __init__(self): self.__expectedCount = 0 @@ -75,13 +28,10 @@ class ToontownLoadingScreen: scale = self.logo.getScale() # self.logo.setPos(scale[0], 0, -scale[2]) self.logo.setPos(0, 0, -scale[2]) - self.toon = None def destroy(self): self.title.destroy() self.gui.removeNode() - if self.toon: - self.toon.delete() self.logo.removeNode() def getTip(self, tipCategory): @@ -90,25 +40,11 @@ class ToontownLoadingScreen: def begin(self, range, label, gui, tipCategory, zoneId): self.waitBar['range'] = range self.title['text'] = label - loadingScreenTex = self.zone2picture.get(ZoneUtil.getBranchZone(zoneId), self.defaultTex) + loadingScreenTex = self.defaultTex self.background = loader.loadTexture(loadingScreenTex) self.__count = 0 self.__expectedCount = range if gui: - if base.localAvatarStyle: - from toontown.toon import Toon - emote = random.choice(self.emotes) - self.toon = Toon.Toon() - self.toon.setDNA(base.localAvatarStyle) - try: self.toon.pose(*emote.values()) - except: self.toon.pose(emote['emote'], emote['frame']) - self.toon.getGeomNode().setDepthWrite(1) - self.toon.getGeomNode().setDepthTest(1) - self.toon.setHpr(205, 0, 0) - self.toon.setScale(0.18) - self.toon.setPos(base.a2dBottomRight.getX()/1.25, 0, -0.034) - self.toon.reparentTo(self.waitBar) - self.waitBar['frameSize'] = (base.a2dLeft+(base.a2dRight/8.15), base.a2dRight-(base.a2dRight/2.57), -0.03, 0.03) self.title.reparentTo(base.a2dpBottomLeft, LOADING_SCREEN_SORT_INDEX) self.title.setPos(0.24, 0, 0.23) self.gui.setPos(0, -0.1, 0) @@ -128,8 +64,6 @@ class ToontownLoadingScreen: self.waitBar.reparentTo(self.gui) self.title.reparentTo(self.gui) self.gui.reparentTo(hidden) - if self.toon: - self.toon.reparentTo(hidden) self.logo.reparentTo(hidden) return (self.__expectedCount, self.__count) From d251898a11e05aaaf4425c65298e9956ca0298b3 Mon Sep 17 00:00:00 2001 From: Loudrob Date: Wed, 1 Apr 2015 06:51:39 -0400 Subject: [PATCH 05/14] Another one. --- toontown/toonbase/ToontownGlobals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toontown/toonbase/ToontownGlobals.py b/toontown/toonbase/ToontownGlobals.py index cfad1f72..34b1dd85 100644 --- a/toontown/toonbase/ToontownGlobals.py +++ b/toontown/toonbase/ToontownGlobals.py @@ -178,7 +178,7 @@ HoodHierarchy = {ToontownCentral: (SillyStreet, LoopyLane, PunchlinePlace), TheBrrrgh: (WalrusWay, SleetStreet, PolarPlace), MinniesMelodyland: (AltoAvenue, BaritoneBoulevard, TenorTerrace), DaisyGardens: (ElmStreet, MapleStreet, OakStreet), - DonaldsDreamland: (LullabyLane, PajamaPlace), + DonaldsDreamland: (LullabyLane, PajamaPlace, RockAByeRoad), GoofySpeedway: ()} WelcomeValleyToken = 0 BossbotHQ = 10000 From 72b6ef5afdac52a12763857abf801050aae89083 Mon Sep 17 00:00:00 2001 From: Loudrob Date: Wed, 1 Apr 2015 07:39:59 -0400 Subject: [PATCH 06/14] Made it not crash uberdog lel --- otp/chat/ChatAgent.py | 4 +- otp/chat/ChatAgentUD.py | 15 +--- otp/chat/ChatManager.py | 80 ++++++++++++++++++++- otp/chat/TalkAssistant.py | 26 ++++++- otp/chat/WhiteList.py | 32 +++------ toontown/uberdog/ClientServicesManagerUD.py | 6 ++ 6 files changed, 119 insertions(+), 44 deletions(-) diff --git a/otp/chat/ChatAgent.py b/otp/chat/ChatAgent.py index 32a84a24..60a21ef9 100644 --- a/otp/chat/ChatAgent.py +++ b/otp/chat/ChatAgent.py @@ -43,9 +43,9 @@ def chatmode(mode=-1): return "You are currently talking in the %s chat mode." % mode2name.get(base.cr.chatAgent.chatMode, "N/A") if not 0 <= mode <= 3: return "Invalid chat mode specified." - if mode == 3 and spellbook.getInvoker().getAdminAccess() < 500: + if mode == 3 and spellbook.getInvoker().getAdminAccess() < 600: return "Chat mode 3 is reserved for system administrators." - if mode == 2 and spellbook.getInvoker().getAdminAccess() < 400: + if mode == 2 and spellbook.getInvoker().getAdminAccess() < 500: return "Chat mode 2 is reserved for administrators." if mode == 1 and spellbook.getInvoker().getAdminAccess() < 200: # Like this will ever happen, but whatever. diff --git a/otp/chat/ChatAgentUD.py b/otp/chat/ChatAgentUD.py index 389678fe..5e9856dc 100644 --- a/otp/chat/ChatAgentUD.py +++ b/otp/chat/ChatAgentUD.py @@ -27,17 +27,7 @@ class ChatAgentUD(DistributedObjectGlobalUD): 2 : "[ADMIN] ", 3 : "[SYSADMIN] ", } - - self.muted = {} - - def muteAccount(self, account, howLong): - print ['muteAccount', account, howLong] - self.muted[account] = int(time.time()/60) + howLong - - def unmuteAccount(self, account): - print ['unmuteAccount', account] - if account in self.muted: - del self.muted[account] + # Open chat def chatMessage(self, message, chatMode): sender = self.air.getAvatarIdFromSender() @@ -46,9 +36,6 @@ class ChatAgentUD(DistributedObjectGlobalUD): issue='Account sent chat without an avatar', message=message) return - if sender in self.muted and int(time.time()/60) < self.muted[sender]: - return - if self.wantWhitelist: cleanMessage, modifications = self.cleanWhitelist(message) else: diff --git a/otp/chat/ChatManager.py b/otp/chat/ChatManager.py index 648a5a93..816eb722 100644 --- a/otp/chat/ChatManager.py +++ b/otp/chat/ChatManager.py @@ -4,6 +4,10 @@ from direct.fsm import State from direct.gui.DirectGui import * from direct.showbase import DirectObject from pandac.PandaModules import * + +from otp.login import LeaveToPayDialog +from otp.login import PrivacyPolicyPanel +from otp.login import SecretFriendsInfoPanel from otp.otpbase import OTPLocalizer from toontown.chat.ChatGlobals import * @@ -45,13 +49,17 @@ class ChatManager(DirectObject.DirectObject): self.__normalObscured = 0 self.openChatWarning = None self.unpaidChatWarning = None + self.teaser = None self.paidNoParentPassword = None self.noSecretChatAtAll = None self.noSecretChatAtAllAndNoWhitelist = None self.noSecretChatWarning = None self.activateChatGui = None + self.chatMoreInfo = None + self.chatPrivacyPolicy = None self.secretChatActivated = None self.problemActivatingChat = None + self.leaveToPayDialog = None self.fsm = ClassicFSM.ClassicFSM('chatManager', [State.State('off', self.enterOff, self.exitOff), State.State('mainMenu', self.enterMainMenu, self.exitMainMenu), State.State('speedChat', self.enterSpeedChat, self.exitSpeedChat), @@ -62,6 +70,7 @@ class ChatManager(DirectObject.DirectObject): State.State('whisperSpeedChat', self.enterWhisperSpeedChat, self.exitWhisperSpeedChat), State.State('whisperSpeedChatPlayer', self.enterWhisperSpeedChatPlayer, self.exitWhisperSpeedChatPlayer), State.State('openChatWarning', self.enterOpenChatWarning, self.exitOpenChatWarning), + State.State('leaveToPayDialog', self.enterLeaveToPayDialog, self.exitLeaveToPayDialog), State.State('unpaidChatWarning', self.enterUnpaidChatWarning, self.exitUnpaidChatWarning), State.State('noSecretChatAtAll', self.enterNoSecretChatAtAll, self.exitNoSecretChatAtAll), State.State('noSecretChatAtAllAndNoWhitelist', self.enterNoSecretChatAtAllAndNoWhitelist, self.exitNoSecretChatAtAllAndNoWhitelist), @@ -69,11 +78,14 @@ class ChatManager(DirectObject.DirectObject): State.State('noFriendsWarning', self.enterNoFriendsWarning, self.exitNoFriendsWarning), State.State('otherDialog', self.enterOtherDialog, self.exitOtherDialog), State.State('activateChat', self.enterActivateChat, self.exitActivateChat), + State.State('chatMoreInfo', self.enterChatMoreInfo, self.exitChatMoreInfo), + State.State('chatPrivacyPolicy', self.enterChatPrivacyPolicy, self.exitChatPrivacyPolicy), State.State('secretChatActivated', self.enterSecretChatActivated, self.exitSecretChatActivated), State.State('problemActivatingChat', self.enterProblemActivatingChat, self.exitProblemActivatingChat), State.State('whiteListOpenChat', self.enterWhiteListOpenChat, self.exitWhiteListOpenChat), State.State('whiteListAvatarChat', self.enterWhiteListAvatarChat, self.exitWhiteListAvatarChat), - State.State('whiteListPlayerChat', self.enterWhiteListPlayerChat, self.exitWhiteListPlayerChat)], 'off', 'off') + State.State('whiteListPlayerChat', self.enterWhiteListPlayerChat, self.exitWhiteListPlayerChat), + State.State('trueFriendTeaserPanel', self.enterTrueFriendTeaserPanel, self.exitTrueFriendTeaserPanel)], 'off', 'off') self.fsm.enterInitialState() return @@ -93,6 +105,10 @@ class ChatManager(DirectObject.DirectObject): self.payButton = None self.unpaidChatWarning.destroy() self.unpaidChatWarning = None + if self.teaser: + self.teaser.cleanup() + self.teaser.unload() + self.teaser = None if self.noSecretChatAtAll: self.noSecretChatAtAll.destroy() self.noSecretChatAtAll = None @@ -105,6 +121,12 @@ class ChatManager(DirectObject.DirectObject): if self.activateChatGui: self.activateChatGui.destroy() self.activateChatGui = None + if self.chatMoreInfo: + self.chatMoreInfo.destroy() + self.chatMoreInfo = None + if self.chatPrivacyPolicy: + self.chatPrivacyPolicy.destroy() + self.chatPrivacyPolicy = None if self.secretChatActivated: self.secretChatActivated.destroy() self.secretChatActivated = None @@ -196,6 +218,8 @@ class ChatManager(DirectObject.DirectObject): if self.wantBackgroundFocus: self.chatInputNormal.chatEntry['backgroundFocus'] = 1 self.acceptOnce('enterNormalChat', self.fsm.request, ['normalChat']) + if not self.wantBackgroundFocus: + self.accept('t', messenger.send, ['enterNormalChat']) def checkObscurred(self): if not self.__scObscured: @@ -387,6 +411,19 @@ class ChatManager(DirectObject.DirectObject): def exitOpenChatWarning(self): self.notify.error('called exitOpenChatWarning() on parent class') + def enterLeaveToPayDialog(self): + if self.leaveToPayDialog == None: + self.leaveToPayDialog = LeaveToPayDialog.LeaveToPayDialog(self.paidNoParentPassword) + self.leaveToPayDialog.setCancel(self.__handleLeaveToPayCancel) + self.leaveToPayDialog.show() + return + + def exitLeaveToPayDialog(self): + if self.leaveToPayDialog: + self.leaveToPayDialog.destroy() + self.leaveToPayDialog = None + return + def enterUnpaidChatWarning(self): self.notify.error('called enterUnpaidChatWarning() on parent class') @@ -429,6 +466,30 @@ class ChatManager(DirectObject.DirectObject): def exitOtherDialog(self): pass + def enterChatMoreInfo(self): + if self.chatMoreInfo == None: + self.chatMoreInfo = SecretFriendsInfoPanel.SecretFriendsInfoPanel('secretFriendsInfoDone') + self.chatMoreInfo.show() + self.accept('secretFriendsInfoDone', self.__secretFriendsInfoDone) + return + + def exitChatMoreInfo(self): + self.chatMoreInfo.hide() + self.ignore('secretFriendsInfoDone') + + def enterChatPrivacyPolicy(self): + if self.chatPrivacyPolicy == None: + self.chatPrivacyPolicy = PrivacyPolicyPanel.PrivacyPolicyPanel('privacyPolicyDone') + self.chatPrivacyPolicy.show() + self.accept('privacyPolicyDone', self.__privacyPolicyDone) + return + + def exitChatPrivacyPolicy(self): + cleanupDialog('privacyPolicyDialog') + self.chatPrivacyPolicy = None + self.ignore('privacyPolicyDone') + return + def enterSecretChatActivated(self): self.notify.error('called enterSecretChatActivated() on parent class') @@ -439,4 +500,19 @@ class ChatManager(DirectObject.DirectObject): self.notify.error('called enterProblemActivatingChat() on parent class') def exitProblemActivatingChat(self): - self.notify.error('called exitProblemActivatingChat() on parent class') \ No newline at end of file + self.notify.error('called exitProblemActivatingChat() on parent class') + + def enterTrueFriendTeaserPanel(self): + self.notify.error('called enterTrueFriendTeaserPanel () on parent class') + + def exitTrueFriendTeaserPanel(self): + self.notify.error('called exitTrueFriendTeaserPanel () on parent class') + + def __handleLeaveToPayCancel(self): + self.fsm.request('mainMenu') + + def __secretFriendsInfoDone(self): + self.fsm.request('activateChat') + + def __privacyPolicyDone(self): + self.fsm.request('activateChat') diff --git a/otp/chat/TalkAssistant.py b/otp/chat/TalkAssistant.py index c6fe782a..22ea8617 100644 --- a/otp/chat/TalkAssistant.py +++ b/otp/chat/TalkAssistant.py @@ -574,6 +574,10 @@ class TalkAssistant(DirectObject.DirectObject): def sendOpenTalk(self, message): error = None doId = base.localAvatar.doId + try: + message.encode('ascii') + except UnicodeEncodeError: + return if base.config.GetBool('want-talkative-tyler', False): if base.localAvatar.zoneId == 2000: tyler = base.cr.doFind('Talkative Tyler') @@ -606,7 +610,7 @@ class TalkAssistant(DirectObject.DirectObject): message, scrubbed = base.localAvatar.scrubTalk(cleanMessage, modifications) - base.cr.ttuFriendsManager.sendUpdate('sendTalkWhisper', [receiverAvId, message]) + base.cr.ttiFriendsManager.sendUpdate('sendTalkWhisper', [receiverAvId, message]) def sendAccountTalk(self, message, receiverAccount): error = None @@ -667,8 +671,24 @@ class TalkAssistant(DirectObject.DirectObject): return error def sendPlayerWhisperSpeedChat(self, type, messageIndex, receiverId): - # TODO: Remove Player system - return None + error = None + if type == SPEEDCHAT_NORMAL: + base.cr.speedchatRelay.sendSpeedchat(receiverId, messageIndex) + message = self.SCDecoder.decodeSCStaticTextMsg(messageIndex) + elif type == SPEEDCHAT_EMOTE: + base.cr.speedchatRelay.sendSpeedchatEmote(receiverId, messageIndex) + message = self.SCDecoder.decodeSCEmoteWhisperMsg(messageIndex, localAvatar.getName()) + return + elif type == SPEEDCHAT_CUSTOM: + base.cr.speedchatRelay.sendSpeedchatCustom(receiverId, messageIndex) + message = self.SCDecoder.decodeSCCustomMsg(messageIndex) + if self.logWhispers: + receiverName = self.findName(receiverId, 1) + newMessage = TalkMessage(self.countMessage(), self.stampTime(), message, localAvatar.doId, localAvatar.getName(), localAvatar.DISLid, localAvatar.DISLname, None, None, receiverId, receiverName, TALK_ACCOUNT, None) + self.historyComplete.append(newMessage) + self.addToHistoryDoId(newMessage, localAvatar.doId) + messenger.send('NewOpenMessage', [newMessage]) + return error def sendGuildSpeedChat(self, type, msgIndex): error = None diff --git a/otp/chat/WhiteList.py b/otp/chat/WhiteList.py index 0011183e..a6c74684 100644 --- a/otp/chat/WhiteList.py +++ b/otp/chat/WhiteList.py @@ -1,41 +1,27 @@ from bisect import bisect_left -import string -import sys -import os + class WhiteList: - - def __init__(self, wordlist): - self.words = [] - for line in wordlist: - self.words.append(line.strip('\n\r').lower()) - - self.words.sort() + def __init__(self, words): + self.words = words self.numWords = len(self.words) def cleanText(self, text): text = text.strip('.,?!') - text = text.lower() - return text + return text.lower() def isWord(self, text): - try: - text = self.cleanText(text) - i = bisect_left(self.words, text) - if i == self.numWords: - return False - return self.words[i] == text - except UnicodeDecodeError: - return False # Lets not open ourselves up to obscure keyboards... - + return self.cleanText(text) in self.words def isPrefix(self, text): text = self.cleanText(text) i = bisect_left(self.words, text) + if i == self.numWords: return False - return self.words[i].startswith(text) + return self.words[i].startswith(text) + def prefixCount(self, text): text = self.cleanText(text) i = bisect_left(self.words, text) @@ -52,4 +38,4 @@ class WhiteList: while j < self.numWords and self.words[j].startswith(text): j += 1 - return self.words[i:j] + return self.words[i:j] diff --git a/toontown/uberdog/ClientServicesManagerUD.py b/toontown/uberdog/ClientServicesManagerUD.py index 98b25865..c9825caa 100644 --- a/toontown/uberdog/ClientServicesManagerUD.py +++ b/toontown/uberdog/ClientServicesManagerUD.py @@ -101,6 +101,12 @@ class AccountDB: def lookup(self, username, callback): pass # Inheritors should override this. + def persistMessage(self, category, description, sender, receiver): + print ['persistMessage', category, description, sender, receiver] + + def persistChat(self, sender, message, channel): + pass + def storeAccountID(self, userId, accountId, callback): self.dbm[str(userId)] = str(accountId) # anydbm only allows strings. if getattr(self.dbm, 'sync', None): From 61bc7a974d706b03ae26d15b9c08d691845537eb Mon Sep 17 00:00:00 2001 From: Loudrob Date: Wed, 1 Apr 2015 08:23:03 -0400 Subject: [PATCH 07/14] ok --- toontown/battle/DistributedBattleBldgAI.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/toontown/battle/DistributedBattleBldgAI.py b/toontown/battle/DistributedBattleBldgAI.py index 94966866..d98879f0 100644 --- a/toontown/battle/DistributedBattleBldgAI.py +++ b/toontown/battle/DistributedBattleBldgAI.py @@ -142,10 +142,10 @@ class DistributedBattleBldgAI(DistributedBattleBaseAI.DistributedBattleBaseAI): self.resumeLastActiveSuitDied = 0 def enterReservesJoining(self, ts=0): - pass + return None def exitReservesJoining(self, ts=0): - pass + return None def enterReward(self): self.timer.startCallback(FLOOR_REWARD_TIMEOUT, self.serverRewardDone) From 010c0752659b22dc08948dc5dd7c5fde31c0d5cf Mon Sep 17 00:00:00 2001 From: Loudrob Date: Wed, 1 Apr 2015 16:29:34 -0400 Subject: [PATCH 08/14] Revert "Made it not crash uberdog lel" This reverts commit 72b6ef5afdac52a12763857abf801050aae89083. --- otp/chat/ChatAgent.py | 4 +- otp/chat/ChatAgentUD.py | 15 +++- otp/chat/ChatManager.py | 80 +-------------------- otp/chat/TalkAssistant.py | 26 +------ otp/chat/WhiteList.py | 32 ++++++--- toontown/uberdog/ClientServicesManagerUD.py | 6 -- 6 files changed, 44 insertions(+), 119 deletions(-) diff --git a/otp/chat/ChatAgent.py b/otp/chat/ChatAgent.py index 60a21ef9..32a84a24 100644 --- a/otp/chat/ChatAgent.py +++ b/otp/chat/ChatAgent.py @@ -43,9 +43,9 @@ def chatmode(mode=-1): return "You are currently talking in the %s chat mode." % mode2name.get(base.cr.chatAgent.chatMode, "N/A") if not 0 <= mode <= 3: return "Invalid chat mode specified." - if mode == 3 and spellbook.getInvoker().getAdminAccess() < 600: + if mode == 3 and spellbook.getInvoker().getAdminAccess() < 500: return "Chat mode 3 is reserved for system administrators." - if mode == 2 and spellbook.getInvoker().getAdminAccess() < 500: + if mode == 2 and spellbook.getInvoker().getAdminAccess() < 400: return "Chat mode 2 is reserved for administrators." if mode == 1 and spellbook.getInvoker().getAdminAccess() < 200: # Like this will ever happen, but whatever. diff --git a/otp/chat/ChatAgentUD.py b/otp/chat/ChatAgentUD.py index 5e9856dc..389678fe 100644 --- a/otp/chat/ChatAgentUD.py +++ b/otp/chat/ChatAgentUD.py @@ -27,7 +27,17 @@ class ChatAgentUD(DistributedObjectGlobalUD): 2 : "[ADMIN] ", 3 : "[SYSADMIN] ", } - + + self.muted = {} + + def muteAccount(self, account, howLong): + print ['muteAccount', account, howLong] + self.muted[account] = int(time.time()/60) + howLong + + def unmuteAccount(self, account): + print ['unmuteAccount', account] + if account in self.muted: + del self.muted[account] # Open chat def chatMessage(self, message, chatMode): sender = self.air.getAvatarIdFromSender() @@ -36,6 +46,9 @@ class ChatAgentUD(DistributedObjectGlobalUD): issue='Account sent chat without an avatar', message=message) return + if sender in self.muted and int(time.time()/60) < self.muted[sender]: + return + if self.wantWhitelist: cleanMessage, modifications = self.cleanWhitelist(message) else: diff --git a/otp/chat/ChatManager.py b/otp/chat/ChatManager.py index 816eb722..648a5a93 100644 --- a/otp/chat/ChatManager.py +++ b/otp/chat/ChatManager.py @@ -4,10 +4,6 @@ from direct.fsm import State from direct.gui.DirectGui import * from direct.showbase import DirectObject from pandac.PandaModules import * - -from otp.login import LeaveToPayDialog -from otp.login import PrivacyPolicyPanel -from otp.login import SecretFriendsInfoPanel from otp.otpbase import OTPLocalizer from toontown.chat.ChatGlobals import * @@ -49,17 +45,13 @@ class ChatManager(DirectObject.DirectObject): self.__normalObscured = 0 self.openChatWarning = None self.unpaidChatWarning = None - self.teaser = None self.paidNoParentPassword = None self.noSecretChatAtAll = None self.noSecretChatAtAllAndNoWhitelist = None self.noSecretChatWarning = None self.activateChatGui = None - self.chatMoreInfo = None - self.chatPrivacyPolicy = None self.secretChatActivated = None self.problemActivatingChat = None - self.leaveToPayDialog = None self.fsm = ClassicFSM.ClassicFSM('chatManager', [State.State('off', self.enterOff, self.exitOff), State.State('mainMenu', self.enterMainMenu, self.exitMainMenu), State.State('speedChat', self.enterSpeedChat, self.exitSpeedChat), @@ -70,7 +62,6 @@ class ChatManager(DirectObject.DirectObject): State.State('whisperSpeedChat', self.enterWhisperSpeedChat, self.exitWhisperSpeedChat), State.State('whisperSpeedChatPlayer', self.enterWhisperSpeedChatPlayer, self.exitWhisperSpeedChatPlayer), State.State('openChatWarning', self.enterOpenChatWarning, self.exitOpenChatWarning), - State.State('leaveToPayDialog', self.enterLeaveToPayDialog, self.exitLeaveToPayDialog), State.State('unpaidChatWarning', self.enterUnpaidChatWarning, self.exitUnpaidChatWarning), State.State('noSecretChatAtAll', self.enterNoSecretChatAtAll, self.exitNoSecretChatAtAll), State.State('noSecretChatAtAllAndNoWhitelist', self.enterNoSecretChatAtAllAndNoWhitelist, self.exitNoSecretChatAtAllAndNoWhitelist), @@ -78,14 +69,11 @@ class ChatManager(DirectObject.DirectObject): State.State('noFriendsWarning', self.enterNoFriendsWarning, self.exitNoFriendsWarning), State.State('otherDialog', self.enterOtherDialog, self.exitOtherDialog), State.State('activateChat', self.enterActivateChat, self.exitActivateChat), - State.State('chatMoreInfo', self.enterChatMoreInfo, self.exitChatMoreInfo), - State.State('chatPrivacyPolicy', self.enterChatPrivacyPolicy, self.exitChatPrivacyPolicy), State.State('secretChatActivated', self.enterSecretChatActivated, self.exitSecretChatActivated), State.State('problemActivatingChat', self.enterProblemActivatingChat, self.exitProblemActivatingChat), State.State('whiteListOpenChat', self.enterWhiteListOpenChat, self.exitWhiteListOpenChat), State.State('whiteListAvatarChat', self.enterWhiteListAvatarChat, self.exitWhiteListAvatarChat), - State.State('whiteListPlayerChat', self.enterWhiteListPlayerChat, self.exitWhiteListPlayerChat), - State.State('trueFriendTeaserPanel', self.enterTrueFriendTeaserPanel, self.exitTrueFriendTeaserPanel)], 'off', 'off') + State.State('whiteListPlayerChat', self.enterWhiteListPlayerChat, self.exitWhiteListPlayerChat)], 'off', 'off') self.fsm.enterInitialState() return @@ -105,10 +93,6 @@ class ChatManager(DirectObject.DirectObject): self.payButton = None self.unpaidChatWarning.destroy() self.unpaidChatWarning = None - if self.teaser: - self.teaser.cleanup() - self.teaser.unload() - self.teaser = None if self.noSecretChatAtAll: self.noSecretChatAtAll.destroy() self.noSecretChatAtAll = None @@ -121,12 +105,6 @@ class ChatManager(DirectObject.DirectObject): if self.activateChatGui: self.activateChatGui.destroy() self.activateChatGui = None - if self.chatMoreInfo: - self.chatMoreInfo.destroy() - self.chatMoreInfo = None - if self.chatPrivacyPolicy: - self.chatPrivacyPolicy.destroy() - self.chatPrivacyPolicy = None if self.secretChatActivated: self.secretChatActivated.destroy() self.secretChatActivated = None @@ -218,8 +196,6 @@ class ChatManager(DirectObject.DirectObject): if self.wantBackgroundFocus: self.chatInputNormal.chatEntry['backgroundFocus'] = 1 self.acceptOnce('enterNormalChat', self.fsm.request, ['normalChat']) - if not self.wantBackgroundFocus: - self.accept('t', messenger.send, ['enterNormalChat']) def checkObscurred(self): if not self.__scObscured: @@ -411,19 +387,6 @@ class ChatManager(DirectObject.DirectObject): def exitOpenChatWarning(self): self.notify.error('called exitOpenChatWarning() on parent class') - def enterLeaveToPayDialog(self): - if self.leaveToPayDialog == None: - self.leaveToPayDialog = LeaveToPayDialog.LeaveToPayDialog(self.paidNoParentPassword) - self.leaveToPayDialog.setCancel(self.__handleLeaveToPayCancel) - self.leaveToPayDialog.show() - return - - def exitLeaveToPayDialog(self): - if self.leaveToPayDialog: - self.leaveToPayDialog.destroy() - self.leaveToPayDialog = None - return - def enterUnpaidChatWarning(self): self.notify.error('called enterUnpaidChatWarning() on parent class') @@ -466,30 +429,6 @@ class ChatManager(DirectObject.DirectObject): def exitOtherDialog(self): pass - def enterChatMoreInfo(self): - if self.chatMoreInfo == None: - self.chatMoreInfo = SecretFriendsInfoPanel.SecretFriendsInfoPanel('secretFriendsInfoDone') - self.chatMoreInfo.show() - self.accept('secretFriendsInfoDone', self.__secretFriendsInfoDone) - return - - def exitChatMoreInfo(self): - self.chatMoreInfo.hide() - self.ignore('secretFriendsInfoDone') - - def enterChatPrivacyPolicy(self): - if self.chatPrivacyPolicy == None: - self.chatPrivacyPolicy = PrivacyPolicyPanel.PrivacyPolicyPanel('privacyPolicyDone') - self.chatPrivacyPolicy.show() - self.accept('privacyPolicyDone', self.__privacyPolicyDone) - return - - def exitChatPrivacyPolicy(self): - cleanupDialog('privacyPolicyDialog') - self.chatPrivacyPolicy = None - self.ignore('privacyPolicyDone') - return - def enterSecretChatActivated(self): self.notify.error('called enterSecretChatActivated() on parent class') @@ -500,19 +439,4 @@ class ChatManager(DirectObject.DirectObject): self.notify.error('called enterProblemActivatingChat() on parent class') def exitProblemActivatingChat(self): - self.notify.error('called exitProblemActivatingChat() on parent class') - - def enterTrueFriendTeaserPanel(self): - self.notify.error('called enterTrueFriendTeaserPanel () on parent class') - - def exitTrueFriendTeaserPanel(self): - self.notify.error('called exitTrueFriendTeaserPanel () on parent class') - - def __handleLeaveToPayCancel(self): - self.fsm.request('mainMenu') - - def __secretFriendsInfoDone(self): - self.fsm.request('activateChat') - - def __privacyPolicyDone(self): - self.fsm.request('activateChat') + self.notify.error('called exitProblemActivatingChat() on parent class') \ No newline at end of file diff --git a/otp/chat/TalkAssistant.py b/otp/chat/TalkAssistant.py index 22ea8617..c6fe782a 100644 --- a/otp/chat/TalkAssistant.py +++ b/otp/chat/TalkAssistant.py @@ -574,10 +574,6 @@ class TalkAssistant(DirectObject.DirectObject): def sendOpenTalk(self, message): error = None doId = base.localAvatar.doId - try: - message.encode('ascii') - except UnicodeEncodeError: - return if base.config.GetBool('want-talkative-tyler', False): if base.localAvatar.zoneId == 2000: tyler = base.cr.doFind('Talkative Tyler') @@ -610,7 +606,7 @@ class TalkAssistant(DirectObject.DirectObject): message, scrubbed = base.localAvatar.scrubTalk(cleanMessage, modifications) - base.cr.ttiFriendsManager.sendUpdate('sendTalkWhisper', [receiverAvId, message]) + base.cr.ttuFriendsManager.sendUpdate('sendTalkWhisper', [receiverAvId, message]) def sendAccountTalk(self, message, receiverAccount): error = None @@ -671,24 +667,8 @@ class TalkAssistant(DirectObject.DirectObject): return error def sendPlayerWhisperSpeedChat(self, type, messageIndex, receiverId): - error = None - if type == SPEEDCHAT_NORMAL: - base.cr.speedchatRelay.sendSpeedchat(receiverId, messageIndex) - message = self.SCDecoder.decodeSCStaticTextMsg(messageIndex) - elif type == SPEEDCHAT_EMOTE: - base.cr.speedchatRelay.sendSpeedchatEmote(receiverId, messageIndex) - message = self.SCDecoder.decodeSCEmoteWhisperMsg(messageIndex, localAvatar.getName()) - return - elif type == SPEEDCHAT_CUSTOM: - base.cr.speedchatRelay.sendSpeedchatCustom(receiverId, messageIndex) - message = self.SCDecoder.decodeSCCustomMsg(messageIndex) - if self.logWhispers: - receiverName = self.findName(receiverId, 1) - newMessage = TalkMessage(self.countMessage(), self.stampTime(), message, localAvatar.doId, localAvatar.getName(), localAvatar.DISLid, localAvatar.DISLname, None, None, receiverId, receiverName, TALK_ACCOUNT, None) - self.historyComplete.append(newMessage) - self.addToHistoryDoId(newMessage, localAvatar.doId) - messenger.send('NewOpenMessage', [newMessage]) - return error + # TODO: Remove Player system + return None def sendGuildSpeedChat(self, type, msgIndex): error = None diff --git a/otp/chat/WhiteList.py b/otp/chat/WhiteList.py index a6c74684..0011183e 100644 --- a/otp/chat/WhiteList.py +++ b/otp/chat/WhiteList.py @@ -1,27 +1,41 @@ from bisect import bisect_left - +import string +import sys +import os class WhiteList: - def __init__(self, words): - self.words = words + + def __init__(self, wordlist): + self.words = [] + for line in wordlist: + self.words.append(line.strip('\n\r').lower()) + + self.words.sort() self.numWords = len(self.words) def cleanText(self, text): text = text.strip('.,?!') - return text.lower() + text = text.lower() + return text def isWord(self, text): - return self.cleanText(text) in self.words + try: + text = self.cleanText(text) + i = bisect_left(self.words, text) + if i == self.numWords: + return False + return self.words[i] == text + except UnicodeDecodeError: + return False # Lets not open ourselves up to obscure keyboards... + def isPrefix(self, text): text = self.cleanText(text) i = bisect_left(self.words, text) - if i == self.numWords: return False - return self.words[i].startswith(text) - + def prefixCount(self, text): text = self.cleanText(text) i = bisect_left(self.words, text) @@ -38,4 +52,4 @@ class WhiteList: while j < self.numWords and self.words[j].startswith(text): j += 1 - return self.words[i:j] + return self.words[i:j] diff --git a/toontown/uberdog/ClientServicesManagerUD.py b/toontown/uberdog/ClientServicesManagerUD.py index c9825caa..98b25865 100644 --- a/toontown/uberdog/ClientServicesManagerUD.py +++ b/toontown/uberdog/ClientServicesManagerUD.py @@ -101,12 +101,6 @@ class AccountDB: def lookup(self, username, callback): pass # Inheritors should override this. - def persistMessage(self, category, description, sender, receiver): - print ['persistMessage', category, description, sender, receiver] - - def persistChat(self, sender, message, channel): - pass - def storeAccountID(self, userId, accountId, callback): self.dbm[str(userId)] = str(accountId) # anydbm only allows strings. if getattr(self.dbm, 'sync', None): From b5c8ba3fcb74f4e929f997f47de2acbbcee144a1 Mon Sep 17 00:00:00 2001 From: Loudrob Date: Wed, 1 Apr 2015 16:29:52 -0400 Subject: [PATCH 09/14] Revert "oo[pssieisss" This reverts commit 260e5af56f690f8724fd0fbabb9ff83ba5115b44. --- config/release/dev.prc | 1 - toontown/chat/TTSequenceList.py | 36 -------------------------- toontown/suit/DistributedSuitBaseAI.py | 3 +-- 3 files changed, 1 insertion(+), 39 deletions(-) delete mode 100644 toontown/chat/TTSequenceList.py diff --git a/config/release/dev.prc b/config/release/dev.prc index 48c30c26..7ac6a986 100644 --- a/config/release/dev.prc +++ b/config/release/dev.prc @@ -27,7 +27,6 @@ want-achievements #f # Chat: want-whitelist #f -want-blacklist-sequence #f # Cashbot boss: want-resistance-toonup #t diff --git a/toontown/chat/TTSequenceList.py b/toontown/chat/TTSequenceList.py deleted file mode 100644 index bf467501..00000000 --- a/toontown/chat/TTSequenceList.py +++ /dev/null @@ -1,36 +0,0 @@ -from pandac.PandaModules import * -from otp.chat.SequenceList import SequenceList -from direct.directnotify import DirectNotifyGlobal - -class TTSequenceList(SequenceList): - - def __init__(self): - self.notify = DirectNotifyGlobal.directNotify.newCategory('TTSequenceList') - sequenceListURL = config.GetString('blacklist-sequence-url', '') - if sequenceListURL == '': - self.notify.warning('No Sequence BL URL specified! Continuing with local sequence.') - SequenceList.__init__(self, self.loadSquencesLocally()) - else: - SequenceList.__init__(self, self.downloadSequences(sequenceListURL)) - - def downloadSequences(self, url): - fs = Ramfile() - http = HTTPClient.getGlobalPtr() - self.ch = http.makeChannel(True) - self.ch.getHeader(DocumentSpec(url)) - doc = self.ch.getDocumentSpec() - self.ch.getDocument(doc) - self.ch.downloadToRam(fs) - return fs.getData().split('\r\n') - - def loadSquencesLocally(self): - vfs = VirtualFileSystem.getGlobalPtr() - filename = Filename('tsequence.dat') - searchPath = DSearchPath() - searchPath.appendDirectory(Filename('/server')) - found = vfs.resolveFilename(filename, searchPath) - if not found: - self.notify.warning("Couldn't find blacklist sequence data file!") - return - data = vfs.readFile(filename, True) - return data.split('\n') diff --git a/toontown/suit/DistributedSuitBaseAI.py b/toontown/suit/DistributedSuitBaseAI.py index f11d1d6d..687bdc91 100644 --- a/toontown/suit/DistributedSuitBaseAI.py +++ b/toontown/suit/DistributedSuitBaseAI.py @@ -117,7 +117,6 @@ class DistributedSuitBaseAI(DistributedAvatarAI.DistributedAvatarAI, SuitBase.Su def useSkeleRevive(self): self.skeleRevives -= 1 self.currHP = self.maxHP - self.d_setHP(self.currHP) self.reviveFlag = 1 def reviveCheckAndClear(self): @@ -196,4 +195,4 @@ class DistributedSuitBaseAI(DistributedAvatarAI.DistributedAvatarAI, SuitBase.Su self.d_setWaiter(flag) def getWaiter(self): - return self.waiter + return self.waiter \ No newline at end of file From c8f5d19c11905ca99983c40bf8309891c426d53d Mon Sep 17 00:00:00 2001 From: Loudrob Date: Wed, 1 Apr 2015 16:30:08 -0400 Subject: [PATCH 10/14] Revert "Added staff chat channels." This reverts commit c72e45fbc469b22937009d4d371109185a1147bf. --- astron/dclass/united.dc | 6 +- otp/chat/ChatAgent.py | 36 +---- otp/chat/ChatAgentUD.py | 140 +++----------------- otp/chat/SequenceList.py | 15 --- otp/chat/WhiteList.py | 45 +------ otp/distributed/DCClassImports.py | 2 +- otp/distributed/OtpDoGlobals.py | 4 +- toontown/ai/ServiceStart.py | 1 - toontown/uberdog/ClientServicesManagerUD.py | 27 +--- 9 files changed, 33 insertions(+), 243 deletions(-) delete mode 100644 otp/chat/SequenceList.py diff --git a/astron/dclass/united.dc b/astron/dclass/united.dc index 655b2477..3f3ee41c 100644 --- a/astron/dclass/united.dc +++ b/astron/dclass/united.dc @@ -255,10 +255,8 @@ dclass MagicWordManager : DistributedObject { }; dclass ChatAgent : DistributedObject { - adminChat(uint32 aboutId, string message); - chatMessage(string(0-256) message, uint8 chatMode) clsend; - whisperMessage(uint32 receiverAvId, string(0-256) message) clsend; - sfWhisperMessage(uint32 receiverAvId, string(0-256) message) clsend; + adminChat(uint32, string); + chatMessage(string(0-256)) clsend; }; dclass FriendManager : DistributedObject { diff --git a/otp/chat/ChatAgent.py b/otp/chat/ChatAgent.py index 32a84a24..1b9f8889 100644 --- a/otp/chat/ChatAgent.py +++ b/otp/chat/ChatAgent.py @@ -1,17 +1,14 @@ from direct.distributed.DistributedObjectGlobal import DistributedObjectGlobal from pandac.PandaModules import * from otp.otpbase import OTPGlobals -from otp.ai.MagicWordGlobal import * class ChatAgent(DistributedObjectGlobal): def __init__(self, cr): DistributedObjectGlobal.__init__(self, cr) - self.chatMode = 0 def delete(self): self.ignoreAll() self.cr.chatManager = None - self.cr.chatAgent = None DistributedObjectGlobal.delete(self) return @@ -20,35 +17,4 @@ class ChatAgent(DistributedObjectGlobal): messenger.send('adminChat', [aboutId, message]) def sendChatMessage(self, message): - self.sendUpdate('chatMessage', [message, self.chatMode]) - - def sendWhisperMessage(self, receiverAvId, message): - self.sendUpdate('whisperMessage', [receiverAvId, message]) - - def sendSFWhisperMessage(self, receiverAvId, message): - self.sendUpdate('sfWhisperMessage', [receiverAvId, message]) - -@magicWord(category=CATEGORY_MODERATOR, types=[int]) -def chatmode(mode=-1): - """ Set the chat mode of the current avatar. """ - mode2name = { - 0 : "user", - 1 : "moderator", - 2 : "administrator", - 3 : "system administrator", - } - if base.cr.chatAgent is None: - return "No ChatAgent found." - if mode == -1: - return "You are currently talking in the %s chat mode." % mode2name.get(base.cr.chatAgent.chatMode, "N/A") - if not 0 <= mode <= 3: - return "Invalid chat mode specified." - if mode == 3 and spellbook.getInvoker().getAdminAccess() < 500: - return "Chat mode 3 is reserved for system administrators." - if mode == 2 and spellbook.getInvoker().getAdminAccess() < 400: - return "Chat mode 2 is reserved for administrators." - if mode == 1 and spellbook.getInvoker().getAdminAccess() < 200: - # Like this will ever happen, but whatever. - return "Chat mode 1 is reserved for moderators." - base.cr.chatAgent.chatMode = mode - return "You are now talking in the %s chat mode." % mode2name.get(mode, "N/A") + self.sendUpdate('chatMessage', [message]) diff --git a/otp/chat/ChatAgentUD.py b/otp/chat/ChatAgentUD.py index 389678fe..b90b782d 100644 --- a/otp/chat/ChatAgentUD.py +++ b/otp/chat/ChatAgentUD.py @@ -2,151 +2,41 @@ from direct.directnotify import DirectNotifyGlobal from direct.distributed.DistributedObjectGlobalUD import DistributedObjectGlobalUD # TODO: OTP should not depend on Toontown... Hrrm. from toontown.chat.TTWhiteList import TTWhiteList -from toontown.chat.TTSequenceList import TTSequenceList -from otp.distributed import OtpDoGlobals -import time class ChatAgentUD(DistributedObjectGlobalUD): notify = DirectNotifyGlobal.directNotify.newCategory("ChatAgentUD") def announceGenerate(self): DistributedObjectGlobalUD.announceGenerate(self) - self.wantBlacklistSequence = config.GetBool('want-blacklist-sequence', True) - self.wantWhitelist = config.GetBool('want-whitelist', True) - if self.wantWhitelist: - self.whiteList = TTWhiteList() - if self.wantBlacklistSequence: - self.sequenceList = TTSequenceList() - self.chatMode2channel = { - 1 : OtpDoGlobals.OTP_MOD_CHANNEL, - 2 : OtpDoGlobals.OTP_ADMIN_CHANNEL, - 3 : OtpDoGlobals.OTP_SYSADMIN_CHANNEL, - } - self.chatMode2prefix = { - 1 : "[MOD] ", - 2 : "[ADMIN] ", - 3 : "[SYSADMIN] ", - } - - self.muted = {} - def muteAccount(self, account, howLong): - print ['muteAccount', account, howLong] - self.muted[account] = int(time.time()/60) + howLong + self.whiteList = TTWhiteList() - def unmuteAccount(self, account): - print ['unmuteAccount', account] - if account in self.muted: - del self.muted[account] - # Open chat - def chatMessage(self, message, chatMode): + def chatMessage(self, message): sender = self.air.getAvatarIdFromSender() if sender == 0: - self.air.writeServerEvent('suspicious', accId=self.air.getAccountIdFromSender(), - issue='Account sent chat without an avatar', message=message) - return - - if sender in self.muted and int(time.time()/60) < self.muted[sender]: - return - - if self.wantWhitelist: - cleanMessage, modifications = self.cleanWhitelist(message) - else: - cleanMessage, modifications = message, [] - self.air.writeServerEvent('chat-said', avId=sender, chatMode=chatMode, msg=message, cleanMsg=cleanMessage) - - # TODO: The above is probably a little too ugly for my taste... Maybe AIR - # should be given an API for sending updates for unknown objects? - if chatMode != 0: - # Staff messages do not need to be cleaned. [TODO: Blacklist this?] - if message.startswith('.'): - # This is a thought bubble, move the point to the start. - cleanMessage = '.' + self.chatMode2prefix.get(chatMode, "") + message[1:] - else: - cleanMessage = self.chatMode2prefix.get(chatMode, "") + message - modifications = [] - DistributedAvatar = self.air.dclassesByName['DistributedAvatarUD'] - dg = DistributedAvatar.aiFormatUpdate('setTalk', sender, self.chatMode2channel.get(chatMode, sender), - self.air.ourChannel, - [0, 0, '', cleanMessage, modifications, 0]) - self.air.send(dg) - self.air.csm.accountDB.persistChat(sender, message, self.air.ourChannel) - - # Regular filtered chat - def whisperMessage(self, receiverAvId, message): - sender = self.air.getAvatarIdFromSender() - if sender == 0: - self.air.writeServerEvent('suspicious', accId=self.air.getAccountIdFromSender(), - issue='Account sent chat without an avatar', message=message) + self.air.writeServerEvent('suspicious', self.air.getAccountIdFromSender(), + 'Account sent chat without an avatar', message) return - cleanMessage, modifications = self.cleanWhitelist(message) - # Maybe a better "cleaner" way of doing this, but it works - self.air.writeServerEvent('whisper-said', avId=sender, reciever=receiverAvId, msg=message, cleanMsg=cleanMessage) - DistributedAvatar = self.air.dclassesByName['DistributedAvatarUD'] - dg = DistributedAvatar.aiFormatUpdate('setTalkWhisper', receiverAvId, receiverAvId, self.air.ourChannel, - [sender, sender, '', cleanMessage, modifications, 0]) - self.air.send(dg) - - # True friend unfiltered chat - def sfWhisperMessage(self, receiverAvId, message): - sender = self.air.getAvatarIdFromSender() - if sender == 0: - self.air.writeServerEvent('suspicious', accId=self.air.getAccountIdFromSender(), - issue='Account sent chat without an avatar', message=message) - return - - cleanMessage = self.cleanBlacklist(message) - - self.air.writeServerEvent('sf-whisper-said', avId=sender, reciever=receiverAvId, msg=message, cleanMsg=cleanMessage) - DistributedAvatar = self.air.dclassesByName['DistributedAvatarUD'] - dg = DistributedAvatar.aiFormatUpdate('setTalkWhisper', receiverAvId, receiverAvId, self.air.ourChannel, - [sender, sender, '', cleanMessage, [], 0]) - self.air.send(dg) - - # Filter the chat message - def cleanWhitelist(self, message): modifications = [] words = message.split(' ') offset = 0 + WantWhitelist = config.GetBool('want-whitelist', 1) for word in words: - if word and not self.whiteList.isWord(word): + if word and not self.whiteList.isWord(word) and WantWhitelist: modifications.append((offset, offset+len(word)-1)) offset += len(word) + 1 cleanMessage = message - if self.wantBlacklistSequence: - modifications += self.cleanSequences(cleanMessage) - for modStart, modStop in modifications: - # Traverse through modification list and replace the characters of non-whitelisted words and/or blacklisted sequences with asterisks. - cleanMessage = cleanMessage[:modStart] + '*' * (modStop - modStart + 1) + cleanMessage[modStop + 1:] + cleanMessage = cleanMessage[:modStart] + '*'*(modStop-modStart+1) + cleanMessage[modStop+1:] - return (cleanMessage, modifications) + self.air.writeServerEvent('chat-said', sender, message, cleanMessage) - # Check the black list for black-listed words - def cleanBlacklist(self, message): - # We don't have a black list so we just return the full message - return message - - # Check for black-listed word sequences and scrub accordingly. - def cleanSequences(self, message): - modifications = [] - offset = 0 - words = message.split() - for wordit in xrange(len(words)): - word = words[wordit].lower() - seqlist = self.sequenceList.getList(word) - if len(seqlist) > 0: - for seqit in xrange(len(seqlist)): - sequence = seqlist[seqit] - splitseq = sequence.split() - if len(words) - (wordit + 1) >= len(splitseq): - cmplist = words[wordit + 1:] - del cmplist[len(splitseq):] - cmplist = [word.lower() for word in cmplist] - if cmp(cmplist, splitseq) == 0: - modifications.append((offset, offset + len(word) + len(sequence) - 1)) - offset += len(word) + 1 - - return modifications + # TODO: The above is probably a little too ugly for my taste... Maybe AIR + # should be given an API for sending updates for unknown objects? + DistributedAvatar = self.air.dclassesByName['DistributedAvatarUD'] + dg = DistributedAvatar.aiFormatUpdate('setTalk', sender, sender, + self.air.ourChannel, + [0, 0, '', cleanMessage, modifications, 0]) + self.air.send(dg) \ No newline at end of file diff --git a/otp/chat/SequenceList.py b/otp/chat/SequenceList.py deleted file mode 100644 index 0021efd3..00000000 --- a/otp/chat/SequenceList.py +++ /dev/null @@ -1,15 +0,0 @@ -class SequenceList: - - def __init__(self, wordlist): - self.list = {} - for line in wordlist: - if line is '': - continue - split = line.split(':') - self.list[split[0].lower()] = [word.rstrip('\r\n').lower() for word in split[1].split(',')] - - def getList(self, word): - if word in self.list: - return self.list[word] - else: - return [] \ No newline at end of file diff --git a/otp/chat/WhiteList.py b/otp/chat/WhiteList.py index 0011183e..8be965a6 100644 --- a/otp/chat/WhiteList.py +++ b/otp/chat/WhiteList.py @@ -1,55 +1,22 @@ from bisect import bisect_left -import string -import sys -import os class WhiteList: - - def __init__(self, wordlist): - self.words = [] - for line in wordlist: - self.words.append(line.strip('\n\r').lower()) - - self.words.sort() + def __init__(self, words): + self.words = words self.numWords = len(self.words) def cleanText(self, text): text = text.strip('.,?!') - text = text.lower() - return text + return text.lower() def isWord(self, text): - try: - text = self.cleanText(text) - i = bisect_left(self.words, text) - if i == self.numWords: - return False - return self.words[i] == text - except UnicodeDecodeError: - return False # Lets not open ourselves up to obscure keyboards... - + return self.cleanText(text) in self.words def isPrefix(self, text): text = self.cleanText(text) i = bisect_left(self.words, text) + if i == self.numWords: return False - return self.words[i].startswith(text) - def prefixCount(self, text): - text = self.cleanText(text) - i = bisect_left(self.words, text) - j = i - while j < self.numWords and self.words[j].startswith(text): - j += 1 - - return j - i - - def prefixList(self, text): - text = self.cleanText(text) - i = bisect_left(self.words, text) - j = i - while j < self.numWords and self.words[j].startswith(text): - j += 1 - - return self.words[i:j] + return self.words[i].startswith(text) \ No newline at end of file diff --git a/otp/distributed/DCClassImports.py b/otp/distributed/DCClassImports.py index 08fd1b8b..8b6c09a8 100644 --- a/otp/distributed/DCClassImports.py +++ b/otp/distributed/DCClassImports.py @@ -2,7 +2,7 @@ from pandac.PandaModules import * -hashVal = 4270694562L +hashVal = 598642574 from toontown.coghq import DistributedCashbotBossSafe, DistributedCashbotBossCrane, DistributedBattleFactory, DistributedCashbotBossTreasure, DistributedCogHQDoor, DistributedSellbotHQDoor, DistributedFactoryElevatorExt, DistributedMintElevatorExt, DistributedLawOfficeElevatorExt, DistributedLawOfficeElevatorInt, LobbyManager, DistributedMegaCorp, DistributedFactory, DistributedLawOffice, DistributedLawOfficeFloor, DistributedLift, DistributedDoorEntity, DistributedSwitch, DistributedButton, DistributedTrigger, DistributedCrushableEntity, DistributedCrusherEntity, DistributedStomper, DistributedStomperPair, DistributedLaserField, DistributedGolfGreenGame, DistributedSecurityCamera, DistributedMover, DistributedElevatorMarker, DistributedBarrelBase, DistributedGagBarrel, DistributedBeanBarrel, DistributedHealBarrel, DistributedGrid, ActiveCell, DirectionalCell, CrusherCell, DistributedCrate, DistributedSinkingPlatform, BattleBlocker, DistributedMint, DistributedMintRoom, DistributedMintBattle, DistributedStage, DistributedStageRoom, DistributedStageBattle, DistributedLawbotBossGavel, DistributedLawbotCannon, DistributedLawbotChair, DistributedCogKart, DistributedCountryClub, DistributedCountryClubRoom, DistributedMoleField, DistributedCountryClubBattle, DistributedMaze, DistributedFoodBelt, DistributedBanquetTable, DistributedGolfSpot diff --git a/otp/distributed/OtpDoGlobals.py b/otp/distributed/OtpDoGlobals.py index 1371df4a..f665ced4 100644 --- a/otp/distributed/OtpDoGlobals.py +++ b/otp/distributed/OtpDoGlobals.py @@ -88,6 +88,4 @@ OTP_ZONE_ID_DISTRICTS = 3 OTP_ZONE_ID_DISTRICTS_STATS = 4 OTP_ZONE_ID_ELEMENTS = 5 OTP_NET_MESSENGER_CHANNEL = (OTP_DO_ID_UBER_DOG << 32) + OTP_ZONE_ID_MANAGEMENT -OTP_MOD_CHANNEL = 6200 -OTP_ADMIN_CHANNEL = 6400 -OTP_SYSADMIN_CHANNEL = 6500 +OTP_STAFF_CHANNEL = 6200 diff --git a/toontown/ai/ServiceStart.py b/toontown/ai/ServiceStart.py index 02df1a35..4850f968 100644 --- a/toontown/ai/ServiceStart.py +++ b/toontown/ai/ServiceStart.py @@ -35,7 +35,6 @@ if args.astron_ip: localconfig += 'air-connect %s\n' % args.astron_ip if args.eventlogger_ip: localconfig += 'eventlog-host %s\n' % args.eventlogger_ip loadPrcFileData('Command-line', localconfig) - from otp.ai.AIBaseGlobal import * from toontown.ai.ToontownAIRepository import ToontownAIRepository diff --git a/toontown/uberdog/ClientServicesManagerUD.py b/toontown/uberdog/ClientServicesManagerUD.py index 98b25865..c8b3e188 100644 --- a/toontown/uberdog/ClientServicesManagerUD.py +++ b/toontown/uberdog/ClientServicesManagerUD.py @@ -422,26 +422,13 @@ class LoginAccountFSM(OperationFSM): datagram.addChannel(self.csm.GetAccountConnectionChannel(self.accountId)) self.csm.air.send(datagram) - # Subscribe to any "staff" channels that the account has access to. - access = self.account.get('ADMIN_ACCESS', 0) - if access >= 200: - # Subscribe to the moderator channel. - dg = PyDatagram() - dg.addServerHeader(self.target, self.csm.air.ourChannel, CLIENTAGENT_OPEN_CHANNEL) - dg.addChannel(OtpDoGlobals.OTP_MOD_CHANNEL) - self.csm.air.send(dg) - if access >= 400: - # Subscribe to the administrator channel. - dg = PyDatagram() - dg.addServerHeader(self.target, self.csm.air.ourChannel, CLIENTAGENT_OPEN_CHANNEL) - dg.addChannel(OtpDoGlobals.OTP_ADMIN_CHANNEL) - self.csm.air.send(dg) - if access >= 500: - # Subscribe to the system administrator channel. - dg = PyDatagram() - dg.addServerHeader(self.target, self.csm.air.ourChannel, CLIENTAGENT_OPEN_CHANNEL) - dg.addChannel(OtpDoGlobals.OTP_SYSADMIN_CHANNEL) - self.csm.air.send(dg) + # Add this connection to extra channels which may be useful: + if self.accessLevel > 100: + datagram = PyDatagram() + datagram.addServerHeader(self.target, self.csm.air.ourChannel, + CLIENTAGENT_OPEN_CHANNEL) + datagram.addChannel(OtpDoGlobals.OTP_STAFF_CHANNEL) + self.csm.air.send(datagram) # Now set their sender channel to represent their account affiliation: datagram = PyDatagram() From 233dbd4ba924df1833def47c53f430affb8b80b6 Mon Sep 17 00:00:00 2001 From: Loudrob Date: Thu, 2 Apr 2015 08:23:24 -0400 Subject: [PATCH 11/14] sequence asslist and chathoes --- .gitignore | 3 +- astron/dclass/united.dc | 6 +- otp/chat/ChatAgent.py | 37 +++++- otp/chat/ChatAgentUD.py | 131 +++++++++++++++++--- otp/chat/SequenceList.py | 15 +++ otp/chat/WhiteList.py | 20 ++- otp/distributed/DCClassImports.py | 2 +- otp/distributed/OtpDoGlobals.py | 5 +- toontown/ai/ServiceStart.py | 4 +- toontown/chat/TTSequenceList.py | 36 ++++++ toontown/toonbase/ToontownGlobals.py | 2 +- toontown/uberdog/ClientServicesManagerUD.py | 27 ++-- 12 files changed, 255 insertions(+), 33 deletions(-) create mode 100644 otp/chat/SequenceList.py create mode 100644 toontown/chat/TTSequenceList.py diff --git a/.gitignore b/.gitignore index c7885aa0..ec0c1d93 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,5 @@ screenshots/ backups/ contentpacks/ resources/ -save.dat \ No newline at end of file +save.dat +ai-crash.txt \ No newline at end of file diff --git a/astron/dclass/united.dc b/astron/dclass/united.dc index 3f3ee41c..655b2477 100644 --- a/astron/dclass/united.dc +++ b/astron/dclass/united.dc @@ -255,8 +255,10 @@ dclass MagicWordManager : DistributedObject { }; dclass ChatAgent : DistributedObject { - adminChat(uint32, string); - chatMessage(string(0-256)) clsend; + adminChat(uint32 aboutId, string message); + chatMessage(string(0-256) message, uint8 chatMode) clsend; + whisperMessage(uint32 receiverAvId, string(0-256) message) clsend; + sfWhisperMessage(uint32 receiverAvId, string(0-256) message) clsend; }; dclass FriendManager : DistributedObject { diff --git a/otp/chat/ChatAgent.py b/otp/chat/ChatAgent.py index 1b9f8889..0de10879 100644 --- a/otp/chat/ChatAgent.py +++ b/otp/chat/ChatAgent.py @@ -1,14 +1,17 @@ from direct.distributed.DistributedObjectGlobal import DistributedObjectGlobal from pandac.PandaModules import * from otp.otpbase import OTPGlobals +from otp.ai.MagicWordGlobal import * class ChatAgent(DistributedObjectGlobal): def __init__(self, cr): DistributedObjectGlobal.__init__(self, cr) + self.chatMode = 0 def delete(self): self.ignoreAll() self.cr.chatManager = None + self.cr.chatAgent = None DistributedObjectGlobal.delete(self) return @@ -17,4 +20,36 @@ class ChatAgent(DistributedObjectGlobal): messenger.send('adminChat', [aboutId, message]) def sendChatMessage(self, message): - self.sendUpdate('chatMessage', [message]) + self.sendUpdate('chatMessage', [message, self.chatMode]) + + def sendWhisperMessage(self, receiverAvId, message): + self.sendUpdate('whisperMessage', [receiverAvId, message]) + + def sendSFWhisperMessage(self, receiverAvId, message): + self.sendUpdate('sfWhisperMessage', [receiverAvId, message]) + +@magicWord(category=CATEGORY_MODERATOR, types=[int]) +def chatmode(mode=-1): + """ Set the chat mode of the current avatar. """ + mode2name = { + 0 : "user", + 1 : "moderator", + 2 : "administrator", + 3 : "system administrator", + } + if base.cr.chatAgent is None: + return "No ChatAgent found." + if mode == -1: + return "You are currently talking in the %s chat mode." % mode2name.get(base.cr.chatAgent.chatMode, "N/A") + if not 0 <= mode <= 3: + return "Invalid chat mode specified." + if mode == 3 and spellbook.getInvoker().getAdminAccess() < 500: + return "Chat mode 3 is reserved for system administrators." + if mode == 2 and spellbook.getInvoker().getAdminAccess() < 400: + return "Chat mode 2 is reserved for administrators." + if mode == 1 and spellbook.getInvoker().getAdminAccess() < 200: + # Like this will ever happen, but whatever. + return "Chat mode 1 is reserved for moderators." + base.cr.chatAgent.chatMode = mode + return "You are now talking in the %s chat mode." % mode2name.get(mode, "N/A") + diff --git a/otp/chat/ChatAgentUD.py b/otp/chat/ChatAgentUD.py index b90b782d..e39cbc98 100644 --- a/otp/chat/ChatAgentUD.py +++ b/otp/chat/ChatAgentUD.py @@ -2,41 +2,138 @@ from direct.directnotify import DirectNotifyGlobal from direct.distributed.DistributedObjectGlobalUD import DistributedObjectGlobalUD # TODO: OTP should not depend on Toontown... Hrrm. from toontown.chat.TTWhiteList import TTWhiteList +from toontown.chat.TTSequenceList import TTSequenceList +from otp.distributed import OtpDoGlobals class ChatAgentUD(DistributedObjectGlobalUD): notify = DirectNotifyGlobal.directNotify.newCategory("ChatAgentUD") def announceGenerate(self): DistributedObjectGlobalUD.announceGenerate(self) - - self.whiteList = TTWhiteList() - - def chatMessage(self, message): + self.wantBlacklistSequence = config.GetBool('want-blacklist-sequence', True) + self.wantWhitelist = config.GetBool('want-whitelist', True) + if self.wantWhitelist: + self.whiteList = TTWhiteList() + if self.wantBlacklistSequence: + self.sequenceList = TTSequenceList() + self.chatMode2channel = { + 1 : OtpDoGlobals.OTP_MOD_CHANNEL, + 2 : OtpDoGlobals.OTP_ADMIN_CHANNEL, + 3 : OtpDoGlobals.OTP_SYSADMIN_CHANNEL, + } + self.chatMode2prefix = { + 1 : "[MOD] ", + 2 : "[ADMIN] ", + 3 : "[SYSADMIN] ", + } + # Open chat + def chatMessage(self, message, chatMode): sender = self.air.getAvatarIdFromSender() if sender == 0: - self.air.writeServerEvent('suspicious', self.air.getAccountIdFromSender(), - 'Account sent chat without an avatar', message) + self.air.writeServerEvent('suspicious', accId=self.air.getAccountIdFromSender(), + issue='Account sent chat without an avatar', message=message) return + if self.wantWhitelist: + cleanMessage, modifications = self.cleanWhitelist(message) + else: + cleanMessage, modifications = message, [] + self.air.writeServerEvent('chat-said', avId=sender, chatMode=chatMode, msg=message, cleanMsg=cleanMessage) + + # TODO: The above is probably a little too ugly for my taste... Maybe AIR + # should be given an API for sending updates for unknown objects? + if chatMode != 0: + # Staff messages do not need to be cleaned. [TODO: Blacklist this?] + if message.startswith('.'): + # This is a thought bubble, move the point to the start. + cleanMessage = '.' + self.chatMode2prefix.get(chatMode, "") + message[1:] + else: + cleanMessage = self.chatMode2prefix.get(chatMode, "") + message + modifications = [] + DistributedAvatar = self.air.dclassesByName['DistributedAvatarUD'] + dg = DistributedAvatar.aiFormatUpdate('setTalk', sender, self.chatMode2channel.get(chatMode, sender), + self.air.ourChannel, + [0, 0, '', cleanMessage, modifications, 0]) + self.air.send(dg) + + # Regular filtered chat + def whisperMessage(self, receiverAvId, message): + sender = self.air.getAvatarIdFromSender() + if sender == 0: + self.air.writeServerEvent('suspicious', accId=self.air.getAccountIdFromSender(), + issue='Account sent chat without an avatar', message=message) + return + + cleanMessage, modifications = self.cleanWhitelist(message) + # Maybe a better "cleaner" way of doing this, but it works + self.air.writeServerEvent('whisper-said', avId=sender, reciever=receiverAvId, msg=message, cleanMsg=cleanMessage) + DistributedAvatar = self.air.dclassesByName['DistributedAvatarUD'] + dg = DistributedAvatar.aiFormatUpdate('setTalkWhisper', receiverAvId, receiverAvId, self.air.ourChannel, + [sender, sender, '', cleanMessage, modifications, 0]) + self.air.send(dg) + + # True friend unfiltered chat + def sfWhisperMessage(self, receiverAvId, message): + sender = self.air.getAvatarIdFromSender() + if sender == 0: + self.air.writeServerEvent('suspicious', accId=self.air.getAccountIdFromSender(), + issue='Account sent chat without an avatar', message=message) + return + + cleanMessage = self.cleanBlacklist(message) + + self.air.writeServerEvent('sf-whisper-said', avId=sender, reciever=receiverAvId, msg=message, cleanMsg=cleanMessage) + DistributedAvatar = self.air.dclassesByName['DistributedAvatarUD'] + dg = DistributedAvatar.aiFormatUpdate('setTalkWhisper', receiverAvId, receiverAvId, self.air.ourChannel, + [sender, sender, '', cleanMessage, [], 0]) + self.air.send(dg) + + # Filter the chat message + def cleanWhitelist(self, message): modifications = [] words = message.split(' ') offset = 0 - WantWhitelist = config.GetBool('want-whitelist', 1) for word in words: - if word and not self.whiteList.isWord(word) and WantWhitelist: + if word and not self.whiteList.isWord(word): modifications.append((offset, offset+len(word)-1)) offset += len(word) + 1 cleanMessage = message + if self.wantBlacklistSequence: + modifications += self.cleanSequences(cleanMessage) + for modStart, modStop in modifications: - cleanMessage = cleanMessage[:modStart] + '*'*(modStop-modStart+1) + cleanMessage[modStop+1:] + # Traverse through modification list and replace the characters of non-whitelisted words and/or blacklisted sequences with asterisks. + cleanMessage = cleanMessage[:modStart] + '*' * (modStop - modStart + 1) + cleanMessage[modStop + 1:] + + return (cleanMessage, modifications) + + # Check the black list for black-listed words + def cleanBlacklist(self, message): + # We don't have a black list so we just return the full message + return message + + # Check for black-listed word sequences and scrub accordingly. + def cleanSequences(self, message): + modifications = [] + offset = 0 + words = message.split() + for wordit in xrange(len(words)): + word = words[wordit].lower() + seqlist = self.sequenceList.getList(word) + if len(seqlist) > 0: + for seqit in xrange(len(seqlist)): + sequence = seqlist[seqit] + splitseq = sequence.split() + if len(words) - (wordit + 1) >= len(splitseq): + cmplist = words[wordit + 1:] + del cmplist[len(splitseq):] + cmplist = [word.lower() for word in cmplist] + if cmp(cmplist, splitseq) == 0: + modifications.append((offset, offset + len(word) + len(sequence) - 1)) + offset += len(word) + 1 + + return modifications + - self.air.writeServerEvent('chat-said', sender, message, cleanMessage) - # TODO: The above is probably a little too ugly for my taste... Maybe AIR - # should be given an API for sending updates for unknown objects? - DistributedAvatar = self.air.dclassesByName['DistributedAvatarUD'] - dg = DistributedAvatar.aiFormatUpdate('setTalk', sender, sender, - self.air.ourChannel, - [0, 0, '', cleanMessage, modifications, 0]) - self.air.send(dg) \ No newline at end of file diff --git a/otp/chat/SequenceList.py b/otp/chat/SequenceList.py new file mode 100644 index 00000000..0021efd3 --- /dev/null +++ b/otp/chat/SequenceList.py @@ -0,0 +1,15 @@ +class SequenceList: + + def __init__(self, wordlist): + self.list = {} + for line in wordlist: + if line is '': + continue + split = line.split(':') + self.list[split[0].lower()] = [word.rstrip('\r\n').lower() for word in split[1].split(',')] + + def getList(self, word): + if word in self.list: + return self.list[word] + else: + return [] \ No newline at end of file diff --git a/otp/chat/WhiteList.py b/otp/chat/WhiteList.py index 8be965a6..94dc8b3c 100644 --- a/otp/chat/WhiteList.py +++ b/otp/chat/WhiteList.py @@ -19,4 +19,22 @@ class WhiteList: if i == self.numWords: return False - return self.words[i].startswith(text) \ No newline at end of file + return self.words[i].startswith(text) + + def prefixCount(self, text): + text = self.cleanText(text) + i = bisect_left(self.words, text) + j = i + while j < self.numWords and self.words[j].startswith(text): + j += 1 + + return j - i + + def prefixList(self, text): + text = self.cleanText(text) + i = bisect_left(self.words, text) + j = i + while j < self.numWords and self.words[j].startswith(text): + j += 1 + + return self.words[i:j] diff --git a/otp/distributed/DCClassImports.py b/otp/distributed/DCClassImports.py index 8b6c09a8..08fd1b8b 100644 --- a/otp/distributed/DCClassImports.py +++ b/otp/distributed/DCClassImports.py @@ -2,7 +2,7 @@ from pandac.PandaModules import * -hashVal = 598642574 +hashVal = 4270694562L from toontown.coghq import DistributedCashbotBossSafe, DistributedCashbotBossCrane, DistributedBattleFactory, DistributedCashbotBossTreasure, DistributedCogHQDoor, DistributedSellbotHQDoor, DistributedFactoryElevatorExt, DistributedMintElevatorExt, DistributedLawOfficeElevatorExt, DistributedLawOfficeElevatorInt, LobbyManager, DistributedMegaCorp, DistributedFactory, DistributedLawOffice, DistributedLawOfficeFloor, DistributedLift, DistributedDoorEntity, DistributedSwitch, DistributedButton, DistributedTrigger, DistributedCrushableEntity, DistributedCrusherEntity, DistributedStomper, DistributedStomperPair, DistributedLaserField, DistributedGolfGreenGame, DistributedSecurityCamera, DistributedMover, DistributedElevatorMarker, DistributedBarrelBase, DistributedGagBarrel, DistributedBeanBarrel, DistributedHealBarrel, DistributedGrid, ActiveCell, DirectionalCell, CrusherCell, DistributedCrate, DistributedSinkingPlatform, BattleBlocker, DistributedMint, DistributedMintRoom, DistributedMintBattle, DistributedStage, DistributedStageRoom, DistributedStageBattle, DistributedLawbotBossGavel, DistributedLawbotCannon, DistributedLawbotChair, DistributedCogKart, DistributedCountryClub, DistributedCountryClubRoom, DistributedMoleField, DistributedCountryClubBattle, DistributedMaze, DistributedFoodBelt, DistributedBanquetTable, DistributedGolfSpot diff --git a/otp/distributed/OtpDoGlobals.py b/otp/distributed/OtpDoGlobals.py index f665ced4..54267485 100644 --- a/otp/distributed/OtpDoGlobals.py +++ b/otp/distributed/OtpDoGlobals.py @@ -88,4 +88,7 @@ OTP_ZONE_ID_DISTRICTS = 3 OTP_ZONE_ID_DISTRICTS_STATS = 4 OTP_ZONE_ID_ELEMENTS = 5 OTP_NET_MESSENGER_CHANNEL = (OTP_DO_ID_UBER_DOG << 32) + OTP_ZONE_ID_MANAGEMENT -OTP_STAFF_CHANNEL = 6200 +OTP_MOD_CHANNEL = 6200 +OTP_ADMIN_CHANNEL = 6400 +OTP_SYSADMIN_CHANNEL = 6500 + diff --git a/toontown/ai/ServiceStart.py b/toontown/ai/ServiceStart.py index 4850f968..a554f035 100644 --- a/toontown/ai/ServiceStart.py +++ b/toontown/ai/ServiceStart.py @@ -54,5 +54,7 @@ except SystemExit: raise except Exception: info = PythonUtil.describeException() - simbase.air.writeServerEvent('ai-exception', simbase.air.getAvatarIdFromSender(), simbase.air.getAccountIdFromSender(), info) + simbase.air.writeServerEvent('ai-exception', avId=simbase.air.getAvatarIdFromSender(), accId=simbase.air.getAccountIdFromSender(), exception=info) + with open(config.GetString('ai-crash-log-name', 'ai-crash.txt'), 'w+') as file: + file.write(info + "\n") raise diff --git a/toontown/chat/TTSequenceList.py b/toontown/chat/TTSequenceList.py new file mode 100644 index 00000000..bf467501 --- /dev/null +++ b/toontown/chat/TTSequenceList.py @@ -0,0 +1,36 @@ +from pandac.PandaModules import * +from otp.chat.SequenceList import SequenceList +from direct.directnotify import DirectNotifyGlobal + +class TTSequenceList(SequenceList): + + def __init__(self): + self.notify = DirectNotifyGlobal.directNotify.newCategory('TTSequenceList') + sequenceListURL = config.GetString('blacklist-sequence-url', '') + if sequenceListURL == '': + self.notify.warning('No Sequence BL URL specified! Continuing with local sequence.') + SequenceList.__init__(self, self.loadSquencesLocally()) + else: + SequenceList.__init__(self, self.downloadSequences(sequenceListURL)) + + def downloadSequences(self, url): + fs = Ramfile() + http = HTTPClient.getGlobalPtr() + self.ch = http.makeChannel(True) + self.ch.getHeader(DocumentSpec(url)) + doc = self.ch.getDocumentSpec() + self.ch.getDocument(doc) + self.ch.downloadToRam(fs) + return fs.getData().split('\r\n') + + def loadSquencesLocally(self): + vfs = VirtualFileSystem.getGlobalPtr() + filename = Filename('tsequence.dat') + searchPath = DSearchPath() + searchPath.appendDirectory(Filename('/server')) + found = vfs.resolveFilename(filename, searchPath) + if not found: + self.notify.warning("Couldn't find blacklist sequence data file!") + return + data = vfs.readFile(filename, True) + return data.split('\n') diff --git a/toontown/toonbase/ToontownGlobals.py b/toontown/toonbase/ToontownGlobals.py index 34b1dd85..cfad1f72 100644 --- a/toontown/toonbase/ToontownGlobals.py +++ b/toontown/toonbase/ToontownGlobals.py @@ -178,7 +178,7 @@ HoodHierarchy = {ToontownCentral: (SillyStreet, LoopyLane, PunchlinePlace), TheBrrrgh: (WalrusWay, SleetStreet, PolarPlace), MinniesMelodyland: (AltoAvenue, BaritoneBoulevard, TenorTerrace), DaisyGardens: (ElmStreet, MapleStreet, OakStreet), - DonaldsDreamland: (LullabyLane, PajamaPlace, RockAByeRoad), + DonaldsDreamland: (LullabyLane, PajamaPlace), GoofySpeedway: ()} WelcomeValleyToken = 0 BossbotHQ = 10000 diff --git a/toontown/uberdog/ClientServicesManagerUD.py b/toontown/uberdog/ClientServicesManagerUD.py index c8b3e188..98b25865 100644 --- a/toontown/uberdog/ClientServicesManagerUD.py +++ b/toontown/uberdog/ClientServicesManagerUD.py @@ -422,13 +422,26 @@ class LoginAccountFSM(OperationFSM): datagram.addChannel(self.csm.GetAccountConnectionChannel(self.accountId)) self.csm.air.send(datagram) - # Add this connection to extra channels which may be useful: - if self.accessLevel > 100: - datagram = PyDatagram() - datagram.addServerHeader(self.target, self.csm.air.ourChannel, - CLIENTAGENT_OPEN_CHANNEL) - datagram.addChannel(OtpDoGlobals.OTP_STAFF_CHANNEL) - self.csm.air.send(datagram) + # Subscribe to any "staff" channels that the account has access to. + access = self.account.get('ADMIN_ACCESS', 0) + if access >= 200: + # Subscribe to the moderator channel. + dg = PyDatagram() + dg.addServerHeader(self.target, self.csm.air.ourChannel, CLIENTAGENT_OPEN_CHANNEL) + dg.addChannel(OtpDoGlobals.OTP_MOD_CHANNEL) + self.csm.air.send(dg) + if access >= 400: + # Subscribe to the administrator channel. + dg = PyDatagram() + dg.addServerHeader(self.target, self.csm.air.ourChannel, CLIENTAGENT_OPEN_CHANNEL) + dg.addChannel(OtpDoGlobals.OTP_ADMIN_CHANNEL) + self.csm.air.send(dg) + if access >= 500: + # Subscribe to the system administrator channel. + dg = PyDatagram() + dg.addServerHeader(self.target, self.csm.air.ourChannel, CLIENTAGENT_OPEN_CHANNEL) + dg.addChannel(OtpDoGlobals.OTP_SYSADMIN_CHANNEL) + self.csm.air.send(dg) # Now set their sender channel to represent their account affiliation: datagram = PyDatagram() From 1ad8c9aec20d85efb787a26eb9f7740b09b50c5c Mon Sep 17 00:00:00 2001 From: DenialMC Date: Thu, 2 Apr 2015 15:58:11 +0300 Subject: [PATCH 12/14] Add *.pets to gitignore --- .gitignore | 1 + .../databases/air_cache/pets_401000001.pets | 54 ------------------- 2 files changed, 1 insertion(+), 54 deletions(-) delete mode 100644 astron/databases/air_cache/pets_401000001.pets diff --git a/.gitignore b/.gitignore index ec0c1d93..2b600e9e 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ cmd.exe # Game-specific files and directories: preferences.json *.json +*.pets logs/ screenshots/ backups/ diff --git a/astron/databases/air_cache/pets_401000001.pets b/astron/databases/air_cache/pets_401000001.pets deleted file mode 100644 index e1f5f382..00000000 --- a/astron/databases/air_cache/pets_401000001.pets +++ /dev/null @@ -1,54 +0,0 @@ -(dp1 -I4000 -(lp2 -I8 -aI25 -aI166 -aI149 -aI59 -asI1000 -(lp3 -I20 -aI156 -aI148 -aI67 -aI107 -asI9000 -(lp4 -I144 -aI49 -aI71 -aI198 -aI134 -asI2000 -(lp5 -I145 -aI195 -aI42 -aI10 -aI65 -asI5000 -(lp6 -I238 -aI37 -aI127 -aI207 -aI232 -asI7000 -(lp7 -I183 -aI112 -aI190 -aI222 -aI14 -asI3000 -(lp8 -I80 -aI160 -aI214 -aI38 -aI241 -asS'day' -p9 -I16526 -s. \ No newline at end of file From acfdd18629c24c6d3bf15a57b3de71089fdaf9e0 Mon Sep 17 00:00:00 2001 From: DenialMC Date: Thu, 2 Apr 2015 17:02:01 +0300 Subject: [PATCH 13/14] Put QuestScripts and SequenceList into the code --- .gitignore | 7 - otp/chat/ChatAgentUD.py | 4 +- otp/chat/SequenceList.py | 341 +++++++++++++++++++++++++++++- toontown/chat/TTSequenceList.py | 36 ---- toontown/quest/QuestParser.py | 59 ++---- toontown/quest/QuestScripts.py | 362 ++++++++++++++++++++++++++++++++ 6 files changed, 722 insertions(+), 87 deletions(-) delete mode 100644 toontown/chat/TTSequenceList.py create mode 100644 toontown/quest/QuestScripts.py diff --git a/.gitignore b/.gitignore index 2b600e9e..a4e646e1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,6 @@ # Python artifacts: *.pyc -# Windows -cmd.exe - -# Eclipse IDE: -.project -.pydevproject - # PyCharm .idea diff --git a/otp/chat/ChatAgentUD.py b/otp/chat/ChatAgentUD.py index e39cbc98..cc1f700a 100644 --- a/otp/chat/ChatAgentUD.py +++ b/otp/chat/ChatAgentUD.py @@ -2,8 +2,8 @@ from direct.directnotify import DirectNotifyGlobal from direct.distributed.DistributedObjectGlobalUD import DistributedObjectGlobalUD # TODO: OTP should not depend on Toontown... Hrrm. from toontown.chat.TTWhiteList import TTWhiteList -from toontown.chat.TTSequenceList import TTSequenceList from otp.distributed import OtpDoGlobals +import SequenceList class ChatAgentUD(DistributedObjectGlobalUD): notify = DirectNotifyGlobal.directNotify.newCategory("ChatAgentUD") @@ -15,7 +15,7 @@ class ChatAgentUD(DistributedObjectGlobalUD): if self.wantWhitelist: self.whiteList = TTWhiteList() if self.wantBlacklistSequence: - self.sequenceList = TTSequenceList() + self.sequenceList = SequenceList.SequenceList() self.chatMode2channel = { 1 : OtpDoGlobals.OTP_MOD_CHANNEL, 2 : OtpDoGlobals.OTP_ADMIN_CHANNEL, diff --git a/otp/chat/SequenceList.py b/otp/chat/SequenceList.py index 0021efd3..95b7efdd 100644 --- a/otp/chat/SequenceList.py +++ b/otp/chat/SequenceList.py @@ -1,8 +1,8 @@ class SequenceList: - def __init__(self, wordlist): + def __init__(self): self.list = {} - for line in wordlist: + for line in sequences.split('\n'): if line is '': continue split = line.split(':') @@ -12,4 +12,339 @@ class SequenceList: if word in self.list: return self.list[word] else: - return [] \ No newline at end of file + return [] + +sequences = ''' +$:exe,kk zzz,k zzz,ex,hit,hits,hole,whole,ole,ooo le,holes +'n:i gg,i grow,i gross,i grr,i grrr,i gah +'s:exe,kk zzz,k zzz,ex,hit,hits,u kk,uk +.:,Y . +42:0 +4:20,2 0,twenty,chan,twin tea,twin ty +69:ed,ing +8:=,- +<:=,- +=:8,=,- +a,ah,ahh,ahhh,ahhhhh,ahhhhhh:zzz,sees,$,'s +ace,as,ash,ask,asp,ashton:hole,whole,ole,ooo le,holes,zzz,'s +ack:ools +ai,ay,ayy,ayyy,ayyyy:ds +al:coco ol,cool +an:a hon,a honda,a con,a cone,ail,ails,ailed,ailing,al,ale,ales,all,awl,us,u.s.,u.s.a.,u si,usa,use,used,using,uses,uss +ann:a hon,a honda,a con,a cone,al,ails,ailed,ailing,ale,ales,all,awl,us,u.s.,u.s.a.,u si,usa,use,used,using,uses,uss +anna:hon,honda,con da,con duh,cone da,cone duh +anne:a hon,a honda,a con,a cone,al,us,u.s.,u.s.a.,u si,usa,use,used,using,uses,uss +ape's:me,you,him,his,their,him,them,your,yourself,ur self +ape:me,you,him,his,their,him,them,your,yourself,ur self +apes:me,you,him,his,their,him,them,your,yourself,ur self +ate:me out,you out,u out,her out +ball:it more +ban:gg +bass:hole,whole,ole,stir,stir ed,stair,stair ed,tar,star,stared,tt a r ed,holes +bat:star,stair,stair ed,star,stared +bay:be maker +be,bee,bo,boo:ach,i tea see ache,i tee see ache,i tea sea ache,i tee sea ache,eye tea see ache,eye tee see ache,eye tea sea ache,eye tee sea ache,itches,itch,jay,jays,job,jobs,etch,cheese,itching,each,shh,shhh,shhhh,shhhhhh,it cha,cha,ache +beast:tea al i tea,tea al i ty,tea al i tie +ben:dover,dove err,doves err +bend:over +bet:ouch +big:deck,decks,dock,docks,clock,clocks,cook,cooks +bit,bite:cha,chi,chez,chin,chine,china,chose,chow,chess,itch,itches,ach,cheese,cheddar,shh,shhh,shhhh,shhhhhh +bla:zz it,zzz it,k tar,kk tar +black:tar,k tar,kk tar +blew:job,jobs +bloat:job,jobs +bloo:job,jobs +blowfish:job,jobs +blowy:job,jobs +blue:waffle,job,jobs +bob:zzz,zz +bon:r,or,err,errs,me,him,it,ro,her +bone:r,or,err,errs,me,him,it,ro,her +boo:be,bee,bees,by,ty,bye,byes,tay,tea +boot:bee,bees,ty,y +bos:ton +bow:job,jobs +brass:hole,whole,ole,ooo le,holes +bull:sheep,sheeps,ship,shift +bulls:hit,sheep,sheeps,ship,shift +burn:in hello +but:hole,whole,plug,plugs,sec,toll,head,face +by:itch,itches +cam:bucket,buckets,dumpster,girl,girls,on me,tastes +came:bucket,buckets,dumpster,on me,tastes,in you,in u +cee:man,men,min,mins,moon,ex,a tt le,xii,exe,kk zzz +chic:a go,ago +chin:kk +class:hole,whole,ole +climb:max,maxed,maxes,maxing +climbed:max,maxed,maxes,maxing +climbs:max,maxed,maxes,maxing +clue:luxe,lucks +coca:in,ing +cog:awk +come:bucket,buckets,dumpster,on me,tastes +comes:bucket,buckets,dumpster,on me,tastes +con:dim,dims,dome,domes,dooms,doom,do hm,do hmm,do hmmm,do mm +concentration:camp +coop:kk +cop:kk +corn:oh graphic,ooo,hoo +cunning:link us,link is +curry:man cher,men cher,min cher,moon cher +da:am,mm,yum +dab:itch,itches +dah:am,yum +dat:as,ask,asp,asset,ashton +day:um,yum +dee:bag,kay,k +di:i do,ill do,ill does,kk,ill dot,i'll do,i'll dot,i'll does,ik,i +dill:doe,do,dot,does +ding:us,usa,uss,u.s.a. +dip:stick +dirt:y,ye,eh +docs:me,you,him,his,their,him,them,your +dot:come +dr:ugh,un kk +duck,luck,buck:err,error,errors,my life,everyone,me,ing,yourself,your self,ur self +ducked:your,ur,his,her,you +due:shh,shhh,shhhh,shhhhhh +dug:rugs +dumbo:as,ash,ask,asp +eat:me out,you out,u out,her out +eating:me out,you out,u out,her out +eats:me out,you out,u out,her out +eh:bo la,bowl a,rekt ion,rekt ions,wrekt ion,wrekt ions +el:mayo +ex:tube,tubes,at,cream mint +f.a.q.:ed,err,error,errors,ear,ears,you,ate,eat,gate,goat,got,ing,this,my life,everyone,me,off,king +face:book +fad:gg ate,gg eat,gate,get,it,goat,git +fads:gg ate,gg eat,eat,gate,get,it,goat,git +fake:king,k ing,k eng,kk ing,kk eng,off +family,dad,sister,brother,mom:dead,deads +far:kk,king,k ing,k eng,kk ing,kk eng +fat:as,asset,tas +faye:get,git,got +few:ack or,hack or,kk,king,ok,k ing,k eng,kk ing,kk eng +fill:my kitty,your kitty,her kitty,his kitty,their kitty,ur kitty +finger,fingers,fin gg err:you,me,her,him,them,us,your,ur,yourself,u +flack:you,king,ing,this,my life,everyone,me,off +flick:you,king,ing,this,my life,everyone,me,off +flock:ed,err,error,errors,ear,ears,you,ate,eat,gate,goat,got,ing,this,my life,everyone,me,off,king,u,you,yourself,ur +flowerpot:head,headed,heading,heads +flowerpots:head,headed,heading,heads +flunk:ing,king,eng,in gg,her,u,you,ur,yourself +foe:kk,king,ok,k ing,k eng,kk ing,kk eng +fog:ate,eat,gate,get,it,goat,got +folk:ed,err,error,errors,ear,ears,you,gate,goat,ing,this,my life,everyone,me,off,king +folks:ed,err,error,errors,ear,ears,you,gate,goat,ing,this,my life,everyone,me,off +for:kk,king,k ing,k eng,kk ing,kk eng,twenty,twin ty,20,twin tea +fork:err,error,errors,ear,ears,you,this,my life,everyone,me,off,king,ing,her,eng,in,u,ur,hair,air +four:chan,twenty,20,2 0,twin ty,twin tea +freaky:in,ing +free:kin,k in,k ing,k eng +fuchsia:err,error,errors,ear,ears,you,this,my life,everyone,me,off +fun:king,k ing,k eng,kk ing,kk eng,luck +gah:ay,yay +gee:mail,ay,yay +gen:it,i tall,i tail,i tails +get:wasted,waste ed,bent,hi,high,higher,highest,lay +gets:wasted,waste ed,hi,high,higher,highest,lay +getting:wasted,waste ed,hi,high,higher,highest,lay +gg:ay,a y,ah y,ayy,aye +girl,girls:1 cup,one cup,on cup,won cup,and a cup,plus a cup +give:me head,me pleasure,a truck +glass,glory:hole,whole,ole,ooo le,holes +go:to hello +got:wasted,waste ed,hi,high,higher,highest,ooo hello +grape:me,you,him,his,their,him,them,your,ed,yourself,ur self +grapes:me,you,him,his,their,him,them,your,ed,yourself,ur self +grass:hole,whole,ole,ooo le,holes +half:baked +hand:job,jobs +hang:your,yourself,ur self,myself,my self,me,you +hate:black people,back people,white people +have:sec,see ex +haved:sec,see ex +having:sec,see ex +he:ill,ii,ell,el +her:as,asp,bowls,bowl's,bows,bock,butted,but,come,pew,period,ah,dee,ash +hill:yourself,your self,ur self,u err self,u r self +his:as,asp,bowls,bowl's,bows,bock,butted,but,come,pew,period,ah,dee,ash +hit's:learn +hit:learn +hits:learn +hm:arr y juan,arr y jane,arr y jan,arr y jam +hmm:arr y juan,arr y jane,arr y jan,arr y jam +hmmm:arr y juan,arr y jane,arr y jan,arr y jam +horn:y,horn eh,knee,ie,i +honk:y,eye +hot:mail,come +hue:jazz +huge:as,mass,ashton,ask,asp,jazz,ash +huger:as,mass,ashton,ask,asp,jazz,ash +i'm:moist,wet,hard +i:es,es bean,es beans,es be an,es be ann,es be anne,es be i an,es be i ann,es be i anne,:c k,=c k,;c k,gg a,gg ah,gg ahh,gg ahhh,gg ahhhhh,gg ha +ice:hole,whole,ole,ooo le +id:i +if:uk +im:moist,wet,hard +in:he'll,the assistant,your mom,your mother,your assistant,ur assistant,ur mom,ur mother,the as,your as,ur as +inst:a gram,ah gram,ahh gram,ahhh gram,ahhhhh gram,ahhhhhh gram +instant:graham,grand +inter:course +jack's:ed,ing,me,myself,her,herself,him,himself,of,off,ourselves,they,themselves,us,you,yourself,u late +jack:ed,ing,me,myself,her,herself,him,himself,off,ourselves,they,themselves,us,you,yourself,u late +jacks:ed,ing,me,myself,her,herself,him,himself,of,off,ourselves,they,themselves,us,you,yourself,u late +jazz:hole,ole,on +kay:kay kay +kin:kk y +kind:kk y +king:kk y +kk:awk,bock,err,ill,ills,kk +knee:gg,grow,gross,grr,grrr,gah,gas,gauss +kneed:gg,grow,gross,grr,grrr,gah,gas,gauss +knit:gah +kun:tt +kyle's:yourself,your self,ur self,u err self,u r self +kyle:yourself,your self,ur self,u err self,u r self +kyles:yourself,your self,ur self,u err self,u r self +lap:dance +last:name +less:be i an,be i ann,be i anne,be an,be ann,be anne,bean,beans +little:sit,hitch,itch +lucks:clan +luxe:clan +ma:stir bait +making,make,makes,made:him hard,love +marry:juan a,juan ha,juan ah,jane,jan,jam +mary:juan a,juan ha,juan ah,jane,jan,jam +mass:hole,whole,ole,ooo le,stir bait +mast:are bait,are baits,are baiter,are bait eng,are bait ed,stir bait +master:bait,baits,baiter,bait eng,bait ed +mastered:bait,baits,baiter,bait eng,bait ed +mastering:bait,baits,baiter,bait eng,bait ed +masters:bait,baits,baiter,bait eng,bait ed +mayor:a juan,ah juan +men:str u ate +mexican:brown +mike:hawk,hawks,hunt,hunts +mm:arr y juan,arr y jane,arr y jan,arr y jam +mo,moe,moo:foe,foes,for,four +moon:shine +mother:flick,flicker,fork,fuchsia,duck,ducking,folk,folks,yuck,flock,heck,truck,funky,flunky,fax,quacker,bucker,bicker,faker,fake,flunk,flunking,tru +my,mah:as,asp,bowls,bowl's,bows,bock,butted,but,come,pew,period,ah,dee,ash,di ik,deck,decks,dock,docks,cook,cooks +nada:zen,zeke,z.z. +nag:zen,zeke,z.z.,grr,grrr,a,ah +nah:zen,zeke,z.z.,gg a,gg ah +nay:kit,grow,growl,gah,gg a,gg ah +neigh,nigh,nik:err,grr,grrr,grrrrrrrl,grow,grove,gurl,girl,gear,gears,gross,ah,a,gah +new:york,fork,folk,forks,folks +not:zen,zeke,z.z. +octopus:y,ye,sea,seas +octopuses:y,ye,sea,seas +of:u kk,uk +oh:rn y +old:are you,r you,are u,r u +omg:egg al +on:your knees,your knee +open:legs,leg +or:gah some,gah sum,gg y,gee +other:flick,flicker,fork,fuchsia,duck,folk,folks,yuck,flock,heck,truck,funky,flunky,fax,quacker,bucker,bicker +pah:key,keys +pant:tease,teas,ties +passed:off +pause:i,eek,eh +pea:nest,mess,pea,pi,pie,do file,knees,nice,niece +peck:err +peep:show +pen:ice,iced,ices,icing,island,eh tray,eh tate,15,is,1s,i zzz,his,1 5 +pens:ice,iced,ices,icing,island,eh tray,eh tate,15,is,1s,i zzz,his,1 5 +period:cramps +pet:oh pile,oh piles,oh file,oh files +pew:cee,say,says,sea,seas,see,sees,she,shes,she's,si +phony:number,numb err +pi:pi,ssw +piece,peace:of shift,of ship,of shut,of shirt +play:boy +pooh:cee,say,says,sea,seas,see,sees,she,shes,she's,si +pose:eh +pound:ed,ing,me,myself,her,herself,him,himself,of,off,ourselves,they,themselves,us,you,yourself +pounds:ed,ing,me,myself,her,herself,him,himself,of,off,ourselves,they,themselves,us,you,yourself +pour:on,no +pro:st i tut,stick tut +purr:cee,say,says,sea,seas,see,sees,she,shes,she's,si +push:y,ye,cee,say,says,sea,seas,see,sees,she,shes,she's,si +put:cee,say,says,sea,seas,see,sees,she,shes,she's,si +queue:ear +rake:you +rap:me,you,her,his,their,him,them,your,ed,35,yourself,ur self,eh me,ping +ray:ping,pi +re:tar ed,tart,tarts,tar tt ed,tar teed,tar dead,tar deed,tar dee ed,tar dad +read:tube,tubes +red:tube,tubes +reed:tube,tubes +rekt:um,hum,u hmm,huh,u hm,u hmmm +roll:grass,in the hay,in the hey +rub:one off,one of,1 off,1 of,on off,on of +san:francisco +sass:hole,whole,ole +sassy:hole,whole,ole +saw:kk +sc:hum,um,u hmm,huh,u hm,u hmmm +sea,see,sec::man,men,min,mins,moon,ex,a tt le,xii,exe,kk zzz +seem:en,an,man,men,min,ex,a tt le +sell,selling,sold:cracked,cracked-uptick,crackin',cracking,crackle,crackle's,crackles,crackly,herbs +sew:kk +she:it,hitting,its,ex i,mail,mails,mailed,mailing,male,males,tt,i,ii +shh,shhh,shhhh,shhhhhh,shy:it,eat,hit,hits,its,ex i,he mail,he mails,he mailed,he mailing,he male,he males,ii tt,i it,i tt +shut:the duck,the luck +si:u tt,exe,kk zzz,k zzz,ex +ski:it,ii tt +skill:your,yourself,ur self,myself,my self,me,you +sky:pea,peas,peel,pen,pet,pi,pie,peta,pico,pens,pop,hype,ape,pets,peep,per,pell,pa +snap,nap:chat +so:exe,kk zzz,k zzz,ex,kk +sock,socks,shucks:it,on it,my deck,my dock,my doc,ur deck,ur dock,your deck,your dock,his deck,his dock,cooks,cook,my cook,ur cook,your cook,his cook,my cooks,ur cooks,your cooks,his cooks,deck,decks,a dock,a deck,a docks,a decks,a cook,a cooks,my duck,my ducks,dock +sofa:king,kin,keen,kings +some:cricket +son,sun:of a bit,of a peach,of a be,of a bee +st:on ed,rip +stone:ed +stu:pit,pod +stuck:my duck,my dock,my deck,ing +sue:kk,lute,lutes +sugar:daddy +tah:tas,tah +tea:bag,bagged,bagging,bags +test:i cools,i cool,tickle,tickles +the:di,hello,flunk +tho:tt,tea,tee,ty +to:he'll +too:he'll +truck:eh ru,ing,eng,you,u,up,ed,her,or +tt:its,its,it +two:he'll +uk:you,u +un:tee +under:my skirt,her skirt,your skirt,my dress,her dress,your dress,ur skirt,ur dress +ur:but,bum,as,period,hole,holes +vague:in a,i nah +vern:gen +vet:china +via:grape +wanna:duck +wat:the hello,the fork,the duck,the freaky,the yuck,your sky,ur sky,the fire truck,the truck,the he'll +we,whee:ed,neigh is,knees +what:the hello,the fork,the duck,the freaky,the yuck,your sky,ur sky,the truck,the fire truck,the he'll +white:power +who:err,errs,re,ree +wrap:me,you,him,them,them +wut:the hello,the fork,the duck,the freaky,the yuck,your sky,ur sky,the truck,the fire truck,the he'll +you:a hole,in me +your:as,but,bum,come,period,hole,holes,ash,sass +yuck:err,error,errors,my life,me,ing,you,dee +zone:tan +zzz:3 ex,33 ex,ex,ugh eng,hole,holes +''' \ No newline at end of file diff --git a/toontown/chat/TTSequenceList.py b/toontown/chat/TTSequenceList.py deleted file mode 100644 index bf467501..00000000 --- a/toontown/chat/TTSequenceList.py +++ /dev/null @@ -1,36 +0,0 @@ -from pandac.PandaModules import * -from otp.chat.SequenceList import SequenceList -from direct.directnotify import DirectNotifyGlobal - -class TTSequenceList(SequenceList): - - def __init__(self): - self.notify = DirectNotifyGlobal.directNotify.newCategory('TTSequenceList') - sequenceListURL = config.GetString('blacklist-sequence-url', '') - if sequenceListURL == '': - self.notify.warning('No Sequence BL URL specified! Continuing with local sequence.') - SequenceList.__init__(self, self.loadSquencesLocally()) - else: - SequenceList.__init__(self, self.downloadSequences(sequenceListURL)) - - def downloadSequences(self, url): - fs = Ramfile() - http = HTTPClient.getGlobalPtr() - self.ch = http.makeChannel(True) - self.ch.getHeader(DocumentSpec(url)) - doc = self.ch.getDocumentSpec() - self.ch.getDocument(doc) - self.ch.downloadToRam(fs) - return fs.getData().split('\r\n') - - def loadSquencesLocally(self): - vfs = VirtualFileSystem.getGlobalPtr() - filename = Filename('tsequence.dat') - searchPath = DSearchPath() - searchPath.appendDirectory(Filename('/server')) - found = vfs.resolveFilename(filename, searchPath) - if not found: - self.notify.warning("Couldn't find blacklist sequence data file!") - return - data = vfs.readFile(filename, True) - return data.split('\n') diff --git a/toontown/quest/QuestParser.py b/toontown/quest/QuestParser.py index 2a95cb06..ba0229e9 100644 --- a/toontown/quest/QuestParser.py +++ b/toontown/quest/QuestParser.py @@ -1,17 +1,9 @@ -import copy from direct.directnotify import DirectNotifyGlobal from direct.interval.IntervalGlobal import * from direct.showbase import AppRunnerGlobal from direct.showbase import DirectObject from direct.showbase import PythonUtil -import os from pandac.PandaModules import * -import re -import sys -import token -import tokenize - -import BlinkingArrows from otp.speedchat import SpeedChatGlobals from toontown.ai import DistributedBlackCatMgr from toontown.chat.ChatGlobals import * @@ -20,7 +12,7 @@ from toontown.suit import SuitDNA from toontown.toon import ToonHeadFrame from toontown.toonbase import TTLocalizer from toontown.toonbase import ToontownBattleGlobals - +import copy, os, re, sys, token, tokenize, QuestScripts, BlinkingArrows notify = DirectNotifyGlobal.directNotify.newCategory('QuestParser') lineDict = {} @@ -49,28 +41,26 @@ def init(): def clear(): globalVarDict.clear() -def readFile(filename): +def readFile(): global curId - scriptFile = StreamReader(vfs.openReadFile(filename, 1), 1) - def readline(): - return scriptFile.readline().replace('\r', '') - - gen = tokenize.generate_tokens(readline) - line = getLineOfTokens(gen) - while line is not None: - if line == []: - line = getLineOfTokens(gen) - continue - if line[0] == 'ID': - parseId(line) - elif curId is None: - notify.error('Every script must begin with an ID') - else: - lineDict[curId].append(line) + + for line in QuestScripts.script.split('\n'): + def readline(): + return line + gen = tokenize.generate_tokens(readline) line = getLineOfTokens(gen) - - return - + + while line is not None: + if line == []: + line = getLineOfTokens(gen) + continue + if line[0] == 'ID': + parseId(line) + elif curId is None: + notify.error('Every script must begin with an ID') + else: + lineDict[curId].append(line) + line = getLineOfTokens(gen) def getLineOfTokens(gen): tokens = [] @@ -908,13 +898,4 @@ class NPCMoviePlayer(DirectObject.DirectObject): return Sequence(Func(grabCurTrackAccess), LerpFunctionInterval(updateGagLevel, fromData=1, toData=7, duration=0.3), WaitInterval(3.5), LerpFunctionInterval(updateGagLevel, fromData=7, toData=1, duration=0.3), Func(restoreTrackAccess), Func(messenger.send, 'donePreview')) -searchPath = DSearchPath() -if __debug__: - searchPath.appendDirectory(Filename('../resources/phase_3/etc')) -searchPath.appendDirectory(Filename('resources/phase_3/etc')) -searchPath.appendDirectory(Filename('/phase_3/etc')) -scriptFile = Filename('QuestScripts.txt') -found = vfs.resolveFilename(scriptFile, searchPath) -if not found: - notify.error('Could not find QuestScripts.txt file') -readFile(scriptFile) +readFile() \ No newline at end of file diff --git a/toontown/quest/QuestScripts.py b/toontown/quest/QuestScripts.py new file mode 100644 index 00000000..271919d5 --- /dev/null +++ b/toontown/quest/QuestScripts.py @@ -0,0 +1,362 @@ +script = ''' +ID quest_assign_101 +CLEAR_CHAT npc +LOAD squirt1 "phase_3.5/models/gui/tutorial_gui" "squirt1" +LOAD squirt2 "phase_3.5/models/gui/tutorial_gui" "squirt2" +LOAD toonBuilding "phase_3.5/models/gui/tutorial_gui" "toon_buildings" +LOAD cogBuilding "phase_3.5/models/gui/tutorial_gui" "suit_buildings" +LOAD cogs "phase_3.5/models/gui/tutorial_gui" "suits" +POSHPRSCALE cogs -1.05 7 0 0 0 0 1 1 1 +POSHPRSCALE toonBuilding -1.05 7 0 0 0 0 1.875 1.875 1.875 +POSHPRSCALE cogBuilding -1.05 7 0 0 0 0 1.875 1.875 1.875 +POSHPRSCALE squirt1 -1.05 7 0 0 0 0 1.875 1.875 1.875 +POSHPRSCALE squirt2 -1.05 7 0 0 0 0 1.875 1.875 1.875 +REPARENTTO camera npc +POS camera -2.2 5.2 3.3 +HPR camera 215 5 0 +WRTREPARENTTO camera localToon +PLAY_ANIM npc "right-hand-start" 1 +WAIT 1 +REPARENTTO cogs camera +LERP_SCALE cogs 1.875 1.875 1.875 0.5 +WAIT 1.0833 +LOOP_ANIM npc "right-hand" 1 +FUNCTION npc "angryEyes" +FUNCTION npc "blinkEyes" +LOCAL_CHAT_CONFIRM npc QuestScript101_1 "CFReversed" +LOCAL_CHAT_CONFIRM npc QuestScript101_2 "CFReversed" +REPARENTTO cogs hidden +REPARENTTO toonBuilding camera +LOCAL_CHAT_CONFIRM npc QuestScript101_3 "CFReversed" +REPARENTTO toonBuilding hidden +REPARENTTO cogBuilding camera +FUNCTION npc "sadEyes" +FUNCTION npc "blinkEyes" +LOCAL_CHAT_CONFIRM npc QuestScript101_4 "CFReversed" +REPARENTTO cogBuilding hidden +REPARENTTO squirt1 camera +FUNCTION npc "normalEyes" +FUNCTION npc "blinkEyes" +LOCAL_CHAT_CONFIRM npc QuestScript101_5 "CFReversed" +REPARENTTO squirt1 hidden +REPARENTTO squirt2 camera +LOCAL_CHAT_CONFIRM npc QuestScript101_6 "CFReversed" +LERP_SCALE squirt2 1 1 0.01 0.5 +WAIT 0.5 +REPARENTTO squirt2 hidden +OBSCURE_LAFFMETER 0 +SHOW laffMeter +POS laffMeter 0 0 0 +SCALE laffMeter 0.075 0.075 0.075 +LERP_POS laffMeter 1.7 0 0.87 1 +LERP_SCALE laffMeter 0.2 0.2 0.2 0.6 +WAIT 1.0833 +LOCAL_CHAT_CONFIRM npc QuestScript101_8 "CFReversed" +LOCAL_CHAT_CONFIRM npc QuestScript101_9 "CFReversed" +FUNCTION npc "sadEyes" +FUNCTION npc "blinkEyes" +LAFFMETER 15 15 +WAIT 0.1 +LAFFMETER 14 15 +WAIT 0.1 +LAFFMETER 13 15 +WAIT 0.1 +LAFFMETER 12 15 +WAIT 0.1 +LAFFMETER 11 15 +WAIT 0.1 +LAFFMETER 10 15 +WAIT 0.1 +LAFFMETER 9 15 +WAIT 0.1 +LAFFMETER 8 15 +WAIT 0.1 +LAFFMETER 7 15 +WAIT 0.1 +LAFFMETER 6 15 +WAIT 0.1 +LAFFMETER 5 15 +WAIT 0.1 +LAFFMETER 4 15 +WAIT 0.1 +LAFFMETER 3 15 +WAIT 0.1 +LAFFMETER 2 15 +WAIT 0.1 +LAFFMETER 1 15 +WAIT 0.1 +LAFFMETER 0 15 +LOCAL_CHAT_CONFIRM npc QuestScript101_10 "CFReversed" +FUNCTION npc "normalEyes" +FUNCTION npc "blinkEyes" +LAFFMETER 15 15 +WAIT 0.5 +LERP_POS laffMeter 0.15 0.15 0.15 1 +LERP_SCALE laffMeter 0.085 0.085 0.085 0.6 +PLAY_ANIM npc "right-hand-start" -2 +WAIT 1.0625 +LOOP_ANIM npc "neutral" +WAIT 0.5 +LERP_HPR npc -50 0 0 0.5 +FUNCTION npc "surpriseEyes" +FUNCTION npc "showSurpriseMuzzle" +PLAY_ANIM npc "right-point-start" 1.5 +WAIT 0.6944 +LOOP_ANIM npc "right-point" +LOCAL_CHAT_CONFIRM npc QuestScript101_11 "CFReversed" +LOCAL_CHAT_CONFIRM npc QuestScript101_12 "CFReversed" +PLAY_ANIM npc "right-point-start" -1 +LERP_HPR npc -0.068 0 0 0.75 +WAIT 1.0417 +FUNCTION npc "angryEyes" +FUNCTION npc "blinkEyes" +FUNCTION npc "hideSurpriseMuzzle" +LOOP_ANIM npc "neutral" +FUNCTION localToon "questPage.showQuestsOnscreenTutorial" +LOCAL_CHAT_CONFIRM npc QuestScript101_13 "CFReversed" +FUNCTION localToon "questPage.hideQuestsOnscreenTutorial" +LOCAL_CHAT_CONFIRM npc QuestScript101_14 1 "CFReversed" +FUNCTION npc "normalEyes" +FUNCTION npc "blinkEyes" +UPON_TIMEOUT FUNCTION cogs "removeNode" +UPON_TIMEOUT FUNCTION toonBuilding "removeNode" +UPON_TIMEOUT FUNCTION cogBuilding "removeNode" +UPON_TIMEOUT FUNCTION squirt1 "removeNode" +UPON_TIMEOUT FUNCTION squirt2 "removeNode" +UPON_TIMEOUT LOOP_ANIM npc "neutral" +UPON_TIMEOUT SHOW laffMeter +UPON_TIMEOUT POS laffMeter 0.15 0.15 0.15 +UPON_TIMEOUT SCALE laffMeter 0.085 0.085 0.085 +POS localToon 0.776 14.6 0 +HPR localToon 47.5 0 0 +FINISH_QUEST_MOVIE + + +ID quest_incomplete_110 +DEBUG "quest assign 110" +LOCAL_CHAT_CONFIRM npc QuestScript110_1 +OBSCURE_BOOK 0 +SHOW bookOpenButton +LOCAL_CHAT_CONFIRM npc QuestScript110_2 +ARROWS_ON 1.364477 -0.89 0 1.664477 -0.64 90 +LOCAL_CHAT_PERSIST npc QuestScript110_3 +WAIT_EVENT "enterStickerBook" +ARROWS_OFF +SHOW_BOOK +HIDE bookPrevArrow +HIDE bookNextArrow +CLEAR_CHAT npc +WAIT 0.5 +TOON_HEAD npc -0.2 -0.45 1 +LOCAL_CHAT_CONFIRM npc QuestScript110_4 +ARROWS_ON 0.85 -0.75 -90 0.85 -0.75 -90 +SHOW bookNextArrow +LOCAL_CHAT_PERSIST npc QuestScript110_5 +WAIT_EVENT "stickerBookPageChange-3" +HIDE bookPrevArrow +HIDE bookNextArrow +ARROWS_OFF +CLEAR_CHAT npc +WAIT 0.5 +LOCAL_CHAT_CONFIRM npc QuestScript110_6 +ARROWS_ON 0.85 -0.75 -90 0.85 -0.75 -90 +SHOW bookNextArrow +LOCAL_CHAT_PERSIST npc QuestScript110_7 +WAIT_EVENT "stickerBookPageChange-4" +HIDE bookNextArrow +HIDE bookPrevArrow +ARROWS_OFF +CLEAR_CHAT npc +LOCAL_CHAT_CONFIRM npc QuestScript110_8 +LOCAL_CHAT_CONFIRM npc QuestScript110_9 +LOCAL_CHAT_PERSIST npc QuestScript110_10 +ENABLE_CLOSE_BOOK +ARROWS_ON 1.364477 -0.89 0 1.664477 -0.64 90 +WAIT_EVENT "exitStickerBook" +ARROWS_OFF +TOON_HEAD npc 0 0 0 +HIDE_BOOK +HIDE bookOpenButton +LOCAL_CHAT_CONFIRM npc QuestScript110_11 1 +UPON_TIMEOUT OBSCURE_BOOK 0 +UPON_TIMEOUT ARROWS_OFF +UPON_TIMEOUT HIDE_BOOK +UPON_TIMEOUT COLOR_SCALE bookOpenButton 1 1 1 1 +UPON_TIMEOUT TOON_HEAD npc 0 0 0 +UPON_TIMEOUT SHOW bookOpenButton +FINISH_QUEST_MOVIE + +ID tutorial_blocker +HIDE localToon +REPARENTTO camera npc +FUNCTION npc "stopLookAround" +POS camera 0.0 6.0 4.0 +HPR camera 180.0 0.0 0.0 +LOCAL_CHAT_CONFIRM npc QuestScriptTutorialBlocker_1 +WAIT 0.8 +LOCAL_CHAT_CONFIRM npc QuestScriptTutorialBlocker_2 +WAIT 0.8 +POS camera -5.0 -9.0 6.0 +HPR camera -25.0 -10.0 0.0 +POS localToon 203.8 18.64 -0.475 +HPR localToon -90.0 0.0 0.0 +SHOW localToon +LOCAL_CHAT_CONFIRM npc QuestScriptTutorialBlocker_3 +OBSCURE_CHAT 1 0 +SHOW chatScButton +WAIT 0.6 +ARROWS_ON -1.3644 0.91 180 -1.5644 0.74 -90 +LOCAL_CHAT_PERSIST npc QuestScriptTutorialBlocker_4 +WAIT_EVENT "enterSpeedChat" +ARROWS_OFF +BLACK_CAT_LISTEN 1 +WAIT_EVENT "SCChatEvent" +BLACK_CAT_LISTEN 0 +WAIT 0.5 +CLEAR_CHAT localToon +REPARENTTO camera localToon +LOCAL_CHAT_CONFIRM npc QuestScriptTutorialBlocker_5 "CFReversed" +LOCAL_CHAT_CONFIRM npc QuestScriptTutorialBlocker_6 "CFReversed" +OBSCURE_CHAT 0 0 +SHOW chatNormalButton +WAIT 0.6 +LOCAL_CHAT_CONFIRM npc QuestScriptTutorialBlocker_7 "CFReversed" +LOCAL_CHAT_CONFIRM npc QuestScriptTutorialBlocker_8 1 "CFReversed" +LOOP_ANIM npc "walk" +LERP_HPR npc 270 0 0 0.5 +WAIT 0.5 +LOOP_ANIM npc "run" +LERP_POS npc 217.4 18.81 -0.475 0.75 +LERP_HPR npc 240 0 0 0.75 +WAIT 0.75 +LERP_POS npc 222.4 15.0 -0.475 0.35 +LERP_HPR npc 180 0 0 0.35 +WAIT 0.35 +LERP_POS npc 222.4 5.0 -0.475 0.75 +WAIT 0.75 +REPARENTTO npc hidden +FREE_LOCALTOON +UPON_TIMEOUT ARROWS_OFF +UPON_TIMEOUT OBSCURE_CHAT 0 0 +UPON_TIMEOUT REPARENTTO camera localToon +FINISH_QUEST_MOVIE + +ID gag_intro +SEND_EVENT "disableGagPanel" +SEND_EVENT "disableBackToPlayground" +HIDE inventory +TOON_HEAD npc 0 0 1 +WAIT 0.1 +LOCAL_CHAT_CONFIRM npc QuestScriptGagShop_1 +LERP_POS npcToonHead -0.64 0 -0.74 0.7 +LERP_SCALE npcToonHead 0.82 0.82 0.82 0.7 +LERP_COLOR_SCALE purchaseBg 1 1 1 1 0.6 0.6 0.6 1 0.7 +WAIT 0.7 +SHOW inventory +LOCAL_CHAT_CONFIRM npc QuestScriptGagShop_1a +LOCAL_CHAT_PERSIST npc QuestScriptGagShop_3 +SEND_EVENT "enableGagPanel" +WAIT_EVENT "inventory-selection" +CLEAR_CHAT npc +WAIT 0.5 +LOCAL_CHAT_CONFIRM npc QuestScriptGagShop_4 +LOCAL_CHAT_PERSIST npc QuestScriptGagShop_5 +WAIT 0.5 +SHOW_PREVIEW +CLEAR_CHAT npc +WAIT 0.5 +SET_BIN backToPlaygroundButton "gui-popup" +LERP_POS backToPlaygroundButton -0.12 0 0.18 0.5 +LERP_SCALE backToPlaygroundButton 2 2 2 0.5 +LERP_COLOR_SCALE backToPlaygroundButton 1 1 1 1 2.78 2.78 2.78 1 0.5 +LERP_COLOR_SCALE inventory 1 1 1 1 0.6 0.6 0.6 1 0.5 +WAIT 0.5 +START_THROB backToPlaygroundButton 2.78 2.78 2.78 1 2.78 2.78 2.78 0.7 2 +LOCAL_CHAT_CONFIRM npc QuestScriptGagShop_6 +STOP_THROB +LERP_POS backToPlaygroundButton 0.72 0 -0.045 0.5 +LERP_SCALE backToPlaygroundButton 1.04 1.04 1.04 0.5 +LERP_COLOR_SCALE backToPlaygroundButton 2.78 2.78 2.78 1 1 1 1 1 0.5 +WAIT 0.5 +CLEAR_BIN backToPlaygroundButton +SET_BIN playAgainButton "gui-popup" +LERP_POS playAgainButton -0.12 0 0.18 0.5 +LERP_SCALE playAgainButton 2 2 2 0.5 +LERP_COLOR_SCALE playAgainButton 1 1 1 1 2.78 2.78 2.78 1 0.5 +WAIT 0.5 +START_THROB playAgainButton 2.78 2.78 2.78 1 2.78 2.78 2.78 0.7 2 +LOCAL_CHAT_CONFIRM npc QuestScriptGagShop_7 +STOP_THROB +LERP_POS playAgainButton 0.72 0 -0.24 0.5 +LERP_SCALE playAgainButton 1.04 1.04 1.04 0.5 +LERP_COLOR_SCALE playAgainButton 2.78 2.78 2.78 1 1 1 1 1 0.5 +WAIT 0.5 +CLEAR_BIN playAgainButton +LOCAL_CHAT_CONFIRM npc QuestScriptGagShop_8 1 +TOON_HEAD npc 0 0 0 +LERP_COLOR_SCALE inventory 0.6 0.6 0.6 1 1 1 1 1 0.5 +LERP_COLOR_SCALE purchaseBg 0.6 0.6 0.6 1 1 1 1 1 0.5 +WAIT 0.5 +SEND_EVENT "enableBackToPlayground" +UPON_TIMEOUT TOON_HEAD npc 0 0 0 +UPON_TIMEOUT SHOW inventory +UPON_TIMEOUT SEND_EVENT "enableGagPanel" +UPON_TIMEOUT SEND_EVENT "enableBackToPlayground" + +ID quest_incomplete_120 +CHAT_CONFIRM npc QuestScript120_1 +CHAT_CONFIRM npc QuestScript120_2 1 +FINISH_QUEST_MOVIE + +ID quest_assign_121 +CHAT_CONFIRM npc QuestScript121_1 1 +FINISH_QUEST_MOVIE + +ID quest_assign_130 +CHAT_CONFIRM npc QuestScript130_1 1 +FINISH_QUEST_MOVIE + +ID quest_assign_131 +CHAT_CONFIRM npc QuestScript131_1 1 +FINISH_QUEST_MOVIE + +ID quest_assign_140 +CHAT_CONFIRM npc QuestScript140_1 1 +FINISH_QUEST_MOVIE + +ID quest_assign_141 +CHAT_CONFIRM npc QuestScript141_1 1 +FINISH_QUEST_MOVIE + +ID quest_incomplete_145 +CHAT_CONFIRM npc QuestScript145_1 1 +LOAD frame "phase_4/models/gui/tfa_images" "FrameBlankA" +LOAD tunnel "phase_4/models/gui/tfa_images" "tunnelSignA" +POSHPRSCALE tunnel 0 0 0 0 0 0 0.8 0.8 0.8 +REPARENTTO tunnel frame +POSHPRSCALE frame 0 0 0 0 0 0 0.1 0.1 0.1 +REPARENTTO frame aspect2d +LERP_SCALE frame 1.0 1.0 1.0 1.0 +WAIT 3.0 +LERP_SCALE frame 0.1 0.1 0.1 0.5 +WAIT 0.5 +REPARENTTO frame hidden +CHAT_CONFIRM npc QuestScript145_2 1 +UPON_TIMEOUT FUNCTION frame "removeNode" +FINISH_QUEST_MOVIE + + +ID quest_incomplete_150 +CHAT_CONFIRM npc QuestScript150_1 +ARROWS_ON 1.65 0.51 -120 1.65 0.51 -120 +SHOW_FRIENDS_LIST +CHAT_CONFIRM npc QuestScript150_2 +ARROWS_OFF +HIDE_FRIENDS_LIST +CHAT_CONFIRM npc QuestScript150_3 +HIDE bFriendsList +CHAT_CONFIRM npc QuestScript150_4 1 +UPON_TIMEOUT HIDE_FRIENDS_LIST +UPON_TIMEOUT ARROWS_OFF +FINISH_QUEST_MOVIE +''' \ No newline at end of file From 7065e2b06f3e7cb586883cd1fef7367275eca3fe Mon Sep 17 00:00:00 2001 From: DenialMC Date: Sat, 4 Apr 2015 07:57:23 +0300 Subject: [PATCH 14/14] Fix loading --- toontown/quest/QuestParser.py | 40 +++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/toontown/quest/QuestParser.py b/toontown/quest/QuestParser.py index ba0229e9..3b8e0896 100644 --- a/toontown/quest/QuestParser.py +++ b/toontown/quest/QuestParser.py @@ -12,7 +12,8 @@ from toontown.suit import SuitDNA from toontown.toon import ToonHeadFrame from toontown.toonbase import TTLocalizer from toontown.toonbase import ToontownBattleGlobals -import copy, os, re, sys, token, tokenize, QuestScripts, BlinkingArrows +from toontown.quest import QuestScripts +import copy, re, tokenize, BlinkingArrows, StringIO notify = DirectNotifyGlobal.directNotify.newCategory('QuestParser') lineDict = {} @@ -43,24 +44,27 @@ def clear(): def readFile(): global curId - - for line in QuestScripts.script.split('\n'): - def readline(): - return line - gen = tokenize.generate_tokens(readline) - line = getLineOfTokens(gen) - - while line is not None: - if line == []: - line = getLineOfTokens(gen) - continue - if line[0] == 'ID': - parseId(line) - elif curId is None: - notify.error('Every script must begin with an ID') - else: - lineDict[curId].append(line) + script = StringIO.StringIO(QuestScripts.script) + + def readLine(): + return script.readline().replace('\r', '') + + gen = tokenize.generate_tokens(readLine) + line = getLineOfTokens(gen) + + while line is not None: + if line == []: line = getLineOfTokens(gen) + continue + if line[0] == 'ID': + parseId(line) + elif curId is None: + notify.error('A script must begin with an ID') + else: + lineDict[curId].append(line) + line = getLineOfTokens(gen) + + script.close() def getLineOfTokens(gen): tokens = []