uberdog: Starts

This commit is contained in:
Open Toontown 2022-12-17 02:30:59 -05:00
parent bf9cb79078
commit 13e7bf0b61
5 changed files with 668 additions and 0 deletions

380
otp/uberdog/UberDog.py Normal file
View File

@ -0,0 +1,380 @@
"""
The Uber Distributed Obeject Globals server.
"""
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.fsm.ClassicFSM import ClassicFSM
from direct.fsm.State import State
from otp.otpbase import OTPGlobals
from otp.distributed import OtpDoGlobals
from otp.distributed.OtpDoGlobals import *
from otp.ai.AIRepository import AIRepository
from otp.ai import TimeManagerAI
from pandac.PandaModules import *
from otp.uberdog.AccountDetailRecord import AccountDetailRecord, SubDetailRecord
from otp.ai.AIMsgTypes import *
class UberDog(AIRepository):
notify = directNotify.newCategory("UberDog")
def __init__(
self, mdip, mdport, esip, esport, dcFileNames,
serverId, minChannel, maxChannel):
AIRepository.__init__(
self, mdip, mdport, esip, esport, dcFileNames,
serverId, minChannel, maxChannel, dcSuffix = 'UD')
# We're responsible for keeping track of who's online with which avatar
self.onlineAccountDetails = {}
self.onlineAvatars = {}
self.onlinePlayers = {}
self.pending={}
self.doId2doCache={}
if hasattr(self, 'setVerbose'):
if self.config.GetBool('verbose-uberrepository'):
self.setVerbose(1)
# The AI State machine
self.fsm = ClassicFSM(
'UberDog', [
State('off',
self.enterOff,
self.exitOff,
['connect']),
State('connect',
self.enterConnect,
self.exitConnect,
['noConnection', 'playGame',]),
State('playGame',
self.enterPlayGame,
self.exitPlayGame,
['noConnection']),
State('noConnection',
self.enterNoConnection,
self.exitNoConnection,
['connect'])],
# initial state
'off',
# final state
'off',
)
self.fsm.enterInitialState()
self.fsm.request("connect")
def _connected(self):
"""
Callback for when we successfully connect to the otp_server cluster.
"""
self.setConnectionName("UberDog")
AIRepository._connected(self)
# Listen for Account and Avatar online/offline messages
self.registerForChannel(CHANNEL_PUPPET_ACTION)
self.fsm.request("playGame")
def dispatchUpdateToDoId(self, dclassName, fieldName, doId, args, channelId=None):
# dispatch immediately to local object if it's local, otherwise send
# it over the wire
obj = self.doId2do.get(doId)
if obj is not None:
assert obj.__class__.__name__ == (dclassName + self.dcSuffix)
method = getattr(obj, fieldName)
apply(method, args)
else:
self.sendUpdateToDoId(dclassName, fieldName, doId, args, channelId)
def dispatchUpdateToGlobalDoId(self, dclassName, fieldName, doId, args):
# dispatch immediately to local object if it's local, otherwise send
# it over the wire
obj = self.doId2do.get(doId)
if obj is not None:
assert obj.__class__.__name__ == dclassName
method = getattr(obj, fieldName)
apply(method, args)
else:
self.sendUpdateToGlobalDoId(dclassName, fieldName, doId, args)
@report(types = ['args'], dConfigParam = 'avatarmgr')
def handleAccountUsage(self, di):
priorAccount = di.getUint32() # Historic - used only in __dev__ atm
newAccount = di.getUint32()
if priorAccount == 0 and newAccount == 0:
assert self.notify.debug("priorAccount==0 and newAccount==0, ignoring accountUsage message")
return
accountDetailRecord = AccountDetailRecord()
accountDetailRecord.openChatEnabled = (di.getString() == "YES")
accountDetailRecord.createFriendsWithChat = (di.getString() == "YES")
accountDetailRecord.chatCodeCreation = (di.getString() == "YES")
access = di.getString()
if access == "VELVET":
access = OTPGlobals.AccessVelvetRope
elif access == "FULL":
access = OTPGlobals.AccessFull
else:
access = OTPGlobals.AccessUnknown
accountDetailRecord.piratesAccess = access
accountDetailRecord.familyAccountId = di.getInt32()
accountDetailRecord.playerAccountId = di.getInt32()
accountDetailRecord.playerName = di.getString()
accountDetailRecord.playerNameApproved = di.getInt8()
accountDetailRecord.maxAvatars = di.getInt32()
accountDetailRecord.numFamilyMembers = di.getInt16()
accountDetailRecord.familyMembers = []
for i in range(accountDetailRecord.numFamilyMembers):
accountDetailRecord.familyMembers.append(di.getInt32())
logoutReason = di.getInt32()
# Now retrieve the subscription information
accountDetailRecord.numSubs = di.getUint16()
for i in range(accountDetailRecord.numSubs):
subDetailRecord = SubDetailRecord()
subDetailRecord.subId = di.getUint32()
subDetailRecord.subOwnerId = di.getUint32()
subDetailRecord.subName = di.getString()
subDetailRecord.subActive = di.getString()
access = di.getString()
if access == "VELVET":
access = OTPGlobals.AccessVelvetRope
elif access == "FULL":
access = OTPGlobals.AccessFull
else:
access = OTPGlobals.AccessUnknown
subDetailRecord.subAccess = access
subDetailRecord.subLevel = di.getUint8()
subDetailRecord.subNumAvatars = di.getUint8()
subDetailRecord.subNumConcur = di.getUint8()
subDetailRecord.subFounder = (di.getString() == "YES")
# Add this subscription to the dict on the account record
accountDetailRecord.subDetails[subDetailRecord.subId] = subDetailRecord
# How many avatar slots total do you get in this game?
accountDetailRecord.maxAvatarSlots = di.getInt8()
assert self.notify.debug("accountDetailRecord: %s" % accountDetailRecord)
if priorAccount:
# Send any previous account offline
self.accountOffline(priorAccount)
pass
if newAccount:
# Set up the new guy
self.accountOnline(newAccount, accountDetailRecord)
pass
pass
@report(types = ['args'], dConfigParam = 'avatarmgr')
def handleAvatarUsage(self, di):
priorAvatar = di.getUint32()
newAvatar = di.getUint32()
if priorAvatar == 0 and newAvatar == 0:
assert self.notify.debug("priorAvatar==0 and newAvatar==0, ignoring avatarUsage message")
return
newAvatarType = di.getUint16()
accountId = di.getUint32()
openChatEnabled = di.getString()
createFriendsWithChat = di.getString()
chatCodeCreation = di.getString()
piratesAccess = di.getString()
familyAccountId = di.getInt32()
playerAccountId = di.getInt32()
playerName = di.getString()
playerNameApproved = di.getInt8()
maxAvatars = di.getInt32()
numFamilyMembers = di.getInt16()
familyMembers = []
for i in range(numFamilyMembers):
familyMembers.append(di.getInt32())
if openChatEnabled == "YES":
openChatEnabled = 1
else:
openChatEnabled = 0
if priorAvatar:
# Send any previous avatar offline
self.avatarOffline(accountId, priorAvatar)
pass
if newAvatar:
# Set up the new guy
self.avatarOnline(newAvatar, newAvatarType,
playerAccountId,
playerName,
playerNameApproved,
openChatEnabled,
createFriendsWithChat,
chatCodeCreation)
pass
pass
@report(types = ['args'], dConfigParam = 'avatarmgr')
def accountOnline(self, accountId, accountDetailRecord):
self.writeServerEvent('accountOnline', accountId, '')
self.onlineAccountDetails[accountId] = accountDetailRecord
messenger.send('accountOnline', [accountId])
pass
@report(types = ['args'], dConfigParam = 'avatarmgr')
def accountOffline(self, accountId):
self.writeServerEvent('accountOffline', accountId, '')
self.onlineAccountDetails.pop(accountId, None)
self.onlinePlayers.pop(accountId, None)
messenger.send('accountOffline', [accountId])
pass
@report(types = ['args'], dConfigParam = 'avatarmgr')
def getAccountDetails(self, accountId):
return self.onlineAccountDetails.get(accountId)
@report(types = ['args'], dConfigParam = 'avatarmgr')
def isAccountOnline(self, accountId):
return accountId in self.onlineAccountDetails
@report(types = ['args'], dConfigParam = 'avatarmgr')
def isAvatarOnline(self, avatarId):
return avatarId in self.onlineAvatars
@report(types = ['args'], dConfigParam = 'avatarmgr')
def getAvatarAccountOnline(self, avatarId):
return self.onlineAvatars.get(avatarId, 0)
@report(types = ['args'], dConfigParam = 'avatarmgr')
def getAccountOnlineAvatar(self, accountId):
return self.onlinePlayers.get(accountId, 0)
@report(types = ['args'], dConfigParam = 'avatarmgr')
def checkAccountId(self, accountId):
if not accountId:
# SUSPICIOUS
self.notify.warning("Bogus accountId: %s" % accountId)
self.writeServerEvent('suspicious', accountId, 'bogus accountId in OtpAvatarManagerUD')
elif not self.isAccountOnline(accountId):
# SUSPICIOUS
self.notify.warning("Got request from account not online: %s" % accountId)
self.writeServerEvent('suspicious', accountId, 'request from offline account in OtpAvatarManagerUD')
else:
# Everything checks out
return True
return False
@report(types = ['args'], dConfigParam = 'avatarmgr')
def avatarOnline(self, avatarId, avatarType, accountId, playerName, playerNameApproved,
openChatEnabled, createFriendsWithChat, chatCodeCreation):
self.writeServerEvent('avatarOnline', avatarId, '%s|%s|%s|%s|%s|%s' % (
accountId, playerName, playerNameApproved, openChatEnabled,
createFriendsWithChat, chatCodeCreation))
self.onlineAvatars[avatarId] = accountId
self.onlinePlayers[accountId] = avatarId
simpleInfo = [avatarId, avatarType]
fullInfo = [avatarId,
accountId,
playerName,
playerNameApproved,
openChatEnabled,
createFriendsWithChat,
chatCodeCreation]
# necessary for local UD manager objects
messenger.send("avatarOnline", simpleInfo)
messenger.send("avatarOnlinePlusAccountInfo", fullInfo)
pass
@report(types = ['args'], dConfigParam = 'avatarmgr')
def avatarOffline(self, accountId, avatarId):
self.writeServerEvent('avatarOffline', avatarId, '')
self.onlinePlayers.pop(accountId, None)
self.onlineAvatars.pop(avatarId, None)
# necessary for local UD manager objects
messenger.send("avatarOffline", [avatarId])
pass
###################################
# Assumed Obsolete as of 6/29/09
#
# If you're reading this and there
# haven't been any strange UD crashes
# here lately, you can probably delete
# the next few functions.
###################################
def _addObject(self, context, distributedObject):
"""
Handle a new distributed object arriving by adding
it to the cache calling self.handleGotDo().
"""
assert False, 'JCW: Testing for obsolete functions. If this crashes, let Josh know'
doId=distributedObject.getDoId()
assert not self.doId2doCache.has_key(doId)
if not self.doId2doCache.has_key(doId):
self.doId2doCache[doId]=distributedObject
self.handleGotDo(distributedObject)
def handleGotDo(self, distributedObject):
"""
This allows derived classes to override the handling
of new distributed objects arriving in the cache.
By default, this will loop through the pending calls
for that object and make the function calls. It
will also remove the handled calls from the pending set.
"""
assert False, 'JCW: Testing for obsolete functions. If this crashes, let Josh know'
assert self.doId2doCache.has_key(doId)
pending=self.pending.get(doId)
if pending is not None:
del self.pending[doId]
for i in pending:
apply(i[0], i[2])
def deleteObject(self, doId):
"""
Ask for the object to be removed from the private
distributed object cache.
"""
assert False, 'JCW: Testing for obsolete functions. If this crashes, let Josh know'
if self.doId2doCache.had_key(doId):
self.unregisterForChannel(doId)
#self.deleteObject(doId)
del self.doId2doCache[doId]
#HACK:
self.unregisterForChannel(doId)
AIRepository.deleteObject(self.doId)
def uniqueName(self, desc):
return desc
if __dev__:
"""
Early warning system for unsupported use of the Uberdog Repository
"""
def deleteObjects(self):
assert 0
def createDistrict(self, districtId, districtName):
assert 0
def deleteDistrict(self, districtId):
assert 0
def enterDistrictReset(self):
assert 0
def exitDistrictReset(self):
assert 0

View File

@ -0,0 +1,10 @@
"""instantiate global ShowBase object"""
from otp.ai.AIBase import *
# We're going to end up importing this accidentally anyway, so we
# might as well import it explicitly, and share the same AIBase
# object.
from otp.ai.AIBaseGlobal import *
__builtins__["uber"] = simbase

View File

@ -0,0 +1,34 @@
from toontown.toonbase import TTLocalizer
language = TTLocalizer.getLanguage()
# Log config
logFatal = True
logError = True
logWarning = True
logLog = True
logInfo = True
logDebug = False
logChat = True
logSecurity = True
logMaxLinesInMemory = 100
# DB config
ttDbHost = "localhost"
ttDbPort = 3306
if language == 'castillian':
ttDbName = "es_toontownTopDb"
elif language == "japanese":
ttDbName = "jp_toontownTopDb"
elif language == "portuguese":
ttDbName = "br_toontownTopDb"
elif language == "french":
ttDbName = "french_toontownTopDb"
else:
ttDbName = "toontownTopDb"
ttDbUser = "ttDb_user"
ttDbPasswd = "toontastic2008"

108
toontown/uberdog/Start.py Normal file
View File

@ -0,0 +1,108 @@
"""
Start the Toontown UberDog (Uber Distributed Object Globals server).
"""
from panda3d.core import loadPrcFile
# TODO: use argparse for this?
configs = ('etc/Configrc.prc',)
for prc in configs:
loadPrcFile(prc)
import builtins
from direct.task.Task import Task
class game:
name = "uberDog"
process = "server"
builtins.game = game()
import time
import os
import sys
if os.getenv('TTMODELS'):
from pandac.PandaModules import getModelPath, Filename
# In the publish environment, TTMODELS won't be on the model
# path by default, so we always add it there. In the dev
# environment, it'll be on the model path already, but it
# doesn't hurt to add it again.
getModelPath().appendDirectory(Filename.expandFrom("$TTMODELS/built"))
from direct.showbase.PythonUtil import *
from otp.uberdog.UberDogGlobal import *
from toontown.coderedemption import TTCodeRedemptionConsts
from toontown.uberdog.ToontownUberDog import ToontownUberDog
from toontown.uberdog import PartiesUdConfig
print("Initializing the Toontown UberDog (Uber Distributed Object Globals server)...")
uber.mdip = uber.config.GetString("msg-director-ip", "127.0.0.1")
uber.mdport = uber.config.GetInt("msg-director-port", 6666)
uber.esip = uber.config.GetString("event-server-ip", "127.0.0.1")
uber.esport = uber.config.GetInt("event-server-port", 4343)
stateServerId = uber.config.GetInt("state-server-id", 20100000)
uber.objectNames = set(os.getenv("uberdog_objects", "").split())
minChannel = uber.config.GetInt("uberdog-min-channel", 200400000)
maxChannel = uber.config.GetInt("uberdog-max-channel", 200449999)
uber.sbNSHost = uber.config.GetString("sb-host","")
uber.sbNSPort = uber.config.GetInt("sb-port",6053)
uber.sbListenPort = 6060
uber.clHost = "127.0.0.1"
uber.clPort = 9090
uber.allowUnfilteredChat = uber.config.GetInt("allow-unfiltered-chat",0)
uber.bwDictPath = ""
uber.RATManagerHTTPListenPort = uber.config.GetInt("rat-port",8080)
uber.awardManagerHTTPListenPort = uber.config.GetInt("award-port",8888)
uber.inGameNewsMgrHTTPListenPort = uber.config.GetInt("in-game-news-port",8889)
uber.mysqlhost = uber.config.GetString("mysql-host", PartiesUdConfig.ttDbHost)
uber.codeRedemptionMgrHTTPListenPort = uber.config.GetInt('code-redemption-port', 8998)
uber.crDbName = uber.config.GetString("tt-code-db-name", TTCodeRedemptionConsts.DefaultDbName)
uber.cpuInfoMgrHTTPListenPort = uber.config.GetInt("security_ban_mgr_port",8892)
uber.air = ToontownUberDog(
uber.mdip, uber.mdport,
uber.esip, uber.esport,
None,
stateServerId,
minChannel,
maxChannel)
# How we let the world know we are not running a service
uber.aiService = 0
uber.wantEmbeddedOtpServer = uber.config.GetInt(
"toontown-uberdog-want-embedded-otp-server", 0)
if uber.wantEmbeddedOtpServer:
otpServerPath = uber.config.GetString(
"toontown-uberdog-otp-server-path", "c:/toonsrv")
sys.path.append(otpServerPath)
import otp_server_py
if not otp_server_py.serverInit(otpServerPath):
sys.exit(1)
def ServerYield(task):
otp_server_py.serverLoop()
return Task.cont
uber.taskMgr.add(ServerYield, 'serverYield')
__builtins__["otpServer"] = otp_server_py
try:
run()
except:
info = describeException()
#uber.air.writeServerEvent('uberdog-exception', districtNumber, info)
raise

View File

@ -0,0 +1,136 @@
"""
The Toontown Uber Distributed Object Globals server.
"""
from pandac.PandaModules import *
import time
if __debug__:
from direct.showbase.PythonUtil import *
from direct.directnotify.DirectNotifyGlobal import directNotify
from otp.distributed import OtpDoGlobals
from otp.ai.AIMsgTypes import *
from otp.ai import TimeManagerAI
from otp.uberdog.UberDog import UberDog
from otp.friends.AvatarFriendsManagerUD import AvatarFriendsManagerUD
from toontown.uberdog.DistributedDeliveryManagerUD import DistributedDeliveryManagerUD
from toontown.uberdog.DistributedMailManagerUD import DistributedMailManagerUD
from toontown.parties import ToontownTimeManager
from toontown.rpc.RATManagerUD import RATManagerUD
from toontown.rpc.AwardManagerUD import AwardManagerUD
from toontown.uberdog import TTSpeedchatRelayUD
from toontown.uberdog import DistributedInGameNewsMgrUD
from toontown.uberdog import DistributedCpuInfoMgrUD
from otp.uberdog.RejectCode import RejectCode
class ToontownUberDog(UberDog):
notify = directNotify.newCategory("UberDog")
def __init__(
self, mdip, mdport, esip, esport, dcFilenames,
serverId, minChannel, maxChannel):
assert self.notify.debugStateCall(self)
# TODO: The UD needs to know server time, but perhaps this isn't
# the place to do this? -SG-SLWP
self.toontownTimeManager = ToontownTimeManager.ToontownTimeManager()
self.toontownTimeManager.updateLoginTimes(time.time(), time.time(), globalClock.getRealTime())
def isManagerFor(name):
return len(uber.objectNames) == 0 or name in uber.objectNames
self.isFriendsManager = False # latest from Ian this should not run anymore
#self.isFriendsManager = isManagerFor('friends')
self.isSpeedchatRelay = isManagerFor('speedchatRelay')
self.isGiftingManager = isManagerFor('gifting')
self.isMailManager = False # isManagerFor('mail')
self.isPartyManager = isManagerFor('party')
self.isRATManager = False # isManagerFor('RAT')
self.isAwardManager = isManagerFor('award')
self.isCodeRedemptionManager = isManagerFor('coderedemption')
self.isInGameNewsMgr = isManagerFor('ingamenews')
self.isCpuInfoMgr = isManagerFor('cpuinfo')
self.isRandomSourceManager = False # isManagerFor('randomsource')
UberDog.__init__(
self, mdip, mdport, esip, esport, dcFilenames,
serverId, minChannel, maxChannel)
def createObjects(self):
UberDog.createObjects(self)
# Ask for the ObjectServer so we can check the dc hash value
self.queryObjectAll(self.serverId)
if self.isFriendsManager:
self.playerFriendsManager = self.generateGlobalObject(
OtpDoGlobals.OTP_DO_ID_PLAYER_FRIENDS_MANAGER,
"TTPlayerFriendsManager")
if self.isSpeedchatRelay:
self.speedchatRelay = self.generateGlobalObject(
OtpDoGlobals.OTP_DO_ID_TOONTOWN_SPEEDCHAT_RELAY,
"TTSpeedchatRelay")
if self.isGiftingManager:
self.deliveryManager = self.generateGlobalObject(
OtpDoGlobals.OTP_DO_ID_TOONTOWN_DELIVERY_MANAGER,
"DistributedDeliveryManager")
if self.isMailManager:
self.mailManager = self.generateGlobalObject(
OtpDoGlobals.OTP_DO_ID_TOONTOWN_MAIL_MANAGER,
"DistributedMailManager")
if self.isPartyManager:
self.partyManager = self.generateGlobalObject(
OtpDoGlobals.OTP_DO_ID_TOONTOWN_PARTY_MANAGER,
"DistributedPartyManager")
if simbase.config.GetBool('want-ddsm', 1):
self.dataStoreManager = self.generateGlobalObject(
OtpDoGlobals.OTP_DO_ID_TOONTOWN_TEMP_STORE_MANAGER,
"DistributedDataStoreManager")
if self.isRATManager:
self.RATManager = self.generateGlobalObject(
OtpDoGlobals.OTP_DO_ID_TOONTOWN_RAT_MANAGER,
"RATManager")
if self.isAwardManager:
self.awardManager = self.generateGlobalObject(
OtpDoGlobals.OTP_DO_ID_TOONTOWN_AWARD_MANAGER,
"AwardManager")
if config.GetBool('want-code-redemption', 1):
if self.isCodeRedemptionManager:
self.codeRedemptionManager = self.generateGlobalObject(
OtpDoGlobals.OTP_DO_ID_TOONTOWN_CODE_REDEMPTION_MANAGER,
"TTCodeRedemptionMgr")
if self.isInGameNewsMgr:
self.inGameNewsMgr = self.generateGlobalObject(
OtpDoGlobals.OTP_DO_ID_TOONTOWN_IN_GAME_NEWS_MANAGER,
"DistributedInGameNewsMgr")
if self.isCpuInfoMgr:
self.cpuInfoMgr = self.generateGlobalObject(
OtpDoGlobals.OTP_DO_ID_TOONTOWN_CPU_INFO_MANAGER,
"DistributedCpuInfoMgr")
if self.isRandomSourceManager:
self.randomSourceManager = self.generateGlobalObject(
OtpDoGlobals.OTP_DO_ID_TOONTOWN_NON_REPEATABLE_RANDOM_SOURCE,
"NonRepeatableRandomSource")
def getDatabaseIdForClassName(self, className):
return DatabaseIdFromClassName.get(
className, DefaultDatabaseChannelId)
if __debug__:
def status(self):
if self.isGiftingManager:
print("deliveryManager is", self.deliveryManager)
if self.isFriendsManager:
print("playerFriendsManager is ",self.playerFriendsManager)