// player_c.cpp -- Player cache routines. // // $Id: player_c.cpp,v 1.11 2005/06/11 19:11:46 sdennis Exp $ // #include "copyright.h" #include "autoconf.h" #include "config.h" #include "externs.h" #include "attrs.h" typedef struct player_cache { dbref player; int money; int queue; int qmax; int cflags; struct player_cache *next; } PCACHE; CHashTable pcache_htab; PCACHE *pcache_head; #define PF_REF 0x0002 #define PF_MONEY_CH 0x0004 void pcache_init(void) { pool_init(POOL_PCACHE, sizeof(PCACHE)); pcache_head = NULL; } static void pcache_reload1(dbref player, PCACHE *pp) { const char *cp = atr_get_raw(player, A_MONEY); if (cp && *cp) { pp->money = mux_atol(cp); } else { pp->cflags |= PF_MONEY_CH; pp->money = 0; } int m = -1; cp = atr_get_raw(player, A_QUEUEMAX); if (cp && *cp) { m = mux_atol(cp); if (m < 0) { m = -1; } } pp->qmax = m; } PCACHE *pcache_find(dbref player) { if ( !Good_obj(player) || !OwnsOthers(player)) { return NULL; } PCACHE *pp = (PCACHE *)hashfindLEN(&player, sizeof(player), &pcache_htab); if (pp) { pp->cflags |= PF_REF; return pp; } pp = alloc_pcache("pcache_find"); pp->queue = 0; pp->cflags = PF_REF; pp->player = player; pcache_reload1(player, pp); pp->next = pcache_head; pcache_head = pp; hashaddLEN(&player, sizeof(player), pp, &pcache_htab); return pp; } void pcache_reload(dbref player) { PCACHE *pp = pcache_find(player); if (!pp) { return; } pcache_reload1(player, pp); } static void pcache_save(PCACHE *pp) { IBUF tbuf; if (pp->cflags & PF_MONEY_CH) { mux_ltoa(pp->money, tbuf); atr_add_raw(pp->player, A_MONEY, tbuf); } pp->cflags &= ~PF_MONEY_CH; } void pcache_trim(void) { PCACHE *pp = pcache_head; PCACHE *pplast = NULL; while (pp) { PCACHE *ppnext = pp->next; if ( pp->queue || (pp->cflags & PF_REF)) { // This entry either has outstanding commands in the queue or we need to let it age. // pp->cflags &= ~PF_REF; pplast = pp; } else { // Unlink and destroy this entry. // if (pplast) { pplast->next = ppnext; } else { pcache_head = ppnext; } pcache_save(pp); hashdeleteLEN(&(pp->player), sizeof(pp->player), &pcache_htab); free_pcache(pp); } pp = ppnext; } } void pcache_sync(void) { PCACHE *pp = pcache_head; while (pp) { pcache_save(pp); pp = pp->next; } } int a_Queue(dbref player, int adj) { if (OwnsOthers(player)) { PCACHE *pp = pcache_find(player); if (pp) { pp->queue += adj; return pp->queue; } } return 0; } int QueueMax(dbref player) { int m = 0; if (OwnsOthers(player)) { PCACHE *pp = pcache_find(player); if (pp) { if (pp->qmax >= 0) { m = pp->qmax; } else { // @queuemax was not valid so we use the game-wide limit. // m = mudconf.queuemax; if ( Wizard(player) && m < mudstate.db_top + 1) { m = mudstate.db_top + 1; } } } } return m; } int Pennies(dbref obj) { if (mudstate.bStandAlone) { const char *cp = atr_get_raw(obj, A_MONEY); if (cp) { return mux_atol(cp); } } else if (OwnsOthers(obj)) { PCACHE *pp = pcache_find(obj); if (pp) { return pp->money; } } return 0; } void s_Pennies(dbref obj, int howfew) { if (mudstate.bStandAlone) { IBUF tbuf; mux_ltoa(howfew, tbuf); atr_add_raw(obj, A_MONEY, tbuf); } else if (OwnsOthers(obj)) { PCACHE *pp = pcache_find(obj); if (pp) { pp->money = howfew; pp->cflags |= PF_MONEY_CH; } } }