Example #1
0
void Game::update()
{
	switch (current_state)
	{
		case GS_START:
		{
			if (!countdown)
			{
				countdown = smgr->addBillboardTextSceneNode(guienv->getBuiltInFont(), L"READY!", 0, dimension2d<f32>(200.0f, 200.0f));
				countdown->setText(L"READY!");
				countdown->setTextColor(SColor(255,230,100,0));
				countdown->setPosition(vector3df(3454,500,1256));
				//countdown->setScale(vector3df(10,10,10));
				(*object->begin())->getSceneNode()->setPosition(vector3df(3454,500,1256));
				(*object->begin())->getSceneNode()->setRotation(vector3df(0,260,0));
				nr_of_laps = 0;
				last_time = clock();
			}
			
			u32 time = clock();
			if ((time - last_time)/CLOCKS_PER_SEC >= 1)
			{
				current_state = GS_COUNTING_DOWN;
			}
			break;
		}
		case GS_COUNTING_DOWN:
		{
			u32 time = clock();
			
			if ((time - last_time)/CLOCKS_PER_SEC >= 3)
			{
				current_state = GS_RUNNING;
				countdown->remove();
				countdown = NULL;
				last_time = clock();
			}
			else
			{
				stringw str = "";
				str += (3 - (time - last_time)/CLOCKS_PER_SEC);
				countdown->setText(str.c_str());
			}
			
			break;
		}
		case GS_RUNNING:
		{
			u32 time = clock();
			time = time - last_time;
			
			// Update the car
			reciever->dispatch();
			
			stringw str;
			str += "LAP ";
			str += nr_of_laps;
			str += " / ";
			str += max_laps;
			str += "\nTOTAL TIME: ";
			str += time/CLOCKS_PER_SEC;
			str += " seconds";
			str += "\nUSE ARROW KEYS TO PLAY";
			info->setText(str.c_str());
			
			// Transition
			if (nr_of_laps > max_laps)
			{
				current_state = GS_GAME_OVER;

				countdown = smgr->addBillboardTextSceneNode(guienv->getBuiltInFont(), L"GOAL!", 0, dimension2d<f32>(150.0f, 150.0f));
				countdown->setText(L"GOAL!");
				countdown->setTextColor(SColor(255,230,100,0));
				vector3df v = (*object->begin())->getSceneNode()->getPosition();
				v.Y = 500.0f;
				countdown->setPosition(v);

				IAnimatedMeshSceneNode *cp = checkpoint->back();
				checkpoint->pop_back();
				checkpoint->push_front(cp);
			}
			
			break;
		}
		case GS_GAME_OVER:
		{
			if (reciever->getNextState() == GS_QUIT)
			{
				device->closeDevice();
			}
			else if (reciever->getNextState() == GS_START)
			{
				current_state = GS_START;
				countdown->remove();
				countdown = NULL;
			}
			else
			{
				stringw str = info->getText();
				str += "\nPRESS ENTER TO CONTINUE\nESC TO QUIT";
				info->setText(str.c_str());
			}

			break;
		}
	}
	
	reciever->setCurrentState(current_state);
	
	// Update everything else
	vector<GameObject*>::iterator i = object->begin();
	for (; i != object->end(); i++)
	{
		(*i)->update();
	}
	
	if (current_state == GS_RUNNING)
	{
		// Car intersects checkpoint
		i = object->begin();
		for (; i != object->end(); i++)
		{
			if ((*i)->getID() == 1)
			{
				// Intersects, front and push_back
				IAnimatedMeshSceneNode *cp = checkpoint->front();
				aabbox3d<f32> box = (*i)->getSceneNode()->getTransformedBoundingBox();
				if (box.intersectsWithBox(cp->getTransformedBoundingBox()))
				{
					checkpoint->pop_front();
					checkpoint->push_back(cp);
					
					// First?
					if (cp == first_checkpoint)
					{
						nr_of_laps++;
					}
				}
			}
		}
	}
}
void dns_cache_prune(DnsCache *c) {
        usec_t t = 0;

        assert(c);

        /* Remove all entries that are past their TTL */

        for (;;) {
                _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
                DnsCacheItem *i;

                i = prioq_peek(c->by_expiry);
                if (!i)
                        break;

                if (t <= 0)
                        t = now(CLOCK_BOOTTIME);

                if (i->until > t)
                        break;

                /* Take an extra reference to the key so that it
                 * doesn't go away in the middle of the remove call */
                key = dns_resource_key_ref(i->key);
                dns_cache_remove(c, key);
        }
}

static int dns_cache_item_prioq_compare_func(const void *a, const void *b) {
        const DnsCacheItem *x = a, *y = b;

        if (x->until < y->until)
                return -1;
        if (x->until > y->until)
                return 1;
        return 0;
}

static int dns_cache_init(DnsCache *c) {
        int r;

        assert(c);

        r = prioq_ensure_allocated(&c->by_expiry, dns_cache_item_prioq_compare_func);
        if (r < 0)
                return r;

        r = hashmap_ensure_allocated(&c->by_key, &dns_resource_key_hash_ops);
        if (r < 0)
                return r;

        return r;
}

static int dns_cache_link_item(DnsCache *c, DnsCacheItem *i) {
        DnsCacheItem *first;
        int r;

        assert(c);
        assert(i);

        r = prioq_put(c->by_expiry, i, &i->prioq_idx);
        if (r < 0)
                return r;

        first = hashmap_get(c->by_key, i->key);
        if (first) {
                LIST_PREPEND(by_key, first, i);
                assert_se(hashmap_replace(c->by_key, first->key, first) >= 0);
        } else {
                r = hashmap_put(c->by_key, i->key, i);
                if (r < 0) {
                        prioq_remove(c->by_expiry, i, &i->prioq_idx);
                        return r;
                }
        }

        return 0;
}

static DnsCacheItem* dns_cache_get(DnsCache *c, DnsResourceRecord *rr) {
        DnsCacheItem *i;

        assert(c);
        assert(rr);

        LIST_FOREACH(by_key, i, hashmap_get(c->by_key, rr->key))
                if (i->rr && dns_resource_record_equal(i->rr, rr) > 0)
                        return i;

        return NULL;
}

static void dns_cache_item_update_positive(DnsCache *c, DnsCacheItem *i, DnsResourceRecord *rr, usec_t timestamp) {
        assert(c);
        assert(i);
        assert(rr);

        i->type = DNS_CACHE_POSITIVE;

        if (!i->by_key_prev) {
                /* We are the first item in the list, we need to
                 * update the key used in the hashmap */

                assert_se(hashmap_replace(c->by_key, rr->key, i) >= 0);
        }

        dns_resource_record_ref(rr);
        dns_resource_record_unref(i->rr);
        i->rr = rr;

        dns_resource_key_unref(i->key);
        i->key = dns_resource_key_ref(rr->key);

        i->until = timestamp + MIN(rr->ttl * USEC_PER_SEC, CACHE_TTL_MAX_USEC);

        prioq_reshuffle(c->by_expiry, i, &i->prioq_idx);
}

static int dns_cache_put_positive(
                DnsCache *c,
                DnsResourceRecord *rr,
                usec_t timestamp,
                int owner_family,
                const union in_addr_union *owner_address) {

        _cleanup_(dns_cache_item_freep) DnsCacheItem *i = NULL;
        DnsCacheItem *existing;
        int r;

        assert(c);
        assert(rr);
        assert(owner_address);

        /* New TTL is 0? Delete the entry... */
        if (rr->ttl <= 0) {
                dns_cache_remove(c, rr->key);
                return 0;
        }

        if (rr->key->class == DNS_CLASS_ANY)
                return 0;
        if (rr->key->type == DNS_TYPE_ANY)
                return 0;

        /* Entry exists already? Update TTL and timestamp */
        existing = dns_cache_get(c, rr);
        if (existing) {
                dns_cache_item_update_positive(c, existing, rr, timestamp);
                return 0;
        }

        /* Otherwise, add the new RR */
        r = dns_cache_init(c);
        if (r < 0)
                return r;

        dns_cache_make_space(c, 1);

        i = new0(DnsCacheItem, 1);
        if (!i)
                return -ENOMEM;

        i->type = DNS_CACHE_POSITIVE;
        i->key = dns_resource_key_ref(rr->key);
        i->rr = dns_resource_record_ref(rr);
        i->until = timestamp + MIN(i->rr->ttl * USEC_PER_SEC, CACHE_TTL_MAX_USEC);
        i->prioq_idx = PRIOQ_IDX_NULL;
        i->owner_family = owner_family;
        i->owner_address = *owner_address;

        r = dns_cache_link_item(c, i);
        if (r < 0)
                return r;

        i = NULL;
        return 0;
}

static int dns_cache_put_negative(
                DnsCache *c,
                DnsResourceKey *key,
                int rcode,
                usec_t timestamp,
                uint32_t soa_ttl,
                int owner_family,
                const union in_addr_union *owner_address) {

        _cleanup_(dns_cache_item_freep) DnsCacheItem *i = NULL;
        int r;

        assert(c);
        assert(key);
        assert(owner_address);

        dns_cache_remove(c, key);

        if (key->class == DNS_CLASS_ANY)
                return 0;
        if (key->type == DNS_TYPE_ANY)
                return 0;
        if (soa_ttl <= 0)
                return 0;

        if (!IN_SET(rcode, DNS_RCODE_SUCCESS, DNS_RCODE_NXDOMAIN))
                return 0;

        r = dns_cache_init(c);
        if (r < 0)
                return r;

        dns_cache_make_space(c, 1);

        i = new0(DnsCacheItem, 1);
        if (!i)
                return -ENOMEM;

        i->type = rcode == DNS_RCODE_SUCCESS ? DNS_CACHE_NODATA : DNS_CACHE_NXDOMAIN;
        i->key = dns_resource_key_ref(key);
        i->until = timestamp + MIN(soa_ttl * USEC_PER_SEC, CACHE_TTL_MAX_USEC);
        i->prioq_idx = PRIOQ_IDX_NULL;
        i->owner_family = owner_family;
        i->owner_address = *owner_address;

        r = dns_cache_link_item(c, i);
        if (r < 0)
                return r;

        i = NULL;
        return 0;
}

int dns_cache_put(
                DnsCache *c,
                DnsQuestion *q,
                int rcode,
                DnsAnswer *answer,
                unsigned max_rrs,
                usec_t timestamp,
                int owner_family,
                const union in_addr_union *owner_address) {

        unsigned i;
        int r;

        assert(c);
        assert(q);