blob: 33a081f8d2fad3374b944310faeb1eb246d5b245 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001/*
2 * Beispieldatei fuer einen einfachen Master, der Spielerdaten auch
3 * ueber reboots, resets und updates hinweg speichert, und gleichzeitg
4 * dafuer sorgt, dass die Datenmengen nicht immer groesser werden.
5 *
6 * By: Rumata@MorgenGrauen 3/99
7 *
8 */
9
10// Von diesem Objekt gibt es keine Clones, sondern nur die Blueprint.
11// Das Konstrukt if( clonep(ME) ) destruct(this_object()); ist dadurch
12// obsolet.
13#pragma no_clone
14
15#include <properties.h>
16#include <defines.h>
17
18// Ort, an dem die Daten gespeichert werden koennen. Die Endung .o
19// wird vom System angehaengt.
20#define SAVEFILE "/doc/beispiele/master/opferstocklog"
21
22// Dieses ist der Klient, der diesen Master benutzt. Dieser Wert wird
23// in diesem Programm zwar nicht benutzt, steht hier aber, damit man
24// weiss, wofuer dieser Master gut ist.
25#define CLIENT "/doc/beispiele/master/opferstock"
26
27// Es braucht kein Objekt inheritet werden, da wir keinerlei Spiel-
28// Funktionitaet brauchen. Der Master kann nicht genommen, bewegt oder
29// sonstwie innherlab des Muds benutzt werden. Insbesondere sollen
30// im savefile zum Master keine Properties oder so auftauchen.
31// inhert "/std/thing";
32
33// Um diese Daten geht es.
34// Das Mapping speichert zu jedem Spieler, wann das letzte Mal durch einen
35// der Klienten das Alignment geaendert wurde. Alte Daten werden bei
36// Gelegenheit geloescht.
37mapping data;
38
39void purge();
40
41void create() {
42
43 // Damit Schreibzugriff auf Savefile moeglich.
44 seteuid(getuid());
45
46 if( restore_object( SAVEFILE ) ) {
47 purge();
48 } else {
49 data = ([]);
50 save_object( SAVEFILE ); // Damit Savefile und Daten immer synchron sind.
51 }
52}
53
54// Diese Funktion testet einen einzelnen Eintrag, ob er veraltet ist.
55// (ist nicht Jahr 2038-fest :-)
56int notExpired( string name, int date ) {
57 return time() - date < 86400;
58}
59
60// Das Mapping untersuchen, ob Eintraege vorhanden sind, die nicht
61// mehr benoetigt werden.
62// (In diesem Fall sind das Eintraege, die aelter als einen Tag sind.)
63// Es reicht uns, diese Funktion einmal pro reboot auszufuehren. Bei
64// anderen Anwendungen koennte das natuerlich haeufiger noetig sein.
65void purge() {
66 data = filter_indices( data, #'notExpired );
67 save_object( SAVEFILE );
68}
69
70// Diese Funktion ist die eingetliche Funktion, die "gemastert" werden
71// soll, also für mehrere Opferstoecke gemeinsam benutzt wird.
72// Der Opferstock uebergibt das Spielerobjekt und die gewuenschte
73// Alignmentaenderung, als Ergebnis wird 1 geliefert, wenn eine Aenderung
74// vorgenommen wurde (0 sonst) und das Alignment des Spielers entsprechend
75// gesetzt.
76int addAlignment( object player, int align ) {
77 int newAlign;
78 string name;
79
80 /*
81 // Falls man verhindern will, dass nur der Klient auf die Daten zugreift,
82 // kann man hier noch Abfragen einbauen, typischerweise sieht das dann so
83 // aus:
84 if( object_name(previous_object())[0..xxx] != CLIENT ) return -1;
85 // oder
86 if( geteuid(previous_object()) != geteuid() ) return -1;
87 // etc. etc.
88 */
89
90 name = geteuid(player);
91
92 // Nur eine Aenderung pro Tag.
93 // Wir benutzen hier, dass data[name] == 0 ist, falls data den Namen nicht
94 // enthaelt!
95 if( notExpired( name, data[name] ) ) return 0;
96
97 // Daten setzen und speichern.
98 data[name] = time();
99 save_object( SAVEFILE );
100
101 // Maximale Aenderung: 200
102 if( align < -200 ) align = -200;
103 if( align > 200 ) align = 200;
104
105 newAlign = player->QueryProp( P_ALIGN ) + align;
106
107 // Kappung bei +-1000
108 if( newAlign < -1000 ) newAlign = -1000;
109 if( newAlign > 1000 ) newAlign = 1000;
110
111 player->SetProp( P_ALIGN, newAlign );
112 return 1;
113}
114
115// Schlussbemerkung:
116//
117// Gewitzte Programmierer koennten den Klient und den Master in einer
118// Datei zusammen ablegen. Die Blueprint wird als Master, die Clones werden
119// als Klienten benutzt. Ich habe das hier bewusst anders gemacht und empfehle
120// das auch als Vorbild, weil so der Code wesentlich besser zu verstehen ist.