toontown-just-works/toontown/shtiker/PurchaseManagerAI.py

318 lines
14 KiB
Python
Raw Normal View History

2024-07-07 18:08:39 -05:00
from otp.ai.AIBaseGlobal import *
from panda3d.core import *
from direct.distributed.ClockDelta import *
from PurchaseManagerConstants import *
import copy
from direct.task.Task import Task
from direct.distributed import DistributedObjectAI
from direct.directnotify import DirectNotifyGlobal
from toontown.toonbase import ToontownGlobals
from toontown.minigame import MinigameGlobals
class PurchaseManagerAI(DistributedObjectAI.DistributedObjectAI):
notify = DirectNotifyGlobal.directNotify.newCategory('PurchaseManagerAI')
def __init__(self, air, avArray, mpArray, previousMinigameId, trolleyZone, newbieIdList = []):
DistributedObjectAI.DistributedObjectAI.__init__(self, air)
self.avIds = copy.deepcopy(avArray)
self.minigamePoints = copy.deepcopy(mpArray)
self.previousMinigameId = previousMinigameId
self.trolleyZone = trolleyZone
self.newbieIds = copy.deepcopy(newbieIdList)
self.isShutdown = 0
for i in xrange(len(self.avIds), 4):
self.avIds.append(0)
for i in xrange(len(self.minigamePoints), 4):
self.minigamePoints.append(0)
self.playerStates = [None,
None,
None,
None]
self.playersReported = [None,
None,
None,
None]
self.playerMoney = [0,
0,
0,
0]
for i in xrange(len(self.avIds)):
avId = self.avIds[i]
if avId <= 3:
self.playerStates[i] = PURCHASE_NO_CLIENT_STATE
self.playersReported[i] = PURCHASE_CANTREPORT_STATE
elif avId in self.air.doId2do:
if avId not in self.getInvolvedAvIds():
self.playerStates[i] = PURCHASE_EXIT_STATE
self.playersReported[i] = PURCHASE_REPORTED_STATE
else:
self.playerStates[i] = PURCHASE_WAITING_STATE
self.playersReported[i] = PURCHASE_UNREPORTED_STATE
else:
self.playerStates[i] = PURCHASE_DISCONNECTED_STATE
self.playersReported[i] = PURCHASE_CANTREPORT_STATE
for avId in self.getInvolvedAvIds():
if avId > 3 and avId in self.air.doId2do:
self.acceptOnce(self.air.getAvatarExitEvent(avId), self.__handleUnexpectedExit, extraArgs=[avId])
av = self.air.doId2do[avId]
avIndex = self.findAvIndex(avId)
money = av.getMoney()
if avIndex == None:
self.notify.warning('__init__ avIndex is none but avId=%s' % avId)
continue
self.playerMoney[avIndex] = money
if self.playerMoney[avIndex] < 0:
simbase.air.writeServerEvent('suspicious', avId, 'toon has invalid money %s, forcing to zero' % money)
self.playerMoney[avIndex] = 0
av.addMoney(self.minigamePoints[avIndex])
self.air.writeServerEvent('minigame', avId, '%s|%s|%s|%s' % (self.previousMinigameId,
self.trolleyZone,
self.avIds,
self.minigamePoints[avIndex]))
self.receivingInventory = 1
self.receivingButtons = 1
return
def delete(self):
taskMgr.remove(self.uniqueName('countdown-timer'))
self.ignoreAll()
DistributedObjectAI.DistributedObjectAI.delete(self)
def getInvolvedAvIds(self):
avIds = []
for avId in self.avIds:
if avId not in self.newbieIds:
avIds.append(avId)
return avIds
def getMinigamePoints(self):
return self.minigamePoints
def getAvIds(self):
return self.avIds
def getNewbieIds(self):
return self.newbieIds
def getPlayerMoney(self):
return self.playerMoney
def d_setPlayerStates(self, stateArray):
self.sendUpdate('setPlayerStates', stateArray)
return None
def getPlayerStates(self):
return self.playerStates
def getCountdown(self):
self.startCountdown()
return globalClockDelta.getRealNetworkTime()
def startCountdown(self):
if not config.GetBool('disable-purchase-timer', 0):
taskMgr.doMethodLater(PURCHASE_COUNTDOWN_TIME, self.timeIsUpTask, self.uniqueName('countdown-timer'))
def requestExit(self):
avId = self.air.getAvatarIdFromSender()
avIndex = self.findAvIndex(avId)
if avIndex is None:
self.air.writeServerEvent('suspicious', avId, 'PurchaseManager.requestExit: unknown avatar: %s' % (avId,))
return
if self.receivingButtons:
if avId in self.air.doId2do:
av = self.air.doId2do[avId]
if avIndex == None:
self.air.writeServerEvent('suspicious', avId, 'PurchaseManager.requestExit not on list')
self.notify.warning('Avatar ' + str(avId) + ' requested Exit, but is not on the list!')
else:
avState = self.playerStates[avIndex]
if avState == PURCHASE_PLAYAGAIN_STATE or avState == PURCHASE_WAITING_STATE:
self.playerStates[avIndex] = PURCHASE_EXIT_STATE
self.handlePlayerLeaving(avId)
else:
self.air.writeServerEvent('suspicious', avId, 'PurchaseManager.requestExit invalid transition to exit')
self.notify.warning('Invalid transition to exit state.')
else:
self.air.writeServerEvent('suspicious', avId, 'PurchaseManager.requestExit unknown avatar')
self.notify.warning('Avatar ' + str(avId) + ' requested Exit, but is not in doId2do.' + ' Assuming disconnected.')
self.playerStates[avIndex] = PURCHASE_DISCONNECTED_STATE
self.playersReported[avIndex] = PURCHASE_CANTREPORT_STATE
self.ignore(self.air.getAvatarExitEvent(avId))
self.d_setPlayerStates(self.playerStates)
if self.getNumUndecided() == 0:
self.timeIsUp()
else:
self.air.writeServerEvent('suspicious', avId, 'PurchaseManager.requestExit not receiving requests now')
self.notify.warning('Avatar ' + str(avId) + ' requested Exit, but I am not receiving button requests now.')
return
def requestPlayAgain(self):
avId = self.air.getAvatarIdFromSender()
if self.findAvIndex(avId) == None:
self.air.writeServerEvent('suspicious', avId, 'PurchaseManager.requestPlayAgain: unknown avatar')
return
if self.receivingButtons:
if avId in self.air.doId2do:
av = self.air.doId2do[avId]
avIndex = self.findAvIndex(avId)
if avIndex == None:
self.air.writeServerEvent('suspicious', avId, 'PurchaseManager.requestPlayAgain not on list')
self.notify.warning('Avatar ' + str(avId) + ' requested PlayAgain, but is not on the list!')
else:
avState = self.playerStates[avIndex]
if avState == PURCHASE_WAITING_STATE:
self.notify.debug(str(avId) + ' wants to play again')
self.playerStates[avIndex] = PURCHASE_PLAYAGAIN_STATE
else:
self.air.writeServerEvent('suspicious', avId, 'PurchaseManager.requestPlayAgain invalid transition to PlayAgain')
self.notify.warning('Invalid transition to PlayAgain state.')
else:
self.air.writeServerEvent('suspicious', avId, 'PurchaseManager.requestPlayAgain unknown avatar')
self.notify.warning('Avatar ' + str(avId) + ' requested PlayAgain, but is not in doId2do.' + ' Assuming disconnected.')
avIndex = self.findAvIndex(avId)
self.playerStates[avIndex] = PURCHASE_DISCONNECTED_STATE
self.playersReported[avIndex] = PURCHASE_CANTREPORT_STATE
self.ignore(self.air.getAvatarExitEvent(avId))
self.d_setPlayerStates(self.playerStates)
if self.getNumUndecided() == 0:
self.timeIsUp()
else:
self.air.writeServerEvent('suspicious', avId, 'PurchaseManager.requestPlayAgain not receiving requests now')
self.notify.warning('Avatar ' + str(avId) + ' requested PlayAgain, but I am not receiving button ' + 'requests now.')
return
def setInventory(self, blob, newMoney, done):
avId = self.air.getAvatarIdFromSender()
if self.receivingInventory:
if avId in self.air.doId2do:
av = self.air.doId2do[avId]
avIndex = self.findAvIndex(avId)
if avIndex == None:
self.air.writeServerEvent('suspicious', avId, 'PurchaseManager.setInventory not on list')
self.notify.warning('Avatar ' + str(avId) + ' requested purchase, but is not on the list!')
else:
newInventory = av.inventory.makeFromNetString(blob)
currentMoney = av.getMoney()
if av.inventory.validatePurchase(newInventory, currentMoney, newMoney):
av.setMoney(newMoney)
if not done:
return
if self.playersReported[avIndex] != PURCHASE_UNREPORTED_STATE:
self.air.writeServerEvent('suspicious', avId, 'PurchaseManager.setInventory bad report state')
self.notify.warning('Bad report state: ' + str(self.playersReported[avIndex]))
else:
av.d_setInventory(av.inventory.makeNetString())
av.d_setMoney(newMoney)
else:
self.air.writeServerEvent('suspicious', avId, 'PurchaseManager.setInventory invalid purchase')
self.notify.warning('Avatar ' + str(avId) + ' attempted an invalid purchase.')
av.d_setInventory(av.inventory.makeNetString())
av.d_setMoney(av.getMoney())
self.playersReported[avIndex] = PURCHASE_REPORTED_STATE
if self.getNumUnreported() == 0:
self.shutDown()
else:
self.air.writeServerEvent('suspicious', avId, 'PurchaseManager.setInventory not receiving inventory')
self.notify.warning('Not receiving inventory. Ignored ' + str(avId) + "'s request")
return
def d_setPurchaseExit(self):
self.sendUpdate('setPurchaseExit', [])
return None
def timeIsUpTask(self, task):
self.timeIsUp()
return Task.done
def timeIsUp(self):
self.d_setPurchaseExit()
taskMgr.remove(self.uniqueName('countdown-timer'))
self.receivingButtons = 0
self.receivingInventory = 1
return None
def shutDown(self):
if self.isShutdown:
self.notify.warning('Got shutDown twice')
return
self.isShutdown = 1
from toontown.minigame import MinigameCreatorAI
playAgainNum = self.getNumPlayAgain()
if playAgainNum > 0:
MinigameCreatorAI.createMinigame(self.air, self.getPlayAgainList(), self.trolleyZone, minigameZone=self.zoneId, previousGameId=self.previousMinigameId, newbieIds=self.newbieIds)
else:
MinigameCreatorAI.releaseMinigameZone(self.zoneId)
self.requestDelete()
self.ignoreAll()
return None
def findAvIndex(self, avId):
for i in xrange(len(self.avIds)):
if avId == self.avIds[i]:
return i
return None
def getNumUndecided(self):
undecidedCounter = 0
for playerState in self.playerStates:
if playerState == PURCHASE_WAITING_STATE:
undecidedCounter += 1
return undecidedCounter
def getPlayAgainList(self):
playAgainList = []
for i in xrange(len(self.playerStates)):
if self.playerStates[i] == PURCHASE_PLAYAGAIN_STATE:
playAgainList.append(self.avIds[i])
return playAgainList
def getNumPlayAgain(self):
playAgainCounter = 0
for playerState in self.playerStates:
if playerState == PURCHASE_PLAYAGAIN_STATE:
playAgainCounter += 1
return playAgainCounter
def getNumUnreported(self):
unreportedCounter = 0
for playerState in self.playersReported:
if playerState == PURCHASE_UNREPORTED_STATE:
unreportedCounter += 1
elif playerState == PURCHASE_REPORTED_STATE:
pass
elif playerState == PURCHASE_CANTREPORT_STATE:
pass
else:
self.notify.warning('Weird report state: ' + str(playerState))
return unreportedCounter
def __handleUnexpectedExit(self, avId):
self.notify.warning('Avatar: ' + str(avId) + ' has exited unexpectedly')
index = self.findAvIndex(avId)
if index == None:
self.notify.warning('Something is seriously screwed up...' + 'An avatar exited unexpectedly, and they' + ' are not on my list!')
else:
self.playerStates[index] = PURCHASE_DISCONNECTED_STATE
self.playersReported[index] = PURCHASE_CANTREPORT_STATE
self.d_setPlayerStates(self.playerStates)
if self.receivingButtons:
if self.getNumUndecided() == 0:
self.timeIsUp()
if self.receivingInventory:
if self.getNumUnreported() == 0:
self.shutDown()
return
def handlePlayerLeaving(self, avId):
pass