Posts | Tags | Archive

Fixing save file corruption in Ridiculous Fishing

Ridiculous Fishing is a game by Vlambeer about fishing. That's if you can call chainsawing fish and blowing them out of the sky with a bazooka "fishing".

I've been playing this game on and off for a while now, but just recently I had a problem where my save file somehow got corrupted, making the app refuse to open.

The problem first manifested as the game freezing for up to 5 seconds when navigating around the UI or buying items in the in-game store. Since I was running the game on a Nexus 5 (not the latest and greatest, but pretty close), it seemed weird. The delay got longer and longer until the game eventually crashed and refused to reopen.

Since I was pretty far into the game (I only needed to catch one more species of fish!), I opted to try to fix it instead of just wiping the app's data and starting again. I initially tried clearing the app's cache and reinstalling the app, but the problem persisted.

The next step was to dump the games's data to my computer so I could do some analysis on it. Some exploration on the device revealed that the settings and data were stored in the folder /data/data/com.vlambeer.RidiculousFishing.humble (I have the Humble Bundle version of the app).

To pull that folder to my current directory, I used ADB:

1
2
adb root #Restart adbd on the device with root permissions
adb pull /data/data/com.vlambeer.RidiculousFishing.humble/

A quick du -h revealed that something was very wrong in the files/Library/Preferences/com.vlambeer.RidiculousFishing.humble.plist file. It should've been just a text document, but was well over 200MB.

After trying out of habit to open the file in Vim and having it hang (oops), I paged through the document with less. About halfway through the file, there was a line containing &amp;lt;message&amp;gt;@eggbirdTBA Take it to the Smartypants Bar (no, that's not a formatting error, in the plist there's XML data stored in a <string> element, requiring the < and > characters to be escaped) followed by about 200MB of garbage.

Apparently there are ways to load huge files in Vim, as well as other text editors that handle them nicely, but since I already knew what line was causing the issue, a simple sed command would do the trick.

1
sed '/Take it to the Smartypants Bar/d' com.vlambeer.RidiculousFishing.humble.plist > temp.plist

Total size of temp.plist: 107.11KB. Much better.

After going though and deleting some lines around the one that was removed (to make the XML valid again), I pushed the file back to the device:

1
adb push temp.plist /data/data/com.vlambeer.RidiculousFishing.humble/files/Library/Preferences/com.vlambeer.RidiculousFishing.humble.plist

Success! The game opened properly, all the freezing issues were gone, and my save data was still there.

Now to find that stupid Mimic Fish...


Reinstalling an Android app without losing data

When an application isn't opening (and clearing the cache doesn't help) it sometimes helps to reinstall it. However, uninstalling then reinstalling the app normally will delete all the data associated with it.

The way around this is to directly call the package manager from the shell and give it the -k argument, which tells it to keep the data and cache directories.

Simply connect the device to a computer with ADB installed and run:

1
adb -d shell "pm uninstall -k com.package.name"

Then just reinstall the app (either from an apk file or the Play Store) and the app will be back with all of its data intact.


Git checkout - autocomplete local branches only

Having Git autocomplete branch names when doing a checkout is super useful. Having the autocomplete hang for 30 seconds because it has to look up all 3000 of the remote branches in a massive repo is not so useful. It's actually pretty frustrating.

My solution: changing the git checkout autocomplete to only look at local branches, while using a git checkoutr alias to preserve the original behaviour (because sometimes it's actually needed).

How it's done:

Define an alias for checkout

We're going to use the same checkout command for the remote checkout, but need to have a different command so the script can differentiate between them. Making an alias does exactly this.

Create the alias by running git config --global alias.checkoutr checkout

Change the autocompletion function

The checkout autocomplete behaviour is defined in a function called _git_checkout in the git autocompletion file. We're going to override the function with our own version that has different autocomplete logic in it.

The location of the file varies over different operating systems and configurations, but here are a few spots to look:

  • /etc/bash_completion.d/git
  • /usr/share/bash-completion/completions/git

For a brew-installed git autocomplete on macOS, the file will probably be $(brew --prefix)/etc/bash_completion.d/git-completion.bash

Once you've found the file, copy the entire _git_checkout function into your .bashrc (or equivalent non-login shell startup script). Now look for the line

__git_complete_refs $track_opt

We're going to replace that line with:

1
2
3
4
5
if [ "$command" = "checkoutr" ]; then
    __git_complete_refs $track_opt
else
    __gitcomp_direct "$(__git_heads "" "$cur" " ")"
fi

After saving and re-sourcing your .bashrc file, git will autocomplete local branches and tags when using git checkout, but will go back to the default behaviour of autocompleting all references when using git checkoutr.

Credits to a combination of answers on this StackOverflow post.

EDIT 2017-10-02: Updated to work with git v2.13.0 thanks to Alexander Ko's comment.
EDIT 2018-03-24: Updated to speed up branch and tag completion.

© Carey Metcalfe. Built using Pelican. Theme is subtle by Carey Metcalfe. Based on svbhack by Giulio Fidente.