chat: Implement staff chat(s) using staff channels.

This was so much fun to write! Also, it doesn't matter if a hacked client
sends a different chatMode, because only staff will see it and they can
take action accordingly.

The message prefixing was only a temporary solution to let the other staff
members know that they are talking in a staff chat mode. Perhaps in the
future, this should use different chat bubble colours.
This commit is contained in:
Harvir 2014-06-03 17:07:33 +01:00
parent 302d0daa32
commit 57049d3192
3 changed files with 48 additions and 7 deletions

View file

@ -285,7 +285,7 @@ dclass OtpAvatarManager : DistributedObject {
dclass ChatAgent : DistributedObject {
adminChat(uint32 aboutId, string message);
chatMessage(string(0-256) message) clsend;
chatMessage(string(0-256) message, uint8 chatMode) clsend;
whisperMessage(uint32 receiverAvId, string(0-256) message) clsend;
sfWhisperMessage(uint32 receiverAvId, string(0-256) message) clsend;
};

View file

@ -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,10 +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_MODERATION, 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")

View file

@ -2,6 +2,7 @@ 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 otp.distributed import OtpDoGlobals
class ChatAgentUD(DistributedObjectGlobalUD):
notify = DirectNotifyGlobal.directNotify.newCategory("ChatAgentUD")
@ -10,9 +11,18 @@ class ChatAgentUD(DistributedObjectGlobalUD):
DistributedObjectGlobalUD.announceGenerate(self)
self.whiteList = TTWhiteList()
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):
def chatMessage(self, message, chatMode):
sender = self.air.getAvatarIdFromSender()
if sender == 0:
self.air.writeServerEvent('suspicious', accId=self.air.getAccountIdFromSender(),
@ -25,8 +35,11 @@ class ChatAgentUD(DistributedObjectGlobalUD):
# 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?]
cleanMessage = self.chatMode2prefix.get(chatMode, "") + message
DistributedAvatar = self.air.dclassesByName['DistributedAvatarUD']
dg = DistributedAvatar.aiFormatUpdate('setTalk', sender, sender,
dg = DistributedAvatar.aiFormatUpdate('setTalk', sender, self.chatMode2channel.get(chatMode, sender),
self.air.ourChannel,
[0, 0, '', cleanMessage, modifications, 0])
self.air.send(dg)
@ -44,7 +57,7 @@ class ChatAgentUD(DistributedObjectGlobalUD):
# 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,
dg = DistributedAvatar.aiFormatUpdate('setTalkWhisper', receiverAvId, receiverAvId, self.air.ourChannel,
[sender, sender, '', cleanMessage, modifications, 0])
self.air.send(dg)
@ -60,7 +73,7 @@ class ChatAgentUD(DistributedObjectGlobalUD):
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,
dg = DistributedAvatar.aiFormatUpdate('setTalkWhisper', receiverAvId, receiverAvId, self.air.ourChannel,
[sender, sender, '', cleanMessage, [], 0])
self.air.send(dg)