dw_fluffos_v2/
dw_fluffos_v2/fluffos-2.9-ds2.05/
dw_fluffos_v2/fluffos-2.9-ds2.05/ChangeLog.old/
dw_fluffos_v2/fluffos-2.9-ds2.05/Win32/
dw_fluffos_v2/fluffos-2.9-ds2.05/compat/
dw_fluffos_v2/fluffos-2.9-ds2.05/compat/simuls/
dw_fluffos_v2/fluffos-2.9-ds2.05/include/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/clone/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/command/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/data/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/etc/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/include/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/inherit/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/inherit/master/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/log/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/compiler/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/efuns/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/operators/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/u/
dw_fluffos_v2/fluffos-2.9-ds2.05/tmp/
dw_fluffos_v2/fluffos-2.9-ds2.05/windows/
dw_fluffos_v2/lib/
dw_fluffos_v2/lib/binaries/cmds/
dw_fluffos_v2/lib/binaries/cmds/creator/
dw_fluffos_v2/lib/binaries/cmds/living/
dw_fluffos_v2/lib/binaries/cmds/player/
dw_fluffos_v2/lib/binaries/d/admin/obj/
dw_fluffos_v2/lib/binaries/d/liaison/
dw_fluffos_v2/lib/binaries/global/virtual/
dw_fluffos_v2/lib/binaries/global/virtual/setup_compiler/
dw_fluffos_v2/lib/binaries/obj/handlers/autodoc/
dw_fluffos_v2/lib/binaries/obj/handlers/terrain_things/
dw_fluffos_v2/lib/binaries/obj/misc/
dw_fluffos_v2/lib/binaries/obj/misc/buckets/
dw_fluffos_v2/lib/binaries/obj/monster/
dw_fluffos_v2/lib/binaries/obj/reactions/
dw_fluffos_v2/lib/binaries/obj/reagents/
dw_fluffos_v2/lib/binaries/secure/cmds/creator/
dw_fluffos_v2/lib/binaries/secure/master/
dw_fluffos_v2/lib/binaries/std/
dw_fluffos_v2/lib/binaries/std/dom/
dw_fluffos_v2/lib/binaries/std/effects/object/
dw_fluffos_v2/lib/binaries/std/guilds/
dw_fluffos_v2/lib/binaries/std/languages/
dw_fluffos_v2/lib/binaries/std/races/
dw_fluffos_v2/lib/binaries/std/room/
dw_fluffos_v2/lib/binaries/std/room/basic/
dw_fluffos_v2/lib/binaries/std/shops/
dw_fluffos_v2/lib/binaries/std/shops/inherit/
dw_fluffos_v2/lib/binaries/www/
dw_fluffos_v2/lib/cmds/guild-race/
dw_fluffos_v2/lib/cmds/guild-race/crafts/
dw_fluffos_v2/lib/cmds/guild-race/other/
dw_fluffos_v2/lib/cmds/playtester/
dw_fluffos_v2/lib/cmds/playtester/senior/
dw_fluffos_v2/lib/d/admin/
dw_fluffos_v2/lib/d/admin/log/
dw_fluffos_v2/lib/d/admin/mapper/31-10-01/mapmaker/event/
dw_fluffos_v2/lib/d/admin/meetings/
dw_fluffos_v2/lib/d/admin/obj/
dw_fluffos_v2/lib/d/admin/room/we_care/
dw_fluffos_v2/lib/d/admin/save/
dw_fluffos_v2/lib/d/dist/
dw_fluffos_v2/lib/d/dist/mtf/
dw_fluffos_v2/lib/d/dist/pumpkin/
dw_fluffos_v2/lib/d/dist/pumpkin/chars/
dw_fluffos_v2/lib/d/dist/pumpkin/desert/
dw_fluffos_v2/lib/d/dist/pumpkin/gumboot/
dw_fluffos_v2/lib/d/dist/pumpkin/hospital/
dw_fluffos_v2/lib/d/dist/pumpkin/inherit/
dw_fluffos_v2/lib/d/dist/pumpkin/map/
dw_fluffos_v2/lib/d/dist/pumpkin/plain/
dw_fluffos_v2/lib/d/dist/pumpkin/pumpkin/
dw_fluffos_v2/lib/d/dist/pumpkin/save/
dw_fluffos_v2/lib/d/dist/pumpkin/squash/
dw_fluffos_v2/lib/d/dist/pumpkin/terrain/
dw_fluffos_v2/lib/d/dist/pumpkin/woods/
dw_fluffos_v2/lib/d/dist/start/
dw_fluffos_v2/lib/d/learning/TinyTown/buildings/
dw_fluffos_v2/lib/d/learning/TinyTown/map/
dw_fluffos_v2/lib/d/learning/TinyTown/roads/
dw_fluffos_v2/lib/d/learning/add_command/
dw_fluffos_v2/lib/d/learning/arms_and_weps/
dw_fluffos_v2/lib/d/learning/chars/
dw_fluffos_v2/lib/d/learning/cutnpaste/
dw_fluffos_v2/lib/d/learning/examples/npcs/
dw_fluffos_v2/lib/d/learning/examples/player_houses/npcs/
dw_fluffos_v2/lib/d/learning/examples/terrain_map/basic/
dw_fluffos_v2/lib/d/learning/functions/
dw_fluffos_v2/lib/d/learning/handlers/
dw_fluffos_v2/lib/d/learning/help_topics/npcs/
dw_fluffos_v2/lib/d/learning/help_topics/objects/
dw_fluffos_v2/lib/d/learning/help_topics/rcs_demo/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/crowd/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/situations/
dw_fluffos_v2/lib/d/learning/items/
dw_fluffos_v2/lib/d/learning/save/
dw_fluffos_v2/lib/d/liaison/
dw_fluffos_v2/lib/d/liaison/NEWBIE/doc/
dw_fluffos_v2/lib/d/liaison/NEWBIE/save/oldlog/
dw_fluffos_v2/lib/db/
dw_fluffos_v2/lib/doc/
dw_fluffos_v2/lib/doc/creator/
dw_fluffos_v2/lib/doc/creator/autodoc/include/reaction/
dw_fluffos_v2/lib/doc/creator/autodoc/include/ritual_system/
dw_fluffos_v2/lib/doc/creator/autodoc/include/talker/
dw_fluffos_v2/lib/doc/creator/autodoc/include/terrain_map/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/baggage/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/clock/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/clothing/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/cont_save/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/corpse/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/money/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/monster/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/scabbard/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/service_provider/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/state_changer/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/wand/
dw_fluffos_v2/lib/doc/creator/autodoc/std/book_dir/
dw_fluffos_v2/lib/doc/creator/autodoc/std/key/
dw_fluffos_v2/lib/doc/creator/autodoc/std/learning/
dw_fluffos_v2/lib/doc/creator/autodoc/std/map/
dw_fluffos_v2/lib/doc/creator/autodoc/std/race/
dw_fluffos_v2/lib/doc/creator/autodoc/std/weapon_logic/
dw_fluffos_v2/lib/doc/creator/files/
dw_fluffos_v2/lib/doc/creator/policy/
dw_fluffos_v2/lib/doc/creator/room/
dw_fluffos_v2/lib/doc/effects/
dw_fluffos_v2/lib/doc/ideas/
dw_fluffos_v2/lib/doc/known_command/
dw_fluffos_v2/lib/doc/lpc/basic_manual/
dw_fluffos_v2/lib/doc/lpc/intermediate/
dw_fluffos_v2/lib/doc/new/add_command/
dw_fluffos_v2/lib/doc/new/handlers/
dw_fluffos_v2/lib/doc/new/living/
dw_fluffos_v2/lib/doc/new/living/race/
dw_fluffos_v2/lib/doc/new/living/spells/
dw_fluffos_v2/lib/doc/new/player/
dw_fluffos_v2/lib/doc/new/room/guild/
dw_fluffos_v2/lib/doc/new/room/outside/
dw_fluffos_v2/lib/doc/new/room/storeroom/
dw_fluffos_v2/lib/doc/object/
dw_fluffos_v2/lib/doc/playtesters/
dw_fluffos_v2/lib/doc/policy/
dw_fluffos_v2/lib/doc/weapons/
dw_fluffos_v2/lib/global/handlers/
dw_fluffos_v2/lib/global/virtual/setup_compiler/
dw_fluffos_v2/lib/include/
dw_fluffos_v2/lib/include/cmds/
dw_fluffos_v2/lib/include/effects/
dw_fluffos_v2/lib/include/npc/
dw_fluffos_v2/lib/include/shops/
dw_fluffos_v2/lib/net/daemon/chars/
dw_fluffos_v2/lib/net/inherit/
dw_fluffos_v2/lib/net/intermud3/
dw_fluffos_v2/lib/net/intermud3/services/
dw_fluffos_v2/lib/net/obj/
dw_fluffos_v2/lib/net/save/
dw_fluffos_v2/lib/net/smnmp/
dw_fluffos_v2/lib/net/snmp/
dw_fluffos_v2/lib/obj/amulets/
dw_fluffos_v2/lib/obj/b_day/
dw_fluffos_v2/lib/obj/examples/
dw_fluffos_v2/lib/obj/food/alcohol/
dw_fluffos_v2/lib/obj/food/chocolates/
dw_fluffos_v2/lib/obj/food/fruits/
dw_fluffos_v2/lib/obj/food/meat/
dw_fluffos_v2/lib/obj/food/nuts/
dw_fluffos_v2/lib/obj/food/seafood/
dw_fluffos_v2/lib/obj/food/vegetables/
dw_fluffos_v2/lib/obj/fungi/
dw_fluffos_v2/lib/obj/furnitures/artwork/
dw_fluffos_v2/lib/obj/furnitures/bathroom/
dw_fluffos_v2/lib/obj/furnitures/beds/
dw_fluffos_v2/lib/obj/furnitures/cabinets/
dw_fluffos_v2/lib/obj/furnitures/chairs/
dw_fluffos_v2/lib/obj/furnitures/chests/
dw_fluffos_v2/lib/obj/furnitures/clocks/
dw_fluffos_v2/lib/obj/furnitures/crockery/
dw_fluffos_v2/lib/obj/furnitures/cupboards/
dw_fluffos_v2/lib/obj/furnitures/cushions/
dw_fluffos_v2/lib/obj/furnitures/fake_plants/
dw_fluffos_v2/lib/obj/furnitures/lamps/
dw_fluffos_v2/lib/obj/furnitures/mirrors/
dw_fluffos_v2/lib/obj/furnitures/outdoor/
dw_fluffos_v2/lib/obj/furnitures/safes/
dw_fluffos_v2/lib/obj/furnitures/shelves/
dw_fluffos_v2/lib/obj/furnitures/sideboards/
dw_fluffos_v2/lib/obj/furnitures/sofas/
dw_fluffos_v2/lib/obj/furnitures/stoves/
dw_fluffos_v2/lib/obj/furnitures/tables/
dw_fluffos_v2/lib/obj/furnitures/wardrobes/
dw_fluffos_v2/lib/obj/handlers/
dw_fluffos_v2/lib/obj/handlers/autodoc/
dw_fluffos_v2/lib/obj/jewellery/anklets/
dw_fluffos_v2/lib/obj/jewellery/bracelets/
dw_fluffos_v2/lib/obj/jewellery/earrings/
dw_fluffos_v2/lib/obj/jewellery/misc/
dw_fluffos_v2/lib/obj/jewellery/necklaces/
dw_fluffos_v2/lib/obj/jewellery/rings/
dw_fluffos_v2/lib/obj/media/
dw_fluffos_v2/lib/obj/misc/buckets/
dw_fluffos_v2/lib/obj/misc/jars/
dw_fluffos_v2/lib/obj/misc/papers/
dw_fluffos_v2/lib/obj/misc/player_shop/
dw_fluffos_v2/lib/obj/misc/shops/
dw_fluffos_v2/lib/obj/misc/traps/
dw_fluffos_v2/lib/obj/monster/
dw_fluffos_v2/lib/obj/monster/godmother/
dw_fluffos_v2/lib/obj/monster/transport/
dw_fluffos_v2/lib/obj/plants/inherit/
dw_fluffos_v2/lib/obj/potions/
dw_fluffos_v2/lib/open/boards/
dw_fluffos_v2/lib/save/autodoc/
dw_fluffos_v2/lib/save/bank_accounts/
dw_fluffos_v2/lib/save/boards/frog/
dw_fluffos_v2/lib/save/books/bed_catalog/
dw_fluffos_v2/lib/save/creators/
dw_fluffos_v2/lib/save/mail/
dw_fluffos_v2/lib/save/mail/p/
dw_fluffos_v2/lib/save/soul/data/
dw_fluffos_v2/lib/save/tasks/
dw_fluffos_v2/lib/save/vaults/
dw_fluffos_v2/lib/secure/cmds/lord/
dw_fluffos_v2/lib/secure/config/
dw_fluffos_v2/lib/secure/items/
dw_fluffos_v2/lib/secure/player/
dw_fluffos_v2/lib/soul/
dw_fluffos_v2/lib/soul/i/
dw_fluffos_v2/lib/soul/j/
dw_fluffos_v2/lib/soul/k/
dw_fluffos_v2/lib/soul/o/
dw_fluffos_v2/lib/soul/q/
dw_fluffos_v2/lib/soul/to_approve/
dw_fluffos_v2/lib/soul/u/
dw_fluffos_v2/lib/soul/v/
dw_fluffos_v2/lib/soul/wish_list/
dw_fluffos_v2/lib/soul/y/
dw_fluffos_v2/lib/soul/z/
dw_fluffos_v2/lib/std/creator/
dw_fluffos_v2/lib/std/effects/
dw_fluffos_v2/lib/std/effects/attached/
dw_fluffos_v2/lib/std/effects/external/
dw_fluffos_v2/lib/std/effects/fighting/
dw_fluffos_v2/lib/std/effects/other/
dw_fluffos_v2/lib/std/environ/
dw_fluffos_v2/lib/std/guilds/
dw_fluffos_v2/lib/std/hospital/
dw_fluffos_v2/lib/std/house/
dw_fluffos_v2/lib/std/house/onebedhouse/
dw_fluffos_v2/lib/std/house/onebedhut/
dw_fluffos_v2/lib/std/house/tworoomflat/
dw_fluffos_v2/lib/std/languages/
dw_fluffos_v2/lib/std/liquids/
dw_fluffos_v2/lib/std/nationality/
dw_fluffos_v2/lib/std/nationality/accents/
dw_fluffos_v2/lib/std/nationality/accents/national/
dw_fluffos_v2/lib/std/nationality/accents/regional/
dw_fluffos_v2/lib/std/npc/goals/
dw_fluffos_v2/lib/std/npc/goals/basic/
dw_fluffos_v2/lib/std/npc/goals/misc/
dw_fluffos_v2/lib/std/npc/inherit/
dw_fluffos_v2/lib/std/npc/plans/
dw_fluffos_v2/lib/std/npc/plans/basic/
dw_fluffos_v2/lib/std/outsides/
dw_fluffos_v2/lib/std/races/shadows/
dw_fluffos_v2/lib/std/room/basic/topography/
dw_fluffos_v2/lib/std/room/controller/
dw_fluffos_v2/lib/std/room/controller/topography/
dw_fluffos_v2/lib/std/room/furniture/games/
dw_fluffos_v2/lib/std/room/furniture/inherit/
dw_fluffos_v2/lib/std/room/inherit/carriage/
dw_fluffos_v2/lib/std/room/inherit/topography/
dw_fluffos_v2/lib/std/room/punishments/
dw_fluffos_v2/lib/std/room/topography/area/
dw_fluffos_v2/lib/std/room/topography/iroom/
dw_fluffos_v2/lib/std/room/topography/milestone/
dw_fluffos_v2/lib/std/shadows/
dw_fluffos_v2/lib/std/shadows/attached/
dw_fluffos_v2/lib/std/shadows/curses/
dw_fluffos_v2/lib/std/shadows/disease/
dw_fluffos_v2/lib/std/shadows/fighting/
dw_fluffos_v2/lib/std/shadows/room/
dw_fluffos_v2/lib/std/shops/controllers/
dw_fluffos_v2/lib/std/shops/objs/
dw_fluffos_v2/lib/std/shops/player_shop/
dw_fluffos_v2/lib/std/shops/player_shop/office_code/
dw_fluffos_v2/lib/std/socket/
dw_fluffos_v2/lib/www/
dw_fluffos_v2/lib/www/external/autodoc/
dw_fluffos_v2/lib/www/external/java/telnet/Documentation/
dw_fluffos_v2/lib/www/external/java/telnet/Documentation/images/
dw_fluffos_v2/lib/www/external/java/telnet/examples/
dw_fluffos_v2/lib/www/external/java/telnet/tools/
dw_fluffos_v2/lib/www/pics/
dw_fluffos_v2/lib/www/secure/creator/
dw_fluffos_v2/lib/www/secure/editors/
dw_fluffos_v2/lib/www/secure/survey_results/
dw_fluffos_v2/win32/
/* $Id: multiplayer.c,v 1.17 2003/05/30 06:23:05 ceres Exp $ */
/**
 * Keeps track of the marked multi players.
 * Called by the login handler, checking people against a list of
 * previous multiplayers, and if they are on the list, check if
 * they are already on.
 * <pre><code>
 * vars are:
 *  string *gits: an array of names of suspected multiplayers
 *  string *denied_parcels: an array of names of multiplayers prevented from
 *                          using the parcel system for sending parcels
 *  mapping allowed: the keys are the names of verified non-multiplayers,
 *                   the values are the names of people they are allowed to
 *                   play with.
 * </pre></code>
 */

#include <login_handler.h>
#include <playerinfo.h>

#define SAVE_FILE   "/save/multiplayer"
#define ALIST "/secure/alist"
#define ALLOWED_ITEMS ({ "/obj/misc/club_badge", "/obj/misc/al_receipt" })
string *denied_parcels;
mapping allowed;

protected void create() {
  string denied_parcel;
  int changed = 0;

  denied_parcels = ({ });
  allowed = ([ ]);
  seteuid(master()->creator_file(file_name()));
  if (file_size(SAVE_FILE + ".o") > 0) {
    unguarded((: restore_object, SAVE_FILE, 1 :));
  }

  foreach (denied_parcel in denied_parcels) {
    if (!PLAYER_HANDLER->test_user(denied_parcel)) {
      denied_parcels -= ({ denied_parcel });
      changed = 1;
    }
  }
  if (changed) {
    unguarded((: save_object, SAVE_FILE :));
  }
}

private void save_me() {
  unguarded((: save_object, SAVE_FILE :));
}

/**
 * Called by the player object to see if a logon inform should be given
 * about duplicate players from the same IP address.
 * @param user the player being checked
 * @param others the others logged on from the same IP
 * @return array of not allowed dups
 */
string *check_allowed(mixed user, mixed *others) {
  string *not_allowed;
  mixed tmp, alt;

  if(objectp(user))
    user = user->query_name();

  // See if they're an alt of someone. If so check if their alt
  // has an allowed list.
  if(!allowed[user] && PLAYERINFO_HANDLER->query_alt_of(user) != "")
    user = PLAYERINFO_HANDLER->query_alt_of(user);

  not_allowed = ({ });
  foreach(tmp in others) {
    if(objectp(tmp))
      tmp = tmp->query_name();
    alt = PLAYERINFO_HANDLER->query_alt_of(tmp);
    if(!alt)
      alt = tmp;
    if(!allowed[user] || member_array(alt, allowed[user]) == -1)
      not_allowed += ({ tmp }); 
  }

  return not_allowed;
}

/**
 * Adds a player to the multiplayer list.
 * @param git the name of the suspected multiplayer
 * @return 0 if they are not a user, 1 if they are
 */
int add_git(string git) {
  PLAYERINFO_HANDLER->add_entry(this_player(), git, "multiplay",
                                "Caught multiplaying.\n");
  return 1;
}

/**
 * Adds a player to the allowed multi IP list.
 * @param user the name of the player
 * @param other the name of another user which is not an alt
 * @return 0 if they are not a user, 1 if they are
 */
int add_allowed(string user, string other) {
  int oldsize, changed;

  if (!(PLAYER_HANDLER->test_user(user) && PLAYER_HANDLER->test_user(other))) {
    return 0;
  }
  if(PLAYERINFO_HANDLER->query_alt_of(user))
    user = PLAYERINFO_HANDLER->query_alt_of(user);
  if(PLAYERINFO_HANDLER->query_alt_of(other))
    other = PLAYERINFO_HANDLER->query_alt_of(other);

  if (undefinedp(allowed[user])) {
    allowed[user] = ({ other });
  } else {
    oldsize = sizeof(allowed[user]);
    allowed[user] |= ({ other });
  }
  if (!oldsize || (oldsize != sizeof(allowed[user]))) {
    changed = 1;
    PLAYERINFO_HANDLER->add_entry(this_player(), user, "multiplay",
                                  "Added to multiplayer handler as allowed "
                                  "together with " + other + ".\n");
  }

  if (undefinedp(allowed[other])) {
    allowed[other] = ({ user });
  } else {
    oldsize = sizeof(allowed[other]);
    allowed[other] |= ({ user });
  }
  if (!oldsize || (oldsize != sizeof(allowed[other]))) {
    changed = 1;
    PLAYERINFO_HANDLER->add_entry(this_player(), other, "multiplay",
                                  "Added to multiplayer handler as allowed "
                                  "together with " + user + ".\n");
  }
  if (changed) {
    call_out((: save_me :), 1);
  }
  return 1;
} /* add_allowed() */

/**
 * Remove a person from allowed multi IP list.
 * @param user the name of the player to remove
 * @return 0 if they are not in the list, 1 if they are
 */
int delete_allowed(string user) {
  if(PLAYERINFO_HANDLER->query_alt_of(user))
    user = PLAYERINFO_HANDLER->query_alt_of(user);
  if (undefinedp(allowed[user]))
    return 0;
  map_delete(allowed, user);
  call_out((: save_me :), 1);
  PLAYERINFO_HANDLER->add_entry(this_player(), user, "multiplay",
                                "Deleted from multiplayer handler "
                                "(allowed).\n");
  return 1;
} /* delete_allowed() */

/**
 * Returns the current allowed multi player IP list
 * @return the list of allowed multi players
 */
mapping query_allowed() {
  return copy(keys(allowed));
} /* query_allowed() */

/**
 * Adds a user to the list of users not allowed to use the parcel system
 * Only Lords and Liaison deputies are allowed to add a user to this array
 * @param user the name of the player
 */
int add_denied_parcel(string user) {
  if (!"/secure/master"->query_lord(geteuid(previous_object())) &&
      !"/d/liaison/master"->query_deputy(geteuid(previous_object()))) {
    write("You do not have permission to add a user to this list.\n");
    return 0;
  }
  if (member_array( user, denied_parcels) != -1) {
    denied_parcels -= ({ user });
  }
  if (!PLAYER_HANDLER->test_user(user)) {
    return 0;
  }
  denied_parcels += ({ lower_case(user) });
  call_out((: save_me :), 1);
  PLAYERINFO_HANDLER->add_entry(this_player(), user, "multiplay",
                            "Denied the use of the parcel system.\n");
  return 1;
} /* add_denied_parcel() */

/**
 * Removes a user from the list of users not allowed to use the parcel system
 * Only Lords and Liaison deputies are allowed to remove a user from this array
 * @param user the name of the player
 * @return 0 if they are not in the list, 1 if they are
 */
int remove_denied_parcel(string user) {
  if (!"/secure/master"->query_lord(geteuid(previous_object())) &&
      !"/d/liaison/master"->query_deputy(geteuid(previous_object()))) {
    write("You do not have permission to remove a user to this list.\n");
    return 0;
  }
  if (member_array(user, denied_parcels) == -1)
    return 0;
  denied_parcels -= ({ user });
  call_out((: save_me :), 1);
  PLAYERINFO_HANDLER->add_entry(this_player(), user, "multiplay",
                           "Allowed the use of the parcel system.\n");
  return 1;
} /* remove_denied_parcel() */

/**
 * Checks user against the parcels array
 * @param user the name of the player
 * @returns 0 if they are not in the list, 1 if they are
 */
int member_denied_parcel( string user ) {
  if (member_array(user, denied_parcels) == -1)
    return 0;
  return 1;
} /* member_denied_parcel() */

/**
 * Returns the current list of players denied use of the parcel system.
 * @return the list of denied parcel users
 */
string *query_denied_parcels() {
  return copy(denied_parcels);
} /* query_denied_parcels() */

/** @ignore yes */
varargs void mark_log(string user, string comment) {
  if (!comment) {
    log_file("MULTIPLAYERS", ctime(time())
             + " " + user
             + " Previous log entries handled.\n");
    PLAYERINFO_HANDLER->add_entry(this_player(), user, "multiplay",
                                  "Previous log entries handled.\n");
  } else {
    log_file("MULTIPLAYERS", ctime(time())
             + " " + user
             + ": " + comment + "\n" );
    PLAYERINFO_HANDLER->add_entry(this_player(), user, "multiplay", 
                                  comment + "\n");
  }
} /* mark_log() */

/** @ignore yes */
string query_name() {
  return "Multiplayer handler";
}

void record_object(string action, object player, object item) {
  mixed stuff;

  stuff = item->query_property("dropped");
  if(sizeof(stuff) && player->query_name() != stuff[0])
    stuff = ({ player->query_name(), query_ip_number(player), time(),
                 stuff[0] });
  else
    stuff = ({ player->query_name(), query_ip_number(player), time() });
  item->add_property("dropped", stuff, 1800);
}

int check_multiplayers(string action, object player, object item) {
  mixed stuff;
  string direction, verb, res, is;
  
  if(objectp(player) && !interactive(player))
    return 0;
  
  stuff = item->query_property("dropped");
  if(!stuff)
    return 0;

  is = "";
  switch(action) {
  case "get":
    verb = " got ";
    direction = " from ";
    break;
  case "give":
    verb = " was given ";
    direction = " by ";
    is = "is ";
    break;
  case "slip":
    verb = " was slipped ";
    direction = " by ";
    is = "is ";
    break;
  case "palm":
    verb = " palmed ";
    direction = " from ";
    break;
  case "plant":
    verb = " planted "; 
    direction = " on ";
    is = "is ";
    break;
  case "recover":
    verb = " recovered ";
    direction = " from ";
    break;
  }
    
  if(stuff[0] != player->query_name() &&
     query_ip_number(player) == stuff[1] &&
     sizeof(check_allowed(player, ({ stuff[0]}) ))) {
    // Simple IP check.
    res = capitalize(player->query_name()) + verb + item->a_short() +
      direction + stuff[0] + " who " + is +"logged in from the same "
      "address.";
  } else if(direction != " by " &&
            player->query_name() == stuff[0] &&
            player->query_refresh_time() > stuff[2]) {
    // Refresh check.
    res = capitalize(player->query_name()) + verb + item->a_short() +
      " after a refresh.";
  } else if(ALIST->query_alt(player->query_name(), stuff[0]) == 100) {
    // Registered alt check.
    res = capitalize(player->query_name()) + verb + item->a_short() +
      direction + stuff[0] + " who is " + player->query_possessive() +
      " alt.";
  } else if(ALIST->query_alt(player->query_name(), stuff[0]) >= 60) {
    // Possible alt check.
    res = capitalize(player->query_name()) + verb +  item->a_short() +
      direction + stuff[0] + " who is POSSIBLY " +
      player->query_possessive() + " alt.";
  } else if(sizeof(stuff) == 4) {
    // Do third party checks.

    if(player->query_name() == stuff[3]) {
      if(player->query_refresh_time() > stuff[2]) {
        // Indirect refresh check.
        res = capitalize(player->query_name()) + verb + item->a_short() +
          " after a refresh" + direction + stuff[0] + ".";
      }
    } else if(ALIST->query_alt(player->query_name(), stuff[3]) == 100) {
      // Indirect registered alt check.
      res = capitalize(player->query_name()) + verb + item->a_short();
      if(stuff[0] != player->query_name())
        res += " via " + stuff[0];
      res += direction + stuff[3] + " who is " + player->query_possessive() +
        " alt.";
    } else if(ALIST->query_alt(player->query_name(), stuff[3]) >= 60) {
      // Indirect possible alt check.
      res = capitalize(player->query_name()) + verb + item->a_short();
      if(stuff[0] != player->query_name())
        res += " via " + stuff[0];
      res += direction + stuff[3] + " who is _POSSIBLY_ " +
        player->query_possessive() + " alt.";
    }
  } else if((PLAYER_HANDLER->test_creator(stuff[0]) ||
             PLAYER_HANDLER->test_property(stuff[0], "test character")) &&
            !player->query_creator() &&
            !player->query_property("test character") &&
            member_array(base_name(item), ALLOWED_ITEMS) == -1 &&
            base_name(item)[0..14] != "/d/liaison/TOYS") {

    res = capitalize(player->query_name()) + verb + item->a_short() +
      direction + stuff[0];
    user_event("inform", res, "cheat");
    log_file("/d/admin/log/CHEAT", ctime(time()) + ": " +
             player->convert_message(res) + "\n");
    return 0;
  }
  if(res) {
    user_event("inform", res, "multiplayer");
    log_file("MULTIPLAYERS", ctime(time()) + ": " +
             player->convert_message(res) + "\n");
  }

  return 0;
}