ppackage - expiring time seems to have no effect


currently I provide a game using the package system of panda3d. For some reason the p3d does not redownload the packages if I upload an new version at the host (upload = overwrite old version).

Any idea would be helpful.

dl.dropbox.com/u/6841319/p3dcore.log link to a log.
dl.dropbox.com/u/6841319/main.pdef link to the def file.

Are you embedding the p3d file in a web page, or are you offering the p3d file for download and execution directly? The behavior is different in each case.

If you embed the p3d file in a web page, then the runtime will by default contact the server at each launch to see if there is a newer version available, and download the appropriate updates before launching. It does this because it is safe to assume that you have an internet connection and you don’t mind using it if you are running from a web page.

If the p3d file is run directly by the user, for instance by clicking on it or using the panda3d app, then the default is not to contact the server. The assumption is that the user might not have a valid internet connection and might not appreciate it being activated at each launch.

If you do want the p3d file to check for updates even if it is being run directly, you can run the panda3d executable with the -n option. Hmm, I’m not sure if there’s a way to change this behavior within the p3d file itself.


The second one is the case and this explains it. So I would have to tell the people to update the program manually by calling it from a terminal?

EDIT: is there a way to start an update during execution or would i have to add a update-button which simply calls the p3d itself with the -n argument?

Hi, I thought I may be able to help out here.

I’ve got an application similar to an MMORPG for example.

Players download and install the game, and then double click the icon, it checks for updates, and then runs.

What I decided to do, was build a very very small p3d that is only an updater. So, it opens the p3d window, and installs my packages for my application.

It would go a little like this:

double click p3d
-> It runs my ‘updater’ application
-> -> my ‘updater’ application installs my ‘game_main’ package
-> -> -> my ‘updater’ once finished, calls ‘import main’ for example
-> -> -> -> wahla, the game is running and updated

So I suggest to you: replace your applications p3d file with a very small p3d containing your ‘updater’ written in python, basically all it should do is display ‘updating’ on the screen, and use appRunner.installPackage() (more about this in the manual) to install your applications packages from your webserver.

After the packages are done downloading, make a simple import statement within your function ‘import main’ ‘import mygame’ etc.

It actually works out very nicely.

There is one little flaw, appRunner.installPackage() by default never looks for updates from the server either, basically it’s the same as double clicking your p3d locally, you’d have to run it with -n.

So that raises the question “Well what good is any of what you just said then?” well as it turns out there’s a simple fix for this. Assuming that your applications installs it’s core packages at runtime using appRunner.installPackage(), before any calls to installPackage, use this code:

if base.appRunner:
	base.appRunner.verifyContents = base.appRunner.P3DVCForce

This, as far as I am aware of, is the same as using -n on the command line.
This of course, will only work if your application installs it’s packages on it’s own, because otherwise the package would already be installed and setting base.appRunner.verifyContents would be very useless. Since there’s no installing of packages once you’re own code is running.

Here’s a base example (pseudo code - actually it does work, fill in the blanks with your packages etc though) of how you’d do this:

from direct.directbase import DirectStart

if base.appRunner:
	base.appRunner.verifyContents = base.appRunner.P3DVCForce

from direct.p3d.PackageInstaller import PackageInstaller

HOSTURL = 'http://www.mywebsite.com/path/to/my/packages/'
PANDA_VERSION = 'cmu_1.7' #- Mostly this is cmu_1.7, you can look inside the generated package directory you upload to check for this normally it'd be like mypackage/cmu_1.7/<bunch of other files here> the cmy_1.x string is what you want

('mypackage', PANDA_VERSION, HOSTURL),

class myUpdater(PackageInstaller):
	def __init__(self):
		PackageInstaller.__init__(self, base.appRunner)
		if base.appRunner:
			for package, version, hosturl in PACKAGES:
				self.addPackage(package, version, hosturl)

	def downloadStarted(self):
		print 'Download started'

	def packageStarted(self, package):
		self.progress['text'] = package.getFormattedName()
		self.log('Downloading %s : %s%%' % (package.getFormattedName(), int(package.downloadProgress)))
	#	print 'packageStarted', package.getFormattedName(), package.downloadProgress

	def packageProgress(self, package, progress):
		progress = int(progress * 100)
		if (self.lastValue == progress) == False:
			if str(progress).endswith('0'):
				self.log('Downloading %s : %s%%' % (package.getFormattedName(), progress))
		self.lastValue = progress
		self.progress['value'] = progress
	def downloadProgress(self, overallProgress):
		overallProgress = int(overallProgress * 100)
	 	print 'Overall progress: %s%%' % overallProgress

	def packageFinished(self, package, success):
		print 'Finished %s : %s%%' % (package.getFormattedName(), int(package.downloadProgress))

	def onExit(self):
		print 'Will now import main'
		import main

	def downloadFinished(self, success):
		if success:
			print 'Overall progress: finished.'
			print 'Overall progress: failure.'
			print 'Download failure, check internet connection and try again'

u = myUpdater()

Obviously you would want to show the user something while it’s updating, though. DO that with panda’s gui system.
And update your gui where I’ve put all the print statements, for example.

I hope this helps, you, it’s certainly worked well for me.

Thanks for your example but to be honoust it looks more like a workaround than a clean solution. Maybe there is a way to “tell” panda3d to get some flags from the p3d itself? I.E. it would be very helful if I could tell panda3d to generate the logfile by default.

I guess i found the log question ( “config(log_basename = ‘whateveryouwant’)” might be the solution).