Merge Directory

Like the override directory, files inside the merge directory are relative to the World of Goo installation directory. However that's where the similarity ends. Files in the merge directory are not replaced, they are merged with the 2dboy originals (and possibly also merged with the results of lower-priority mods). Consequently the merge directory only operates on XML files.

The format of files in this directory are XSLT stylesheets, enabling full control of the produced XML. For each file that you want to merge, GooTool decrypts the 2dboy original, merges in your changes, and encrypts it back. (It also makes a backup of the original; it always merges from the 2dboy original and doesn't do incremental merging as that would have unexpected results when enabling and disabling addins).

The filenames end with the .xsl extension instead of .bin. An example of a full filename relative to your goomod root would be merge/res/levels/GoingUp/GoingUp.level.xsl. Note that the .bin suffix is replaced with .xsl.

Some knowledge of XSLT and XPath will help create complex merging rules, but the rest of this page contains some examples. You may also find davidc's XML Diff tool helpful - you give it the original XML file and your modified XML file, and it gives you back an XSL file that will make the changes.

Default rule

You need a default rule to copy across anything not matched by any other rules. Here it is:

  <!-- Copy everything not matched by another rule -->
  <xsl:template match="* | comment()">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

Modify existing elements

You can modify existing elements by selecting them with your XPath. Remember to copy @* to preserve the other attributes, and to apply-templates to copy their child elements. The follow example selects all BallInstance elements, copies their attributes, and then overrides their type attribute:

  <!-- Change existing balls to UglyProduct -->
  <xsl:template match="/level/BallInstance">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:attribute name="type">UglyProduct</xsl:attribute>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

Remember that the most specific rule matches, so here we select the balls where their id attribute is less than 4, and copy them unchanged. In this example, we're changing to UglyProduct balls, which don't have strands defined, so we don't want to touch the first 4 balls which are already connected.

  <!-- But we must leave the first 4 balls alone, since -->
  <!-- Ugly balls don't have strand definitions -->
  <xsl:template match="/level/BallInstance[@id < 4]">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

In this example we modify the visualdebug attribute of the level element to enable graphical display of the level scene structure.

  <xsl:template match="/level">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <!-- set visual debug. set attributes after copying them, so we can overwrite -->
      <xsl:attribute name="visualdebug">true</xsl:attribute>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

Deleting and inserting elements

Here we match all strand elements and delete them simply by not copying them at all.

  <!-- Delete existing strand instances -->
  <xsl:template match="/level/Strand"/>

If we wanted to add more Strands back in, we could select the "Arms" comment and add them there:

  <xsl:template match="/level/comment()[contains(., 'Arms')]">
    <xsl:copy/>
    <Strand .... insert our strands here >
  </xsl:template>

Or, because WoG doesn't validate against a DTD, we could just add them to the end of the level element. This is probably preferable in case comments are removed or changed by another addin or by 2dboy in a future release.

Note that the new stuff is inside the <xsl:copy> - if outside it would append after the level is already closed!

  <xsl:template match="/level">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
 
      <Strand .... insert our strands here >
 
    </xsl:copy>
  </xsl:template>

Full example

This example modifies the EconomicDivide (displayed name: Small Divide) level using the above examples. The first template copies everything that isn't matched by another template untouched. The second template removes all balls. The third inserts balls where the old balls were (after the Balls comment). The fourth deletes all strands. The fifth modifies the level element by enabling visualdebug, and adds new Strands to the end of the file (demonstrating the second method of adding elements).

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 
  <!-- Copy everything not matched by another rule -->
  <xsl:template match="* | comment()">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>
 
  <!-- Delete existing ball instances -->
  <xsl:template match="/level/BallInstance"/>
 
  <!-- insert drip balls into the place where the previous balls were -->
  <xsl:template match="/level/comment()[contains(., 'Balls')]">
    <xsl:copy/>
    <BallInstance type="water" x="-459.69" y="262.68" id="0" angle="0" />
    <BallInstance type="water" x="-341.64" y="279.34" id="1" angle="0" />
    <BallInstance type="water" x="-232.63" y="284.03" id="2" angle="0" />
    <BallInstance type="water" x="-122.63" y="284.03" id="3" angle="0" />
    <BallInstance type="water" x="-122.63" y="184.03" id="4" angle="0" />
 
    <BallInstance type="water" x="-329.74" y="411.84" id="5" angle="0" />
    <BallInstance type="water" x="-329.74" y="411.84" id="6" angle="0" />
    <BallInstance type="water" x="-329.74" y="411.84" id="7" angle="0" />
    <BallInstance type="water" x="-329.74" y="411.84" id="8" angle="0" />
    <BallInstance type="water" x="-329.74" y="411.84" id="9" angle="0" />
    <BallInstance type="water" x="-329.74" y="411.84" id="10" angle="0" />
  </xsl:template>
 
  <!-- Delete existing strand instances -->
  <xsl:template match="/level/Strand"/>
 
  <!-- Set visual debug and insert new Strands -->
  <xsl:template match="/level">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <!-- set visual debug. set attributes after copying them, so we can overwrite -->
      <xsl:attribute name="visualdebug">true</xsl:attribute>
      <xsl:apply-templates/>
 
      <!-- Here is where we can insert nodes at the end of the file -->
      <!-- As a demo, just insert the new strands at the end -->
 
      <Strand gb1="0" gb2="1" />
      <Strand gb1="1" gb2="2" />
      <Strand gb1="2" gb2="3" />
      <Strand gb1="3" gb2="4" />
 
    </xsl:copy>
  </xsl:template>
</xsl:transform>

Result

How the goo am I going to reach the exit now?

You can see a similar example in action in the merger-test addin.