13 Feb 2015
Run a Minecraft Server on OSX Boot2Docker
Here’s how I did it. I hope you find it useful!
One-time Setup
Do these steps once, to initialize Boot2Docker:
Step 1: Install Docker for OS X
Step 2: Create a directory to hold your Minecraft files. This needs to be
under the /Users part of your file system because boot2docker automatically
mounts /Users to the boot2docker-vm.
mkdir /Users/yourname/minecraft/data
Step 3: Initialize boot2docker
boot2docker init
Step 4: Forward the TCP port Minecraft uses from the Mac to the boot2docker-vm.
VBoxManage modifyvm “boot2docker-vm” –natpf1 “tcp-port25565,tcp,,25565,,25565”;
Start Minecraft
Do these steps every time you want to start your Minecraft server.
Step 1: Start boot2docker.
boot2docker start
Step 2: Set up the shell variables so you can use the docker command.
$(boot2docker shellinit)
Step 3: Run the minecraft container.
CONTAINER=$(docker run -v /Users/yourname/minecraft/data:/data -d -e EULA=TRUE -e VERSION=LATEST -p 25565:25565 itzg/minecraft-server)
The first time your run this it will take a few minutes to download and
install minecraft. After that it should be much faster
View the Minecraft Server Log
docker logs $CONTAINER
This prints out the logs from the container (you set the CONTAINER variable as
part of the docker run command above.)
If you’ve lost track of your container, you can list all currently running
containers.
docker ps
If you don’t see any containers, you container may have already exited. The
Minecraft server will exit if it encounters an error while running.
Shut Down
You can shut down all running containers and quit boot2Docker by using the
stop command:
boot2docker stop
Note that the Minecraft Server files will be stored in
/Users/yourname/minecraft/data, and when you’ve stopped the server you can
edit the files using your mac. (You might want to edit the files in order to
modify the server settings.)
09 Feb 2015
I’ve been reading the book Masters of Doom
about the careers of John Carmack and John Romero. I have ported their games
Doom and Quake to many
different
platforms. It was interesting to read
about their lives and game business.
The book brought back memories of development in the ‘80’s, and ’90s. Things
were simpler (and worse) then.
Some other John & John links:
The Rise and Fall of Ion Storm
Stormy Weather
Carmack QuakeCon Keynotes
12 Jan 2015
I’ve long-since misplaced the source code to my Atari 800 game Dandy Dungeon.
But thanks to the Atari800MacX
emulator and the emulation scene, I’ve been able to play an emulated version
of my original game. That’s been helpful for remembering all the little
details of gameplay.
For example, I was able to determine that the original game animated the
arrows at 15 Hz and the players and monsters at 7.5 Hz.
FWIW I think the emulator may be slightly incorrect about the HBLANK
processing emulation. I’m pretty sure that the color background for the 4th
line of text should be a different color from the color background of the 3rd
line of text.
The iOS version of the game is progressing – the dual thumbstick virtual
controls work well.
The next step (and it’s a big one) is going to be multiplayer support. GameKit
here I come.
05 Jan 2015
There are a total of 3 draw calls and 2 textures in this scene:
The whole tile map is rendered as a single draw call: a single 2-triangle tile
that’s instanced Row x Column times, using a 3D texture as a texture atlas. I
originally used point sprites, but switched to instanced triangles because I
wanted to use non-square tiles.
The virtual joystick is rendered as two coarse triangle strip rings, using a
1D radial texture. Note the anti aliasing. (I could have used quads, but
wanted to minimize overdraw.)
So far Metal has been fairly straightforward to use, at least for someone like
me coming from a DirectX 9 / Xbox 360 / Android OpenGL ES 2.0 background.
02 Jan 2015
At my house we are trending towards having N+1 laptops for N people, because
(a) I need to keep my work laptop separate from my home laptop, and (b)
frequently everyone in the family wants to use their laptops at the same
time.
The same goes for tablets, and when the kids are old enough to have phones I
expect it will be the same for phones.
I tried using multi-user accounts on shared family tablets and laptops, but
ended up assigning each kid their own devices. It was simpler from an account
management point of view, and the kids like personalizing their devices with
stickers and cases.
Having assigned devices also makes it easier to give different Internet and
gaming privileges to different kids, depending on age and maturity.
A downside of assigned devices is that not all the devices have the same
features. People complain about hand-me-down devices, as well as the perverse
incentive created when an accidentally broken device is replaced by a brand
new, better device.
02 Jan 2015
When I started working on Android in 2007, I had never owned a mobile phone.
When Andy Rubin heard this, he looked at me, grinned, and said “man, you’re on
the wrong project!”
But actually, being late to mobile worked out well. In the early days of
Android the daily build was rough. Our Sooner and
G1 prototypes often wouldn’t work
reliably as phones, and that drove the other Android developers crazy. But
since I was not yet relying on a mobile phone, it didn’t bother me much.
Seven years later, mobile’s eaten the world.
But I still haven’t internalized what that means. I think I’m still too
personal-computer-centric in my thinking and my planning.
Here’s some recent changes that I’m still trying to come to grips with:
- Android and iOS are the important client operating systems. The web is now a legacy system.
- Containerized Linux is the important server operating system. Everything else is legacy.
- OS X is the important programmer’s desktop OS (because it’s required for iOS development, and adequate for Android and containerized Linux development.)
- The phone is the most important form factor, with tablet in second place.
- Media has moved from local storage to streaming.
- Programming cultural discussion has moved from blogs & mailing lists to Hacker News, Reddit & Twitter. (To be fair, these new forums mostly link back to blog posts for the actual content.)
In reaction, I’ve stopped working on the following projects:
- Terminal Emulator for Android. When I started this project, all Android devices had hardware keyboards. But those days are long gone. And unfortunately for most people there isn’t a compelling use case for an on-the-device terminal emulator. The compelling command-line use cases for mobile are SSH-ing from the mobile device to another machine, and adb-ing into the Android device from a desktop.
- BitTorrent clients. My clients were written just for fun, to learn how to use the Golang and node.js networking libraries. With the fun/learning task accomplished, and with BitTorrent usage in decline, there isn’t much point in working on these clients. (Plus I didn’t like dealing with bug reports related to sketchy torrent sites.)
- New languages. For the platforms I’m interested in, the practical languages are C/C++, Java, Objective C, and Swift. (And Golang for server-side work.)
- I spent much of the past seven years experimenting with dynamic languages, but a year of using Python and JavaScript in production was discouraging. The brevity was great, but the loss of control was not.
Personal Projects for 2015
First, I’m going to port my ancient game Dandy to mobile. It needs a lot of
work to “work” on mobile, but it’s a simple enough game that the port should
be possible to do on a hobby time budget. I’m probably going to go closed-
source on this project, but I may blog the progress, because the process of
writing down my thoughts should be helpful.
After that, we’ll see how it goes!
02 Jan 2015
I’ve been reading Game Programming Patterns by Bob Nystrom.
It’s available to read online for free, as well as for
purchase in a variety of formats.
A good book for people who are writing a video game engine. I found myself
agreeing with pretty much everything in this book.
Note - this book is about internal software design. It’s not about game
design, or graphics, physics, audio, input, monetization strategies, etc. So
you won’t be able to write a hit video game after reading this book. But if
you happen to be writing an engine for a video game, this book will help you
write a better one.
Edit – and I’ve finished reading it. It was a quick read, but a good one. I
consider myself an intermediate level game developer. I’ve written a few
simple games and I’ve worked on several other games. (For example, I’ve ported
Quake to many different computers over the years.)
For me the most educational chapters were Game Loop and
Component, although
Bytecode and
Data Locality were also
quite interesting.
I like that the chapters have links to relevant external documents for further
research.
I felt smarter after reading this book.
02 Jan 2015
It’s been a while since my last post – I’ve been posting inside the Google
internal ecosystem, but haven’t posted much publicly.
What have I been up to in the past 3 years?
Work
Prototyped a Dart runtime for Android. Amusingly enough, this
involved almost no Dart code. It was 90% Python coding (wrangling Gyp build system scripts) and 10% C++ coding
(calling the Dart VM).
Extended the Audio players for Google Play Music’s Web client. I learned
ActionScript, the Closure dialect of JavaScript, and HTML5 Audio APIs (Web Audio and EME.)
Started working on the Google Play Music iOS client.
I learned Objective C, Swift, iOS and Sqlite.
Personal Projects
Prototyped a Go language runtime for Android. Unpublished, but luckily the
Go team is picking up the slack.
Finished working on Terminal Emulator for Android.
I’m keeping it on life support, but no new features.
Personal Life
Started exercising again after a 10 year hiatus. It’s good to get back into shape.
Switched to a low cholesterol diet. Google’s cafes make this pretty easy to do.
Watched my kids grow!
12 Sep 2011
Today I backed up all my family pictures and videos to Picasa Web Albums.
For several months I have been thinking of ways to backup my pictures to
somewhere outside my house. I wanted something simple, scalable and
inexpensive.
When I read that
Google+ users can store unlimited pictures sized <= 2048 x 2048 and videos <= 15 minutes long,
I decided to try using Google+ to back up my media.
Full disclosure: I work for Google, which probably predisposes me to like and
use Google technologies.
Unfortunately I had my pictures in so many folders that it wasn’t very
convenient to use either Picasa or
Picasa Web Albums Uploader to upload them.
Luckily, I’m a programmer, and Picasa Web Albums has a public API for
uploading images. Over the course of an afternoon, I wrote a Python script to
upload my pictures and videos from my home computer to my Picasa Web Album
account. I put it up on GitHub:
picasawebuploader
Good things:
- The Google Data Protocol is easy to use.
- Python’s built-in libraries made file and directory traversal easy.
- OSX’s built-in “sips” image processing utility made it easy to scale images.
Bad things:
- The documentation for the Google Data Protocol is not well organized or comprehensive.
- It’s undocumented how to upload videos. Luckily I found a Flicker-to-Picasa-Web script that showed me how.
To do:
- Use multiple threads to upload images in parallel.
- Prompt for password if not supplied on command line.
20 Dec 2010
I wrote an asynchronous directory tree walker in
node.js. Note the use of Continuation Passing Style in
the fileCb callback. That allows the callback to perform its own asynchronous
operations before continuing the directory walk.
(This code is provided under the Apache Licence
2.0.)
// asynchronous tree walk
// root - root path
// fileCb - callback function (file, next) called for each file
// -- the callback must call next(falsey) to continue the iteration,
// or next(truthy) to abort the iteration.
// doneCb - callback function (err) called when iteration is finished
// or an error occurs.
//
// example:
//
// forAllFiles('~/',
// function (file, next) { sys.log(file); next(); },
// function (err) { sys.log("done: " + err); });
function forAllFiles(root, fileCb, doneCb) {
fs.readdir(root, function processDir(err, files) {
if (err) {
fileCb(err);
} else {
if (files.length > 0) {
var file = root + '/' + files.shift();
fs.stat(file, function processStat(err, stat) {
if (err) {
doneCb(err);
} else {
if (stat.isFile()) {
fileCb(file, function(err) {
if (err) {
doneCb(err);
} else {
processDir(false, files);
}
});
} else {
forAllFiles(file, fileCb, function(err) {
if (err) {
doneCb(err);
} else {
processDir(false, files);
}
});
}
}
});
} else {
doneCb(false);
}
}
});
}