Why CITS got git

June 23rd, 2009

Subversion is good, don’t get me wrong, git is just better! In a nutshell, git is a fast distributed version control system, which supports a much more flexible style of development than Subversion. The two features that prompted me to switch were its distributed nature and its support for branching.

The distributed part is interesting; instead of checking out “the latest version” then checking in your changes, you make a complete clone of the repository (including history), do whatever you want with it, then merge your changes to wherever, you want, however you want. The main reason this is interesting to me (and the main thing that prompted me to use git) is that it means I can work completely ‘offline’, in that I can view full history, make commits, branch and so on without having access to the server. My server is actually an ordinary desktop PC that dual boots into Windows, so sometimes it’s not available, and being able to still work properly when it’s not on is brilliant. Using Subversion, I would end up building up large changelists whilst waiting to be able to commit, which is a bad thing. Additionally I wouldn’t be able to view history or revert anything to a previous version, which are two things that are needed more often than you’d think.

Git’s branching is also very useful to me. It supports fast and local branching and merging; branching is a lightweight operation, you can have branches that are local to only one repository, and merging is pretty brilliant.

I tend to flit between tasks depending on how I feel when I sit down to do some work. Sometimes I’ll want to do some refactoring, sometimes I want to work on a new feature, sometimes I feel like making some new art. Under Subversion, one way to do this would be to work on all of these in the same working directory and selectively commit parts of that when they are ready. That’s dangerous because it’s then impossible to test changes in isolation – I may end up checking in something that depends on something I’m not checking in. It also becomes a pain when changes overlap, as you then can’t selectively commit anyway.

You could also save changelists and apply them when you want to do some more work, or commit, but then you’re losing many of the benefits of source control, in that each of these features is effectively now one version, and they’re not backed up on a server.

Another way to do it would be to create branches and work within those, but Subversion doesn’t do branches very nicely. Branches are basically just a dumb copy of the whole working directory to another directory, and as such are checked in to the main repository visible to everyone. With git, you can quite easily create and switch to a new branch, do some fiddling, switch to another branch, fiddle some more, merge the two branches and commit the result. This is perfect for me, and is exactly what I do, except with several days between each step! You can commit several times to each branch, you can store work in progress (via git-stash) so you don’t have ugly half-finished commits, and the ‘main’ repository (the central server visible by everyone) needn’t know about any of this. You just push to it once a series of commits that make up some number of features is deemed ‘done’.

Of course there are plenty of other niceties that come with using git, but these were the two most important things to me.

I’ll go into exactly how I use git in my next git post. Stay tuned :)

Migrating from Subversion to git

May 17th, 2009

One of the things I’ve been busy with is migrating Cities in the Sky’s source control from Subversion to git. I’ll go over the reasons in full in a later post, but in a nutshell, git supports my workflow better than Subversion since it is distributed and supports fast branching and merging.

Now, there are some good guides dotted around the net which deal with migrating from Subversion to git, and with setting up a git server in a secure and maintainable manner, but I found them lacking a little in friendliness and details. There are also a lot of blog posts that more or less copy those guides and add in nothing of their own, sometimes to cheaply draw visitors to their sites, sometimes “in case I forget where the original is”, and sometimes just for the hell of it. Rather than add that little bit more redundancy to the Internet, I thought I’d write up a friendly explanation about just what these guides are doing, along with some extra advice I discovered to be useful.

Installing git and git-svn

So let’s get started! The first step is creating a git repository from your Subversion repository, which is made pretty easy through the use of git-svn, which is a tool for using git locally with a remote Subversion repository. I’m going to go ahead and assume you’re using some flavour of Linux – I’m using Ubuntu. I believe git-svn is supposed to be installed as part of git, but for whatever reason it isn’t on Ubuntu, so to install git and git-svn I had to do this:

sudo apt-get install git-core git-svn

Converting your repository from Subversion to git

Once you have installed git and git-svn, follow this guide on Simplistic Complexity and you’ll have a local git repository containing the full history of your Subversion repository with all the Subversion users mapped to git users. This bit is pretty easy, so the only piece of advice I have for this step is that in the users file you can add entries even for those ‘no author’ commits – just use the exact string Subversion reports as the author of the commit. For example, my users file looked like this:

Ben = Ben Hymers <my.email@host.com>
ben = Ben Hymers <my.email@host.com>
(no author) = Ben Hymers <my.email@host.com>
root = Ben Hymers <my.email@host.com>

There will often be odd users like these near the beginning of a project’s history, from the initial import or just before proper authentication was set up. Including these lines ‘fixes’ the history for the git repository.

Securely serving your git repository

The next step is to set up your server to serve your new git repository securely, since at the moment it is just on the local filesystem and will only be available to users that have permission to access the directory. Read through the excellent directions in this article on scie.nti.st. If you understood them perfectly then go ahead and use them, if not then read on!

Some background knowledge

It’s probably helpful to mention that a git repository is basically just a directory, which contains metadata and a big load of compressed bits and bobs which comprise the data of your project over its history, and optionally a working copy. If it has a working copy, which is typically the case when you’re a developer doing some work on the repository, the git data will be stored in ‘.git/’ in the root of your project, whilst the working copy will be present as normal. If it doesn’t have a working copy, it is what’s called a ‘bare’ repository, which is typically what a server will use as it has no need to modify anything, and the git data will just be stored straight in the directory. A ‘git server’ then is some process that makes this directory available to others via something other than just the filesystem.

The way we’re going to serve up the git repository is via SSH. Once it’s set up, commands you issue to git that require the address of the repository (clone, push and so on) will cause git to SSH into the server machine, to the directory that is the git repository, to perform their monkey business.

I hadn’t really used SSH before this so it was all quite alien to me, but there are plenty of articles on SSH and public key authentication on the web; I suggest you read one of those to understand why we’re creating keys, how they’re used, and what they mean.

We set up a user called ‘git’ who will own all the repositories. We do this so we can keep the permissions as specific as possible (if a user is compromised, damage is limited) and to avoid having to set up a user on the server and grant them permissions to the appropriate git repositories every time a new external user wants access. Instead, all access to the git repositories will be done via the git user – external users will SSH into the server as user ‘git’.

It’s also handy to know that git repositories are commonly named with the suffix ‘.git’, to show that the directory is a git repository. It’s like a file extension for directories.

Finally, the git documentation says that addresses of the form “[user@]host.xz:path/to/repo.git” are equivalent to addresses of the form “ssh://[user@]host.xz/~/path/to/repo.git”.

So, with those nuggets of knowledge in hand it becomes a bit clearer what lines like “git clone git@my_server:my_repository.git” mean. ‘git clone‘ is the command to clone a repository given as the argument. The strange-looking address can actually be reinterpreted as “ssh://git@my_server/~/my_repository.git”. Breaking that apart, we see that we are connecting using the SSH protocol as user ‘git’ to ‘my_server’, in the directory ‘~/my_repository.git’. ‘~’ is unix shorthand for the home directory, and since we are connecting as user ‘git’ this will be git’s home, which is where the repository resides. Isn’t that clever?

Setting up gitosis

Now, what’s this gitosis stuff all about, and how does it help you create and maintain git repositories? Well, you could create the git user, and log in as git to add users’ keys and to create repositories in your home directory yourself, but that would get a bit tedious, and quite tricky when you have multiple repositories that each have different permissions. Gitosis automates all that, and hosts the configuration via git in a clever recursive manner.

Follow the commands in the first section of the article linked above and you’ll have checked out (via git) the gitosis config, ready to create repositories and authenticate users. Note that initially there will only be one user able to access the configuration – the user whose public key you initially gave to gitosis – which is nice and safe. It doesn’t have to be someone local to the server. Configuration is pretty simple – there is a directory for public keys, into which you place keys you collect from users’ machines. Then there is a configuration file, in which you list groups, which consist of users that are members, and permissions to repositories. Repositories are created implicitly – list one as writeable by some group, and after you commit the config changes it will exist and you can start pushing to it.

So, to add a user, get them to generate a public key and give it to you. You then name the key appropriately (e.g. “ben@windowsmachine.pub”) and place it in keydir/. Find or create a group that has the permissions you want the user to have, and add the name of the public key file (without the .pub extension) to the ‘users’ section of that group.

If you want to allow more people access to the configuration, do the same and add them to the default ‘gitosis-admin’ group, which has write access to the gitosis-admin repository, the one you are editing. You won’t want to go doing this too much for security purposes, but I did it to grant myself access from my other machines. Commit your changes and gitosis will update its configuration automagically.

The only advice I need to give on setting up gitosis is to follow the directions exactly, to the letter. A little knowledge is a dangerous thing, and since I have a little knowledge I ended up skipping out some commands or doing them my way since I thought I knew what I was doing, and as a result ended up undoing and redoing most of those steps several times until I realised I’d broken the whole thing and had to start from the very beginning.

Tying it all together

To tie these two steps together – converting your repository from Subersion to git, and hosting it via gitosis – you just need to push your new git repository to one you have listed in your gitosis config. You can either do this by giving the address of the repository to the push command, like so:

git push git@my_server:my_repository.git

Or you can add a ‘remote’ to your git config so push has a ‘default’ place to push to, like so:

git remote rm origin
git remote add origin git@my_server:my_repository.git
git push

We remove the remote ‘origin’ first since it’ll likely already be set to the location of the git-svn repository you cloned from, and there’s little point pushing back to that one! ‘origin’ is as it sounds – where the repository was cloned from – and is the default remote to push to. There are plenty of other rules that determine what ‘default’ means but none will apply unless you’ve done anything other than what’s listed here! Consult the git-remote and git-push documentation for more details.

From then on it’s business as usual, and you can use whatever git workflow you fancy. Since you’ve just converted from Subversion you’re probably used to the checkout -> edit -> update/merge -> commit workflow, in which case you’ll probably want to mimic that until you get used to git and want to try out anything crazy. I found the Git – SVN Crash Course useful for this.

There you have it then; hopefully with the combination of the articles I have linked and the extra explanation of what they are doing I have given, you will be able to migrate from Subversion to git in a secure and maintainable way with ease. Good luck!

Random bits and bobs

May 13th, 2009

Just a small update this time; I noticed the lighting was a bit odd in that the surface of the island seemed to be shaded uniformly and the underside was a bit too light, so I tweaked that.

Also I noticed looking at the past few screenshots that the island is the same each time, when it’s meant to be random! That’s a shame since I spent quite a while making a nice island generator. So I reinstated that code and now it’s generating random islands again every time.

Lighting tweaks and random island

You may also have noticed that I’m now using Flickr to host screenshots (well done you). I chose Flickr because Picasa seems to reduce the quality of its thumbnails massively, which is really annoying and makes CITS look even worse than it should do. Also Flickr’s image previews happen to be exactly the same width as the text on this page which pleases me :)

Still, one tiny update in over a month? I’d be a bit miffed if I were you. Trust me though, I’ve been doing all sorts of other interesting things (that don’t deserve screenshots) which I’ll post about very soon!

Happy little chaps and demolition

April 6th, 2009

As I said in my last post, the next thing I wanted to get done was to fix up the physics on the raisable buildings by rejiggling the code for the Building class. I’ve now added ‘Debris’ which is spawned by each ‘Building’ when it decides it’s time to fall off the island. Currently all the buildings just spawn a piece of debris that looks exactly like the building itself, though in the raisable building’s case this means one piece per floor.Broken buildings and little people Since the physics can be a tad unstable at times, this can result in interesting-looking explosions such as that pictured in this screenshot!

You may also notice there are some bright orange buildings there. If you don’t notice them you’re not looking very hard. They’re just replacements I made for the ‘tudor house’ mesh that I borrowed from Ogre right at the start of this project – it was unnecessarily highly detailed, a bit ugly, and not mine. These new buildings have only one of those problems.

I also replaced the graphics of the people – they’re now little chaps made out of several cuboids (what an evolutionary leap!). They’re even textured! You can’t see it from the screenshot, but they each have a smiley happy face. They’re blissfully unaware that if ‘trippedOver’ ever returns true, they’ll be launched upwards with ‘10′ force, which although unitless is definitely quite deadly, and comical.

Next I’m going to do a bit more rejiggling (’refactoring’ is a term many programmers use inappropriately, so it’s sort of lost its meaning. ‘Rejiggling’ is a good replacement I think), since there are a few bits of code that are being duplicated every time I add a new type of object. After that I’ll be adding some ’special’ buildings and updating the game logic a bit, which will be fun :) That will probably have to wait until after Easter though, since I’m off to France with my girlfriend for a bit first!

Skyscrapers

March 30th, 2009

Tonight I added those raisable buildings I was talking about. This involved a lot more work than you’d think! Mostly this was because it’s quite a radical change from the way things are done currently. Each building is made up of several meshes now – a ground floor, a roof, and several middle floors, whereas before there was the assumption that there was a 1:1:1 mapping between building, physics object and mesh.

You may also notice that I’ve thrown some random rotations of buildings into the mix. This pretty much came for free when I was adding in all the other stuff, so I’m happy since it makes things look a whole load more interesting! Similarly, it’ll now be easy for me to add things like stilts/foundations to make sure buildings don’t hover like they can now, or to add scaffolding temporarily just after construction, or to change the appearance of buildings entirely (make them more futuristic as the game progresses or the buildings are developed enough). All graphical niceties that I’ll get to in time!

Unfortunately I’ve broken the physics on those buildings since they can no longer just take their position and orientation from their physics component (otherwise the whole building would be at ground floor level), but I haven’t bothered to fix this since that’s next on my list of things to revamp. I’ll make buildings spawn ‘building chunk’ objects when they collapse, which will improve things in many ways – the Building class will then have one responsibility rather than two (it currently has states for ‘free’ and ‘attached’, the ‘controlled’ state being lost when I factored that out into the ‘Piece’ class), there will be the possibility for multiple building chunks with different graphics to that of the building they came from (proper bits of rubble!), and the Building object will need physics only for collision detection and not to physically attach it to the island.

Still bringing home the bacon

March 20th, 2009

Well, if you didn’t know already you’ll know after reading this or this – Rare announced last month that it would be doing some ‘restructuring’, which is a friendly term for sacking a bunch of people. The whole process has been farcical at best, and has demoralised everyone thoroughly, but the powers that be have now let some people go. Thankfully I’m not one of them (which is fortunate since my redundancy payout would be pennies, and the Midlands isn’t exactly bursting with game development studios that would welcome me with open arms), but it’s been difficult seeing some of the people I work with depart, especially those that weren’t planning on walking out anyway. I hope they land on their feet, and something better finds them.

So there you go, a brief ‘behind the scenes’ glimpse at the sham of a mockery of a sham that is the games industry.

Surprise!

March 8th, 2009

Hah, I bet you didn’t think I’d wait this long before posting those interesting things, did you? Did you?

What I’ve done is had a good ol’ rethink of the way the gameplay is going to work. Up until now, the idea has been that individual buildings fall from the sky and get attached to the island when they hit it. If you build on top of an old building, you destroy both the old and the new. Your score was going to be decided on a measure of each building’s quality (depending on where on the island it was placed, and which other buildings were around and so on), multiplied by the number of people, to get a rough measure of the total ‘happiness’ of your population.

The problem with this is that you’d quickly run out of space and end up being forced to destroy all your old buildings. There would come a time when your island is full, and your task would change from building a nice city to coaxing the physics system into not wrecking everything each time you place a building. Development would be linear, and capped, and I don’t think that would be very fun.

I went through a few more ideas after this, and after some discussions with the guys at work (that means you Rich!) and an old university chum (that means you Mike!), I’ve come up with something that plays well in my head, which I intend to try out. It’s just a few changes to the old idea, but I think they add up to something quite fun.

Instead of dropping actual buildings, you now drop pieces which can create buildings, or perform some other function. The main pieces will be ‘raise’ pieces, which will raise whichever buildings they hit (or create them if not present. These buildings will be your ordinary houses, and the idea will be to just have as many of these as high as you can make them. Of course the higher they are the less stable they are. The other main types of pieces will be the special pieces, which build buildings like docks, windmills, farms, mines and so on. These will generally have some criteria for where they can be built – docks at the edge, windmills up high, farms on flat ground – and will sometimes have gameplay effects other than their physical presence – mines will mine out a cavity inside the island gradually which will act as a negative weight, docks will attract merchants which will serve as other physics objects to get in the way.

Scoring remains cumulative over time, but instead of the previous sum of building scores times population, it will be a general ‘development’ score (which I see being a sum of ordinary buildings and their heights), affected by several multipliers relating to the special pieces. These multipliers will be things like ‘have 3 docks’, ‘have 3 windmills’, ‘have a really tall ordinary building’, and will be shown as greyed out icons next to the score when inactive, and lit up when active, probably with some crazy effects when several of them are acting together.

I’ve made a start, in that I’ve re-jiggled things to no longer drop buildings but to drop pieces, and I’ve added multi-part pieces (just an ‘L’ shaped raise piece at the moment), and added the base functionality for the raising mechanic (Note that you can also see the temporary Flash-based replacement for the in-game GUI in this screenshot!). In doing all this I’ve learnt some 3D modelling with Blender, which was different. Just today I figured out how to do UV editing and texturing, and exporting that information from Blender into a format that OGRE can use. All that must have appealed to my previously undiscovered inner artiste, since I then spent a few days learning to use my graphics tablet to do a spot of ‘digital painting’, but that’s a story for another day!

About bloody time!

January 26th, 2009

I started work on CITS again a couple of weeks ago, yet somehow it’s taken all that time just to get a couple of really very simple things done. All I wanted to do was to replace Simul Weather with a skybox of a Simul Weather sky, for debug builds, because it takes half a minute to load. So I went to the Ogre forums to ask how to go about saving a cubemap of the current scene out to file. I got no responses (thanks Ogre community!), so I made up my own way. Prepare for a rant.

I figured I’d just have the camera render to texture, then on a button press have it spin round to face each direction, update the texture and save it out. My first bit of fun was in tracking down a bug caused by Simul using the same string name for a texture as I did (moral of that story: don’t use string identifiers for bloody textures! What’s wrong with pointers or other unique handles?). Even so, once I’d sorted that, I found that it just didn’t work like that, and kept saving the currently rendered view.

So I thought I’d have six cameras each with their own render target, which I’d set off all at the same time. Except that did exactly the same thing.

So then I added in loads of calls to various Ogre update functions, to render extra frames in-between updating the camera and saving images. This worked to a certain extent, but gave very strange warped images for some directions, presumably because the Simul state depends on the previous frame and isn’t correct for sudden changes in viewing angle.

So then I thought I’d have twelve buttons mapped; six to get the current camera facing each direction, and six to save out the current view to each file, so I could allow the state to settle manually. Except that generated all sorts of weird twisting artifacts half the time, and the other half it’d make the clouds progressively blurrier each time I pressed a button to change the view.

So then I sat and tweaked values and mucked about with different ways of setting the camera’s direction, and eventually discovered that you could press the buttons in a certain order to get acceptable results, which finally worked. Sadly the sides of the cube don’t quite match up despite setting a FOV of 90 degrees and aspect ratio of 1, and the images are even more over-exposed than they appeared in-game (quite how I don’t know), but I was really quite bored of Ogre and Simul now and wanted to get on with something more fun.

Unfortunately in the process of all this I’d had to downgrade Ogre from SVN HEAD to the last stable release, 1.6, since I suspected it of being buggy, and it just wasn’t playing ball with CITS. It turned out that at some point there had been a switch from one memory manager to another, which required me to edit the Ogre source to change it back to the normal one. That was great fun, since changing something so fundamental requires a recompile, which takes a good hour or so.

Then OPAL went bad. Well, the code that converts an Ogre mesh to a format OPAL can understand went bad. I’d made some assumptions about the index buffer format Ogre uses, which were valid before 1.6, were valid after 1.6, but apparently weren’t valid at the instant 1.6 was released. That’s the fun I’ve been having this evening.

It’s finally done now though, and I can get on with some more important tasks!

There are a couple of other more interesting bits of news about the game, but they can wait for another update!

Flash-tastic

November 8th, 2008

Well, I sorted out a new Simul license so the sky is back to normal (and so I can post screenshots again!). I’ve also done a load more work on the UI. It’s still not totally functional, but the high scores screen displays high scores and the in-game UI shows points and tilt like it did before, so I’m back to normal functionality at least. I also did some clever-but-not-really things like learning a bit of Actionscript, and scaling the Flash output based on viewport resolution.

The high scores screen you see is the result of several hours of tweaking and fiddling. I’m fed up with temporary graphics so I thought I’d try to create something a bit more permanent. It turns out I’m not so good at this though – it looks a little boring to me. It’s not abysmal, but it’s not good either. There’s a chap at work who’s marvellous when it comes to interface graphics, maybe I’ll ask him to sketch something up for me, so I can at least get a nice theme and colour scheme going.

I’ll probably improve the UI functionality next, though there’s another little side-project I’ve been dying to get my teeth into for the past few weeks, so we shall see… yes, we shall see…

Into my face

October 28th, 2008

I had a little time to play with Hikari, a UI library for Ogre that effectively wraps a Flash control and adds some C++ interoperability. This means that I can make a little Flash application and have it run in-game as the user interface, which is much more flexible, easy to modify and generally nice than the Ogre overlay system I’m using at the moment.

I’ve made a Flash file for the menu, in-game UI and high-scores table and they’re being displayed in-game instead of the ugly temporary overlay graphics I had before (that you never did and never will see!). They’re not functional yet since I haven’t really had the time to learn Flash, and the input code I wrote doesn’t keep track of cursor position yet which would make buttons useless. That’s next on the agenda though.

I shan’t give you a screenshot since I still haven’t sorted out a Simul Weather license, so everything looks very ugly!