Is it possible to export units from a module or saved game?

I have done some searching and I think the answer is probably no, but I’m curious if it’s possible to save a group of units that are in a vassal saved game file and export them to load into another game (using the same module)? Or could I possibly edit a module to include a group of forces (obviously not making the module available for public use)?

Thanks for any help,

Chris

From a saved game, no (they’re encrypted to prevent cheating, IIRC). Version 3.7, which has an initial beta available now (VASSAL 3.7.0-beta 1 released), will have the ability to export and import sections of a module as XML files, however.

With a bit of hackery it is possible to extract piece, prototype, etc. information from a module.

  • Open the vmod module with some ZIP utility

    • file-roller on GNOME GNU/Linux
    • WinZip on Windoze (and MacOuze?)
    • iZip on MacOuze
    • … and countless others
    • Some OSs think that the ending of a file name is what determines the format of the file - e.g., Windoze and to some extent MacOuze. On those systems, you may need to rename your module to end in .zip - E.g., rename (or copy) MyModule.vmod to MyModule.zip - note that Windoze will likely warning that this will make the file “unusable” - sigh.
      • What really matters is the data inside the file. ZIP files have some “magic” bytes in the beginning that identifies the data - namely PK. Sensible OSs will use that information (in addition to file endings) to discover what kind of data we’re dealing with.
  • In the ZIP file you will find the file buildFile.xml which contains all the definitions of pieces, prototypes, and so on. Use a plain text editor or some fancy XML editor to open this file.

    • Now find the piece prototype definitions that you’re interested in. For example

      <VASSAL.build.module.PrototypesContainer>
        <VASSAL.build.module.PrototypeDefinition name="infantry prototype" description="">+/null/mark;Type	piece;;;;/infantry	null;0;0;;0</VASSAL.build.module.PrototypeDefinition>
      

      for an infantry prototype, or

        <VASSAL.build.module.PieceWindow name="Counters" defaultWidth="0" hidden="false" hotkey="67,520" scale="1.0" text="" tooltip="Show/hide piece window" icon="unit-icon.png">
         <VASSAL.build.widget.TabWidget entryName="Counters">
           <VASSAL.build.widget.PanelWidget entryName="Soviet" fixed="false" nColumns="1" vert="false">
             <VASSAL.build.widget.ListWidget entryName="Soviet counters" height="0" width="300" scale="1.0" divider="150">
               <VASSAL.build.widget.PieceSlot entryName="soviet 1S" gpid="32" height="72" width="72" icon="">+/null/prototype;Soviet prototype	prototype;infantry prototype\	prototype;army prototype\\	prototype;land prototype\\\	emb2;;130;A;Flip;130;[;;130;];;;1;false;0;0;soviet_1S.png,soviet_1S_flipped.png;,Reduced +;true;Step;;;false;;1;1;true;65,130;70,130;;;1.0\\\\	report;70\,130;$location$: $newPieceName$ $menuCommand$ *;;;;true\\\\\	mark;left\\\\\\	mark;right\\\\\\\	mark;factors\\\\\\\\	calcProp;CF;{(Step_Level==2)?ReducedCF:FullCF};\\\\\\\\\	calcProp;DF;{(Step_Level==2)?ReducedDF:FullDF};\\\\\\\\\\	calcProp;MF;{(Step_Level==2)?ReducedMF:FullMF};\\\\\\\\\\\	mark;FullCF\\\\\\\\\\\\	mark;FullDF\\\\\\\\\\\\\	mark;FullMF\\\\\\\\\\\\\\	mark;ReducedCF\\\\\\\\\\\\\\\	mark;ReducedDF\\\\\\\\\\\\\\\\	mark;ReducedMF\\\\\\\\\\\\\\\\\	mark;RawCF\\\\\\\\\\\\\\\\\\	mark;RawMF\\\\\\\\\\\\\\\\\\\	piece;;;soviet_1S.png;soviet 1S/	\	\\	\\\	2\\\\	-1\\\\\	[shift=(0 .2)]soviet id \\\\\\	1S \\\\\\\	chit 2 factors=10 4 \\\\\\\\	\\\\\\\\\	\\\\\\\\\\	\\\\\\\\\\\	10\\\\\\\\\\\\	10\\\\\\\\\\\\\	4\\\\\\\\\\\\\\	5\\\\\\\\\\\\\\\	5\\\\\\\\\\\\\\\\	4\\\\\\\\\\\\\\\\\	10\\\\\\\\\\\\\\\\\\	4\\\\\\\\\\\\\\\\\\\	null;0;0;32;0</VASSAL.build.widget.PieceSlot>
      

      for a piece definition. The format of these are a bit tricky so I won’t go into them here.

    • Copy the lines you need to some other text file.

    • Note down any image used by the pieces or the like - e.g., the unit soviet 1S above uses the images

      • soviet_1S.png
      • soviet_1S_flipped.png
  • Now back in the ZIP file you will find the folder images. Open that folder

    • Find all the images that you noted down above and copy them to some other folder (outside the ZIP).
  • Now open your target module with a ZIP manager

  • Open the file buildFile.xml and copy’n’paste the definitions you previously copied into appropriate places in the target buildFile.xml (consult the source buildFile.xml for hints)

    • Note, the gpid numbers should all be unique, but I believe the VASSAL editor will fix that for you on the next load.
    • Make sure to save the target buildFile.xml and that it is written to the ZIP file (ZIP files are in principle either read-only or write-only)
  • Copy all the images you need into the sub directory images of the target ZIP file.

    • Make sure the images are written to the ZIP file.
  • Now close the target ZIP file (and possibly rename it back to end in .vmod).

  • Open your target vmod in the VASSAL editor and fix up things.

Alternatively, if you have a bit of Python experience, you can use my module pywargame. I won’t go into details, about it here, but a rough sketch would be

from pywargame import *

with VMod('source.vmod','r') as sourceVmod:
     sourceBuild = sourceVmod.getBuildFile()
     sourceGame = sourceBuild.getGame()

     targetVmod = VMod('target.vmod')
     targetBuild = BuildFile()
     targetGame =  targetBuild.addGame()
     targetGame.addBasicCommandEncoder()
     piecesWindow = targetGame.addPieceWindow(name   = 'Counters',hotkey = key('C',ALT))
     
     piecesToCopy = ["soviet 1S", ...]

     for pieceName in piecesToCopy:
           sourcePieces = sourceGame.getSpecificPieces(pieceName)
           if len(sourcePieces) <= 0: continue 

           piecesWindow.addPiece(sourcePieces[0])
           images = []
           for trait in sourcePieces[0].getTraits():
                if isinstance(trait,BasicTrait):
                   images.append(trait.get('filename',''))
                elif isinstance(trait,LayerTrait):
                   images.extend(trait.get('images',[]))

           images = ['images/'+i for i in images if i != '']
           sourceImages = sourceVmod.getFiles(images)
           for imgName, imgData in zip(images, sourceImages):
                targetVmod.addFile(imgName, imgData)
           

    targetVmod.addFiles(**{VMod.BUILD_FILE  :
                                     targetBuild.encode() })

Now, the above is of course only if you’re comfortable with Python programming.

Yours,

Christian

Thanks fellows, it seems even attempting this is beyond my capabilities, which I expected to be the case. I appreciate you answering in such detail.

Chris

You can also use notepad ++. Install the compare add in.
Do all that unzipping stuff.
Open the buildfile.xml of the module you want to copy from. Set this file as the one to compare against.
Open the buildfile.xml of the module you want to copy stuff into from the first.
Run compare.
Notepad++ will highlight all the differences.
Scroll down till you find the entries you want to copy across. Select whole lines and use copy, paste.

Be aware that this can set up a GPID conflict. Vassal handles that well enough, but the modules may not.

Save and rezip.

I find it easier to remember which is which by renaming the buildfile.xml to buildfile(modulename/version).xml. If you do that do not forget to remove the(modulesname/version) before rezipping.