Telnet-Keepalive: Delay konfigurierbar

Das Delay fuer das Telnet Keepalive ist ueber die Prop
P_TELNET_KEEPALIVE_DELAY konfigurierbar.
Momentan koennen das nur Magier. Fuer Spieler sollte
ein sinnvoller Default gewaehlt werden und bei Bedarf
durch einen Magier geaendert werden.

Change-Id: I556f298bde3b4ee8ece6df01051010316c2436b3
diff --git a/doc/pcmd/telnet b/doc/pcmd/telnet
index 029317f..489708f 100644
--- a/doc/pcmd/telnet
+++ b/doc/pcmd/telnet
@@ -32,6 +32,7 @@
 
  SIEHE AUCH:
     telnegs, telnet keepalive, telnet gmcp
+    P_TELNET_KEEPALIVE_DELAY
 
  LETZTE AeNDERUNG:
-    15.01.2018, Zesstra
+    26.07.2019, Zesstra
diff --git a/doc/pcmd/telnet_keepalive b/doc/pcmd/telnet_keepalive
index eecbfd7..770ceba 100644
--- a/doc/pcmd/telnet_keepalive
+++ b/doc/pcmd/telnet_keepalive
@@ -19,11 +19,11 @@
     Verbindung terminiert wird. Daher besitzen die Spielershells ein
     einschaltbares 'Telnet-Keep-Alive'.
 
-    Diese Funktion schickt alle 4 min Daten an eure Clients, die diese
-    nicht anzeigen, aber ihrerseits beantworten/bestaetigen (sofern der Client
-    dies unterstuetzt). So gibt es in der Verbindung zum Mud min. alle 4 min
-    Datenverkehr. Das sollte Verbindungsabbruechen durch Inaktivitaet
-    vorbeugen.
+    Diese Funktion schickt regelmaessig (Standardeinstellung: alle 4 min)
+    Daten an eure Clients, die diese nicht anzeigen, aber ihrerseits
+    beantworten/bestaetigen (sofern der Client dies unterstuetzt). So gibt
+    es in der Verbindung zum Mud regelmaessig Datenverkehr. Das sollte
+    Verbindungsabbruechen durch Inaktivitaet vorbeugen.
 
     Bitte schaltet diese Funktion aber nur ein, wenn ihr sie braucht, d.h.
     ohne sie Probleme mit Verbindungsabbruechen beim Ideln habt.
@@ -32,11 +32,9 @@
 
     Ohne Argumente wird der aktuelle Zustand angezeigt.
 
-    Hinweis fuer Magier: Magier im Magiermodus (mschau ein) kommen leider
-    nicht in den Genuss dieses Features, weil sie keinen Heartbeat haben.
-
  SIEHE AUCH:
-    telnegs, telnet gmcp
+    telnegs, telnet gmcp,
+    P_TELNET_KEEPALIVE_DELAY
 
  LETZTE AeNDERUNG:
-    08.12.2015, Zesstra
+    26.07.2019, Zesstra
diff --git a/doc/sphinx/props/P_TELNET_KEEPALIVE_DELAY.rst b/doc/sphinx/props/P_TELNET_KEEPALIVE_DELAY.rst
new file mode 100644
index 0000000..d50b4cb
--- /dev/null
+++ b/doc/sphinx/props/P_TELNET_KEEPALIVE_DELAY.rst
@@ -0,0 +1,39 @@
+P_TELNET_KEEPALIVE_DELAY
+========================
+
+NAME
+----
+
+     P_TELNET_KEEPALIVE_DELAY "p_lib_telnet_alive_delay"
+
+DEFINIERT IN
+------------
+
+     <player/telnetneg.h>
+
+BESCHREIBUNG
+------------
+
+     In dieser Property kann der zeitliche Abstand zwischen zwei Aussendungen
+     der "Telnet Timing Mark", welche fuer das Telnet keep-alive benutzt wird,
+     bestimmt werden. Die Angabe ist in Heartbeats.
+     Eine 0 fuehrt zu einer Standardverzoegerung (zur Zeit 240 s).
+
+     Wenn diese Property in einem Magier (oder Spieler) gesetzt wird, sollte
+     experimentell ermittelt werden, welcher Wert sinnvoll ist. Dies kann z.B.
+     dadurch erfolgen, dass von 120 (Heartbeats) eine stufenweise Reduktion
+     erfolgt, bis kein Disconnect mehr erfolgt. Helfen sehr niedrige Werte
+     nicht, sollte die Verzoegerung wieder erhoeht werden bzw. das Keepalive
+     ganz abgeschaltet werden.
+
+BEMERKUNGEN
+-----------
+
+     Die Property sollte nicht auf weniger als 30 gesetzt werden.
+
+SIEHE AUCH
+----------
+
+     :doc:`../pcmd/telnet`
+
+25.07.2019, Zesstra
diff --git a/std/player/base.c b/std/player/base.c
index e83930e..b48fadc 100644
--- a/std/player/base.c
+++ b/std/player/base.c
@@ -73,6 +73,7 @@
 #include "/secure/questmaster.h"
 #include "/secure/lepmaster.h"
 #include <events.h>
+#include <player/telnetneg.h>
 
 #undef NAME /* DEFINED BY UDP.H; BAD NAME CLASH :( */
 #define NAME(who) capitalize(getuid(who))
@@ -742,7 +743,7 @@
   * @return 1, falls der Spieler Keep-Alive Paket wuenscht, sonst 0. 
   * @see heart_beat()
 */
-protected int CheckTelnetKeepAlive() {
+protected int CheckTelnetKeepAlive(int delay) {
   if (telnet_tm_counter > 0) {
     // Spieler hat offenbar ein Keep-Alive konfiguriert ...
     if (!(--telnet_tm_counter)) {
@@ -753,7 +754,7 @@
       // alle 120 HBs (240s, 4min).
       // sollte eigentlich 240 / __HEART_BEAT_INTERVAL__ sein. Aber spart
       // eine Operation im HB. ;-)
-      telnet_tm_counter = 120;
+      telnet_tm_counter = delay || 120;
     }
     return 1; // Keep-Alive ist eingeschaltet
   }
@@ -809,7 +810,7 @@
   if (CheckDailyPlaytime())
     return;
 
-  CheckTelnetKeepAlive();
+  CheckTelnetKeepAlive(QueryProp(P_TELNET_KEEPALIVE_DELAY));
 
   life::heart_beat();
   combat::heart_beat();
@@ -4213,11 +4214,16 @@
 
 private int set_keep_alive(string str) {
   if (str == "ein") {
-    telnet_tm_counter = 240 / __HEART_BEAT_INTERVAL__;
-    tell_object(this_object(), break_string(
-        "An Deinen Client werden jetzt alle 4 Minuten unsichtbare Daten "
+    telnet_tm_counter = QueryProp(P_TELNET_KEEPALIVE_DELAY) || (240 / __HEART_BEAT_INTERVAL__);
+    tell_object(this_object(), break_string( sprintf(
+        "An Deinen Client werden jetzt alle %i Sekunden unsichtbare Daten "
         "geschickt, um zu verhindern, dass Deine Verbindung zum "MUDNAME
-        " beendet wird.", 78));
+        " beendet wird.",
+        telnet_tm_counter*__HEART_BEAT_INTERVAL__), 78));
+    // Bei Magiern ist der HB evtl. ausgeschaltet und muss eingeschaltet
+    // werden.
+    if (!object_info(this_object(), OC_HEART_BEAT))
+      configure_object(this_object(), OC_HEART_BEAT, 1);
   }
   else if (str == "aus") {
     telnet_tm_counter = 0;
diff --git a/std/shells/magier.c b/std/shells/magier.c
index 90da043..efde69f 100644
--- a/std/shells/magier.c
+++ b/std/shells/magier.c
@@ -40,6 +40,7 @@
 #include <properties.h>
 #include <new_skills.h>
 #include <config.h>
+#include <player/telnetneg.h>
 
 protected void create()
 {
@@ -76,7 +77,8 @@
 
   if (!QueryProp(P_WANTS_TO_LEARN)||((en=QueryEnemies())&&sizeof(en[0])))
     base::heart_beat();
-  else if (!CheckTelnetKeepAlive()) {
+  else if (!CheckTelnetKeepAlive(QueryProp(P_TELNET_KEEPALIVE_DELAY)))
+  {
     // Wenn der Magier kein Telnet Keep-Alive wuenscht, kann der HB ganz
     // abgeschaltet werden. Sonst muss er aber weiterlaufen, damit
     // CheckTelnetKeepAlive() regelmaessig gerufen wird.
diff --git a/sys/player/telnetneg.h b/sys/player/telnetneg.h
index 415ed90..6a5f1ca 100644
--- a/sys/player/telnetneg.h
+++ b/sys/player/telnetneg.h
@@ -9,6 +9,7 @@
 #ifndef _TELNETNEG_H_
 #define _TELNETNEG_H_
 
+#define P_TELNET_KEEPALIVE_DELAY "p_lib_telnet_alive_delay"
 #endif
 
 #ifdef NEED_PROTOTYPES