mongoose concurrency problem in a MMO game

102 views
Skip to first unread message

Cesar Langlois

unread,
Jul 1, 2013, 8:03:50 AM7/1/13
to mongoo...@googlegroups.com
Hi everyone
I'm working on a game made with nodejs and mongoose.

This is a MMO game on an hexagonal map.
Each player owns one or more entities which can fight IA entities on the hexagonal map.

Each entity is an entry in my entity collection, whith fields like : life, maxLife, type, minAttack, maxAttack, defense, position ...

So for each fight, I will do that :
 - find a target on the same hexa of my fighter
 - then I will subtract its life by my fighter attack value
 - then set the target flag death if its life is equal or below 0
 - then update my entity parameters ( killcount, damagecount )
 - then save the target.

So the code is more or less  the following :



exports
.fight = function( fighter, hexa, callback )
{
  
var conditions = fighter.type != 'ia' ?
  
{ 'position.x' : hexa.position.x, 'position.y' : hexa.position.y, '_id' : { $ne: fighter._id }, 'type' : 'ia', 'dead': false } :
  
{ 'position.x' : hexa.position.x, 'position.y' : hexa.position.y, '_id' : { $ne: fighter._id }, 'type' : { $ne: 'ia' }, 'dead' : false };


  
EntityModel.find( conditions ).limit( 1 ).exec( function( err, targets ) {

    if ( targets.length == 0 )
    {
      callback( null, fighter);
      return;
    }

    
var target = targets[ 0 ];
    
var oldLife = target.life;
    
var attack = fighter.minAttack + Math.random() * ( fighter.maxAttack - fighter.minAttack ) - target.def;
    attack
= attack > 0 ? attack : 0;
    target
.life = oldLife - attack;
    
var damageCount = ( target.life > 0 ) ? attack : oldLife;
    
fighter.damageCount += damageCount;
 

    
if ( target.life <= 0 )
    
{
      
fighter.killCount ++;
      
target.remove( function( err ) {
        
fighter.save( function( err, fighter ) {
          
callback( null, fighter );
        
} );
      
} );
    
}
    
else
    
{ 
      target
.save( function( err, target ) {
        
fighter.save( function( err, fighter )  
          callback( null, fighter );
        
} );
      
} );
    
}

  } );

}





My problem is the following :

if two fighters fight the same target at the same time, one of the fights may be skipped because the life value of the target may be read before the end of the first fight, and then the first fight will be skipped.

I've got the same problem if I want to regen an entity; if a fight is done while I'm doing a regen on an entity, the regen or the fight may not be well done.

Maybe an update instead of a save may solve this kind of issue, but sometimes, I'm not sure that i can do all these operations in just one update.



Si, if anyone has some information about solving these kinds of issue, i'm be glad to head about it.

Best regards

Cesar Langlois


Paul DeCoursey

unread,
Jul 1, 2013, 8:36:44 AM7/1/13
to mongoo...@googlegroups.com
$inc is an atomic operation and can be done on an update. That would solve for skipped attacks. You might still have weirdness where an attack kills a target and regen happens before the death flag is set and one user sees the target as dead but another does not.

Perhaps a queue that processes these events atomically. It's still difficult to deal with concurrency. I know a few game developers, I can ask them what they think.

Sent from my iPhone
--
Documentation - http://mongoosejs.com/
Plugins - http://plugins.mongoosejs.com/
Bug Reports - http://github.com/learnboost/mongoose
Production Examples - http://mongoosejs.tumblr.com/
StackOverflow - http://stackoverflow.com/questions/tagged/mongoose
Google Groups - https://groups.google.com/forum/?fromgroups#!forum/mongoose-orm
Twitter - https://twitter.com/mongoosejs
IRC - #mongoosejs
---
You received this message because you are subscribed to the Google Groups "Mongoose Node.JS ODM" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mongoose-orm...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

langlois cesar

unread,
Jul 2, 2013, 6:55:32 AM7/2/13
to mongoo...@googlegroups.com
Thank you for your quick answer.
Actually, I've worked on a queue system to manage several fights at the same time, and it works pretty well, but it's difficult to generalize this to all my objects and methods, and it doesnt seem to be very efficient.

I always am glad to hear from other people, so if the developpers you know have more tips about these kind of problems, it would be awesome to have their advices.

Best regards
Cesar


2013/7/1 Paul DeCoursey <pdeco...@gmail.com>
You received this message because you are subscribed to a topic in the Google Groups "Mongoose Node.JS ODM" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/mongoose-orm/cCxlcIcuS2g/unsubscribe.
To unsubscribe from this group and all its topics, send an email to mongoose-orm...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages