mux/src/mguests.cpp

Go to the documentation of this file.
00001 // mguests.cpp -- Multiguest code originally ported from DarkZone.
00002 // Multiguest code rewritten by Matthew J. Leavitt (zenty).
00003 // Idea for @list guest from Ashen-Shugar and the great team of RhostMUSH
00004 //
00005 // $Id: mguests.cpp,v 1.17 2006/01/31 00:17:26 sdennis Exp $
00006 //
00007 
00008 #include "copyright.h"
00009 #include "autoconf.h"
00010 #include "config.h"
00011 #include "externs.h"
00012 
00013 #include <stdlib.h>
00014 
00015 #include "attrs.h"
00016 #include "mguests.h"
00017 #include "powers.h"
00018 #include "comsys.h"
00019 
00020 #define GUEST_HYSTERESIS 20
00021 
00022 CGuests Guest;
00023 
00024 CGuests::CGuests(void)
00025 {
00026     Guests = NULL;
00027     nGuests = 0;
00028     nMaxGuests = 0;
00029 }
00030 
00031 CGuests::~CGuests(void)
00032 {
00033     if (Guests)
00034     {
00035         MEMFREE(Guests);
00036         Guests = NULL;
00037         nGuests = 0;
00038         nMaxGuests = 0;
00039     }
00040 }
00041 
00042 void CGuests::StartUp(void)
00043 {
00044     if (  !Good_obj(mudconf.guest_char)
00045        || mudconf.number_guests <= 0)
00046     {
00047         // The guest system is effectively disabled.
00048         //
00049         return;
00050     }
00051 
00052 
00053     // SizeGuests(mudconf.min_guests);
00054 
00055     // Search the Database for Guest chars and snag em.
00056     //
00057     dbref thing;
00058     DO_WHOLE_DB(thing)
00059     {
00060         if (  Guest(thing)
00061            && isPlayer(thing))
00062         {
00063             SizeGuests(nGuests+1);
00064             Guests[nGuests] = thing;
00065             nGuests++;
00066         }
00067     }
00068 
00069     // Create the Minimum # of guests.
00070     //
00071     for (; nGuests < mudconf.min_guests; nGuests++)
00072     {
00073         SizeGuests(nGuests+1);
00074         Guests[nGuests] = MakeGuestChar();
00075 
00076         // If we couldn't create guest character, break out and let later
00077         // functions handle it.
00078         //
00079         if (Guests[nGuests] == NOTHING)
00080         {
00081             break;
00082         }
00083     }
00084 }
00085 
00086 void CGuests::SizeGuests(int nMin)
00087 {
00088     // We must have at least nMin, but if nMin is sufficiently below
00089     // nMaxGuests, we can also shrink.
00090     //
00091     if (nMin < nGuests)
00092     {
00093         nMin = nGuests;
00094     }
00095     if (  nMaxGuests <= nMin + GUEST_HYSTERESIS
00096        && nMin <= nMaxGuests)
00097     {
00098         return;
00099     }
00100 
00101     dbref *newGuests = (dbref *)MEMALLOC(nMin * sizeof(dbref));
00102     if (Guests)
00103     {
00104         memcpy(newGuests, Guests, nGuests * sizeof(dbref));
00105         MEMFREE(Guests);
00106         Guests = NULL;
00107     }
00108     Guests = newGuests;
00109     nMaxGuests = nMin;
00110 }
00111 
00112 const char *CGuests::Create(DESC *d)
00113 {
00114     // We don't have a main guest character, break out.
00115     //
00116     if (!Good_obj(mudconf.guest_char))
00117     {
00118         return NULL;
00119     }
00120 
00121     // If we have a guest character, let's use it
00122     //
00123     int i;
00124     for (i = 0; i < nGuests; i++)
00125     {
00126         dbref guest_player = Guests[i];
00127 
00128         // If we have something in the list that isn't a guest, lets
00129         // just drop it and make a new one.
00130         //
00131         if (  !Good_obj(guest_player)
00132            || !isPlayer(guest_player)
00133            || !Guest(guest_player))
00134         {
00135             guest_player = Guests[i] = MakeGuestChar();
00136             if (guest_player == NOTHING)
00137             {
00138                 return NULL;
00139             }
00140             else
00141             {
00142                 return Name(guest_player);
00143             }
00144         }
00145 
00146         if (!Connected(guest_player))
00147         {
00148             // Lets try to grab our own name, if we don't have it.
00149             //
00150             sprintf(name, "%s%d", mudconf.guest_prefix, i+1);
00151             dbref j = lookup_player(GOD, name, false);
00152             if (j == NOTHING)
00153             {
00154                 delete_player_name(guest_player, Name(guest_player));
00155                 s_Name(guest_player, name);
00156                 add_player_name(guest_player, Name(guest_player));
00157             }
00158             else
00159             {
00160                 // Release comsys and @mail state.
00161                 //
00162                 ReleaseAllResources(guest_player);
00163                 AddToGuestChannel(guest_player);
00164             }
00165 
00166             // Reset the flags back to the default.
00167             //
00168             db[guest_player].fs = mudconf.player_flags;
00169 
00170             // Add the type and remove wizard.
00171             //
00172             db[guest_player].fs.word[FLAG_WORD1] |= TYPE_PLAYER;
00173             db[guest_player].fs.word[FLAG_WORD1] &= ~WIZARD;
00174 
00175             // Make sure they're a guest.
00176             //
00177             s_Guest(guest_player);
00178 
00179             move_object(guest_player, mudconf.start_room);
00180             s_Pennies(guest_player, Pennies(mudconf.guest_char));
00181             s_Zone(guest_player, Zone(mudconf.guest_char));
00182             s_Parent(guest_player, Parent(mudconf.guest_char));
00183 
00184             // Wipe the attributes.
00185             //
00186             WipeAttrs(guest_player);
00187             ChangePassword(guest_player, GUEST_PASSWORD);
00188 
00189             // Copy them back.
00190             //
00191             atr_cpy(guest_player, mudconf.guest_char, true);
00192             return Name(guest_player);
00193         }
00194     }
00195 
00196     if (nGuests >= mudconf.number_guests)
00197     {
00198         queue_string(d, "Sorry, All guests are currently busy. Try again later.\n");
00199         return NULL;
00200     }
00201     dbref newGuest = MakeGuestChar();
00202     if (newGuest == NOTHING)
00203     {
00204         queue_string(d, "GAME: Error creating guest, please try again later.\n");
00205         return NULL;
00206     }
00207     SizeGuests(nGuests+1);
00208     Guests[nGuests] = newGuest;
00209     nGuests++;
00210     return Name(newGuest);
00211 }
00212 
00213 void CGuests::CleanUp(void)
00214 {
00215     // Verify that our existing pool of guests are reasonable. Replace any
00216     // unreasonable dbrefs.
00217     //
00218     int nPool = nGuests;
00219     if (mudconf.min_guests < nGuests)
00220     {
00221         nPool = mudconf.min_guests;
00222     }
00223     int i;
00224     for (i = 0; i < nPool; i++)
00225     {
00226         if (  !Good_obj(Guests[i])
00227            || !isPlayer(Guests[i])
00228            || !Guest(Guests[i]))
00229         {
00230             Guests[i] = MakeGuestChar();
00231         }
00232     }
00233 
00234     if (nGuests <= mudconf.min_guests)
00235     {
00236         return;
00237     }
00238 
00239     // We have more than the minimum number of guests in the pool. Let's
00240     // see if there are any guests beyond that minimum number that we can
00241     // trim out of the pool.
00242 
00243     // PASS 1: Move connected guests to the beginning of the list.
00244     //
00245     int itmp;
00246     int currGuest = mudconf.min_guests;
00247     for (i = mudconf.min_guests; i < nGuests; i++)
00248     {
00249         if (Connected(Guests[i]))
00250         {
00251             if (i > currGuest)
00252             {
00253                 itmp = Guests[currGuest];
00254                 Guests[currGuest] = Guests[i];
00255                 Guests[i] = itmp;
00256             }
00257             currGuest++;
00258         }
00259     }
00260 
00261     // PASS 2: Destroy unconnected guests.
00262     //
00263     itmp = nGuests;
00264     for (i = mudconf.min_guests; i < itmp;i++)
00265     {
00266         if (!Connected(Guests[i]))
00267         {
00268             if (Good_obj(Guests[i]))
00269             {
00270                 DestroyGuestChar(Guests[i]);
00271             }
00272             nGuests--;
00273         }
00274     }
00275     SizeGuests(nGuests);
00276 }
00277 
00278 dbref CGuests::MakeGuestChar(void)
00279 {
00280     // Search for the first available name.
00281     //
00282     int i;
00283     dbref player;
00284     bool bFound = false;
00285     for (i = 0; i < mudconf.number_guests;i++)
00286     {
00287         sprintf(name, "%s%d", mudconf.guest_prefix, i + 1);
00288         player = lookup_player(GOD, name, false);
00289         if (player == NOTHING)
00290         {
00291             bFound = true;
00292             break;
00293         }
00294     }
00295     if (!bFound)
00296     {
00297         return NOTHING;
00298     }
00299 
00300     // Make the player.
00301     //
00302     const char *pmsg;
00303     player = create_player(name, GUEST_PASSWORD, mudconf.guest_nuker, false, &pmsg);
00304 
00305     // No Player Created?? Return error.
00306     //
00307     if (player == NOTHING)
00308     {
00309         log_text("GUEST: failed in create_player" ENDLINE);
00310         return NOTHING;
00311     }
00312 
00313     // Lets make the player a guest, move it into the starting room,
00314     // don't let it be a wizard, and setup other basics.
00315     //
00316     AddToGuestChannel(player);
00317     s_Guest(player);
00318     move_object(player, mudconf.start_room);
00319     db[player].fs.word[FLAG_WORD1] &= ~WIZARD;
00320     s_Pennies(player, Pennies(mudconf.guest_char));
00321     s_Zone(player, Zone(mudconf.guest_char));
00322     s_Parent(player, Parent(mudconf.guest_char));
00323 
00324     // Copy the attributes.
00325     //
00326     atr_cpy(player, mudconf.guest_char, true);
00327 
00328     // Lock em!
00329     //
00330     do_lock(player, player, player, A_LOCK, 2, tprintf("#%d", player), "=me");
00331     do_lock(player, player, player, A_LENTER, 2, tprintf("#%d", player), "=me");
00332 
00333     // return em!
00334     //
00335     return player;
00336 }
00337 
00338 void CGuests::DestroyGuestChar(dbref guest)
00339 {
00340     // Don't destroy anything not a guest.
00341     //
00342     if (!Guest(guest))
00343     {
00344         return;
00345     }
00346 
00347     // Make sure the nuker is ok.
00348     //
00349     if (  !Wizard(mudconf.guest_nuker)
00350        || !Good_obj(mudconf.guest_nuker))
00351     {
00352         mudconf.guest_nuker = GOD;
00353     }
00354 
00355     // Destroy it!
00356     //
00357     destroy_player(mudconf.guest_nuker, guest);
00358 }
00359 
00360 void CGuests::WipeAttrs(dbref guest)
00361 {
00362     olist_push();
00363 
00364     int atr;
00365     char *as;
00366     for (atr = atr_head(guest, &as); atr; atr = atr_next(&as))
00367     {
00368         ATTR *ap = atr_num(atr);
00369         if (ap)
00370         {
00371             // Get the attr and make sure we can modify it.
00372             //
00373             if (bCanSetAttr(GOD, guest, ap))
00374             {
00375                 atr_clr(guest, ap->number);
00376             }
00377         }
00378     }
00379     olist_pop();
00380 }
00381 
00382 bool CGuests::CheckGuest(dbref player)
00383 {
00384     int i;
00385     for (i = 0; i < nGuests; i++)
00386     {
00387         if (Guests[i] == player)
00388         {
00389             return true;
00390         }
00391     }
00392     return false;
00393 }
00394 
00395 // @list guests, thanks Rhost for the idea!
00396 //
00397 void CGuests::ListAll(dbref player)
00398 {
00399     notify(player, "--------------------------- Current Guests Listing ---------------------------");
00400     notify(player, "*Guest #  : Name            dbref  Status     Last Site");
00401     notify(player, "------------------------------------------------------------------------------");\
00402     char *buff = alloc_lbuf("CGuests-ListAll");
00403     int i;
00404     char *LastSite=alloc_lbuf("CGuests-LastSite");
00405     for (i = 0; i < nGuests; i++)
00406     {
00407         dbref aowner;
00408         int aflags;
00409         atr_get_str(LastSite, Guests[i], A_LASTSITE, &aowner, &aflags);
00410         sprintf(buff, "%sGuest %-3d: %-15s #%-5d %-10s %s",
00411                 (i<mudconf.min_guests ? "*" : " "),
00412                 i, Name(Guests[i]), Guests[i],
00413                 (Connected(Guests[i]) ? "Online" : "NotOnline"),
00414                 LastSite);
00415         notify(player, buff);
00416         if (!Good_obj(Guests[i]))
00417         {
00418             notify(player, tprintf("*** Guest %d (#%d) is an invalid object!",
00419                                    i, Guests[i]));
00420         }
00421     }
00422     free_lbuf(LastSite);
00423     notify(player, tprintf("-----------------------------  Total Guests: %-3d -----------------------------", nGuests));
00424     free_lbuf(buff);
00425 }
00426 
00427 void CGuests::AddToGuestChannel(dbref player)
00428 {
00429     if (  mudconf.guests_channel[0] != '\0'
00430        && mudconf.guests_channel_alias[0] != '\0')
00431     {
00432         do_addcom(player, player, player, 0, 2,
00433             mudconf.guests_channel_alias, mudconf.guests_channel);
00434     }
00435 }
00436 
00437 char CGuests::name[50];

Generated on Mon May 28 04:40:10 2007 for MUX by  doxygen 1.4.7