oldschool-toontown/toontown/ai/DatabaseObject.py

214 lines
6.9 KiB
Python
Raw Normal View History

from panda3d.core import *
from .ToontownAIMsgTypes import *
2019-11-02 17:27:54 -05:00
from direct.directnotify.DirectNotifyGlobal import *
from toontown.toon import DistributedToonAI
from direct.distributed.PyDatagram import PyDatagram
from direct.distributed.PyDatagramIterator import PyDatagramIterator
import types
class DatabaseObject:
notify = directNotify.newCategory('DatabaseObject')
notify.setInfo(0)
def __init__(self, air, doId = None, doneEvent = 'DatabaseObject'):
self.air = air
self.doId = doId
self.values = {}
self.gotDataHandler = None
self.doneEvent = doneEvent
return
def readToon(self, fields = None):
toon = DistributedToonAI.DistributedToonAI(self.air)
self.readObject(toon, fields)
return toon
if simbase.wantPets:
def readPet(self):
from toontown.pets import DistributedPetAI
pet = DistributedPetAI.DistributedPetAI(self.air)
self.readObject(pet, None)
return pet
def readPetProxy(self):
from toontown.pets import DistributedPetProxyAI
petProxy = DistributedPetProxyAI.DistributedPetProxyAI(self.air)
self.readObject(petProxy, None)
return petProxy
def readObject(self, do, fields = None):
self.do = do
className = do.__class__.__name__
self.dclass = self.air.dclassesByName[className]
self.gotDataHandler = self.fillin
if fields != None:
self.getFields(fields)
else:
self.getFields(self.getDatabaseFields(self.dclass))
return
def storeObject(self, do, fields = None):
self.do = do
className = do.__class__.__name__
self.dclass = self.air.dclassesByName[className]
if fields != None:
self.reload(self.do, self.dclass, fields)
else:
dbFields = self.getDatabaseFields(self.dclass)
self.reload(self.do, self.dclass, dbFields)
values = self.values
if fields != None:
values = {}
for field in fields:
if field in self.values:
2019-11-02 17:27:54 -05:00
values[field] = self.values[field]
else:
self.notify.warning('Field %s not defined.' % field)
self.setFields(values)
return
def getFields(self, fields):
context = self.air.dbObjContext
self.air.dbObjContext += 1
self.air.dbObjMap[context] = self
dg = PyDatagram()
dg.addServerHeader(DBSERVER_ID, self.air.ourChannel, DBSERVER_GET_STORED_VALUES)
dg.addUint32(context)
dg.addUint32(self.doId)
dg.addUint16(len(fields))
for f in fields:
dg.addString(f)
self.air.send(dg)
def getFieldsResponse(self, di):
objId = di.getUint32()
if objId != self.doId:
self.notify.warning('Unexpected doId %d' % objId)
return
count = di.getUint16()
fields = []
for i in range(count):
name = di.getString()
fields.append(name)
retCode = di.getUint8()
if retCode != 0:
self.notify.warning('Failed to retrieve data for object %d' % self.doId)
else:
values = []
for i in range(count):
value = di.getString()
values.append(value)
for i in range(count):
found = di.getUint8()
if not found:
self.notify.info('field %s is not found' % fields[i])
try:
del self.values[fields[i]]
except:
pass
else:
self.values[fields[i]] = PyDatagram(values[i])
self.notify.info('got data for %d' % self.doId)
if self.gotDataHandler != None:
self.gotDataHandler(self.do, self.dclass)
self.gotDataHandler = None
if self.doneEvent != None:
messenger.send(self.doneEvent, [self, retCode])
return
def setFields(self, values):
dg = PyDatagram()
dg.addServerHeader(DBSERVER_ID, self.air.ourChannel, DBSERVER_SET_STORED_VALUES)
dg.addUint32(self.doId)
dg.addUint16(len(values))
items = list(values.items())
2019-11-02 17:27:54 -05:00
for field, value in items:
dg.addString(field)
for field, value in items:
dg.addString(value.getMessage())
self.air.send(dg)
def getDatabaseFields(self, dclass):
fields = []
for i in range(dclass.getNumInheritedFields()):
dcf = dclass.getInheritedField(i)
af = dcf.asAtomicField()
if af:
if af.isDb():
fields.append(af.getName())
return fields
def fillin(self, do, dclass):
do.doId = self.doId
for field, value in list(self.values.items()):
2019-11-02 17:27:54 -05:00
if field == 'setZonesVisited' and value.getLength() == 1:
self.notify.warning('Ignoring broken setZonesVisited')
else:
dclass.directUpdate(do, field, value)
def reload(self, do, dclass, fields):
self.doId = do.doId
self.values = {}
for fieldName in fields:
field = dclass.getFieldByName(fieldName)
if field == None:
self.notify.warning('No definition for %s' % fieldName)
else:
dg = PyDatagram()
packOk = dclass.packRequiredField(dg, do, field)
self.values[fieldName] = dg
return
def createObject(self, objectType):
values = {}
for key, value in list(values.items()):
2019-11-02 17:27:54 -05:00
values[key] = PyDatagram(str(value))
context = self.air.dbObjContext
self.air.dbObjContext += 1
self.air.dbObjMap[context] = self
self.createObjType = objectType
dg = PyDatagram()
dg.addServerHeader(DBSERVER_ID, self.air.ourChannel, DBSERVER_CREATE_STORED_OBJECT)
dg.addUint32(context)
dg.addString('')
dg.addUint16(objectType)
dg.addUint16(len(values))
for field in list(values.keys()):
2019-11-02 17:27:54 -05:00
dg.addString(field)
for value in list(values.values()):
2019-11-02 17:27:54 -05:00
dg.addString(value.getMessage())
self.air.send(dg)
def handleCreateObjectResponse(self, di):
retCode = di.getUint8()
if retCode != 0:
self.notify.warning('Database object %s create failed' % self.createObjType)
else:
del self.createObjType
self.doId = di.getUint32()
if self.doneEvent != None:
messenger.send(self.doneEvent, [self, retCode])
return
def deleteObject(self):
self.notify.warning('deleting object %s' % self.doId)
dg = PyDatagram()
dg.addServerHeader(DBSERVER_ID, self.air.ourChannel, DBSERVER_DELETE_STORED_OBJECT)
dg.addUint32(self.doId)
dg.addUint32(3735928559)
2019-11-02 17:27:54 -05:00
self.air.send(dg)