blob: 74821564967a59eb2c8e47d4b38627d445db1132 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2//
3// upd.c
4//
5// $Id: upd.c 8850 2014-06-13 21:34:44Z Zesstra $
6#pragma strict_types
7#pragma save_types
8#pragma range_check
9#pragma no_clone
MG Mud User88f12472016-06-24 23:31:02 +020010
11#define NEED_PROTOTYPES
12#include <magier.h>
13#include <player.h>
14#undef NEED_PROTOTYPES
15#include <debug_info.h>
16#include <wizlevels.h>
17#include <moving.h>
18#include <properties.h>
19#include <logging.h>
20#include <thing/properties.h>
21
22varargs static int _make(string file, int flags, int recursive);
23
24static mixed _query_localcmds()
25{
26 return ({({"upd","_upd",0,LEARNER_LVL}),
27 ({"load","_load",0,LEARNER_LVL})});
28}
29
30//
31// _save(): Spieler in Rettungsraum retten
32// obj: Spielerobjekt(?)
33// inv_save: Rettungsraumname
34// Rueckgabe: 0 wenn kein Spielerobjekt
35// Spielerobjekt, falls doch
36//
37
38static mixed _save( object obj, object inv_saver )
39{
40 if ( query_once_interactive(obj) )
41 {
bugfixd94d0932020-04-08 11:27:13 +020042 ({int})obj->move( inv_saver, NO_CHECK );
MG Mud User88f12472016-06-24 23:31:02 +020043 return obj;
44 }
45 return 0;
46}
47
48
49//
50// _reload(): Objekt laden
51// file: Filename. Muss in der Form /xx/xx/xx.c vorliegen
52// clone: > 0 -> Es soll geclont werden, enthaelt Objektnummer des
53// Vorgaengerobjektes
54// flags: Kommandozeilenoptionen
55// err: Leerstring als Referenz uebergeben. Enthaelt nach dem
56// Aufruf vom _reload() die Fehlermeldungen als String.
57// Rueckgabe: Das neu erzeugte Objekt bzw. das schon vorhandene Objekt
58// bzw. 0, wenn Fehler auftrat.
59//
60
61private object _reload(string file, int clone, int flags, string err)
62{
63 object obj;
64
65 if (!obj=find_object(file[0..<3]+(clone?("#"+clone):"")))
66 {
67 int pos,pos2;
MG Mud User88f12472016-06-24 23:31:02 +020068
69 if(file_size(file)<0)
70 {
71 if (file_size(file)==-1)
72 err = sprintf("upd: %s: Datei existiert nicht.\n", file);
73 else // directory
74 err = sprintf("upd: %s: Verzeichnisse koennen nicht geladen "
75 "werden.\n",file);
76 return obj; // 0
77 }
78 pos = max(file_size(__DEBUG_LOG__),0);
79
80 if ((err = (clone?catch(obj = clone_object(file)):
81 catch(load_object(file)) )) && (flags & UPD_B))
82 {
83 if (( pos2=file_size(__DEBUG_LOG__)) > pos )
84 err+=sprintf("\nBacktrace:\n%s",
85 read_bytes(__DEBUG_LOG__,pos, pos2-pos ));
86 else
87 err+=sprintf("\nKEIN BACKTRACE VERFUEGBAR!\n");
88 }
89 if (!err&&!obj&&(!obj = find_object(file[0..<3])))
90 err += sprintf( "upd: %s: Blueprint nach dem Laden zerstoert.\n",file );
91 }
92 else
93 err=sprintf("upd: Objekt existiert schon: %O\n",obj);
94 return obj;
95}
96
97
98//
99// _update(): File updaten -> Blueprint destructen
100// file: Filename
101// dummy: simulieren? (1->wird nicht aktualisiert)
102// flags: Kommandozeilenoptionen
103// Rueckgabe: -1: Keine Vollzugriff
104// 0: Objekt ist nicht geladen
105// 1: Operation wird durchgefuehrt
106//
107
108private varargs int _update(string file, int dummy, int flags)
109{
110 object obj;
111 string err;
112 if (!dummy && !objectp(obj = find_object(file))) return 0;
113 if (!IS_ARCH(this_object()))
114 {
115 // Schreibrechte nur pruefen, wenn echt aktualisiert werden soll.
116 if(!dummy && !MAY_WRITE(file))
Zesstra9ad254c2019-09-27 00:30:41 +0200117 return (printf("upd: %s: Keine Schreibrechte!\n",file), -1);
118 if(!MAY_READ(file))
MG Mud User88f12472016-06-24 23:31:02 +0200119 return (printf("upd: %s: Keine Leserechte!\n", file), -1);
120 }
121 if (dummy) return 1;
122
123 if ( flags & UPD_D )
124 {
125 object *inv;
126 if (sizeof(inv = deep_inventory(obj)))
127 {
128 printf("upd: %s: Entferne Objekte im Inventar\n", file );
129 if (!(flags&UPD_H))
130 {
131 if(err=catch(filter_objects( inv, "remove", 1 )))
132 printf("upd: %s: Fehlgeschlagen. Grund:\n%s\n",
133 file,err);
134 }
135 if (sizeof(inv = deep_inventory(obj)))
136 filter(inv, function void (object ob)
137 {destruct(ob);});
138 }
139 }
140 if (!(flags&UPD_H))
141 {
bugfixd94d0932020-04-08 11:27:13 +0200142 if(err = catch(({int})obj->remove()))
MG Mud User88f12472016-06-24 23:31:02 +0200143 printf("upd: %s: remove() fehlgeschlagen. Aufruf von " +
144 "destruct().\n",file);
145 }
146 if(objectp(obj)) destruct(obj);
147 return 1;
148}
149
150
151//
152// _instance_upd(): Alle Objekte nach Clones des Objekts durchsuchen
153// file: Filename des Objektes
154// flags: Kommandozeilenargumente
155// obj: Aktuelles Objekt
156// instances: Zahl der gefundenen Instanzen
157//
158
159private void _instance_upd(string file, int flags, mixed obj, int instances,
160 int firstcall)
161{
162 int i;
163 if (firstcall)
164 printf("upd: %s: %s Instanzen.\n",file,flags&UPD_A?"Aktualisiere":"Suche");
165
166 while (get_eval_cost()>220000 && i < sizeof(obj))
167 {
168 if (!objectp(obj[i]))
169 instances--;
170 else
171 {
172 if (flags&UPD_F&&!(flags&UPD_S))
173 printf( "upd: %O gefunden in %s\n", obj[i],
174 environment(obj[i])?object_name(environment(obj[i]))
175 : "keiner Umgebung" );
176 if (flags&UPD_A) _make(object_name(obj[i]), flags & ~(UPD_A|UPD_F),1 );
177 }
178 i++;
179 }
180 if (i < sizeof(obj))
181 call_out( #'_instance_upd/*'*/,2,file,flags,obj[i..],instances,0);
182 else
183 printf( "upd: %s: %d Instanzen %s\n", file, instances,
184 (flags & UPD_A) ? "aktualisiert" : "gefunden" );
185 return;
186}
187
188
189//
190// _do_make(): Alle geerbten Objekte bearbeiten (fuer -m/-v)
191// file: Name des Files
192// clone: 0, wenn blueprint, ansonsten Clonenummer
193// flags: Kommandozeilenparameter
194// dep: geschachteltes Array mit Meldungen (wg. Rekursion)
195// ready: Array der schon bearbeiteten Objekte (wg. Rekursion)
196// Rueckgabe: Array der Objektnamen, die bearbeitet wurden
197// (Array in Array in ...)
198//
199
200varargs private int _do_make( string file,int clone,int flags,mixed dep,
201 string *ready )
202{
203 object obj;
204 string err;
205 string *ilist;
206 mixed downdeps;
207 int ret;
208
209 if (!pointerp(ready)) ready = ({});
210 ready += ({ file });
211
212 if ( !(obj = _reload(file,clone,flags,&err)))
213 {
214 dep += ({ err });
215 return 0;
216 }
217
218 ilist = inherit_list(obj)-ready;
219
220 downdeps = ({});
221
222 while (sizeof(ilist))
223 {
224 ret = _do_make( ilist[0],0,flags, &downdeps, &ready )||ret;
225 ilist[0..0] = ({});
226 ilist -= ready;
227 }
228
229 if ( ret||file_time(file)>program_time(obj)||(flags &UPD_I))
230 if ( _make( file, flags & ~(UPD_M|UPD_I) ,1) < 0 )
231 dep = ({ "{" + explode(file,"/")[<1] + "}", downdeps });
232 else{
233 dep = ({ "[" + explode(file,"/")[<1] + "]", downdeps });
234 ret = 1;
235 }
236 else if (flags&UPD_V) dep += ({ explode(file,"/")[<1], downdeps });
237 return ret;
238}
239
240
241//
242// _make_dep(): Ausgabe des Ererbungsbaumes
243// Objekte im Array dep
244// prefix enthaelt Zeilenanfang (fuer Rekursion)
245// Rueckgabe: String mit dem Vererbungsbaum des Objektes
246//
247
248private string _make_dep( mixed dep, string prefix )
249{
250 string ret;
251 int i, size;
252
253 ret="";
254 size=sizeof(dep);
255 for (i=0; i<size;i++)
256 if (pointerp(dep[i]))
257 ret += _make_dep(dep[i],prefix + (i < (size-1) ? "| ":" "));
258 else
259 ret += prefix + "+-" + dep[i] + "\n";
260 return ret;
261}
262
MG Mud User88f12472016-06-24 23:31:02 +0200263//
264// _make(): Update file
265// file: Filename
266// flags: Kommandozeilenargumente
267//
268
269varargs static int _make(string file, int flags,int recursive)
270{
271 string msg, err, blue;
272 int inst;
273 object obj, inv_saver;
274 mixed tmp;
275
276 msg = "";
277
278 if (!file) return printf( "upd: Kein Filename uebergeben!\n" ), RET_FAIL;
279
280// Filename in Blue, Objektname in blue, Instanznummer in inst
281
282 if (sscanf(file,"%s#%d",blue,inst)==2) blue += ".c";
283 else blue = file + (file[<2..]==".c" ? "" : ".c");
284
285// Alle Instanzen durchsuchen im Falle von -a oder -f
286
287 if ((flags & UPD_LOAD)&&find_object(file))
288 return printf("load: %s: Objekt ist schon geladen.\n",file),RET_OK;
289
290 if ( flags & (UPD_F|UPD_A))
291 {
292 if (inst) return printf( "upd: %s: Eine Instanz kann keine " +
293 "Clones haben.\n",file ), RET_FAIL;
294 if ((tmp=_update(file, 1,flags))==-1)
295 return printf( "upd: %s: Kein Vollzugriff auf die " +
296 "Datei erlaubt.\n",file), RET_FAIL;
297 if (tmp==0) return RET_FAIL;
298
299 tmp=clones(blue[0..<3],2);
300 if (sizeof(tmp))
301 call_out( #'_instance_upd/*'*/, 0, file,flags,tmp,sizeof(tmp),1);
302 else
303 printf( "upd: %s: Keine Clones vorhanden!\n", blue[0..<3]);
304
305 if ( (flags & UPD_F) && !(flags &(UPD_R|UPD_L|UPD_LOAD))) return RET_OK;
306 // Nichts laden -> Auch kein Backup
307 }
308
309// Backupraum festlegen
310
311 if( blue==INV_SAVE ) {
312 printf("upd: Achtung: Raum zum Zwischenspeichern soll geladen werden?!\n");
313 }
314 if ( !(inv_saver=load_object(INV_SAVE)) )
315 {
316 printf("upd: %s: Raum zum Zwischenspeichern des " +
317 "Rauminhalts ist nicht ladbar.\n" +
318 " %s\n",file,INV_SAVE);
319 return RET_FAIL;
320 }
321
322// Wenn das Objekt existiert bzw. Deep aktualisiert werden soll
323
324 if ( (!(flags&UPD_LOAD))&&
325 ((obj = find_object(file)) || (flags & (UPD_M|UPD_I))))
326 {
Arathornb3051452021-05-13 21:13:03 +0200327 object *inv, env;
MG Mud User88f12472016-06-24 23:31:02 +0200328 mapping pro;
329 int i;
330 mixed configdata;
331 int restore_config;
332
Bugfix5f26ae82025-07-03 14:55:24 +0200333 // Wenn Objekt existiert, dann Inhalt und ggf. Daten aus Configure() sichern
MG Mud User88f12472016-06-24 23:31:02 +0200334 if (obj)
335 {
Bugfix5f26ae82025-07-03 14:55:24 +0200336 catch(restore_config=call_resolved(&configdata,obj,
337 "Configure",0);
338 publish);
339 // Wenn UPD_CONF gesetzt wird, _muss_ das Objekt ein oeffentliches
340 // Configure() definieren, sonst erfolgt Abbruch.
341 if ((flags & UPD_CONF) && !restore_config)
MG Mud User88f12472016-06-24 23:31:02 +0200342 {
Bugfix5f26ae82025-07-03 14:55:24 +0200343 printf("upd: %s: hat kein Configure(), Zerstoerung abgebrochen.\n",file);
344 return RET_FAIL;
MG Mud User88f12472016-06-24 23:31:02 +0200345 }
346 if (!(flags&UPD_D)&&(flags&(UPD_L|UPD_R)))
347 {
348 if (i=sizeof(inv=(all_inventory(obj)-({0}))))
349 {
350 mixed items;
351 // Herausbekommen, ob hier Items existieren, die per AddItem
352 // erzeugt werden. Die duerfen nicht gesichert werden.
Vanion50652322020-03-10 21:13:25 +0100353 items=({mixed})obj->QueryProp(P_ITEMS); // mixed, da array of arrays
MG Mud User88f12472016-06-24 23:31:02 +0200354 if (pointerp(items)&&sizeof(items))
355 {
356 items=transpose_array(items)[0];
357 while (i--)
358 if (member(items, inv[i])==-1)
bugfixd94d0932020-04-08 11:27:13 +0200359 ({int})inv[i]->move(inv_saver,NO_CHECK);
MG Mud User88f12472016-06-24 23:31:02 +0200360 }
361 else // In diesem Objekt sind keine Items gesetzt.
bugfixd94d0932020-04-08 11:27:13 +0200362 while (i--) ({int})inv[i]->move(inv_saver,NO_CHECK);
MG Mud User88f12472016-06-24 23:31:02 +0200363 }
364 }
365 else
366 {
367 inv=map( deep_inventory(obj), #'_save/*'*/, inv_saver )-({0});
368 }
369 env = environment(obj);
MG Mud User88f12472016-06-24 23:31:02 +0200370 }
371 else inv = ({});
372
373// Ererbte Objekte durchsuchen.
374 if ( flags & (UPD_M|UPD_I) )
375 {
376 mixed dep;
377 dep = ({});
378 _do_make( blue, inst, flags & ~(UPD_M|UPD_L|UPD_R|UPD_F|UPD_A), &dep );
379 printf( _make_dep( dep, "" ) + "\n" );
380 }
381
382// Tatsaechlichen Update durchfuehren
383
384 if ( _update(file, 0, flags)< 0) return RET_FAIL;
385 msg += (inst ? "zerstoert" : "aktualisiert");
386
387// Neu laden ??
388 if ( flags & (UPD_R|UPD_L) )
389 {
390 if ( obj = _reload( blue,inst,flags, &err ) )
391 msg += ", " + (inst ? "neu geclont" : "neu geladen");
392
Bugfix5f26ae82025-07-03 14:55:24 +0200393// Neu geladen: Konfiguration wiederherstellen
MG Mud User88f12472016-06-24 23:31:02 +0200394 if (!err)
395 {
396 if (!obj) obj = find_object(file);
Bugfix5f26ae82025-07-03 14:55:24 +0200397 // Ggf. Ergebnis von Configure() uebergeben
398 if (restore_config)
MG Mud User88f12472016-06-24 23:31:02 +0200399 {
400 int conf_res;
Vanion50652322020-03-10 21:13:25 +0100401 if (!catch(conf_res=({int})obj->Configure(configdata); publish)
MG Mud User88f12472016-06-24 23:31:02 +0200402 && conf_res == 1)
403 {
404 msg += ", (re-)konfiguriert";
405 }
406 else
407 {
408 msg += ", (Re-)Konfiguration fehlgeschlagen";
409 if (flags & UPD_CONF)
410 printf("upd: Daten von %s konnten nicht rekonfiguriert werden: "
411 "%O\n", file, configdata);
412 }
413 }
414 if (env)
415 {
bugfixd94d0932020-04-08 11:27:13 +0200416 if ( ({int})obj->move( env, NO_CHECK ) <= 0 )
MG Mud User88f12472016-06-24 23:31:02 +0200417 printf( "upd: /%O konnte nicht in /%O zurueckbewegt werden\n",
418 obj, env );
419 else
420 msg += ", bewegt";
421 }
422 if (i=sizeof(inv))
423 {
bugfixd94d0932020-04-08 11:27:13 +0200424 while(i--) if (inv[i]) ({int})inv[i]->move(obj, NO_CHECK );
MG Mud User88f12472016-06-24 23:31:02 +0200425 msg += ", Inhalt zurueckbewegt";
426 }
427 }
428 else
429 return printf( "upd: %s: %s", file, err ), RET_FAIL;
430 }
431 }
432 else
433 if ( !_update(file, 0, flags) && (flags & (UPD_L|UPD_LOAD)) )
434 if ( !_reload( blue, inst, flags, &err ) )
435 return printf( "%s: %s: %s", (flags&UPD_LOAD?"load":"upd"),file, err ),
436 RET_FAIL;
437 else
438 msg += "geladen";
439
440 if ( sizeof(msg)&&!(flags&UPD_S&&recursive) )
441 printf("%s: %s: %s.\n",(flags&UPD_LOAD?"load":"upd"),file,msg);
442 return RET_OK;
443}
444
445//
446// _upd: Objekte laden, zerstoeren und aktualisieren
447//
448
449static int _upd(string cmdline)
450{
451 int flags;
452 mixed *args;
453
454 cmdline=_unparsed_args();
455 args=parseargs(cmdline,&flags,UPD_OPTS,1);
456 if(flags==-1||!sizeof(args))
457 return USAGE("upd [-"+UPD_OPTS+"] <datei> [<datei> ..]");
MG Mud User88f12472016-06-24 23:31:02 +0200458 args=file_list(args,MODE_UPD,0,"/");
459 if(!sizeof(args)) return printf("upd: Keine passende Datei gefunden!\n"),1;
460
461 args=map(args,(: $1[FULLNAME] :))-({0});
462
463 if(!sizeof(args))
464 {
465 printf("upd: Verzeichnisse koennen nicht aktualisiert werden!\n");
466 return 1;
467 }
468 asynchron(args,#'_make,flags,0,0);
469 return 1;
470}
471
472//
473// _load: Objekte laden
474//
475
476static int _load(string cmdline)
477{
478 int flags;
479 mixed *args;
480
481 cmdline=_unparsed_args();
482 args=parseargs(cmdline,&flags,"",1);
483 if(flags==-1||!sizeof(args))
484 return USAGE("load <datei> [<datei> ..]");
485 args=file_list(args,MODE_UPD,0,"/");
486 if(!sizeof(args)) return printf("load: Keine passende Datei gefunden!\n"),1;
487 args=map(args,(: (($1[FILESIZE]!=-2||find_object($1[FULLNAME]))?
488 $1[FULLNAME]:0) :))-({0});
489
490 if(!sizeof(args))
491 return printf("load: Verzeichnisse koennen nicht geladen werden!\n"),1;
492 asynchron(args,#'_make,UPD_LOAD,0,0);
493 return 1;
494}