void ClientGame::processMessage(MessagePtr msg)
{
    switch(msg->getType())
    {
    case MessageType::SRV_ASTEROID_SPAWN:
    {
        print("ClientGame: spawning asteroid\n");
        AsteroidSpawnMessage *spawn_msg = static_cast<AsteroidSpawnMessage*>(msg.get());
        AsteroidPtr ast(new Asteroid(this, spawn_msg->getData(), asteroid_data));
        entities.push_back(ast);
        asteroids.push_back(ast);
    }
    break;
    case MessageType::SRV_SHIP_SPAWN:
    {
        ShipSpawnMessage *spawn_msg = static_cast<ShipSpawnMessage*>(msg.get());
        const ShipSpawnData &d = spawn_msg->getData();

        ShipPtr ship(new Ship(this, d));
        entities.push_back(ship);
        ships.push_back(ship);

        print(format("ClientGame: spawning ship id=%1% name=%2%\n") % ship->getID() % ship->getName());
    }
    break;
    case MessageType::SRV_BULLET_SPAWN:
    {
        BulletSpawnMessage *spawn_msg = static_cast<BulletSpawnMessage*>(msg.get());
        const BulletSpawnData &d = spawn_msg->getData();

        BulletPtr bullet(new Bullet(this, d));
        entities.push_back(bullet);
        if(Audio::distToListener(d.state.position) < 200.0f)
            Audio::playSFX("sounds/laser0.wav", false, d.state.position, 0.5f, 10.0f);
        print(format("ClientGame: spawning bullet id=%1%\n") % bullet->getID());
    }
    break;
    case MessageType::SRV_SHIP_STATE:
    {
        ShipStateMessage *state_msg = static_cast<ShipStateMessage*>(msg.get());
        int id = state_msg->getEntityID();

        //print(format("ClientGame: received ship state data for ship id=%1%\n") % id);

        //TODO use a map?
        for(unsigned int i = 0; i < ships.size(); i++)
            if(ships[i]->getID() == id)
            {
                ships[i]->setStateData(state_msg->getData());
                break;
            }
    }
    break;
    case MessageType::SRV_SHIP_OWNER:
    {
        ShipOwnerMessage *owner_msg = static_cast<ShipOwnerMessage*>(msg.get());
        print("owner message\n");

        for(unsigned int i = 0; i < ships.size(); i++)
            if(ships[i]->getID() == owner_msg->getData().ship_id)
            {
                print("owner message\n");
                player_ship = ships[i];
                ship_cam->setShip(player_ship);
                break;
            }
    }
    case MessageType::SRV_ASTEROID_STATE:
    {
        AsteroidStateMessage *state_msg = static_cast<AsteroidStateMessage*>(msg.get());
        int id = state_msg->getEntityID();

        //print(format("ClientGame: received asteroid state data for asteroid id=%1%\n") % id);

        for(unsigned int i = 0; i < asteroids.size(); i++)
            if(asteroids[i]->getID() == id)
            {
                asteroids[i]->setStateData(state_msg->getData());
                break;
            }
    }
    break;
    case MessageType::SRV_ENTITY_DELETE:
    {
        print("ClientGame: deleting entity\n");
        EntityDeleteMessage *delete_msg = static_cast<EntityDeleteMessage*>(msg.get());
        int id = delete_msg->getData().entity_id;

        for(unsigned int i = 0; i < entities.size(); i++)
            if(entities[i]->getID() == id)
            {
                entities[i]->die();
                entities.erase(entities.begin()+i);
                break;
            }

        if(player_ship && id == player_ship->getID())
            player_ship.reset();

        //TODO do this properly
        for(unsigned int i = 0; i < ships.size(); i++)
            if(ships[i]->getID() == id)
            {
                cml::vector2f pos = ships[i]->getPosition();
                cml::vector3f col1(ships[i]->getBodyColor().data());
                cml::vector3f col2 = cml::vector3f(0.0f, 0.0f, 0.0f);
                ExplosionEmitterPtr e(new ExplosionEmitter(pos, col1, col2, 40, 50.0f, 1.6f));
                particle_system->addEmitter(e);
                if(Audio::distToListener(pos) < 200.0f)
                    Audio::playSFX("sounds/explosion0.wav", false, pos, 0.1f, 10.0f);

                ships.erase(ships.begin()+i);
                break;
            }

        for(unsigned int i = 0; i < asteroids.size(); i++)
            if(asteroids[i]->getID() == id)
            {
                AsteroidPtr a = asteroids[i];
                if(a->getBounds().intersects(game_bounds))
                {
                    cml::vector2f pos = a->getPosition();
                    cml::vector3f col1 = cml::vector3f(1.0f, 0.0f, 0.0f);
                    cml::vector3f col2 = cml::vector3f(0.1f, 0.0f, 0.0f);
                    ExplosionEmitterPtr e(new ExplosionEmitter(pos, col1, col2, 50, 30.0f, 1.6f));
                    particle_system->addEmitter(e);

                    col1.set(0.2f, 0.2f, 0.0f);
                    col2.set(0.0f, 0.0f, 0.0f);
                    ExplosionEmitterQuadsPtr e2(new ExplosionEmitterQuads(pos, col1, col2, 30, 20.0f, 1.6f));
                    particle_system->addEmitter(e2);

                    if(Audio::distToListener(pos) < 300.0f)
                        Audio::playSFX(asteroid_explosions[rand()%asteroid_explosions.size()], false, pos, 0.01f, 1.0f);
                }
                asteroids.erase(asteroids.begin()+i);
                break;
            }

        /*
        for(unsigned int i = 0; i < bullets.size(); i++)
            if(bullets[i]->getID() == id)
            {
                bullets.erase(bullets.begin()+i);
                break;
            }
        */
    }
    break;
    case MessageType::SRV_SCORE:
    {
        ScoreMessage *score_msg = static_cast<ScoreMessage*>(msg.get());
        scores = score_msg->getData();
    }
    break;
    default:
        break;
    }
}