views:

124

answers:

4

This is related to preventing webform resubmission, however this time the context is a web-based RPG. After the player defeats a monster, it would drop an item. So I would want to prevent the user from hitting the back button, or keep refreshing, to 'dupe' the item-drop.

As item drop is frequent, using a DB to store a unique 'drop-transaction-id' seems infeasible to me. I am entertaining an idea below:

  1. For each combat, creating an unique value based on the current date-time, user's id and store it into DB and session. It is possible that given a userid, you can fetch the value back

  2. If the value from session exists in the DB, then the 'combat' is valid and allow the user to access all pages relevant to combat. If it does not exist in DB, then a new combat state is started

  3. When combat is over, the unique value is cleared from DB.

  4. Values which is 30mins old in the DB are purged.

Any opinions, improvements, or pitfalls to this method are welcomed

+2  A: 

Seems like a reasonable approach. I assume you're storing the fact that the player is in combat somewhere anyway. Otherwise, they can just close their browser if they want to avoid a fight?

The combat ending and loot dropping should be treated as an atomary operation. If there is no fight, there can't be any dropping loot.

Thorarin
+1  A: 

That depends on your game design: Do you go more in the direction of roguelikes where only turns count, and therefore long pauses in between moves are definitely possible (like consulting other people via chatroom, note: in NetHack that is not considered cheating)? Can users only save their games on certain points or at any place? That makes a huge difference in the design, e.g. making way for exploits similar to the one Thorarin mentions.

If your game goes the traditional roguelike route of only one save, turn basement and permadeath, then it would be possible to save the number of the current turn for any given character along with any game related information (inventory, maps, enemies and their state), and then check against that at any action of the player, therefore to prevent playing the turn twice.

Residuum
A: 

Alternatively you could bundle everything up in client side javascript, so that even if they did resubmit the form it would generate an entirely new combat/treasure encounter.

Steerpike
... and therefore make them replay the encounter when they are unsatisfied with the inferior treasure from the first roll.
Residuum
If the game is primarily combat based that's not going to make a difference, depends on how the game plays.
Steerpike
Then you end up with piss easy exploits. Never Trust The Client.
Charlie Somerville
+2  A: 

This question is very subjective, there's things you can do or can not do, depending on the already existing data / framework around it.

The solution you've provided should work, but it depends on the unique combat/loot/user data you have available.

I take it this is what you think is best? It's what I think is best :)

  1. Get the userID, along with a unique piece of data from that fight. Something like combat start time, combat end time, etc
  2. Store it in a Database, or what ever storage system you have
  3. Once you collect the loot, delete that record

That way if the that userID, and that unique fight data exists, they haven't got their loot.

And you are right; tracking each piece of loot is too much, you're better off temporarily storing the data.

Sam