/* $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;
}