blob: 80ed899c7da5a34d75ffb4c294422c6ba91cc6c1 [file] [log] [blame]
Zesstra10341b82020-09-12 13:02:54 +02001/* /std/channel_supervisor.c
Zesstra0caa8e42020-08-11 22:51:59 +02002//
Zesstra10341b82020-09-12 13:02:54 +02003// Der Standard-Supervisor fuer Ebenen. Sollte von allen Objekten geerbt
4// werden, die Zugriffsrechte fuer Ebenen verwalten ("das Sagen" auf der Ebene
5// haben).
6// Das Objekt braucht ggf. eine eUID zum Dateizugriff. Zum Setzen dieser ist
7// der Erbende verantwortlich.
8// Standardmaessig wird /p/daemon/channeld.init[.testmud] eingelesen.
9// Erbende koennen ihre Daten auch voellig anderweitig einlesen/ermitteln und
10// Rechte voellig anders pruefen statt gegen ein Level zu pruefen.
11// Das einzig wichtige fuer die Rechtepruefung ist die Funktion
12// ch_check_access(), die vom CHANNELD gerufen wird. Sie muss 1 zurueckgeben,
13// falls die Aktion erlaubt wird und 0 anderenfalls.
14//
15// Benutzung fuer Standardebenen:
16// Dieses Objekt erben, ggf. eine eUID setzen und ch_read_init_file()
17// rufen.
18// Zusaetzlich sollte dieses Objekt aber auch ein Namen haben, weil es
19// damit auf den Ebenen angezeigt wird. (D.h. minimal name() und Name()
20// sollten implementiert/geerbt sein.)
21*/
Zesstra0caa8e42020-08-11 22:51:59 +020022
Zesstra10341b82020-09-12 13:02:54 +020023#pragma strict_types, rtt_checks
Zesstra0caa8e42020-08-11 22:51:59 +020024#pragma no_shadow, no_clone
25
26#include <wizlevels.h>
Zesstra10341b82020-09-12 13:02:54 +020027#include <regexp.h>
Zesstra0caa8e42020-08-11 22:51:59 +020028#include "/p/daemon/channel.h"
29#include <living/description.h>
30
Zesstra0caa8e42020-08-11 22:51:59 +020031/* Speichert Sende- und Empfangslevel sowie Flags zu den einzelnen Channeln.
Zesstra10341b82020-09-12 13:02:54 +020032 mapping ch_access_data = ([ string channel_name : (<ch_access>) ]) */
33struct ch_access {
34 int recv;
35 int send;
36 int flags;
37};
38// nicht nosave hier, damit man es zwar nosave erben kann, aber ggf. auch
39// speichern kann
40protected mapping ch_access_data = m_allocate(0, 1);
Zesstra0caa8e42020-08-11 22:51:59 +020041
Zesstra10341b82020-09-12 13:02:54 +020042// oeffentlicher Name des Supervisors
43protected string ch_sv_name = "Generischer SV";
44
45protected void ch_set_sv_name(string newname)
46{
47 ch_sv_name = newname;
48}
49
50public varargs string name(int casus,int demon)
51{
52 return ch_sv_name;
53}
54
55public varargs string Name(int casus, int demon)
56{
57 return capitalize(name( casus, demon )||"");
58}
59
60// ch_check_access() prueft die Zugriffsberechtigungen auf Ebenen.
Zesstra0caa8e42020-08-11 22:51:59 +020061//
Zesstra10341b82020-09-12 13:02:54 +020062// Wird vom CHANNELD gerufen.
Zesstra0caa8e42020-08-11 22:51:59 +020063// Gibt 1 zurueck, wenn Aktion erlaubt, 0 sonst.
Zesstra0caa8e42020-08-11 22:51:59 +020064//
65// Verlassen (C_LEAVE) ist immer erlaubt. Die anderen Aktionen sind in zwei
66// Gruppen eingeteilt:
67// 1) RECV. Die Aktionen dieser Gruppe sind Suchen (C_FIND), Auflisten
68// (C_LIST) und Betreten (C_JOIN).
69// 2) SEND. Die Aktion dieser Gruppe ist zur Zeit nur Senden (C_SEND).
70//
71// Aktionen werden zugelassen, wenn Spieler/MagierLevel groesser ist als die
72// fuer die jeweilige Aktionsgruppe RECV oder SEND festgelegte Stufe.
Zesstra10341b82020-09-12 13:02:54 +020073// Handelt es sich um eine Magierebene (<accessflags> enthaelt das Flag
74// CH_ACCESS_WIZARD), muss die Magierstufe des Spielers groesser sein als die
75// Mindeststufe der Ebene. Ansonsten wird gegen den Spielerlevel geprueft.
76// Enthaelt <accessflags> das Flag CH_ACCESS_NOGUEST, darf die Ebene nicht von
77// Gaesten benutzt werden.
Zesstra0caa8e42020-08-11 22:51:59 +020078//
79// Wenn RECV_LVL oder SEND_LVL auf -1 gesetzt ist, sind die Aktionen der
80// jeweiligen Gruppen komplett geblockt.
81
Zesstra10341b82020-09-12 13:02:54 +020082public int ch_check_access(string ch, object user, string cmd)
Zesstra0caa8e42020-08-11 22:51:59 +020083{
Zesstra10341b82020-09-12 13:02:54 +020084 struct ch_access access = ch_access_data[ch];
85 // <user> ist Gast, es sind aber keine Gaeste zugelassen? Koennen wir
Zesstra0caa8e42020-08-11 22:51:59 +020086 // direkt ablehnen.
Zesstra10341b82020-09-12 13:02:54 +020087 if ((access.flags & CH_ACCESS_NOGUEST) && ({int})user->QueryGuest())
Zesstra0caa8e42020-08-11 22:51:59 +020088 return 0;
89
90 // Ebenso auf Magier- oder Seherebenen, wenn ein Spieler anfragt, der
91 // noch kein Seher ist.
Zesstra10341b82020-09-12 13:02:54 +020092 if ((access.flags & CH_ACCESS_WIZARD) && query_wiz_level(user) < SEER_LVL)
Zesstra0caa8e42020-08-11 22:51:59 +020093 return 0;
94
95 // Ebene ist Magierebene? Dann werden alle Stufenlimits gegen Magierlevel
96 // geprueft, ansonsten gegen Spielerlevel.
Zesstra10341b82020-09-12 13:02:54 +020097 int level = (access.flags & CH_ACCESS_WIZARD
98 ? query_wiz_level(user)
99 : ({int})user->QueryProp(P_LEVEL));
Zesstra0caa8e42020-08-11 22:51:59 +0200100
101 switch (cmd)
102 {
103 case C_FIND:
104 case C_LIST:
105 case C_JOIN:
Zesstra10341b82020-09-12 13:02:54 +0200106 if (access.recv == -1)
Zesstra0caa8e42020-08-11 22:51:59 +0200107 return 0;
Zesstra10341b82020-09-12 13:02:54 +0200108 if (access.recv <= level)
Zesstra0caa8e42020-08-11 22:51:59 +0200109 return 1;
110 break;
111
112 case C_SEND:
Zesstra10341b82020-09-12 13:02:54 +0200113 if (access.send == -1)
Zesstra0caa8e42020-08-11 22:51:59 +0200114 return 0;
Zesstra10341b82020-09-12 13:02:54 +0200115 if (access.send <= level)
Zesstra0caa8e42020-08-11 22:51:59 +0200116 return 1;
117 break;
118
119 // Verlassen ist immer erlaubt
120 case C_LEAVE:
121 return 1;
Zesstra0caa8e42020-08-11 22:51:59 +0200122 }
123 return 0;
124}
125
Zesstra10341b82020-09-12 13:02:54 +0200126// ch_store_access() - Angaben zu Zugriffsrechten fuer eine Ebene merken
127// Angaben kommen in folgender Reihenfolge:
128// string* chinfo = ({ channel_name, receive_level, send_level,
129// adminflags, channelflags, description,
130// supervisor })
131// mapping &data ist im Regelfall das <ch_access_data>, was per
132// Referenz uebergeben wird (auch wenn das nicht noetig ist,
133// macht es klar, was beabsichtigt ist).
134protected void ch_store_access(string* chinfo, mapping data)
Zesstra0caa8e42020-08-11 22:51:59 +0200135{
Zesstra10341b82020-09-12 13:02:54 +0200136 object supervisor;
Zesstra0caa8e42020-08-11 22:51:59 +0200137
Zesstra10341b82020-09-12 13:02:54 +0200138 // Nur die Angabe des SV (Index 6) im initfile ist optional, alle Elemente
139 // davor muessen da sein. Wenn kein Supervisor angegeben ist, wird der
140 // Default-SV angenommen.
141
142 if (sizeof(chinfo) >= 7)
Zesstra0caa8e42020-08-11 22:51:59 +0200143 {
Zesstra10341b82020-09-12 13:02:54 +0200144 if (stringp(chinfo[6]) && sizeof(chinfo[6]))
145 supervisor = find_object(chinfo[6]);
Zesstra0caa8e42020-08-11 22:51:59 +0200146 }
Zesstra10341b82020-09-12 13:02:54 +0200147 else if (sizeof(chinfo) == 6)
148 supervisor = find_object(DEFAULTSV);
149 else
150 return;
151
152 // Nur Daten merken, wenn wir auch der Supervisor fuer die Ebene sein
153 // sollen.
154 if (supervisor != this_object())
155 return;
156
157 struct ch_access access = (<ch_access>
158 recv: to_int(chinfo[1]),
159 send: to_int(chinfo[2]),
160 flags: to_int(chinfo[3])
161 );
162
163 data[lower_case(chinfo[0])] = access;
164 // Rest der Ebenendaten interessiert uns nicht.
165}
166
167// Liest ein channeld.init file ein. Wenn keines angegeben wird, wird der
168// das Standardfile fuers Mud eingelesen. Die Angaben werden in das Mapping
169// <ch_access_data> uebernommen, dieses vorher aber nicht geloescht.
170// Der Rueckgabewert ist < 0 fuer Fehler, ansonsten die Groesse von
171// <ch_access_data> nach Einlesen des Files.
172protected varargs int ch_read_init_file(string fname)
173{
174 string ch_list;
175 if (!fname)
176 {
177#if !defined(__TESTMUD__) && MUDNAME=="MorgenGrauen"
178 fname = CHMASTER ".init";
179#else
180 fname = CHMASTER ".init.testmud";
181#endif
182 }
183
184 ch_list = read_file(fname);
185 if (!stringp(ch_list))
186 return -1;
187
188 // Channeldatensaetze erzeugen, dazu zuerst Datenfile in Zeilen zerlegen
189 // "Allgemein: 0: 0: 0: 0: Allgemeine Unterhaltungsebene"
190 // Danach drueberlaufen und in Einzelfelder splitten, dabei gleich die
191 // Trennzeichen (Doppelpunkt, Tab und Space) rausfiltern.
192 foreach(string ch : old_explode(ch_list, "\n"))
193 {
194 if (ch[0]=='#')
195 continue;
196 ch_store_access(regexplode(ch, ":[ \t]*", RE_OMIT_DELIM),
197 &ch_access_data);
198 }
199 return sizeof(ch_access_data);
200}
201
202// Nur falls es mal gebraucht wird und damit es schon jetzt alle rufen
203// koennen.
204protected void create()
205{
206}
207
208public varargs int remove(int silent)
209{
210 destruct(this_object());
211 return 1;
Zesstra0caa8e42020-08-11 22:51:59 +0200212}
213