612 lines
24 KiB
Python
612 lines
24 KiB
Python
|
import datetime
|
||
|
import json
|
||
|
import os
|
||
|
import time
|
||
|
|
||
|
from direct.directnotify import DirectNotifyGlobal
|
||
|
from direct.distributed.DistributedObjectAI import DistributedObjectAI
|
||
|
|
||
|
from toontown.catalog import CatalogFurnitureItem
|
||
|
from toontown.catalog import CatalogInvalidItem
|
||
|
from toontown.catalog import CatalogItem
|
||
|
from toontown.catalog import CatalogSurfaceItem
|
||
|
from toontown.catalog import CatalogWindowItem
|
||
|
from toontown.catalog.CatalogItemList import CatalogItemList
|
||
|
from toontown.estate.DistributedBankAI import DistributedBankAI
|
||
|
from toontown.estate.DistributedClosetAI import DistributedClosetAI
|
||
|
from toontown.estate.DistributedFurnitureItemAI import DistributedFurnitureItemAI
|
||
|
from toontown.estate.DistributedPhoneAI import DistributedPhoneAI
|
||
|
from toontown.estate.DistributedTrunkAI import DistributedTrunkAI
|
||
|
from toontown.toonbase import ToontownGlobals
|
||
|
|
||
|
MINUTE = 60
|
||
|
HOUR = 60 * MINUTE
|
||
|
DAY = 24 * HOUR
|
||
|
|
||
|
|
||
|
def getDayId():
|
||
|
return int(time.time() // DAY)
|
||
|
|
||
|
|
||
|
class DistributedFurnitureManagerAI(DistributedObjectAI):
|
||
|
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedFurnitureManagerAI')
|
||
|
serverDataFolder = simbase.config.GetString('server-data-folder', '')
|
||
|
|
||
|
def __init__(self, air, house, interior):
|
||
|
DistributedObjectAI.__init__(self, air)
|
||
|
self.house = house
|
||
|
self.interior = interior
|
||
|
self.ownerId = 0
|
||
|
self.ownerName = ''
|
||
|
self.interiorId = 0
|
||
|
self.atticItems = CatalogItemList(store=CatalogItem.Customization)
|
||
|
self.atticWallpaper = CatalogItemList(store=CatalogItem.Customization)
|
||
|
self.atticWindows = CatalogItemList(store=CatalogItem.Customization)
|
||
|
self.deletedItems = CatalogItemList(store=CatalogItem.Customization)
|
||
|
self.wallpaper = CatalogItemList(store=CatalogItem.Customization)
|
||
|
self.windows = CatalogItemList(store=CatalogItem.Customization | CatalogItem.WindowPlacement)
|
||
|
self.items = []
|
||
|
self.director = 0
|
||
|
self.deletedItemsFilename = ''
|
||
|
self.day2deletedItems = {}
|
||
|
|
||
|
def announceGenerate(self):
|
||
|
DistributedObjectAI.announceGenerate(self)
|
||
|
self.deletedItemsFilename = self.getDeletedItemsFilename()
|
||
|
self.day2deletedItems = self.loadDeletedItems()
|
||
|
taskMgr.add(self.__deletedItemsTask, self.uniqueName('deleted-items-task'))
|
||
|
|
||
|
def delete(self):
|
||
|
for item in self.items[:]:
|
||
|
item.requestDelete()
|
||
|
self.items.remove(item)
|
||
|
|
||
|
taskMgr.remove(self.uniqueName('deleted-items-task'))
|
||
|
DistributedObjectAI.delete(self)
|
||
|
|
||
|
def setOwnerId(self, ownerId):
|
||
|
self.ownerId = ownerId
|
||
|
|
||
|
def d_setOwnerId(self, ownerId):
|
||
|
self.sendUpdate('setOwnerId', [ownerId])
|
||
|
|
||
|
def b_setOwnerId(self, ownerId):
|
||
|
self.setOwnerId(ownerId)
|
||
|
self.d_setOwnerId(ownerId)
|
||
|
|
||
|
def getOwnerId(self):
|
||
|
return self.ownerId
|
||
|
|
||
|
def setOwnerName(self, ownerName):
|
||
|
self.ownerName = ownerName
|
||
|
|
||
|
def d_setOwnerName(self, ownerName):
|
||
|
self.sendUpdate('setOwnerName', [ownerName])
|
||
|
|
||
|
def b_setOwnerName(self, ownerName):
|
||
|
self.setOwnerName(ownerName)
|
||
|
self.d_setOwnerName(ownerName)
|
||
|
|
||
|
def getOwnerName(self):
|
||
|
return self.ownerName
|
||
|
|
||
|
def setInteriorId(self, interiorId):
|
||
|
self.interiorId = interiorId
|
||
|
|
||
|
def d_setInteriorId(self, interiorId):
|
||
|
self.sendUpdate('setInteriorId', [interiorId])
|
||
|
|
||
|
def b_setInteriorId(self, interiorId):
|
||
|
self.setInteriorId(interiorId)
|
||
|
self.d_setInteriorId(interiorId)
|
||
|
|
||
|
def getInteriorId(self):
|
||
|
return self.interiorId
|
||
|
|
||
|
def setAtticItems(self, atticItems):
|
||
|
self.atticItems = CatalogItemList(atticItems, store=CatalogItem.Customization)
|
||
|
|
||
|
def d_setAtticItems(self, atticItems):
|
||
|
self.sendUpdate('setAtticItems', [atticItems])
|
||
|
|
||
|
def b_setAtticItems(self, atticItems):
|
||
|
self.setAtticItems(atticItems)
|
||
|
self.d_setAtticItems(atticItems)
|
||
|
|
||
|
def getAtticItems(self):
|
||
|
return self.atticItems.getBlob()
|
||
|
|
||
|
def setAtticWallpaper(self, atticWallpaper):
|
||
|
self.atticWallpaper = CatalogItemList(atticWallpaper, store=CatalogItem.Customization)
|
||
|
|
||
|
def d_setAtticWallpaper(self, atticWallpaper):
|
||
|
self.sendUpdate('setAtticWallpaper', [atticWallpaper])
|
||
|
|
||
|
def b_setAtticWallpaper(self, atticWallpaper):
|
||
|
self.setAtticWallpaper(atticWallpaper)
|
||
|
self.d_setAtticWallpaper(atticWallpaper)
|
||
|
|
||
|
def getAtticWallpaper(self):
|
||
|
return self.atticWallpaper.getBlob()
|
||
|
|
||
|
def setAtticWindows(self, atticWindows):
|
||
|
self.atticWindows = CatalogItemList(atticWindows, store=CatalogItem.Customization)
|
||
|
|
||
|
def d_setAtticWindows(self, atticWindows):
|
||
|
self.sendUpdate('setAtticWindows', [atticWindows])
|
||
|
|
||
|
def b_setAtticWindows(self, atticWindows):
|
||
|
self.setAtticWindows(atticWindows)
|
||
|
self.d_setAtticWindows(atticWindows)
|
||
|
|
||
|
def getAtticWindows(self):
|
||
|
return self.atticWindows.getBlob()
|
||
|
|
||
|
def setDeletedItems(self, deletedItems):
|
||
|
self.deletedItems = CatalogItemList(deletedItems, store=CatalogItem.Customization)
|
||
|
|
||
|
def d_setDeletedItems(self, deletedItems):
|
||
|
self.sendUpdate('setDeletedItems', [deletedItems])
|
||
|
|
||
|
def b_setDeletedItems(self, deletedItems):
|
||
|
self.setDeletedItems(deletedItems)
|
||
|
self.d_setDeletedItems(deletedItems)
|
||
|
|
||
|
def getDeletedItems(self):
|
||
|
return self.deletedItems.getBlob()
|
||
|
|
||
|
def suggestDirector(self, avId):
|
||
|
if avId and avId != self.ownerId:
|
||
|
self.air.writeServerEvent('suspicious', avId, 'av tried to manage furniture in someone else\'s house')
|
||
|
return
|
||
|
|
||
|
av = self.air.doId2do.get(avId)
|
||
|
director = self.air.doId2do.get(self.director)
|
||
|
if director:
|
||
|
director.b_setGhostMode(0)
|
||
|
else:
|
||
|
av.b_setGhostMode(1)
|
||
|
|
||
|
self.b_setDirector(avId)
|
||
|
self.saveFurniture()
|
||
|
|
||
|
def setDirector(self, director):
|
||
|
self.director = director
|
||
|
|
||
|
def d_setDirector(self, director):
|
||
|
self.sendUpdate('setDirector', [director])
|
||
|
|
||
|
def b_setDirector(self, director):
|
||
|
self.setDirector(director)
|
||
|
self.d_setDirector(director)
|
||
|
|
||
|
def getDirector(self):
|
||
|
return self.director
|
||
|
|
||
|
def moveItemToAtticMessage(self, itemId, context):
|
||
|
avId = self.air.getAvatarIdFromSender()
|
||
|
owner = self._verifyOwner(avId, 'moveItemToAttic', context)
|
||
|
if not owner:
|
||
|
return
|
||
|
|
||
|
item = self.air.doId2do.get(itemId)
|
||
|
if not item or item not in self.items:
|
||
|
self.sendUpdateToAvatarId(avId, 'moveItemToAtticResponse', [ToontownGlobals.FM_InvalidItem, context])
|
||
|
|
||
|
self.atticItems.append(item.catalogItem)
|
||
|
self.b_setAtticItems(self.getAtticItems())
|
||
|
item.requestDelete()
|
||
|
self.items.remove(item)
|
||
|
self.sendUpdateToAvatarId(avId, 'moveItemToAtticResponse', [ToontownGlobals.FM_MovedItem, context])
|
||
|
|
||
|
def moveItemFromAtticMessage(self, index, x, y, z, h, p, r, context):
|
||
|
avId = self.air.getAvatarIdFromSender()
|
||
|
owner = self._verifyOwner(avId, 'moveItemFromAttic', context)
|
||
|
if not owner:
|
||
|
return
|
||
|
|
||
|
try:
|
||
|
item = self.atticItems[index]
|
||
|
except KeyError:
|
||
|
self.air.writeServerEvent('suspicious', avId, 'av tried to move nonexistent attic item')
|
||
|
self.sendUpdateToAvatarId(avId, 'moveItemFromAtticResponse', [ToontownGlobals.FM_InvalidIndex, context])
|
||
|
return
|
||
|
|
||
|
del self.atticItems[index]
|
||
|
self.b_setAtticItems(self.getAtticItems())
|
||
|
item.posHpr = (x, y, z, h, p, r)
|
||
|
obj = self.generateItem(item)
|
||
|
self.sendUpdateToAvatarId(avId, 'moveItemFromAtticResponse', [ToontownGlobals.FM_MovedItem, obj.doId, context])
|
||
|
|
||
|
def deleteItemFromAtticMessage(self, blob, index, context):
|
||
|
# blob is USELESS
|
||
|
avId = self.air.getAvatarIdFromSender()
|
||
|
owner = self._verifyOwner(avId, 'deleteItemFromAttic', context)
|
||
|
if not owner:
|
||
|
return
|
||
|
|
||
|
try:
|
||
|
item = self.atticItems[index]
|
||
|
except KeyError:
|
||
|
self.air.writeServerEvent('suspicious', avId, 'av tried to delete nonexistent attic item')
|
||
|
self.sendUpdateToAvatarId(avId, 'deleteItemFromAtticResponse', [ToontownGlobals.FM_InvalidIndex, context])
|
||
|
return
|
||
|
|
||
|
if not item.isDeletable():
|
||
|
self.sendUpdateToAvatarId(avId, 'deleteItemFromAtticResponse',
|
||
|
[ToontownGlobals.FM_NondeletableItem, context])
|
||
|
return
|
||
|
|
||
|
del self.atticItems[index]
|
||
|
self.b_setAtticItems(self.getAtticItems())
|
||
|
self._deleteItem(item)
|
||
|
self.sendUpdateToAvatarId(avId, 'deleteItemFromAtticResponse', [ToontownGlobals.FM_DeletedItem, context])
|
||
|
|
||
|
def deleteItemFromRoomMessage(self, blob, itemId, context):
|
||
|
# blob has no use here either
|
||
|
avId = self.air.getAvatarIdFromSender()
|
||
|
owner = self._verifyOwner(avId, 'deleteItemFromRoom', context)
|
||
|
if not owner:
|
||
|
return
|
||
|
|
||
|
item = self.air.doId2do.get(itemId)
|
||
|
if not item or item not in self.items:
|
||
|
self.sendUpdateToAvatarId(avId, 'deleteItemFromRoomResponse', [ToontownGlobals.FM_InvalidItem, context])
|
||
|
return
|
||
|
|
||
|
if not item.catalogItem.isDeletable():
|
||
|
self.sendUpdateToAvatarId(avId, 'deleteItemFromRoomResponse',
|
||
|
[ToontownGlobals.FM_NondeletableItem, context])
|
||
|
return
|
||
|
|
||
|
self.items.remove(item)
|
||
|
self._deleteItem(item.catalogItem)
|
||
|
item.requestDelete()
|
||
|
self.sendUpdateToAvatarId(avId, 'deleteItemFromRoomResponse', [ToontownGlobals.FM_DeletedItem, context])
|
||
|
|
||
|
def moveWallpaperFromAtticMessage(self, index, room, context):
|
||
|
avId = self.air.getAvatarIdFromSender()
|
||
|
owner = self._verifyOwner(avId, 'moveWallpaperFromAttic', context)
|
||
|
if not owner:
|
||
|
return
|
||
|
|
||
|
try:
|
||
|
item = self.atticWallpaper[index]
|
||
|
except KeyError:
|
||
|
self.air.writeServerEvent('suspicious', avId, 'av tried to move nonexistent wallpaper')
|
||
|
self.sendUpdateToAvatarId(avId, 'moveWallpaperFromAtticResponse',
|
||
|
[ToontownGlobals.FM_InvalidIndex, context])
|
||
|
return
|
||
|
|
||
|
slot = room * CatalogSurfaceItem.NUM_ST_TYPES + item.getSurfaceType()
|
||
|
self.atticWallpaper[index] = self.wallpaper[slot]
|
||
|
self.b_setAtticWallpaper(self.getAtticWallpaper())
|
||
|
self.wallpaper[slot] = item
|
||
|
self.house.interior.b_setWallpaper(self.wallpaper.getBlob())
|
||
|
self.sendUpdateToAvatarId(avId, 'moveWallpaperFromAtticResponse', [ToontownGlobals.FM_SwappedItem, context])
|
||
|
|
||
|
def deleteWallpaperFromAtticMessage(self, blob, index, context):
|
||
|
# you didn't expect blob to be used, right?
|
||
|
avId = self.air.getAvatarIdFromSender()
|
||
|
owner = self._verifyOwner(avId, 'deleteWallpaperFromAttic', context)
|
||
|
if not owner:
|
||
|
return
|
||
|
|
||
|
try:
|
||
|
item = self.atticWallpaper[index]
|
||
|
except KeyError:
|
||
|
self.air.writeServerEvent('suspicious', avId, 'av tried to delete nonexistent wallpaper')
|
||
|
self.sendUpdateToAvatarId(avId, 'deleteWallpaperFromAtticResponse',
|
||
|
[ToontownGlobals.FM_InvalidIndex, context])
|
||
|
return
|
||
|
|
||
|
del self.atticWallpaper[index]
|
||
|
self.b_setAtticWallpaper(self.getAtticWallpaper())
|
||
|
self._deleteItem(item)
|
||
|
self.sendUpdateToAvatarId(avId, 'deleteWallpaperFromAtticResponse', [ToontownGlobals.FM_DeletedItem, context])
|
||
|
|
||
|
def moveWindowToAtticMessage(self, slot, context):
|
||
|
# meme
|
||
|
pass
|
||
|
|
||
|
def moveWindowFromAtticMessage(self, index, slot, context):
|
||
|
avId = self.air.getAvatarIdFromSender()
|
||
|
owner = self._verifyOwner(avId, 'moveWindowFromAttic', context)
|
||
|
if not owner:
|
||
|
return
|
||
|
|
||
|
try:
|
||
|
item = self.atticWindows[index]
|
||
|
except KeyError:
|
||
|
self.air.writeServerEvent('suspicious', avId, 'av tried to move nonexistent window')
|
||
|
self.sendUpdateToAvatarId(avId, 'moveWindowFromAtticResponse', [ToontownGlobals.FM_InvalidIndex, context])
|
||
|
return
|
||
|
|
||
|
if slot > 5:
|
||
|
self.air.writeServerEvent('suspicious', avId, 'av tried to put window in invalid slot!')
|
||
|
return
|
||
|
|
||
|
item.placement = slot
|
||
|
oldWindow = None
|
||
|
windowIndex = None
|
||
|
for i, window in enumerate(self.windows):
|
||
|
if window.placement == slot:
|
||
|
oldWindow = window
|
||
|
windowIndex = i
|
||
|
|
||
|
if not oldWindow:
|
||
|
self.sendUpdateToAvatarId(avId, 'moveWindowFromAtticResponse', [ToontownGlobals.FM_InvalidIndex, context])
|
||
|
return
|
||
|
|
||
|
self.atticWindows[index] = oldWindow
|
||
|
self.d_setAtticWindows(self.getAtticWindows())
|
||
|
self.windows[windowIndex] = item
|
||
|
self.house.interior.b_setWindows(self.windows.getBlob())
|
||
|
self.sendUpdateToAvatarId(avId, 'moveWindowFromAtticResponse', [ToontownGlobals.FM_SwappedItem, context])
|
||
|
|
||
|
def moveWindowMessage(self, fromSlot, toSlot, context):
|
||
|
# yes
|
||
|
pass
|
||
|
|
||
|
def deleteWindowFromAtticMessage(self, blob, index, context):
|
||
|
# what is blob
|
||
|
avId = self.air.getAvatarIdFromSender()
|
||
|
owner = self._verifyOwner(avId, 'deleteWindowFromAttic', context)
|
||
|
if not owner:
|
||
|
return
|
||
|
|
||
|
try:
|
||
|
item = self.atticWindows[index]
|
||
|
except KeyError:
|
||
|
self.air.writeServerEvent('suspicious', avId, 'av tried to delete nonexistent window')
|
||
|
self.sendUpdateToAvatarId(avId, 'deleteWindowFromAtticResponse', [ToontownGlobals.FM_InvalidIndex, context])
|
||
|
return
|
||
|
|
||
|
del self.atticWindows[index]
|
||
|
self.d_setAtticWindows(self.getAtticWindows())
|
||
|
self._deleteItem(item)
|
||
|
self.sendUpdateToAvatarId(avId, 'deleteWindowFromAtticResponse', [ToontownGlobals.FM_DeletedItem, context])
|
||
|
|
||
|
def recoverDeletedItemMessage(self, blob, index, context):
|
||
|
# blob.
|
||
|
avId = self.air.getAvatarIdFromSender()
|
||
|
owner = self._verifyOwner(avId, 'recoverDeletedItem', context)
|
||
|
if not owner:
|
||
|
return
|
||
|
|
||
|
numItems = len(self.atticItems) + len(self.atticWallpaper) + len(self.atticWindows) + len(self.items)
|
||
|
if numItems + 1 > ToontownGlobals.MaxHouseItems:
|
||
|
self.sendUpdateToAvatarId(avId, 'recoverDeletedItemResponse', [ToontownGlobals.FM_HouseFull, context])
|
||
|
return
|
||
|
|
||
|
try:
|
||
|
item = self.deletedItems[index]
|
||
|
except KeyError:
|
||
|
self.air.writeServerEvent('suspicious', avId, 'av tried to recover nonexistent item')
|
||
|
self.sendUpdateToAvatarId(avId, 'recoverDeletedItemResponse', [ToontownGlobals.FM_InvalidIndex, context])
|
||
|
return
|
||
|
|
||
|
type2attic = {
|
||
|
CatalogSurfaceItem.CatalogSurfaceItem: (
|
||
|
self.atticWallpaper, self.b_setAtticWallpaper, self.getAtticWallpaper),
|
||
|
CatalogFurnitureItem.CatalogFurnitureItem: (self.atticItems, self.b_setAtticItems, self.getAtticItems),
|
||
|
CatalogWindowItem.CatalogWindowItem: (self.atticWindows, self.b_setAtticWindows, self.getAtticWindows)
|
||
|
}
|
||
|
|
||
|
for itemType in type2attic.keys():
|
||
|
if isinstance(item, itemType):
|
||
|
attic, setter, getter = type2attic[itemType]
|
||
|
attic.append(item)
|
||
|
setter(getter())
|
||
|
del self.deletedItems[index]
|
||
|
self.b_setDeletedItems(self.getDeletedItems())
|
||
|
self.removeDeletedItemBlob(item.getBlob().encode('base64'))
|
||
|
self.sendUpdateToAvatarId(avId, 'recoverDeletedItemResponse',
|
||
|
[ToontownGlobals.FM_RecoveredItem, context])
|
||
|
|
||
|
def loadFurniture(self):
|
||
|
for item in CatalogItemList(self.house.getInteriorItems(),
|
||
|
store=CatalogItem.Customization | CatalogItem.Location):
|
||
|
self.generateItem(item)
|
||
|
|
||
|
self.wallpaper = CatalogItemList(self.house.getInteriorWallpaper(), store=CatalogItem.Customization)
|
||
|
self.house.b_setInteriorWallpaper(self.house.getInteriorWallpaper())
|
||
|
self.interior.b_setWallpaper(self.house.getInteriorWallpaper())
|
||
|
self.windows = CatalogItemList(self.house.getInteriorWindows(),
|
||
|
store=CatalogItem.Customization | CatalogItem.WindowPlacement)
|
||
|
self.house.b_setInteriorWindows(self.house.getInteriorWindows())
|
||
|
self.interior.b_setWindows(self.house.getInteriorWindows())
|
||
|
self.b_setAtticItems(self.house.getAtticItems())
|
||
|
self.b_setAtticWallpaper(self.house.getAtticWallpaper())
|
||
|
self.b_setAtticWindows(self.house.getAtticWindows())
|
||
|
self.b_setDeletedItems(self.house.getDeletedItems())
|
||
|
|
||
|
def generateItem(self, item):
|
||
|
itemId = item.furnitureType
|
||
|
if itemId == 1399:
|
||
|
furnitureClass = DistributedPhoneAI
|
||
|
elif item.getFlags() & CatalogFurnitureItem.FLCloset:
|
||
|
furnitureClass = DistributedClosetAI
|
||
|
elif item.getFlags() & CatalogFurnitureItem.FLBank:
|
||
|
furnitureClass = DistributedBankAI
|
||
|
elif item.getFlags() & CatalogFurnitureItem.FLTrunk:
|
||
|
furnitureClass = DistributedTrunkAI
|
||
|
else:
|
||
|
furnitureClass = DistributedFurnitureItemAI
|
||
|
|
||
|
obj = furnitureClass(self.air, self.house, self, item)
|
||
|
obj.generateWithRequired(self.interior.zoneId)
|
||
|
self.items.append(obj)
|
||
|
return obj
|
||
|
|
||
|
def saveFurniture(self):
|
||
|
self.house.b_setInteriorItems(self.getNewItems())
|
||
|
self.house.b_setInteriorWallpaper(self.wallpaper.getBlob())
|
||
|
self.house.b_setInteriorWindows(self.windows.getBlob())
|
||
|
self.interior.b_setWindows(self.windows.getBlob())
|
||
|
self.interior.b_setWallpaper(self.wallpaper.getBlob())
|
||
|
self.house.b_setAtticItems(self.getAtticItems())
|
||
|
self.b_setAtticItems(self.getAtticItems())
|
||
|
self.house.b_setAtticWallpaper(self.getAtticWallpaper())
|
||
|
self.b_setAtticWallpaper(self.getAtticWallpaper())
|
||
|
self.house.b_setAtticWindows(self.getAtticWindows())
|
||
|
self.b_setAtticWindows(self.getAtticWindows())
|
||
|
self.house.b_setDeletedItems(self.getDeletedItems())
|
||
|
self.b_setDeletedItems(self.getDeletedItems())
|
||
|
|
||
|
def getNewItems(self):
|
||
|
items = CatalogItemList(store=CatalogItem.Customization | CatalogItem.Location)
|
||
|
for item in self.items:
|
||
|
items.append(item.catalogItem)
|
||
|
|
||
|
return items.getBlob()
|
||
|
|
||
|
def _verifyOwner(self, avId, message, context):
|
||
|
if self.house.avatarId != avId:
|
||
|
self.air.writeServerEvent('suspicious', avId,
|
||
|
'av tried to send perform furniture management operation %s while not owner!' % message)
|
||
|
self.sendUpdateToAvatarId(avId, message + 'Response', [ToontownGlobals.FM_NotOwner, context])
|
||
|
return False
|
||
|
elif self.director != avId:
|
||
|
self.sendUpdateToAvatarId(avId, message + 'Response', [ToontownGlobals.FM_NotDirector, context])
|
||
|
return False
|
||
|
|
||
|
return True
|
||
|
|
||
|
def _deleteItem(self, item):
|
||
|
self.deletedItems.append(item)
|
||
|
if len(self.deletedItems) > ToontownGlobals.ExtraDeletedItems:
|
||
|
del self.deletedItems[0]
|
||
|
|
||
|
self.b_setDeletedItems(self.getDeletedItems())
|
||
|
self.addDeletedItemBlob(item.getBlob().encode('base64'))
|
||
|
|
||
|
def getNumItems(self):
|
||
|
numItems = len(self.house.interiorItems) + len(self.house.atticItems) + len(self.house.atticWallpaper) + len(
|
||
|
self.house.atticWindows) + len(self.house.interiorWallpaper) + len(self.house.interiorWindows)
|
||
|
return numItems
|
||
|
|
||
|
def getDeletedItemsFilename(self):
|
||
|
return '%s%s%s%s.json' % (self.serverDataFolder, 'houses/', 'deletedItems_', self.house.getDoId())
|
||
|
|
||
|
def loadDeletedItems(self):
|
||
|
try:
|
||
|
deletedItemsFile = open(self.deletedItemsFilename, 'r')
|
||
|
deletedItemsData = json.load(deletedItemsFile)
|
||
|
return deletedItemsData
|
||
|
except:
|
||
|
return {}
|
||
|
|
||
|
def updateDeletedItemsFile(self):
|
||
|
try:
|
||
|
if not os.path.exists(os.path.dirname(self.deletedItemsFilename)):
|
||
|
os.makedirs(os.path.dirname(self.deletedItemsFilename))
|
||
|
|
||
|
deletedItemsFile = open(self.deletedItemsFilename, 'w')
|
||
|
deletedItemsFile.seek(0)
|
||
|
json.dump(self.day2deletedItems, deletedItemsFile)
|
||
|
deletedItemsFile.close()
|
||
|
except:
|
||
|
pass
|
||
|
|
||
|
def addDeletedItemBlob(self, deletedItemBlob, dayId=None):
|
||
|
if dayId is None:
|
||
|
dayId = getDayId()
|
||
|
|
||
|
dayId = str(dayId)
|
||
|
if dayId not in self.day2deletedItems.keys():
|
||
|
self.day2deletedItems[dayId] = []
|
||
|
|
||
|
self.day2deletedItems[dayId].append(deletedItemBlob)
|
||
|
self.updateDeletedItemsFile()
|
||
|
|
||
|
def removeDeletedItemBlob(self, deletedItemBlob, dayId=None):
|
||
|
if not self.day2deletedItems.keys():
|
||
|
return
|
||
|
|
||
|
if dayId is None:
|
||
|
dayId = getDayId()
|
||
|
|
||
|
dayId = str(dayId)
|
||
|
if dayId not in self.day2deletedItems.keys():
|
||
|
dayId = min(self.day2deletedItems.keys())
|
||
|
elif not self.day2deletedItems[dayId]:
|
||
|
del self.day2deletedItems[dayId]
|
||
|
dayId = min(self.day2deletedItems.keys())
|
||
|
|
||
|
dayId = str(dayId)
|
||
|
if dayId in self.day2deletedItems.keys() and deletedItemBlob in self.day2deletedItems[dayId]:
|
||
|
self.day2deletedItems[dayId].remove(deletedItemBlob)
|
||
|
|
||
|
if not self.day2deletedItems[dayId]:
|
||
|
del self.day2deletedItems[dayId]
|
||
|
|
||
|
self.updateDeletedItemsFile()
|
||
|
|
||
|
def __deletedItemsTask(self, task):
|
||
|
changesMade = False
|
||
|
dayId = getDayId()
|
||
|
for deletedItemDay, deletedItemBlobs in self.day2deletedItems.items():
|
||
|
if not deletedItemBlobs or type(deletedItemBlobs) != list:
|
||
|
del self.day2deletedItems[deletedItemDay]
|
||
|
changesMade = True
|
||
|
continue
|
||
|
|
||
|
try:
|
||
|
deletedItemDayId = int(deletedItemDay)
|
||
|
except:
|
||
|
del self.day2deletedItems[deletedItemDay]
|
||
|
changesMade = True
|
||
|
continue
|
||
|
|
||
|
if deletedItemDayId + int(ToontownGlobals.DeletedItemLifetime / 60 / 24) <= dayId:
|
||
|
for deletedItemBlob in deletedItemBlobs[:]:
|
||
|
try:
|
||
|
deletedItem = CatalogItem.getItem(deletedItemBlob.decode('base64'))
|
||
|
except:
|
||
|
self.day2deletedItems[deletedItemDay].remove(deletedItemBlob)
|
||
|
if not self.day2deletedItems[deletedItemDay]:
|
||
|
del self.day2deletedItems[deletedItemDay]
|
||
|
|
||
|
changesMade = True
|
||
|
continue
|
||
|
|
||
|
if isinstance(deletedItem, CatalogInvalidItem.CatalogInvalidItem):
|
||
|
self.day2deletedItems[deletedItemDay].remove(deletedItemBlob)
|
||
|
if not self.day2deletedItems[deletedItemDay]:
|
||
|
del self.day2deletedItems[deletedItemDay]
|
||
|
|
||
|
changesMade = True
|
||
|
continue
|
||
|
|
||
|
if deletedItem not in self.deletedItems:
|
||
|
self.day2deletedItems[deletedItemDay].remove(deletedItemBlob)
|
||
|
if not self.day2deletedItems[deletedItemDay]:
|
||
|
del self.day2deletedItems[deletedItemDay]
|
||
|
|
||
|
changesMade = True
|
||
|
continue
|
||
|
|
||
|
index = self.deletedItems.index(deletedItem)
|
||
|
del self.deletedItems[index]
|
||
|
self.b_setDeletedItems(self.getDeletedItems())
|
||
|
self.day2deletedItems[deletedItemDay].remove(deletedItemBlob)
|
||
|
if not self.day2deletedItems[deletedItemDay]:
|
||
|
del self.day2deletedItems[deletedItemDay]
|
||
|
|
||
|
changesMade = True
|
||
|
|
||
|
if changesMade:
|
||
|
self.updateDeletedItemsFile()
|
||
|
|
||
|
# We want this task to run again at midnight. We'll calculate the seconds until midnight, then
|
||
|
# delay the task from running again until then.
|
||
|
tomorrow = self.air.toontownTimeManager.getCurServerDateTime().now(
|
||
|
tz=self.air.toontownTimeManager.serverTimeZone) + datetime.timedelta(1)
|
||
|
midnight = datetime.datetime(year=tomorrow.year, month=tomorrow.month, day=tomorrow.day, hour=0, minute=0,
|
||
|
second=0, tzinfo=self.air.toontownTimeManager.serverTimeZone)
|
||
|
secondsUntilMidnight = (midnight - self.air.toontownTimeManager.getCurServerDateTime().now(
|
||
|
tz=self.air.toontownTimeManager.serverTimeZone)).seconds
|
||
|
task.delayTime = secondsUntilMidnight
|
||
|
return task.again
|