New master lfun query_userlist().

Introduces a new master function for querying the
userlist (i.e. data from  the secure savefiles).
Contrary to get_userinfo() it returns specific
records from the userlist instead of a whole array.

The existing get_userinfo() function had a very
ill-defined interface. It returned an array which
was usually accessed by the *internal* symbolic
constants from userinfo.h plus an offset. These
could therefore never be changed internally. It
was also completely undocumented.

Also removes the now obsolete query_player_object()
which was also undocumented and used at only two
places (one being the master itself).

Change-Id: I5948deb69fd750dadd746f9089ba9ee9170c8a81
diff --git a/doc/sphinx/lfun/query_userlist.rst b/doc/sphinx/lfun/query_userlist.rst
new file mode 100644
index 0000000..58f1f14
--- /dev/null
+++ b/doc/sphinx/lfun/query_userlist.rst
@@ -0,0 +1,60 @@
+query_userlist()
+================
+
+FUNKTION
+--------
+
+  public mixed query_userlist(string user, int prop)
+
+DEFINIERT IN
+------------
+
+  /secure/master/userinfo.c
+
+ARGUMENTE
+---------
+
+  user
+    UID des abzufragenden Users
+  prop
+    Datum aus der Userliste, welches abgefragt werden soll
+
+BESCHREIBUNG
+------------
+
+  Aus der Userliste des MG wird eine der folgenden Informationen ueber den
+  Spieler <user> abgefragt:
+
+  USER_LEVEL (int)
+    Magierlevel (1 fuer Seher)
+  USER_DOMAIN (string*)
+    Liste der Regionen, in der der Magier RM ist
+  USER_OBJECT (string)
+    Shell des Spielers
+  USER_CREATION_DATE (int)
+    Zeit des ersten Logins
+  USER_GUILD (string*)
+    Gilden, fuer welche die Spielerin Gildenmagierin ist
+  USER_EKTIPS (string)
+    Fuer welche EKs hat der Spieler einen Tip erhalten? Rueckgabe als
+    Bitstring, in welchem die entsprechenden Bits gesetzt sind.
+  USER_FPTIPS (string)
+    Fuer welche FPs hat der Spieler einen Tip erhalten? Rueckgabe als
+    Bitstring, in welchem die entsprechenden Bits gesetzt sind.
+  USER_UIDS_TO_TAKE_CARE (string*)
+    UIDs, fuer welche die Magierin zustaendig ist. Hierbei sind nur explizit
+    eingetragene in diesem Array, nicht welche, fuer sie implizit kraft ihres
+    Amtes zustaendig ist (z.B. als GM oder RM).
+
+  Die o.a. Konstanten sind in <userinfo.h> definiert.
+
+  Wenn der Spieler nicht existiert, wird 0 zurueckgegeben. Ein nicht
+  unterstuetztes <prop> loest einen Laufzeitfehler aus.
+
+SIEHE AUCH
+----------
+
+  :doc:`find_userinfo`
+
+Last modified: 21.01.2020, Zesstra
+
diff --git a/obj/tools/teller/t_player.c b/obj/tools/teller/t_player.c
index d457038..b9ced9d 100644
--- a/obj/tools/teller/t_player.c
+++ b/obj/tools/teller/t_player.c
@@ -21,11 +21,12 @@
 
 _query_race()
 {
-	if( race ) return race;
-		
-	return "/secure/master"
-		->query_player_object(lower_case(name))
-		->QueryProp(P_RACE);
+  if( race )
+    return race;
+  string shell = master()->query_userlist(lower_case(name), USER_OBJECT);
+  if (shell)
+    race = shell->QueryProp(P_RACE);
+  return race;
 }
 
 _query_hands()
diff --git a/secure/master.h b/secure/master.h
index 14c9fab..958043c 100644
--- a/secure/master.h
+++ b/secure/master.h
@@ -99,7 +99,7 @@
 protected mixed *get_full_userinfo(string user);
 public mixed    *get_userinfo(string user);
 public int       get_wiz_level(string user);
-public string    query_player_object( string name );
+public mixed     query_userlist(string user, int prop);
 public int       query_wiz_level(mixed player);
 int              update_wiz_level(string user,int lev);
 protected void   set_guilds(string player, string *guilds);
diff --git a/secure/master/misc.c b/secure/master/misc.c
index 087bdf6..b113ad6 100644
--- a/secure/master/misc.c
+++ b/secure/master/misc.c
@@ -590,7 +590,8 @@
   active=interactive(who);
   printf("OK, renewing %O\n",who);
   efun::configure_object(this_object(), OC_EUID, geteuid(who));
-  err=catch(newob=clone_object(query_player_object(getuid(who))); publish);
+  err=catch(newob=clone_object(query_userlist(getuid(who),USER_OBJECT));
+            publish);
   efun::configure_object(this_object(), OC_EUID, getuid(TO));
   if (err)
   {
diff --git a/secure/master/userinfo.c b/secure/master/userinfo.c
index af7ec8a..fba781f 100644
--- a/secure/master/userinfo.c
+++ b/secure/master/userinfo.c
@@ -467,12 +467,38 @@
       userlist[user,USER_UIDS_TO_TAKE_CARE]});
 }
 
-// liefert das Objekt des users aus der Userlist zurueck.
-public string query_player_object( string name )
-{
-  mixed *userentry;
-  if( !find_userinfo(name) ) return "";
-  return userlist[name,USER_OBJECT];
+public mixed query_userlist(string user, int prop) {
+  if(!sizeof(user))
+    return 0;
+  user=explode(user,".")[0];
+  if (!member(userlist,user) && !find_userinfo(user))
+    return 0;
+  if (userlist[user,USER_LEVEL]==-1)
+    return 0;
+
+  switch(prop)
+  {
+    case USER_LEVEL:
+      return userlist[user,USER_LEVEL];
+    case USER_DOMAIN:
+      return userlist[user,USER_DOMAIN];
+    case USER_OBJECT:
+      return userlist[user,USER_OBJECT];
+    case USER_CREATION_DATE:
+      return userlist[user,USER_CREATION_DATE];
+    case USER_GUILD:
+      return userlist[user,USER_GUILD];
+    case USER_EKTIPS:
+      return userlist[user,USER_EKTIPS];
+    case USER_FPTIPS:
+      return userlist[user,USER_FPTIPS];
+    case USER_UIDS_TO_TAKE_CARE:
+      return userlist[user,USER_UIDS_TO_TAKE_CARE];
+    default:
+      raise_error(sprintf(
+        "Querying property %d in userlist is illegal.\n", prop));
+  }
+  return 0;
 }
 
 // Passwort ok?