MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 1 | // MorgenGrauen MUDlib |
| 2 | // |
| 3 | // channel.c -- channel client |
| 4 | // |
| 5 | // $Id: channel.c 9404 2015-12-13 00:21:44Z Zesstra $ |
| 6 | #pragma strong_types |
| 7 | #pragma save_types |
| 8 | #pragma range_check |
| 9 | #pragma no_clone |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 10 | |
| 11 | #define NEED_PROTOTYPES |
| 12 | #include <util.h> |
| 13 | #include <thing/properties.h> |
| 14 | #include <living/comm.h> |
| 15 | #include <player.h> |
| 16 | #include <player/comm.h> |
| 17 | #include <daemon.h> |
| 18 | #include <player/gmcp.h> |
| 19 | #undef NEED_PROTOTYPES |
| 20 | |
| 21 | #include <wizlevels.h> |
| 22 | #include <defines.h> |
| 23 | #include <properties.h> |
| 24 | #include <sys_debug.h> |
| 25 | #include <regexp.h> |
| 26 | |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 27 | #define P_CHANNEL_SHORT "short_channels" |
| 28 | |
| 29 | #define CHANNELCMDS "[#@%$&()<>a-zA-Z0-9\\-]" |
| 30 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 31 | #define DEFAULT_CHANNELS ({"Abenteuer", "Anfaenger", "Grats", "Tod", "ZT"}) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 32 | #define DEFAULT_SHORTCUTS \ |
| 33 | ([ \ |
| 34 | "b":"Abenteuer", \ |
| 35 | "a":"Allgemein", \ |
| 36 | "B":"Beileid", \ |
| 37 | "q":"D-chat", \ |
| 38 | "G":"Grats", \ |
| 39 | "M":"Moerder", \ |
| 40 | "h":"Seher", \ |
| 41 | "T":"Tod", \ |
| 42 | ]) |
| 43 | |
| 44 | #define WIZARD_SHORTCUTS \ |
| 45 | ([ \ |
| 46 | "P":"D-code", \ |
| 47 | "D":"Debug", \ |
| 48 | "O":"Intercode", \ |
| 49 | "I":"Intermud", \ |
| 50 | "m":"Magier", \ |
| 51 | ]) |
| 52 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 53 | // TODO: <shortcut> wird eigentlich nur in getChannel() sinnvoll verwendet |
| 54 | // Koennte man an sich komplett einsparen und dort wie ueberall sonst auch |
| 55 | // einfach nur mit P_CHANNEL_SHORT arbeiten. |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 56 | private nosave mapping shortcut; |
| 57 | private nosave int c_status; |
| 58 | |
| 59 | void create() |
| 60 | { |
| 61 | Set(P_CHANNELS, SAVE, F_MODE); |
| 62 | Set(P_CHANNELS, DEFAULT_CHANNELS); |
| 63 | Set(P_SWAP_CHANNELS, SAVE, F_MODE); |
| 64 | Set(P_STD_CHANNEL, "Allgemein"); |
| 65 | Set(P_STD_CHANNEL, SAVE, F_MODE); |
| 66 | Set(P_CHANNEL_SHORT, SAVE, F_MODE); |
| 67 | Set(P_CHANNEL_SHORT, DEFAULT_SHORTCUTS |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 68 | + (IS_LEARNER(ME) ? WIZARD_SHORTCUTS : ([]))); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 69 | } |
| 70 | |
Arathorn | 0076469 | 2019-11-27 22:09:31 +0100 | [diff] [blame] | 71 | static <int|string>** _query_localcmds() |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 72 | { |
| 73 | return ({({"-","ChannelParser", 1, 0}), |
| 74 | ({"ebene", "ChannelAdmin", 0, 0}), |
| 75 | ({"ebenen", "ChannelAdmin", 1, 0}), |
| 76 | }); |
| 77 | } |
| 78 | |
Arathorn | 0076469 | 2019-11-27 22:09:31 +0100 | [diff] [blame] | 79 | string* RegisterChannels() |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 80 | { |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 81 | if (extern_call() && |
| 82 | previous_object() != find_object(CHMASTER)) |
Zesstra | f1137e8 | 2019-11-27 23:37:30 +0100 | [diff] [blame] | 83 | return 0; |
| 84 | |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 85 | c_status = 0; |
| 86 | shortcut = QueryProp(P_CHANNEL_SHORT); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 87 | SetProp(P_CHANNELS, map(QueryProp(P_CHANNELS) || ({}), #'lower_case)); |
| 88 | |
| 89 | closure cl = symbol_function("join", CHMASTER); |
| 90 | string* err; |
| 91 | if (closurep(cl)) |
| 92 | { |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 93 | err = filter(QueryProp(P_CHANNELS), cl, ME); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 94 | } |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 95 | if (QueryProp(P_LEVEL) < 5) |
| 96 | return err; |
| 97 | |
| 98 | // CHMASTER->new() gibt bei Erfolg 0 zurueck, d.h. es bleiben |
| 99 | // alle Elemente erhalten, deren Channel nicht erstellt werden konnten. |
| 100 | // Die werden an die Aufrufer zurueckgegeben. |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 101 | return filter(err, "new", CHMASTER, ME); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 102 | } |
| 103 | |
Arathorn | 0076469 | 2019-11-27 22:09:31 +0100 | [diff] [blame] | 104 | string* RemoveChannels() |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 105 | { |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 106 | if (extern_call() && |
| 107 | previous_object() != find_object(CHMASTER)) |
Zesstra | f1137e8 | 2019-11-27 23:37:30 +0100 | [diff] [blame] | 108 | return 0; |
| 109 | |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 110 | string* err = ({}); |
| 111 | |
| 112 | if (!c_status) |
| 113 | c_status = 1; |
| 114 | else |
| 115 | return err; |
| 116 | |
| 117 | closure cl = symbol_function("leave", CHMASTER); |
| 118 | if (closurep(cl)) |
| 119 | { |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 120 | err = filter(QueryProp(P_CHANNELS), cl, ME); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 121 | SetProp(P_CHANNELS, QueryProp(P_CHANNELS) - err); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 122 | } |
| 123 | return err; |
| 124 | } |
| 125 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 126 | varargs private string getName(string|object|closure who, int fall) { |
| 127 | // Objekt zur Closure raussuchen. <o> ist danach entweder jenes Objekt, |
| 128 | // oder aber <who> selbst, das Objekt oder String sein kann. |
| 129 | // |
| 130 | // query_closure_object() KANN auch 0 oder -1 zurueckgeben. In beiden |
| 131 | // Faellen fuehrt das hier zu einem Laufzeit-Typfehler, weil ein Integer |
| 132 | // bzw. die urspruengliche Closure zugewiesen wird. Diesen Fall abzufangen |
| 133 | // und separat zu behandeln, hilft nicht, weil es auch keine alternative |
| 134 | // Moeglichkeit gibt, <who> in verwendbare Daten umzuwandeln, denn das ist |
| 135 | // ja offenbar eine kaputte Closure. Dieser Fall ist ausserdem anscheinend |
| 136 | // so exotisch, dass wir vorerst auf Absicherungen mittels catch() |
| 137 | // verzichten. |
| 138 | string|object o = closurep(who) ? query_closure_object(who) : who; |
| 139 | |
| 140 | // Ist es ein String, pruefen wir, ob es vielleicht ein Objektname ist, |
| 141 | // indem wir es in ein Objekt umzuwandeln versuchen. Schlaegt das fehl, |
| 142 | // schreiben wir <who> wieder zurueck, so dass <o> wieder der urspruengliche |
| 143 | // String ist. |
| 144 | if (stringp(o) && sizeof(o)) |
| 145 | o = find_object(o) || who; |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 146 | |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 147 | // Objekte |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 148 | if (objectp(o)) |
| 149 | { |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 150 | // Magier sehen unsichtbare nicht nur als "Jemand" |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 151 | if (o->QueryProp(P_INVIS) && IS_LEARNING(ME)) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 152 | return "("+capitalize(getuid(o))+")"; |
| 153 | // Froesche mit Namen versorgen. |
| 154 | if (o->QueryProp(P_FROG)) |
| 155 | return "Frosch "+capitalize(getuid(o)); |
| 156 | // Default (Unsichtbare als "Jemand" (s. Name())) |
| 157 | return o->Name(fall, 2)||"<Unbekannt>"; |
| 158 | } |
| 159 | // Strings |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 160 | else if (stringp(o) && sizeof(o)) |
| 161 | { |
| 162 | if (o[0] == '/') |
| 163 | { |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 164 | // unsichtbare Objekte... |
| 165 | int p = strstr(o, "$"); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 166 | if (p != -1) |
| 167 | { |
| 168 | // Magier im Magiermodus kriegen den Realnamen, andere nicht. |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 169 | if (IS_LEARNING(ME)) |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 170 | return o[1..p-1]; |
| 171 | else |
| 172 | return o[p+1..]; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 173 | } |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 174 | else // doch nicht unsichtbar |
| 175 | return (fall == WESSEN ? o+"s" : o); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 176 | } |
| 177 | else |
| 178 | // nicht unsichtbar |
| 179 | return (fall == WESSEN ? o+"s" : o); |
| 180 | } |
| 181 | // Fall-through |
| 182 | return "<Unbekannt>"; |
| 183 | } |
| 184 | |
Arathorn | 69d6ddd | 2019-11-25 21:06:34 +0100 | [diff] [blame] | 185 | // <nonint> unterdrueckt die Ausgabe an den Spieler und liefert den Text |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 186 | // zurueck. Wird nur fuer die Ebenenhistory benutzt. |
Arathorn | 69d6ddd | 2019-11-25 21:06:34 +0100 | [diff] [blame] | 187 | string ChannelMessage(<string|object|int>* msg, int nonint) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 188 | { |
| 189 | string channel_message; |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 190 | string channel = msg[0]; |
Arathorn | 69d6ddd | 2019-11-25 21:06:34 +0100 | [diff] [blame] | 191 | |
| 192 | // Wenn eine Ebenenmeldung ausgegeben werden soll, ist msg[1] ein Objekt, |
| 193 | // im Fall der History aber ein String. Daher wird <sender> als Union |
| 194 | // deklariert. Das ist unproblematisch, weil die beiden Datentypen |
| 195 | // komplett getrennte Wege nehmen: ein Objekt wird an ReceiveMsg() |
| 196 | // durchgereicht (Ebenenmeldung). Ein String wird direkt in die Meldung |
| 197 | // (History) eingebaut, diese an den ChannelParser() zurueckgegeben, der |
| 198 | // sie via More() ausgibt. |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 199 | string|object sender = msg[1]; |
| 200 | string message = msg[2]; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 201 | int msg_type = msg[3]; |
| 202 | |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 203 | if (previous_object() != find_object(CHMASTER) && |
| 204 | previous_object() != ME ) |
| 205 | return 0; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 206 | |
| 207 | string sender_name = getName(sender, msg_type == MSG_GEMOTE ? WESSEN : WER); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 208 | int prepend_indent_flag = |
| 209 | QueryProp(P_MESSAGE_PREPEND) ? BS_PREPEND_INDENT : 0; |
| 210 | |
| 211 | switch (msg_type) |
| 212 | { |
| 213 | case MSG_EMPTY: |
| 214 | channel_message= message+"\n"; |
| 215 | break; |
| 216 | case MSG_GEMOTE: |
| 217 | case MSG_EMOTE: |
| 218 | channel_message = break_string(sender_name + " "+ message+"]", 78, |
| 219 | sprintf("[%s:", channel), |
| 220 | BS_INDENT_ONCE|prepend_indent_flag); |
| 221 | break; |
| 222 | case MSG_SAY: |
| 223 | default: |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 224 | string presay = sprintf("[%s:%s] ", channel, sender_name); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 225 | channel_message = break_string(message, max(78,sizeof(presay)+10), |
| 226 | presay, prepend_indent_flag); |
| 227 | break; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 228 | } |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 229 | |
| 230 | if (nonint) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 231 | return channel_message; |
| 232 | |
| 233 | // Wenn GMCP sich um Uebertragung der Nachricht kuemmert, wird ReceiveMsg() |
Zesstra | 7ccec73 | 2019-01-06 22:10:09 +0100 | [diff] [blame] | 234 | // nicht mehr aufgerufen. getName leider nochmal aufrufen, weil GMCP den |
| 235 | // Namen im Nominativ braucht. |
| 236 | if (msg_type == MSG_GEMOTE) |
| 237 | sender_name = getName(sender, WER); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 238 | if (GMCP_Channel(channel_message, channel, sender_name) != 1) |
| 239 | { |
| 240 | // Der Ebenenname muss in Kleinbuchstaben uebergeben werden, damit die |
| 241 | // Ignorierepruefung funktioniert. Die ignorierestrings sind naemlich alle |
| 242 | // kleingeschrieben. |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 243 | ReceiveMsg(channel_message, |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 244 | MT_COMM|MT_FAR|MSG_DONT_STORE|MSG_DONT_WRAP, |
| 245 | MA_CHANNEL"." + lower_case(channel), 0, sender); |
| 246 | } |
| 247 | return 0; |
| 248 | } |
| 249 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 250 | // string n: Channelname |
| 251 | // <object*|closure|string|object>* a: Channeldaten |
| 252 | // string* m: P_CHANNELS |
| 253 | // string* l: Ausgabeliste. |
| 254 | private void OLDcreateList(string n, <object*|closure|string|object>* a, |
| 255 | string* m, string* l) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 256 | { |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 257 | // Wir suchen das vom Spieler festgelegte Kuerzel fuer die aktuell |
| 258 | // bearbeitete Ebene, falls vorhanden. |
Arathorn | 0076469 | 2019-11-27 22:09:31 +0100 | [diff] [blame] | 259 | string sh = ""; |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 260 | foreach(string sc, string chan : shortcut) { |
| 261 | if ( lower_case(chan) == n ) { |
| 262 | sh = sc; |
| 263 | break; |
| 264 | } |
| 265 | } |
Arathorn | 0076469 | 2019-11-27 22:09:31 +0100 | [diff] [blame] | 266 | |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 267 | l += ({ sprintf("%-12.12'.'s %c[%-1.1s] %|12.12' 's (%-|3' 'd) %-42.42s\n", |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 268 | a[I_NAME], |
| 269 | (member(m, n) != -1 |
| 270 | ? '*' |
| 271 | : ' '), |
| 272 | sh, |
| 273 | a[I_MASTER] |
| 274 | ? getName(a[I_MASTER]) |
| 275 | : getName(a[I_ACCESS]), |
| 276 | sizeof(a[I_MEMBER] - ({ find_object(CHMASTER) })), |
| 277 | (closurep(a[I_INFO]) && objectp(query_closure_object(a[I_INFO]))) |
| 278 | ? funcall(a[I_INFO]) || "- Keine Beschreibung -" |
| 279 | : (stringp(a[I_INFO]) |
| 280 | ? a[I_INFO] |
| 281 | : "- Keine Beschreibung -")) }); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 282 | } |
| 283 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 284 | private void createList(mapping ch_list, string* p_channels, |
| 285 | int show_only_subscribed) { |
| 286 | // Kopfzeile der Tabelle erstellen. |
| 287 | string listhead = |
| 288 | sprintf("%-12.12' 's [A] %|12' 's (%-3' 's) %-42.42s\n", |
| 289 | "Name", "Eigner", "Sp", "Beschreibung"); |
| 290 | // Linie drunter. |
| 291 | listhead += ("-"*78 + "\n"); |
| 292 | |
| 293 | // Rest der Daten erstmal in einem Array zusammenstellen, um es |
| 294 | // anschliessend sortieren zu koennen. |
| 295 | string* entries = ({}); |
| 296 | |
| 297 | object* ch_members; |
| 298 | string|object ch_master; |
| 299 | string ch_real_name, ch_description; |
| 300 | closure|string ch_access; |
| 301 | closure|string ch_info; |
| 302 | string sh; |
| 303 | |
| 304 | foreach(string chname, <object*|closure|string|object>* chdata : ch_list) |
| 305 | { |
| 306 | // Wenn nur abonnierte Ebenen aufgelistet werden sollen, dann alle |
| 307 | // ueberspringen, die nicht in P_CHANNELS stehen. |
| 308 | int is_subscribed = (member(p_channels, chname) > -1); |
| 309 | if (show_only_subscribed && !is_subscribed) |
| 310 | continue; |
| 311 | |
| 312 | ch_members = chdata[I_MEMBER]; |
| 313 | ch_master = chdata[I_MASTER]; |
| 314 | ch_access = chdata[I_ACCESS]; |
| 315 | ch_real_name = chdata[I_NAME]; |
| 316 | ch_info = chdata[I_INFO]; |
| 317 | sh = ""; |
| 318 | |
| 319 | // Ist eine Closure als I_INFO eingetragen, zu der es auch ein Objekt |
| 320 | // gibt, tragen wir deren Rueckgabewert als Beschreibung ein. |
| 321 | if (closurep(ch_info) && objectp(query_closure_object(ch_info))) { |
| 322 | ch_description = funcall(ch_info); |
| 323 | } |
| 324 | // Ist es ein String, wird er unveraendert uebernommen. |
| 325 | else if (stringp(ch_info)) { |
| 326 | ch_description = ch_info; |
| 327 | } |
| 328 | // Sollte nirgends etwas eingetragen sein, oder die Closure 0 zurueck- |
| 329 | // gegeben haben, gibt es eine Defaultbeschreibung. Man haette die |
| 330 | // Variable auch schon mit dem Default initialisieren koennen, der kann |
| 331 | // aber bei Rueckgabe von 0 aus der Closure wieder ueberschrieben werden. |
| 332 | // Daher passiert das erst hier. |
| 333 | ch_description ||= "- Keine Beschreibung -"; |
| 334 | |
| 335 | // Wir brauchen noch das vom Spieler festgelegte Kuerzel fuer die aktuell |
| 336 | // bearbeitete Ebene, falls vorhanden, um es in die Liste eintragen |
| 337 | // zu koennen. |
| 338 | foreach(string _sh_cut, string _chan_name : shortcut) { |
| 339 | if ( lower_case(_chan_name) == chname ) { |
| 340 | sh = _sh_cut; |
| 341 | break; |
| 342 | } |
| 343 | } |
| 344 | |
| 345 | // Jetzt haben wir endlich alle Infos beisammen und koennen die |
| 346 | // Eintraege zusammenbauen. |
| 347 | entries += ({ |
| 348 | sprintf("%-12.12'.'s %c[%-1.1s] %|12.12' 's (%-|3' 'd) %-42.42s\n", |
| 349 | ch_real_name, |
| 350 | is_subscribed ? '*' : ' ', |
| 351 | sh, |
| 352 | ch_master ? getName(ch_master) : getName(ch_access), |
| 353 | sizeof(ch_members - ({ find_object(CHMASTER) })), |
| 354 | ch_description |
| 355 | ) }); |
| 356 | } |
| 357 | |
| 358 | // alphabetisch sortieren |
| 359 | entries = sort_array(entries, #'>); |
| 360 | |
| 361 | More( listhead + // Listenkopf |
| 362 | implode(entries, "") + // Eintraege |
| 363 | "-"*78+"\n" ); // Linie drunter |
| 364 | } |
| 365 | |
| 366 | private string|string* getChannel(string ch) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 367 | { |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 368 | if (!sizeof(ch)) |
Arathorn | 0076469 | 2019-11-27 22:09:31 +0100 | [diff] [blame] | 369 | ch = QueryProp(P_STD_CHANNEL); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 370 | if (shortcut && shortcut[ch]) |
Arathorn | 0076469 | 2019-11-27 22:09:31 +0100 | [diff] [blame] | 371 | ch = shortcut[ch]; |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 372 | return CHMASTER->find(ch, ME); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 373 | } |
| 374 | |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 375 | int ChannelParser(string args) |
| 376 | { |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 377 | string|string* ch; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 378 | int pos, type, err; |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 379 | string tmp; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 380 | notify_fail("Benutzung: -<Ebene>[ ]['|:|;]<Text>\n" |
| 381 | " -<Ebene>[+|-|?|!|*]\n" |
| 382 | " -?\n"); |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 383 | |
Arathorn | b794a19 | 2020-08-06 21:51:28 +0200 | [diff] [blame^] | 384 | args = _unparsed_args(); |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 385 | string|string* cmd = query_verb(); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 386 | if (!cmd && !args) |
| 387 | return 0; |
| 388 | |
| 389 | if (!args) |
| 390 | args = ""; |
| 391 | |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 392 | cmd = cmd[1..]; |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 393 | cmd = regexplode(cmd, "^" CHANNELCMDS "*" "([+-]|\\!|\\?|\\*)*"); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 394 | if (sizeof(cmd) > 1) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 395 | { |
| 396 | //z.B. cmd= ({"","allgemein",":testet"}) |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 397 | if (sizeof(cmd[1]) > 1 && strstr("+-?!*", cmd[1][<1..<1]) > -1) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 398 | tmp = cmd[1][0..<2]; |
| 399 | else |
| 400 | tmp = cmd[1]; |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 401 | |
| 402 | if (cmd[1] != "?" && cmd[1] != "!") |
Zesstra | 57a693e | 2019-01-06 22:08:24 +0100 | [diff] [blame] | 403 | { |
| 404 | ch = getChannel(tmp); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 405 | if (pointerp(ch)) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 406 | { |
| 407 | notify_fail("Diese Angabe war nicht eindeutig! " |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 408 | "Folgende Ebenen passen:\n"+ |
| 409 | implode(ch, ", ")+"\n"); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 410 | return 0; |
| 411 | } |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 412 | else if (!ch) |
| 413 | { |
| 414 | notify_fail("Die Ebene '"+tmp+ "' gibt es nicht!\n"); |
| 415 | return 0; |
| 416 | } |
Zesstra | 57a693e | 2019-01-06 22:08:24 +0100 | [diff] [blame] | 417 | } |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 418 | |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 419 | if (sizeof(cmd[1])) { |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 420 | switch (cmd[1][<1]) { |
| 421 | case '+': |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 422 | switch (CHMASTER->join(ch, ME)) |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 423 | { |
| 424 | case E_ACCESS_DENIED: |
| 425 | notify_fail("Du darfst an die Ebene '"+ch+"' nicht heran.\n"); |
| 426 | return 0; |
| 427 | case E_ALREADY_JOINED: |
| 428 | notify_fail("Du hast diese Ebene schon betreten!\n"); |
| 429 | return 0; |
| 430 | default: |
| 431 | break; |
| 432 | } |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 433 | tell_object(ME,"Du betrittst die Ebene '"+ch+"'.\n"); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 434 | if (member(QueryProp(P_CHANNELS), ch = lower_case(ch)) == -1) |
| 435 | SetProp(P_CHANNELS, QueryProp(P_CHANNELS) + ({ ch })); |
| 436 | return 1; |
| 437 | |
| 438 | case '-': |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 439 | switch (CHMASTER->leave(ch, ME)) |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 440 | { |
| 441 | case E_ACCESS_DENIED: |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 442 | tell_object(ME,"Du kannst die Ebene '"+ch+"' nicht " |
| 443 | "verlassen.\n"); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 444 | break; |
| 445 | case E_NOT_MEMBER: |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 446 | tell_object(ME,"Wie willst Du eine Ebene verlassen, welche Du " |
| 447 | "nicht betreten hast?\n"); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 448 | break; |
| 449 | default: |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 450 | tell_object(ME,"Du verlaesst die Ebene '"+ch+"'.\n"); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 451 | SetProp(P_CHANNELS, |
| 452 | QueryProp(P_CHANNELS) - ({ lower_case(ch), ch })); |
| 453 | break; |
| 454 | } |
| 455 | return 1; |
| 456 | |
| 457 | case '!': |
| 458 | case '?': |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 459 | mapping l = CHMASTER->list(ME); |
| 460 | if (mappingp(l)) |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 461 | { |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 462 | // Es wurde ein Channel angegeben, dessen Infos gefragt sind. |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 463 | if (stringp(ch) && sizeof(ch) && pointerp(l[ch = lower_case(ch)])) |
| 464 | { |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 465 | <object*|closure|string|object>* chdata = l[ch]; |
| 466 | string* m = |
| 467 | sort_array(map(chdata[I_MEMBER], #'getName, WER), #'>) - |
| 468 | ({ CMNAME }); |
| 469 | |
| 470 | string wen; |
| 471 | switch(sizeof(m)) { |
| 472 | case 1: wen = "ein Gesicht"; break; |
| 473 | case 0: wen = "niemanden"; break; |
| 474 | // TODO: mittels Zahlwoerter-Objekt die Zahl als Text |
| 475 | // ausgeben? |
| 476 | default: wen = sprintf("%d Gesichter", sizeof(m)); break; |
| 477 | } |
| 478 | |
| 479 | tell_object(ME, |
| 480 | chdata[I_NAME]+", "+funcall(chdata[I_INFO])+".\n" + |
| 481 | "Du siehst "+wen+" auf der Ebene '"+chdata[I_NAME]+"':\n"+ |
| 482 | break_string(CountUp(m), 78) + |
| 483 | (chdata[I_MASTER] ? getName(chdata[I_MASTER]) |
| 484 | : getName(chdata[I_ACCESS], WER))+ |
| 485 | " hat das Sagen auf dieser Ebene.\n"); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 486 | } |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 487 | // kein Channel angegeben, dann Gesamtliste erzeugen |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 488 | else |
| 489 | { |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 490 | // Wenn nur die abonnierten angezeigt werden sollen |
| 491 | // (Kommando -!), wird die Bedingung im 3. Argument == 1, so |
| 492 | // dass createList() die reduzierte Tabelle erzeugt. |
| 493 | createList(l, QueryProp(P_CHANNELS), (cmd[1][<1] == '!')); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 494 | } |
| 495 | } |
| 496 | return 1; |
| 497 | |
| 498 | case '*': |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 499 | int|<int|string>** hist = CHMASTER->history(ch, ME); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 500 | if (!pointerp(hist) || !sizeof(hist)) |
| 501 | { |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 502 | tell_object(ME,"Es ist keine Geschichte fuer '"+ch+ |
| 503 | "' verfuegbar.\n"); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 504 | return 1; |
| 505 | } |
| 506 | |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 507 | int amount = to_int(cmd[2]); |
| 508 | if (amount <= 0 || amount >= sizeof(hist)) |
| 509 | amount = sizeof(hist); |
| 510 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 511 | string txt = "Folgendes ist auf '"+ch+"' passiert:\n" + |
| 512 | implode(map(hist[<amount..], #'ChannelMessage, 1), ""); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 513 | More(txt); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 514 | return 1; |
| 515 | |
| 516 | default: |
| 517 | break; |
Zesstra | 57a693e | 2019-01-06 22:08:24 +0100 | [diff] [blame] | 518 | } |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 519 | } |
| 520 | } |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 521 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 522 | cmd = implode(cmd[2..], ""); |
| 523 | if (sizeof(cmd)) |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 524 | args = cmd + (sizeof(args) ? " " : "") + args; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 525 | |
| 526 | // KOntrollchars ausfiltern. |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 527 | args = regreplace(args, "[[:cntrl:]]", "", RE_PCRE|RE_GLOBAL); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 528 | if (!sizeof(args)) |
| 529 | return 0; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 530 | |
| 531 | //Wenn cmd leer ist: MSG_SAY |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 532 | if (!sizeof(cmd)) |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 533 | { |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 534 | type = MSG_SAY; |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 535 | } |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 536 | else |
| 537 | { |
| 538 | switch (cmd[0]) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 539 | { |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 540 | case ':' : |
| 541 | type = MSG_EMOTE; |
| 542 | args = args[1..]; |
| 543 | break; |
| 544 | case ';' : |
| 545 | type = MSG_GEMOTE; |
| 546 | args = args[1..]; |
| 547 | break; |
| 548 | case '\'': |
| 549 | args = args[1..]; |
| 550 | // Der Fallthrough in default ist hier Absicht. |
| 551 | default : |
| 552 | type = MSG_SAY; |
| 553 | break; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 554 | } |
| 555 | } |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 556 | |
| 557 | if (!ch || !sizeof(ch)) |
| 558 | ch = QueryProp(P_STD_CHANNEL); |
| 559 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 560 | err = CHMASTER->send(ch, ME, args, type); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 561 | if (err < 0) |
| 562 | { |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 563 | err = CHMASTER->join(ch, ME); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 564 | if (!err) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 565 | { |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 566 | ch = lower_case(ch); |
| 567 | if (member(QueryProp(P_CHANNELS), ch) == -1) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 568 | SetProp(P_CHANNELS, QueryProp(P_CHANNELS) + ({ ch })); |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 569 | err = CHMASTER->send(ch, ME, args, type); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 570 | } |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 571 | } |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 572 | |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 573 | switch (err) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 574 | { |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 575 | case E_ACCESS_DENIED: |
| 576 | notify_fail("Auf der Ebene '"+ch+"' darfst Du nichts sagen.\n"); |
| 577 | return 0; |
| 578 | case E_NOT_MEMBER: |
| 579 | notify_fail("Du hast die Ebene '"+ch+"' nicht betreten!\n"); |
| 580 | return 0; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 581 | } |
| 582 | return 1; |
| 583 | } |
| 584 | |
| 585 | int ChannelAdmin(string args) |
| 586 | { |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 587 | args = _unparsed_args(); |
| 588 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 589 | string target_channel, descr, _sh_cut; |
| 590 | string|string* chans; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 591 | notify_fail("Benutzung: ebene <Abkuerzung>=<Ebene>\n" |
| 592 | " ebene <Abkuerzung>=\n" |
| 593 | " ebene abkuerzungen [standard]\n" |
| 594 | " ebene standard <Ebene>\n" |
| 595 | " ebene an|ein|aus\n" |
| 596 | +(QueryProp(P_LEVEL) >= 5 ? |
| 597 | " ebene neu <Name> <Bezeichnung>\n" |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 598 | " ebene beschreibung <Name> <Beschreibung>\n" : "") |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 599 | +(IS_ARCH(ME) ? |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 600 | " ebene kill <Name>\n" |
| 601 | " ebene clear <Name>\n": "")); |
| 602 | |
| 603 | if (!args || !sizeof(args)) |
| 604 | return 0; |
| 605 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 606 | if (sscanf(args, "kill %s", target_channel) && IS_ARCH(ME)) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 607 | { |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 608 | chans = CHMASTER->find(target_channel, ME); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 609 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 610 | if (!chans) |
| 611 | { |
| 612 | notify_fail("Ebene '"+target_channel+"' nicht gefunden!\n"); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 613 | return 0; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 614 | } |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 615 | else if (pointerp(chans)) |
| 616 | { |
| 617 | notify_fail( |
| 618 | "Das war keine eindeutige Angabe! Folgende Ebenen passen:\n"+ |
| 619 | break_string(CountUp(chans), 78)); |
| 620 | return 0; |
| 621 | } |
| 622 | else if (CHMASTER->remove_channel(target_channel, ME)) |
| 623 | { |
| 624 | notify_fail("Die Ebene '"+target_channel+"' lies sich nicht " |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 625 | "entfernen!\n"); |
| 626 | return 0; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 627 | } |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 628 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 629 | tell_object(ME,"Du entfernst die Ebene '"+target_channel+"'.\n"); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 630 | return 1; |
| 631 | } |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 632 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 633 | if (sscanf(args, "clear %s", target_channel) && IS_ARCH(ME)) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 634 | { |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 635 | chans = CHMASTER->find(target_channel, ME); |
| 636 | |
| 637 | if (!chans) |
| 638 | { |
| 639 | notify_fail("Ebene '"+target_channel+"' nicht gefunden!\n"); |
| 640 | return 0; |
| 641 | } |
| 642 | else if (pointerp(chans)) |
| 643 | { |
| 644 | notify_fail( |
| 645 | "Das war keine eindeutige Angabe! Folgende Ebenen passen:\n"+ |
| 646 | break_string(CountUp(chans), 78)); |
| 647 | return 0; |
| 648 | } |
| 649 | else if (CHMASTER->clear_history(target_channel, ME) == E_ACCESS_DENIED) |
| 650 | { |
| 651 | notify_fail("Der Verlauf zur Ebene '"+target_channel+"' liess sich " |
| 652 | "nicht entfernen!\n"); |
| 653 | return 0; |
| 654 | } |
| 655 | |
| 656 | tell_object(ME,"Du entfernst den Verlauf zur Ebene '"+target_channel+ |
| 657 | "'.\n"); |
| 658 | return 1; |
| 659 | } |
| 660 | |
| 661 | if (sscanf(args, "neu %s %s", target_channel, descr) == 2) |
| 662 | { |
| 663 | notify_fail(break_string("Neue Ebenen kannst Du erst erstellen, wenn " |
| 664 | "Du Spielerstufe 5 erreicht hast.", 78)); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 665 | if (QueryProp(P_LEVEL) < 5) |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 666 | return 0; |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 667 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 668 | notify_fail("Der Name '"+target_channel+"' ist nicht konform!\n"); |
| 669 | if (!sizeof(regexp(({target_channel}), "^" CHANNELCMDS CHANNELCMDS "*"))) |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 670 | return 0; |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 671 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 672 | notify_fail("Der Name '"+target_channel+"' ist zu lang.\n"); |
| 673 | if (sizeof(target_channel) > 20) |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 674 | return 0; |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 675 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 676 | notify_fail("Diese Ebene darfst du nicht erschaffen!\n"); |
| 677 | if (CHMASTER->new(target_channel, ME, descr) == E_ACCESS_DENIED) |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 678 | return 0; |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 679 | |
| 680 | tell_object(ME,"Du erschaffst die Ebene '"+target_channel+"'.\n"); |
| 681 | SetProp(P_CHANNELS, QueryProp(P_CHANNELS) + |
| 682 | ({lower_case(target_channel)})); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 683 | return 1; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 684 | } |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 685 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 686 | if (sscanf(args, "beschreibung %s %s", target_channel, descr) == 2) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 687 | { |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 688 | chans = CHMASTER->find(target_channel, ME); |
| 689 | |
| 690 | if (!chans) |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 691 | { |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 692 | notify_fail("Ebene '"+target_channel+"' nicht gefunden!\n"); |
| 693 | return 0; |
| 694 | } |
| 695 | else if (pointerp(chans)) |
| 696 | { |
| 697 | notify_fail( |
| 698 | "Das war keine eindeutige Angabe! Folgende Ebenen passen:\n"+ |
| 699 | break_string(CountUp(chans), 78)); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 700 | return 0; |
| 701 | } |
| 702 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 703 | mapping ch = CHMASTER->list(ME); |
| 704 | notify_fail("Du bist nicht berechtigt, die Beschreibung der Ebene" |
| 705 | " '"+target_channel+"' zu aendern.\n"); |
| 706 | if (ch[lower_case(chans)][I_MASTER] != ME) |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 707 | return 0; |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 708 | |
| 709 | ch[lower_case(target_channel)][I_INFO] = descr; |
| 710 | tell_object(ME,"Die Ebene '"+target_channel+"' hat ab sofort die " |
| 711 | "Beschreibung:\n"+descr+"\n"); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 712 | return 1; |
| 713 | } |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 714 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 715 | if (sscanf(args, "%s=%s", _sh_cut, target_channel) == 2 && |
| 716 | sizeof(target_channel)) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 717 | { |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 718 | chans = CHMASTER->find(target_channel, ME); |
| 719 | |
| 720 | if (!chans) |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 721 | { |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 722 | notify_fail("Ebene '"+target_channel+"' nicht gefunden!\n"); |
| 723 | return 0; |
| 724 | } |
| 725 | else if (pointerp(chans)) |
| 726 | { |
| 727 | notify_fail( |
| 728 | "Das war keine eindeutige Angabe! Folgende Ebenen passen:\n"+ |
| 729 | break_string(CountUp(chans), 78)); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 730 | return 0; |
| 731 | } |
| 732 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 733 | mapping shortcut_list = QueryProp(P_CHANNEL_SHORT) || ([]); |
| 734 | m_add(shortcut_list, _sh_cut, chans); |
| 735 | SetProp(P_CHANNEL_SHORT, shortcut_list); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 736 | |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 737 | shortcut = QueryProp(P_CHANNEL_SHORT); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 738 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 739 | tell_object(ME,"'"+_sh_cut+"' wird jetzt als Abkuerzung fuer '"+chans+ |
| 740 | "' anerkannt.\n"); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 741 | return 1; |
| 742 | } |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 743 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 744 | if (sscanf(args, "%s=", _sh_cut)) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 745 | { |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 746 | SetProp(P_CHANNEL_SHORT, |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 747 | m_delete(QueryProp(P_CHANNEL_SHORT) || ([]), _sh_cut)); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 748 | shortcut = QueryProp(P_CHANNEL_SHORT); |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 749 | tell_object(ME,"Du loeschst die Abkuerzung '"+_sh_cut+"'.\n"); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 750 | return 1; |
| 751 | } |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 752 | |
| 753 | if (args == "an" || args == "ein") |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 754 | { |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 755 | if (pointerp(QueryProp(P_SWAP_CHANNELS))) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 756 | SetProp(P_CHANNELS, QueryProp(P_SWAP_CHANNELS)); |
| 757 | else |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 758 | SetProp(P_CHANNELS, m_indices(CHMASTER->list(ME))); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 759 | |
| 760 | // <excl> enthaelt die Channelnamen, deren Channel nicht erstellt wurden. |
| 761 | string* excl = RegisterChannels(); |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 762 | tell_object(ME,"Du schaltest folgende Ebenen ein:\n"+ |
| 763 | break_string(CountUp(QueryProp(P_CHANNELS) - excl), 78)); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 764 | SetProp(P_SWAP_CHANNELS, 0); |
| 765 | return 1; |
| 766 | } |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 767 | |
| 768 | if (args == "aus") |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 769 | { |
| 770 | SetProp(P_SWAP_CHANNELS, QueryProp(P_CHANNELS)); |
| 771 | RemoveChannels(); |
| 772 | SetProp(P_CHANNELS, ({})); |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 773 | tell_object(ME,"Du stellst die Ebenen ab.\n"); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 774 | return 1; |
| 775 | } |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 776 | |
Arathorn | 0076469 | 2019-11-27 22:09:31 +0100 | [diff] [blame] | 777 | string* pa = old_explode(args, " "); |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 778 | if (strstr("abkuerzungen", pa[0]) == 0) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 779 | { |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 780 | string txt = ""; |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 781 | if (sizeof(pa) > 1 && strstr("standard", pa[1]) == 0) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 782 | { |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 783 | tell_object(ME,"Die Standardabkuerzungen werden gesetzt.\n"); |
| 784 | SetProp(P_CHANNEL_SHORT, |
| 785 | DEFAULT_SHORTCUTS + (IS_LEARNER(ME) ? WIZARD_SHORTCUTS : ([]))); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 786 | } |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 787 | |
| 788 | mapping scut = QueryProp(P_CHANNEL_SHORT); |
| 789 | string* abbreviations = m_indices(scut); |
| 790 | foreach (string abk : sort_array(abbreviations, #'>)) |
| 791 | { |
| 792 | txt += sprintf("%5.5s = %s\n", abk, scut[abk]); |
Arathorn | dc28afc | 2018-11-26 22:20:59 +0100 | [diff] [blame] | 793 | } |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 794 | More( "Folgende Abkuerzungen sind definiert:\n"+ |
| 795 | sprintf("%-78#s\n", txt) ); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 796 | return 1; |
| 797 | } |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 798 | |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 799 | if (strstr("standard", pa[0]) == 0) |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 800 | { |
| 801 | if (sizeof(pa) < 2) |
| 802 | { |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 803 | notify_fail("Benutzung: ebene standard <Ebene>\n"+ |
| 804 | (QueryProp(P_STD_CHANNEL) |
| 805 | ? "Momentan ist '"+QueryProp(P_STD_CHANNEL)+"' eingestellt.\n" |
| 806 | : "Es ist keine Standardebene eingestellt.\n")); |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 807 | return 0; |
| 808 | } |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 809 | |
| 810 | chans = CHMASTER->find(pa[1], ME); |
| 811 | if (!chans) |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 812 | { |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 813 | notify_fail("Ebene '"+pa[1]+"' nicht gefunden!\n"); |
| 814 | return 0; |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 815 | } |
Arathorn | 78c0837 | 2019-12-11 20:14:23 +0100 | [diff] [blame] | 816 | else if (pointerp(chans)) |
| 817 | { |
| 818 | notify_fail( |
| 819 | "Das war keine eindeutige Angabe! Folgende Ebenen passen:\n"+ |
| 820 | break_string(CountUp(chans), 78)); |
| 821 | return 0; |
| 822 | } |
| 823 | |
| 824 | tell_object(ME,"'"+chans+"' ist jetzt die Standardebene.\n"); |
| 825 | SetProp(P_STD_CHANNEL, chans); |
| 826 | return 1; |
Arathorn | 85de760 | 2019-11-28 23:04:03 +0100 | [diff] [blame] | 827 | } |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 828 | return(0); |
| 829 | } |