Protecting art assets in distributed game?

Hello, I’ve been researching cheap/free engines to use in creating a simple childrens game. I noticed Panda3D mentioned a couple of places (including a job description on gamejobs.com)… so I came, and I read, and I searched.

I see a lot on packing the game for distribution, but (so far) nothing on art asset hiding. I’m not too concerned about someone reverse-engineering the pseudocompiled Python script, but I’d like to try to protect my art assets.

Is there a Web page, FAQ, Wiki page, etc. that can get me some info on this? Or is that functionality missing right now?

All help appreciated.

Panda has a way to pack a whole bunch of art assets into a single big file called a “multifile.” Once you have a multifile, you make a panda call telling it to “mount” the multifile — which means that panda pretends the multifile is a directory. From that point forward, you can load art assets from out of the multifile just by giving the right filename.

Multifiles can be encrypted using a password. In that case, to mount the multifile, you have to give the same password.

Another thing you can do is distribute the art assets in panda’s BAM format. That’s a format which is only compatible with a particular version of panda — ie, a BAM created by panda 1.4.0 can only be used by panda 1.4.0. So even if they did manage to extract your BAM files from your multifile, they’d have an art asset format that can’t be converted to anything else (because there aren’t currently any converters), and which can’t even be used with future versions of panda.

Of course, none of this prevents them from extracting your assets — it just makes it harder. If they have the time to track down that multifile password and write a file format converter, then you’re out of luck.

That’s plenty fine, there’s no way to 100% protect things, I just want to make it difficult for the casual/less-educated amateur to easily break the assets out and claim them as theirs.

Thanks for the response!

I edited my post, see expanded version above.

Is there anyway to hide .pyc files in the same way?

Hide PYC files? I don’t know, for that, I think you need a python expert. I’m sure it’s possible, but I don’t know how.

I do think people worry too much about stuff like this. Professional developers don’t steal code — it’s too risky, the lawsuit could ruin your entire company. Noobs might steal code, but they’re not skilled enough to do anything with it.

Python can import modules directly from a zip file. You only need to add the zip file to the search path :

import sys
sys.path.insert(0, 'yourZipFileName')

The embarrasing thing is, Python can’t import an encrypted zipfile. :angry:

To hide your main script, you can use PyRex to embed Python interpreter :
discourse.panda3d.org/viewtopic.php?t=2643
I never try it though.

oh, just found this :
discourse.panda3d.org/viewtopic.php?t=1919

so I have this package structure :

pyMods
…tri.pyc

mod1
…tri2.pyc

in the main script :

### loadPY imports .py file from multifile
def loadPY(path):
    scriptString = prepPY( VFS.readFile(Filename(path),1) )
    print scriptString
    return scriptString

def prepPY(s):
    '''
    Python is UNIX-based, so it's code parser
    only wants LF for the End-of-Line delimiter
    '''
    # for Windows style, which uses CR+LF, remove the CR
    s=s.replace(chr(13)+chr(10),chr(10))
    # for Mac style, which uses CR only, replace it with LF
    s=s.replace(chr(13),chr(10))
    return s


import marshal
### loadPYbyte imports .pyc or .pyo file from multifile
def loadPYbyte(path):
    # read module file
    marshal_data= VFS.readFile(Filename(path),1)[8:]
    # unmarshal the data
    return marshal.loads(marshal_data)

__builtins__.loadPYbyte=loadPYbyte
__builtins__.prepPY=prepPY
__builtins__.loadPY=loadPY
__builtins__.VFS = VirtualFileSystem.getGlobalPtr()
VFS.mount(Filename('myMultifileName'), '', VirtualFileSystem.MFReadOnly, 'myComplicatedPassword')

# similar to : "from pyMods.tri import *"
exec(loadPYbyte('pyMods/tri.pyc'))

in tri.py :

# similar to : "from pyMods.mod1.tri2 import *"
exec(loadPYbyte('pyMods/mod1/tri2.pyc'))

It works both for the byte-compiled and the source file.

The next question is how to import a dynamic lib ?

Hi, not a response to your question, just a quick “Thank You” to all that responded. I’m going to give Panda3D a try and see if I can Make It Happen! :smiley: