4
\$\begingroup\$

I need to be able to execute certain events at a given time in my game, for example, say the player "Builds a building" this building should take 15mins to process. Implementing this seems straightforward enough, simply enter the event into the database and execute the event when the time comes for it to be completed.

However, it is my understanding that i would need a script that is running permanently on the server and continually checks the event database for delayed events to execute and process them as needed. My question is, is this the right approach or should i be tackling the "event que" differently?

Some of the events that will be processed can effect many different players so they would need to happen in real time, as opposed to be lazy loaded.

You can see similar such event queues in browser games such as travian, grepolis etc.

Update - If i was to implement a purely lazy load method, are there any flaws in the following pseudo code?

    ## upon player_x pages load

## start a loop that will only exit once all needed events have been processed

## check for any events initiated by player_x that are overdue

## get event and lock it for processing

    ## does this event involve another players object?

        ## if it does, then lets check if said object also has any events that should happen before this event

            ## if it has, then lets process one of those events instead, and loop again once processed

            ## if it doesnt have any previous events, then we're free to process this event, do it

## loop till all overdue events for player_x's object are done
\$\endgroup\$
3
  • 1
    \$\begingroup\$ "Some of the events that will be processed can effect many different players so they would need to happen in real time, as opposed to be lazy loaded." Can't you still do it lazily when a player who it would affect needs the data? \$\endgroup\$
    – Tetrad
    Feb 13, 2013 at 21:58
  • \$\begingroup\$ My concern over doing it lazily is that an action may lead to, for example, a change in a resource production rate and if the lazy trigger never gets called due a player being logged out and nobody interacting with their object, then this resource production rate won't update till the next time the player logs in, which would mean the have lost out on some resources... Though now i think about it, perhaps a hybrid approach of this lazy processing and a cron event to deal with "late" events could be the way to go? \$\endgroup\$
    – user26273
    Feb 13, 2013 at 22:05
  • 1
    \$\begingroup\$ Instead of continually checking for events (“polling”), calculate what time the next event needs to be processed, and build an event queue: gamedev.stackexchange.com/questions/24415/… \$\endgroup\$
    – amitp
    Feb 13, 2013 at 22:10

3 Answers 3

4
\$\begingroup\$

I faced a similar problem before and, given your needs, I'd go for a slightly variation of your pseudo-code.

Considering that you could have events issued by other player but which can be needed for stats purpose, for example if I open the "Most resource ladder" I want to see the data up to date for every player, not only me, and stuff like this, I prefer to elaborate events belonging to every players when somebody opens a page, so you will have the "game world" synchronized every time.

Now somebody could say "The first player logging in will have to wait for a ton of events elaboration", but that's not completely true. In fact if you have such a huge amount of events, it means you have lots of players, which means lots of connections, which means that the elaboration load will spread over those connections. If you have fewer connections, they must be generating fewer events, so the load still is not too heavy.

An addition to this strategy could be creating your "event executor" as an independent script, called by users when they load a page, and also called by a cron set like every 15 or 30 minutes, so you can thin the queue even if nobody logs for a while. This way you are sure that the first logging player must at most wait for events expired in the last 15 minutes.

I found this solution pretty smooth in my projects, I hope it can also suit yours.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks for the insight Frhay, yes i think this is the approach i will adopt, along with a cron version that will thin the queue. It seems to be the most elegant solution given the situation and i dare say it can be easily switched between processing a single players events or processing the whole servers... Time for some testing i think, many thanks all :) \$\endgroup\$
    – user26273
    Feb 14, 2013 at 19:46
  • \$\begingroup\$ Always glad to help... :) \$\endgroup\$
    – Frhay
    Feb 15, 2013 at 7:52
1
\$\begingroup\$

It's not uncommon to put in a cron script that invokes a PHP script or whatnot every minute or so.

If you need finer granularity, you need a running event processor.

You can also use a message queue service to submit delayed events that invokes an HTTP script when necessary. Batch processing events will be better for power consumption, though. It's easier to go the cron route, which is compatible with most cheap PHP/MySQL web hosts.

\$\endgroup\$
4
  • \$\begingroup\$ I had considered the cron approach but the nature of the events would mean i'd need a cron running every second which makes me think the continuously running event processor will be the way to go. Thanks for the suggestions, i'll do some reading up on them :) \$\endgroup\$
    – user26273
    Feb 13, 2013 at 20:47
  • 1
    \$\begingroup\$ Do you really need them every second? A good part of game design is taking technical limitations and smoothly integrating them into the design. Might be easier to change the game than to use different tech. \$\endgroup\$ Feb 13, 2013 at 21:08
  • \$\begingroup\$ I beleive so yes, though perhaps not initially with just a few players. However when it comes to scaling for more players there could be multiple events happening per second and not just simple "build" events but "battle" events that could effect many aspects of different players accounts, not all of whom would be online on the time. \$\endgroup\$
    – user26273
    Feb 13, 2013 at 21:24
  • \$\begingroup\$ I should add, similar build queues can be seen in games like travian, grepolis etc. I'm curious how these games handle the events? \$\endgroup\$
    – user26273
    Feb 13, 2013 at 21:35
0
\$\begingroup\$

However, it is my understanding that i would need a script that is running permanently on the server and continually checks the event database for delayed events to execute and process them as needed. My question is, is this the right approach or should i be tackling the "event que" differently?

Assuming your game is only played through player prompts/observation (more on that later), there are simpler ways of doing this.

Assume I am building a house, and it is currently Jan 1, 2019 at 00:00 precisely. If you were to store the building's status as a history table, the game could register two statuses already:

 Player | Building | Status   | Timestamp
=================================================
 Flater | House    | Building | 01/01/2019 00:00
 Flater | House    | Built    | 01/01/2019 00:15

Note that the second line is in the future. But when you fetch the item's current status, you use a query similar to:

SELECT TOP 1 Status
FROM BuildingStatusHistory
WHERE Timestamp <= GETDATE()   -- GETDATE() give you the current date and time
ORDER BY Timestamp DESC

What you will notice is that when I refresh the page before 00:15, the query will return "Building". But when I query the page at 00:15 (or later), the same query will return "Built", even though we did not actually change the database since then.

If you want to show a progress bar, you can do this based on three values:

  • The timestamp of the most recent (already active) status = left side of the progress bar
  • The current time = progress of the progress bar
  • The timestamp of the next event (that is not yet active) = right side of the bar

Assuming your game is only played through player prompts/observation

What I mean by this is that the game is played through player observation:

  • The player sends a web request for information
  • The backend runs a query on the DB
  • The player receives the information they need

If your game is expected to e.g. send out emails to the player when their house is built, that's different. Then, you need some agent that sends that email precisely at 00:15 when the house is built, and this means you either need an always-online component, or (if it's acceptable for your use case) you used a scheduled service that regularly polls the database to see if there are actions that need to be taken (which means your players may have to wait for their email a bit longer).

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .