/************************************** if "map" == NULL : server sends a message to all connected client if "map" != NULL : server sends a message to all connected clients on the map **************************************/ void context_broadcast_text(const char * map, const char * text) { context_t * ctx = NULL; context_lock_list(); ctx = context_list_start; if( ctx == NULL ) { context_unlock_list(); return; } do { /* Skip if not in game */ if( ctx->in_game == false ) { continue; } if( context_is_npc(ctx) == true ) { continue; } /* Skip if the player has not selected its character */ if( ctx->id == NULL ) { continue; } if( ctx->map == 0 ) { continue; } if(map) { /* Skip if not on the same map */ if( strcmp(map,ctx->map) != 0 ) { continue; } } network_send_text(ctx->id, text); } while( (ctx=ctx->next)!= NULL ); context_unlock_list(); }
/************************************** Broadcast upload of a character file to all in_game context on the same map **************************************/ void context_broadcast_character(const char * character) { context_t * ctx = NULL; context_t * character_ctx = NULL; char * filename; context_lock_list(); character_ctx = context_find(character); ctx = context_list_start; if( ctx == NULL ) { context_unlock_list(); return; } filename = strconcat(CHARACTER_TABLE,"/",character,NULL); do { if( context_is_npc(ctx) == true ) { continue; } /* Skip if not in game */ if( ctx->in_game == false ) { continue; } /* Skip if not on the same map */ if( ctx->map) { if( strcmp(character_ctx->map,ctx->map) != 0 ) { continue; } } network_send_file(ctx,filename); } while( (ctx=ctx->next)!= NULL ); free(filename); context_unlock_list(); }
/************************************** Spread the data of a context to all in_game context **************************************/ void context_spread(context_t * context) { context_t * ctx = NULL; context_lock_list(); ctx = context_list_start; if( ctx == NULL ) { context_unlock_list(); return; } do { /* Skip if not in game */ if( ctx->in_game == false ) { continue; } if( context_is_npc(ctx) == true ) { continue; } /* Skip if not on the same map or previous map */ if( ctx->map && context->map && context->prev_map) { if( strcmp(context->map,ctx->map) != 0 && strcmp(context->prev_map,ctx->map) != 0 ) { continue; } } network_send_context_to_context(ctx, context); } while( (ctx=ctx->next)!= NULL ); /* The existing context on the previous map should have been deleted, we don't need this any more -> this will generate less network request */ free(context->prev_map); context->prev_map = NULL; context_unlock_list(); }
/***************************** Kick a character out of the game It does not disconnect it. An NPC could re pop from an out of game state. A player can go back in game after choosing a new character id return -1 if fails *****************************/ int character_out_of_game( const char * id) { context_t * ctx; werr(LOGDEBUG,"Kicking %s out of the game",id); ctx = context_find(id); context_set_in_game(ctx,false); context_spread(ctx); if( context_is_npc(ctx) == true ) { /* Wake up NPC */ if( SDL_TryLockMutex (ctx->cond_mutex) == 0 ) { SDL_CondSignal (ctx->cond); SDL_UnlockMutex (ctx->cond_mutex); } } return 0; }
/***************************** Disconnect a character. This kill a NPC AI thread return -1 if fails *****************************/ int character_disconnect(const char * id) { context_t * ctx; werr(LOGDEVELOPER, "Disconnecting %s", id); ctx = context_find(id); context_set_in_game(ctx, false); context_set_connected(ctx, false); context_spread(ctx); if (context_is_npc(ctx) == true) { /* Wake up NPC */ if (SDL_TryLockMutex(ctx->cond_mutex) == 0) { SDL_CondSignal(ctx->cond); SDL_UnlockMutex(ctx->cond_mutex); } } return 0; }