blob: 22581b1c4e01b81660edc2bdbb03ec824b7c715b [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2//
3// secure/master/destruct.inc -- module of the master object: stuff for destruct.
4//
5// $Id: master.c 7041 2008-10-13 18:18:27Z Zesstra $
6
7#include "/sys/object_info.h"
8
9// privilegierte Objekte, die das destruct() abbrechen duerfen (root objekte
10// duerfen auch ohne, dass sie in dieser Liste erfasst sind):
11private nosave string *deny_destruct_list = ({
12 "/obj/shut", "/room/void", "/room/netztot", "/room/jail" });
13
14// Helferfunktion fuer prepare_destruct()
15private void recursive_remove(object ob, int immediate_destruct) {
16
17 if (efun::object_info(ob, OI_ONCE_INTERACTIVE)) {
18 // Spieler werden ins Void bewegt.
19 int res;
20 tell_object(ob, "Ploetzlich loest sich deine Welt in ihre " +
21 "Bestandteile auf. Zum Glueck wirst\nDu irgendwo " +
22 "hin geschleudert ...\n");
23 // wenn Bewegung buggt oder nicht funktioniert und ob noch existiert,
24 // rekursiv zerstoeren.
25 object oldenv=environment(ob);
Zesstrad872d182019-11-28 20:13:02 +010026 if ( (catch(res=({int})ob->move("/room/void",M_TPORT|M_NOCHECK,0,"faellt");
MG Mud User88f12472016-06-24 23:31:02 +020027 publish) || (ob && environment(ob) == oldenv) )
28 && ob) {
29 // Spieler speichern, dann erst Inventar entleeren, dann remove() und
30 // und destruct() anwenden.
bugfixd94d0932020-04-08 11:27:13 +020031 catch(({void})ob->save_me(1); publish);
MG Mud User88f12472016-06-24 23:31:02 +020032 filter(all_inventory(ob), #'recursive_remove, immediate_destruct);
33 if (!immediate_destruct)
bugfixd94d0932020-04-08 11:27:13 +020034 catch(({int})ob->remove(0);publish);
MG Mud User88f12472016-06-24 23:31:02 +020035 if (ob)
36 destruct(ob);
37 }
38 }
39 else {
40 // kein Spieler. Rekursiv entfernen. Hierbei _zuerst_ rekursiv das
41 // Inventar entfernen und dann ob selber, damit nicht erst das Inventar in
42 // das Environment bewegt wird (soll ja eh zerstoert werden).
43 filter(all_inventory(ob), #'recursive_remove, immediate_destruct);
44 // ggf. zuerst remove versuchen
45 if (!immediate_destruct)
bugfixd94d0932020-04-08 11:27:13 +020046 catch(({int})ob->remove(1);publish);
MG Mud User88f12472016-06-24 23:31:02 +020047 if (ob)
48 destruct(ob);
49 }
50}
51
52// Zerstoerung von ob vorbereiten
53protected mixed prepare_destruct(object ob)
54{
55 object old_env,env,item;
Zesstrad872d182019-11-28 20:13:02 +010056 int|string res;
MG Mud User88f12472016-06-24 23:31:02 +020057
58 // zuerst das notify_destruct() rufen und ggf. abbrechen, falls ob
59 // privilegiert ist.
Zesstrad872d182019-11-28 20:13:02 +010060 catch(res = ({int|string})ob->NotifyDestruct(previous_object()); publish);
MG Mud User88f12472016-06-24 23:31:02 +020061 if (res &&
62 (getuid(ob) == ROOTID ||
63 (IS_ARCH(ob)) ||
64 member(deny_destruct_list, object_name(ob)) >= 0)) {
65 if (stringp(res) && sizeof(res))
66 return res;
67 else
68 return sprintf("%O verweigert die Zerstoerung mittels destruct(). "
69 "Fehlende Rechte von %O?\n",ob, previous_object());
70 }
Zesstrabfdcd9d2020-09-21 19:19:35 +020071
72#if (__VERSION_MICRO__*100 + __VERSION_MINOR__ *10000 + __VERSION_MAJOR__ \
73 * 1000000) <= 3060300
74 // Workaround fuer Driver-Speicherleck in 3.6.2 und 3.6.3: vor dem
75 // Zerstoeren das Encoding wechseln, damit der driver das Handle auf iconv
76 // schliesst.
77 if(interactive(ob))
78 configure_interactive(ob, IC_ENCODING, "UTF-8");
79#endif
80
MG Mud User88f12472016-06-24 23:31:02 +020081 env = environment(ob);
82
83 // Objekt hat kein Env: Alles zerstoeren, Spieler ins Void
84 if (!env) {
85 filter(all_inventory(ob), #'recursive_remove, 1);
86 }
87 else {
88 // Ansonsten alles ins Environment
89 foreach(item : all_inventory(ob))
90 {
91 old_env=environment(item);
92 // M_MOVE_ALL, falls item nen Unitobjekt ist. Sonst clonen die u.U. noch
93 // wieder nen neues Objekt im alten Env.
bugfixd94d0932020-04-08 11:27:13 +020094 if(catch(({int})item->move(env, M_NOCHECK|M_MOVE_ALL);publish))
MG Mud User88f12472016-06-24 23:31:02 +020095 recursive_remove(item, 1);
96 else if (item && environment(item) == old_env)
97 recursive_remove(item, 1);
98 }
99 }
100
101 return 0; // Erfolg
102}
103
104// Anmerkung: liefert 0 zurueck, wenn die sefuns gerade geladen werden.
105string NotifyDestruct(object caller) {
106 // Nicht jeder Magier muss den Master entsorgen koennen.
107 if ((caller != this_object() &&
108 call_sefun("secure_level") < ARCH_LVL)
109 || call_sefun("process_call") ) {
110 return "Du darfst den Mudlib-Master nicht zerstoeren!\n";
111 }
112 return 0;
113}
114