2022-12-16 18:40:57 -06:00
|
|
|
from panda3d.core import *
|
2019-12-30 00:07:56 -06:00
|
|
|
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:
|
2019-12-30 00:07:56 -06:00
|
|
|
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))
|
2019-12-30 00:07:56 -06:00
|
|
|
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
|
2019-12-30 00:07:56 -06:00
|
|
|
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 = {}
|
2019-12-30 00:07:56 -06:00
|
|
|
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))
|
2019-12-30 00:07:56 -06:00
|
|
|
for field in list(values.keys()):
|
2019-11-02 17:27:54 -05:00
|
|
|
dg.addString(field)
|
|
|
|
|
2019-12-30 00:07:56 -06:00
|
|
|
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)
|
2019-12-30 00:07:56 -06:00
|
|
|
dg.addUint32(3735928559)
|
2019-11-02 17:27:54 -05:00
|
|
|
self.air.send(dg)
|