mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
levelAI only sends spec if hash is different, spec is saved by AI
This commit is contained in:
parent
d3e6bb5041
commit
c27e85f890
@ -98,24 +98,37 @@ class DistributedLevel(DistributedObject.DistributedObject,
|
||||
# announceGenerate(). Note that we have to call
|
||||
# gotAllRequired() in the last 'faux-required' DC update
|
||||
# handler. If you add another field, move this to the last one.
|
||||
self.privGotAllRequired()
|
||||
|
||||
def privGotAllRequired(self):
|
||||
self.levelAnnounceGenerate()
|
||||
def levelAnnounceGenerate(self):
|
||||
pass
|
||||
|
||||
def initializeLevel(self, levelSpec):
|
||||
"""subclass should call this as soon as it's located its level spec.
|
||||
Must be called after obj has been generated."""
|
||||
if __debug__:
|
||||
# if we're in debug, ask the server if it wants to send us
|
||||
# if we're in debug, give the server the opportunity to send us
|
||||
# a full spec
|
||||
self.sendUpdate('requestCurrentLevelSpec', [])
|
||||
self.candidateSpec = levelSpec
|
||||
self.sendUpdate('requestCurrentLevelSpec', [hash(levelSpec)])
|
||||
else:
|
||||
self.gotAllRequired()
|
||||
self.privGotSpec(levelSpec)
|
||||
|
||||
if __debug__:
|
||||
def setSpecSenderDoId(self, doId):
|
||||
DistributedLevel.notify.debug(
|
||||
'setSpecSenderDoId: %s' % doId)
|
||||
DistributedLevel.notify.debug('setSpecSenderDoId: %s' % doId)
|
||||
blobSender = toonbase.tcr.doId2do[doId]
|
||||
|
||||
def setSpecBlob(specBlob, blobSender=blobSender, self=self):
|
||||
blobSender.sendAck()
|
||||
from LevelSpec import LevelSpec
|
||||
self.curSpec = eval(specBlob)
|
||||
self.gotAllRequired()
|
||||
spec = eval(specBlob)
|
||||
if spec is None:
|
||||
spec = self.candidateSpec
|
||||
del self.candidateSpec
|
||||
self.privGotSpec(spec)
|
||||
|
||||
if blobSender.isComplete():
|
||||
setSpecBlob(blobSender.getBlob())
|
||||
@ -124,17 +137,7 @@ class DistributedLevel(DistributedObject.DistributedObject,
|
||||
blobSender.setDoneEvent(evtName)
|
||||
self.acceptOnce(evtName, setSpecBlob)
|
||||
|
||||
def gotAllRequired(self):
|
||||
self.levelAnnounceGenerate()
|
||||
def levelAnnounceGenerate(self):
|
||||
pass
|
||||
|
||||
def initializeLevel(self, levelSpec):
|
||||
"""subclass should call this as soon as it's located its level spec.
|
||||
Must be called after obj has been generated."""
|
||||
# if the AI sent us a full spec, use it instead
|
||||
if self.curSpec is not None:
|
||||
levelSpec = self.curSpec
|
||||
def privGotSpec(self, levelSpec):
|
||||
Level.Level.initializeLevel(self, self.doId, levelSpec,
|
||||
self.scenarioIndex)
|
||||
|
||||
|
@ -18,7 +18,7 @@ class DistributedLevelAI(DistributedObjectAI.DistributedObjectAI,
|
||||
Level.Level.__init__(self)
|
||||
# this is one of the required fields
|
||||
self.zoneId = zoneId
|
||||
self.hasBeenEdited = 0
|
||||
self.modified = 0
|
||||
|
||||
def generate(self, levelSpec):
|
||||
self.notify.debug('generate')
|
||||
@ -38,6 +38,8 @@ class DistributedLevelAI(DistributedObjectAI.DistributedObjectAI,
|
||||
|
||||
def delete(self):
|
||||
self.notify.debug('delete')
|
||||
if __debug__:
|
||||
self.saveSpec()
|
||||
self.destroyLevel()
|
||||
DistributedObjectAI.DistributedObjectAI.delete(self)
|
||||
|
||||
@ -91,10 +93,32 @@ class DistributedLevelAI(DistributedObjectAI.DistributedObjectAI,
|
||||
# send a copy to the client-side level obj
|
||||
self.sendUpdate('setAttribChange',
|
||||
[entId, attribName, valueStr])
|
||||
self.hasBeenEdited = 1
|
||||
|
||||
def requestCurrentLevelSpec(self):
|
||||
self.modified = 1
|
||||
self.scheduleSave()
|
||||
|
||||
SavePeriod = simbase.config.GetFloat('factory-save-period', 10)
|
||||
|
||||
def scheduleSave(self):
|
||||
if hasattr(self, 'saveTask'):
|
||||
return
|
||||
self.saveTask = taskMgr.doMethodLater(
|
||||
DistributedLevelAI.SavePeriod,
|
||||
self.saveSpec,
|
||||
self.uniqueName('saveSpec'))
|
||||
|
||||
def saveSpec(self, task=None):
|
||||
DistributedLevelAI.notify.info('saving spec')
|
||||
if hasattr(self, 'saveTask'):
|
||||
del self.saveTask
|
||||
if self.modified:
|
||||
self.levelSpec.saveToDisk()
|
||||
self.modified = 0
|
||||
|
||||
def requestCurrentLevelSpec(self, specHash):
|
||||
senderId = self.air.msgSender
|
||||
spec = None
|
||||
if hash(self.levelSpec) != specHash:
|
||||
spec = self.levelSpec
|
||||
specStr = repr(spec)
|
||||
|
||||
|
@ -10,8 +10,9 @@ class LevelSpec:
|
||||
saving out modified spec data"""
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory("LevelSpec")
|
||||
|
||||
def __init__(self, specDict, scenario=0, entTypeReg=None):
|
||||
def __init__(self, specDict, scenario=0, filename=None, entTypeReg=None):
|
||||
self.specDict = specDict
|
||||
self.filename = filename
|
||||
self.entTypeReg = entTypeReg
|
||||
|
||||
# this maps an entId to the dict that holds its spec;
|
||||
@ -141,6 +142,50 @@ class LevelSpec:
|
||||
# name of module that should be imported by spec py file
|
||||
return 'SpecImports'
|
||||
|
||||
def saveToDisk(self, filename=None):
|
||||
"""returns zero on failure"""
|
||||
import os
|
||||
|
||||
if filename is None:
|
||||
filename = self.filename
|
||||
|
||||
# create a backup
|
||||
try:
|
||||
# does the file exist?
|
||||
exists = 0
|
||||
try:
|
||||
os.stat(filename)
|
||||
exists = 1
|
||||
except OSError:
|
||||
pass
|
||||
if exists:
|
||||
def getBackupFilename(num, filename=filename):
|
||||
return '%s.%03i' % (filename, num)
|
||||
numBackups = 50
|
||||
try:
|
||||
os.unlink(getBackupFilename(numBackups-1))
|
||||
except OSError:
|
||||
pass
|
||||
for i in range(numBackups-1,0,-1):
|
||||
try:
|
||||
os.rename(getBackupFilename(i-1),
|
||||
getBackupFilename(i))
|
||||
except OSError:
|
||||
pass
|
||||
os.rename(filename, getBackupFilename(0))
|
||||
except OSError, e:
|
||||
LevelSpec.notify.warning('error during backup: %s' % str(e))
|
||||
|
||||
retval = 1
|
||||
# wb to create a UNIX-format file
|
||||
f = file(filename, 'wb')
|
||||
try:
|
||||
f.write(self.getPrettyString())
|
||||
except IOError:
|
||||
retval = 0
|
||||
f.close()
|
||||
return retval
|
||||
|
||||
def getPrettyString(self):
|
||||
"""Returns a string that contains the spec data, nicely formatted.
|
||||
This should be used when writing the spec out to file."""
|
||||
@ -256,6 +301,9 @@ class LevelSpec:
|
||||
(levelSpec, self.specDict)
|
||||
)
|
||||
|
||||
def __hash__(self):
|
||||
return hash(repr(self))
|
||||
|
||||
def __repr__(self):
|
||||
return 'LevelSpec(%s, scenario=%s)' % (repr(self.specDict),
|
||||
self.scenario)
|
||||
|
Loading…
x
Reference in New Issue
Block a user