1
\$\begingroup\$

I am working on a browser game where there are citys and their resource productions. Each player has their own production rate for each resource.Lets say stone as example. I have production rate,capacity and timestamp(when production started for that resource) for stone in db.I am pulling production rate from db and updating production value on client(incrementing it) but not in db since updating db value each second is not a good idea.So each time user refreshes page or does some action releated to stone,server checks timestamp and production rate and calculates what should be the value of stone in that time,i mean real value and updates client.

"stone" : {
        "capacity" : 10,
        "count" : 0,
        "timestamp" : 1531470433, // when production started.
        "rate" : 20, //stone production in a minute
}

This calculates users current stone value and updates db.

var allStoneProduction= Math.floor((currentTime - stoneDbTime) * stoneProductionRate /60)

The problem is with capacity.Players are able to increase capacity of each resource.

I can detect when stone capacity going to be full in server since i know production rate and production start time.Then i am making stonecount equal to capacity.

This code checks if storage is full.If its not it sets value of stone production.

var storageFullTime = stoneDbTime+(stoneCapacity/stoneProductionRate)*60

if(currentTime < storageFullTime || currentTime == storageFullTime){
console.log("storage is full!")

Resources.update({ownerId:userid},{$set:{"stone.count":stoneCapacity}})



}else{
Resources.update({ownerId:userid},{$set:{"stone.count":allStoneProduction}})
}

As you see allStoneProduction is actually always going up without checking capacity since its only based on rate and start timestamp.This is ok if there is no max capacity.

If stone count reaches its capacity i stop incrementing on client side by checking stonecount,stonecapacity.(10/10) lets say.

If i change capacity from 10 to 20 on db,client gets new capacity value and starts to increment it 11,12,13... until capacity 20.

But server cant follow up this.Should i also write timestamp of when capacity changed ? I couldnt really write the correct if else logic for this.

So how do i compute this capacity change in server side ? allStoneProduction value doesnt care about reaching max capacity and increasing capacity.So if change capacity and refresh page,i get a wrong stone count.(since in server logic production never stops)

\$\endgroup\$
1
\$\begingroup\$

Here's a two-part approach we can use...

When computing current quantity held, we ensure it can never exceed the current capacity:

GetCurrentQuantity() {
    return Min(
      capacity,
      storedQuantity + (time - lastStorageUpdateTime) * productionRate
    );
}

When incrementing capacity (server-side):

ChangeCapacity(newCapacity) {

    currentQuantity = GetCurrentQuantity ();

    if(currentQuantity == capacity) {
        storedQuantity = currentQuantity
        lastStorageUpdateTime = time;
    }

    capacity = newCapacity;
    UpdateDatabase();
}

This way, when we increase our capacity (and we need to do a database update anyway to log that change), we bake-out any surplus production that could have leaked through the new cap, and reset the timestamp so further incremental production starts from this moment that the cap changed.

(If we were below capacity at the time of the cap increase, then we don't strictly need to do this, since the result comes out the same either way)

You can do a similar update when logging a spending event or changing the production rate, fixing a new starting point for future increases.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.