Wishful Coding

Didn't you ever wish your
computer understood you?

CSS tips and tricks

While working on Sombrero, I encountered a lot of things I did not know how to do properly. I hope they help someone.

width: cling;

Block elements normally fill up all the available width, except when you apply position or float to them. I needed some element to take up the minimal width, without the side effects of floating or positioning. display: table; is the solution I was looking for.

Full-width form fields

Another problem in my magic alignment layout where full-width form fields. Input elements do not take space like normal block elements, no matter the display property.

width: 100%; works, but only as long as you have absolutely no borders, margin, or padding. To get around that, CSS 3 has a property to use the IE 5 box model, which includes padding and borders in the width: box-sizing: border-box;

Collapsing margins

I can’t imagine why I never noticed before, but it turns out CSS collapses margins on “regular” block elements. It’s complicated.

display: run-in;

I never used it, but it seems like an interesting property. It makes things like headings appear inline with the content of the block below it.

Styling range input fields

Some modern browsers support input fields of type="range", for imprecise number values. However, style on these elements is normally completely ignored.

Bring in -webkit-appearance: none;, which turns the slider track back into a normal box. Then apply the knob styling to the ::-webkit-slider-thumb pseudo element.

position all four corners

Another part in my alignment puzzle. Note that not all browsers support this. If you can’t do with 2 sides plus size, it is possible to specify all 4 and leave the sizing implicit.

Published on

Playing Minecraft Offline

Me and my friends like to play Minecraft sometimes, but it often happens to be in the middle of nowhere, without internet. The most interesting part is most often the setup, not the playing.

We usually start by sharing the latest Minecraft binaries and setting up an ad-hoc WiFi network. Then someone boots a server, and we’re set… NOT!

Minecraft usually performs some DRM and verification with the Minecraft website. For the server, this can be disabled by setting online-mode to false in server.properties, but with the client, you’re out of luck.

Initially, the solution consisted of sending someone with a smartphone out to find an open WiFi network. Later, before the new launcher, it used to be possible to fake the login server1. But recently, I found a way to play in offline mode on the client as well.

Spoiler alert: Minecraft is The Matrix.

Minecraft Matrix

That’s it. It had to be said. Now, let’s hack Minecraft Matrix style.

Normally, when you click “Play Offline” after a failed login, you are named “Player”, which means that you are going to kick each other because you all have the same name.

Now, fire up your terminals2, and change directory to the bin folder of your Minecraft directory3.

Now, I can’t read and write Matrix like Mouse4, but luckily, the GNU toolchain can. What we’re going to do is change a few occurrences of “Player” with any string of equal length5.

The first step is to extract the jar. It turns out it works just fine as a directory, and it’s much easier to work with that way.

mv minecraft.jar minecraft-orig.jar
mkdir minecraft.jar
cd minecraft.jar
jar -xf ../minecraft-orig.jar

Now we need to figure out which files need to be modified. Beware of Déjà vu!

grep -r Player .
# Binary file ./ei.class matches
# ./lang/stats_US.lang:stat.playerKills=Player Kills
# Binary file ./net/minecraft/client/Minecraft.class matches
# Binary file ./net/minecraft/client/MinecraftApplet.class matches
# Binary file ./ow.class matches

Some experimentation shows that MinecraftApplet.class is the one that matters. Now you need to use sed to replace “Player” with another name of equal length5.

Mac users will need to install GNU sed, as BSD sed scrambles the binary file beyond repair. I used brew install gnu-sed, but Macports and Fink might also work.

gsed -ibak s/Player/_Notch/g net/minecraft/client/MinecraftApplet.class

Done!

  1. Not anymore, it uses SSL now. 

  2. Mac users can use the “Homebrew” style at fullscreen for extra Matrix factor. 

  3. Mac: ~/Library/Application\ Support/minecraft/bin, Linux: ~/.minecraft/bin, Windows: ~/.AppData/Roaming/.minecraft/bin 

  4. Mouse, please tell me how you wrote the lady in the red dress. 

  5. Equal length you hear me, you’ll crash Minecraft otherwise.  2

The NoSQL Burden

Some people claim that NoSQL is premature optimization and places an extra burden on the developer. The main points seem to be that NoSQL has no schemas and drops consistency in favour of the other parts of CAP(availability, partitioning).

I largely agree, however, I think we should differentiate between two kinds of NoSQL databases.

  1. ScaleDB: Hard-core MapReduce, thousands of nodes, sacrifices everything for speed and scalability. If you use this below Google-size, you have no idea what you’re doing.

  2. EasyDB: Relax, life is to short to update your schema and master SQL, give me an easy API to persist and query my data and I’ll be happy. I really think some NoSQL databases should realize this and drop scalability as a prepackaged buzzword feature and focus on the real needs of the majority of their user base.

Relax, does that word ring a bell? It’s the tag line of CouchDB. With its nice REST API and with replication as the only way to scale horizontally, I think CouchDB classifies as an EasyDB.

However, CouchDB uses MVCC, this avoids locking and provides a form of consistency, but it does place the burden of handling update conflicts on the client. Or… does it?

CouchDB concurrency

I would like to draw a parallel with how Clojure handles controlled shared mutable state. The simplest form present in Clojure is the Atom.

An atom is a MVCC construct that provides a low-level compare-and-set! function that executes an atomic update if the expected old value matches the actual value. Much like CouchDB compares the _rev of a document before updating.

Interestingly, though, atoms also provide the very convenient swap!, which takes a pure function that takes the old value and returns the new one. swap! calls compare-and-set! in a loop, recomputing the new value on every iteration until the update succeeds.

So what about CouchDB? Can we have easy fire-and-forget updates there as well? Yes we can! I previously hacked together an atom implementation on top of CouchDB, but it turns out CouchDB already offers a little known feature called Document Update Handlers, which does exactly this.

Sadly, the Clojure view server included with Clutch does not yet include support for document update handlers, but this can be easily remedied!