blob: 5f34f065a31946392fe1ecf715d78c0b6114257e [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// ----------------------------------------------------------------------
2// Tellerstapel, ein Stackorientiertes magiertool.
3// Rumata 15.09.93
4// ----------------------------------------------------------------------
5#include "teller.h"
6inherit "std/secure_thing";
7inherit T_CMDS;
8inherit T_EFUN;
9inherit "std/more";
10
11#include "/secure/wizlevels.h"
12
13nosave mapping tcommands;
14nosave string owner_name;
15
16void logaccess( string s );
17static void do_msg( string s, object o );
18static string|int parseNext( string str, mixed auxstack, string funname );
19static mixed nextAlpha( string s );
20static varargs void restore_stack( string* argv, int args );
21static int do_call( string fun, int mit_return );
22static int do_call_efun( string fun, int mit_return );
23static int do_lpc( string str, int mit_return );
24static int do_cmd( string str );
25int error( string s );
26
27static void tAddCmd( mixed cmd )
28{
29 int i;
30
31 //if (find_player("rikus")) tell_object(find_player("rikus"),sprintf("%O\n",cmd));
32 if( !pointerp(cmd) )
33 m_add(tcommands, cmd, cmd);
34 else
35 for( i=0; i<sizeof(cmd); i++ )
36 m_add(tcommands, cmd[i], cmd[0]);
37}
38
39void create()
40{
41 if( IS_BLUE(ME) ) return;
42 if( !find_player(getuid()) ) return;
43 owner_name = find_player(getuid())->name(WESSEN,1);
44
45 secure_thing::create();
46 t_cmds::create();
47 SetProp( P_NAME, "Tellerstapel" );
48 SetProp( P_GENDER, MALE );
49 AddId( ({"teller","stapel","tellerstapel"}) );
50 SetProp( P_NODROP, "Wozu denn?\n" );
51 SetProp( P_NEVERDROP, 1 );
52 SetProp( P_READ_MSG, "Die Gravur besagt: 'Aus der Rumata-Manufaktur'\n" );
53 tcommands = ([]);
54
55 tAddCmd( "say" );
56 tAddCmd( ({"names","nam"}) );
57 tAddCmd( "secureinv" );
58 tAddCmd( "logaccess" );
59 tAddCmd( "pretty" );
60 tAddCmd( "doprofile" );
61 tAddCmd( ({"clear","clr"}));
62 tAddCmd( "pop" );
63 tAddCmd( "dup" );
64 tAddCmd( "swap" );
65 tAddCmd( ({"evaluate","eval"}) );
66
67 tAddCmd( "here" );
68 tAddCmd( "me" );
69
70 tAddCmd( ({"memory","mem"}) );
71 tAddCmd( "dump" );
72 tAddCmd( "restore" );
73 tAddCmd( "top" );
74 tAddCmd( "wer" );
75 tAddCmd( ({"stack","stk"}) );
76 tAddCmd( ({"snoopers","snoop"}) );
77 tAddCmd( "callouts" );
78 tAddCmd( ({"callouts_bang","callouts!"}) );
79 tAddCmd( ({"heartbeats","beats"}) );
80 tAddCmd( "inv" );
81 tAddCmd( ({"rekinv","rinv"}) );
82 tAddCmd( "scan" );
83 tAddCmd( "if" );
84
85 tAddCmd( ({"array","arr"}) );
86 tAddCmd( ({"split","spl"}) );
87 tAddCmd( ({"player","pl"}) );
88 tAddCmd( ({"living","lv"}) );
89 tAddCmd( ({"object","ob"}) );
90
91 tAddCmd( ({"debuginfo","dinfo"}) );
92 tAddCmd( ({"clone","cln"}) );
93 tAddCmd( ({"update","upd"}) );
94 tAddCmd( ({"update_bang","update!","upd!"}) );
95 tAddCmd( ({"move","mv"}) );
96 tAddCmd( ({"destruct","dest","des"}) );
97 tAddCmd( ({"remove","rem"}) );
98 tAddCmd( ({"destruct_bang","destruct!","dest!","des!","remove!","rem!"}) );
99 tAddCmd( ({"roomupdate","rupdate","rupd","rup"}) );
100 tAddCmd( ({"roomupdate_bang","roomupdate!","rupdate!","rupd!","rup!"}) );
101 tAddCmd( ({"extroomupdate","rupdate*","rupd*","rup*"}) );
102 tAddCmd( ({"extroomupdate_bang","roomupdate*!","rupdate*!","rupd*!","rup*!",
103 "rup!*" }) );
104 tAddCmd( ({"cleanof","clnof"}) );
105 tAddCmd( ({"cleanof_bang","cleanof!","clnof!"}) );
106
107 tAddCmd( "ping" );
108}
109
110void init()
111{
112 //logaccess( "init" );
113 ::init();
114 if ( !IS_WIZARD(PL) || environment()!=PL )
115 return;
116 add_action( "parse", ",", 1 );
117 add_action( "jonglier", "jonglier", 1 );
118 add_action( "message", "message" );
119 add_action( "message", "msg" );
120}
121
122short()
123{
124 logaccess( "short" );
125 return "Ein Stapel Teller.\n";
126}
127
128id( str )
129{
130 logaccess( "id" );
131 return ::id(str);
132}
133
134name( casus, dem, force )
135{
136 logaccess( "name" );
137 return ::name( casus, dem, force );
138}
139
140long()
141{
142 string answer;
143
144 answer =
145 "Du betrachtest "+owner_name+" magischen Tellerstapel. Die einzelnen Teller sind\n"
146 +"bis auf eine kleine Inschrift auf dem Boden weiss. Wenn Du hiermit\n"
147 +"jonglierst, kann ALLES passieren.\n";
148
149 if( getuid(PL) == getuid() )
150 {
151 answer +=
152 ( mit_say
153 ? "Die Teller sind beim Jonglieren sichtbar.\n"
154 : "Die Teller sind beim Jonglieren unsichtbar.\n"
155 ) + ( mit_namen
156 ? "Die Teller nennen die Dinge beim Namen.\n"
157 : "Die Teller nennen die Dinge beim Filenamen.\n"
158 ) + ( pretty
159 ? "Die Teller haben ein verschnoerkeltes Muster.\n"
160 : "Die Teller sind geradezu schmucklos.\n"
161 ) + ( dologaccess
162 ? "Die Teller spueren Zugriffe.\n"
163 : ""
164 ) + ( secureinv
165 ? "Die Teller bewachen Dein Inventar.\n"
166 : ""
167 ) + ( do_profile
168 ? "Die Teller werden beim Einloggen aktiv.\n"
169 : ""
170 );
171 }
172 return answer;
173}
174
175void _set_autoloadobj( mixed val )
176{
177 if( !pointerp(val) ) return;
178 val += ({ 0,0,0,0,0,0 });
179 mit_namen = val[0];
180 mit_say = val[1];
181 set_heart_beat( secureinv = val[2] );
182 dologaccess = val[3];
183 pretty = val[4];
184 do_profile = val[5];
185 if( do_profile ) call_out( "_load_profile", 0, this_player() );
186}
187
188mixed _query_autoloadobj()
189{
190 return ({ mit_namen, mit_say, secureinv, dologaccess, pretty,
191 do_profile });
192}
193
194void _load_profile( object pl )
195{
196 string pf,errmsg;
197
198 if( geteuid() && pl && geteuid(pl)==geteuid()
199 && file_size(pf="/players/"+geteuid()+"/.profile.c")>0
200 && (errmsg=catch(call_other(pf,"setup",pl)))
201 )
202 printf( "Error loading profile: %O\n", errmsg );
203}
204
205void logaccess( string str )
206{
207 if( RPL && dologaccess && getuid()!=getuid(RPL) && find_player(getuid())
208 && previous_object() && getuid(previous_object()) != ROOTID
209 && query_wiz_level(getuid())>=query_wiz_level(getuid(RPL))
210 )
211 tell_object( find_player(getuid()), "MEMO: " + str + "() von "
212 + RPL->name(WEM) + " via ["
213 + object_name(previous_object())+"].\n"
214 );
215 if( secureinv && find_player(getuid()) && !member(heart_beat_info(),ME) )
216 {
217 tell_object( find_player(getuid()), "MEMO: heart_beat restartet!.\n" );
218 set_heart_beat(TRUE);
219 }
220}
221
222// ----------------------------------------------------------------------
223// Hilfe-Funktionen
224// ----------------------------------------------------------------------
225static int secure()
226{
227 int i;
228 if( process_call() || secure_level()<query_wiz_level(RPL) ) return 0;
229 for( i=0; previous_object(i)==RPL; i++ )
230 ;
231 return (!previous_object(i) || previous_object()==ME)
232 && getuid()==getuid(RPL) && IS_WIZARD(RPL);
233}
234
235int jonglier( string str )
236{
237 string arg;
238
239 logaccess( "jongliere" );
240 if( !str || id(str) || sscanf( str, "mit %s", arg ) == 1 )
241 {
242 if( !secure() )
243 write(
244 "Dieser Tellerstapel ist nichts fuer Dich. Suche Dir einen eigenen.\n"
245 );
246 else
247 write(
248 "Der Jonglierbefehl lautet \";\" oder \",\".\n"
249 + "\";hilfe <befehl>\" gibt Dir Hilfestellung.\n"
250 );
251 return TRUE;
252 }
253 return 0;
254}
255
256static int zeige_hilfe( string str )
257{
258 if( !stringp(str) ) str = "general";
259 str = implode( old_explode( HELP(str), "/../" ), "/" );
260 if( file_size(str) > 0 )
261 {
262 More( str, 1 );
263 return TRUE;
264 }
265 write( "Zu diesem Thema gibt es keine Hilfe.\n" );
266 return TRUE;
267}
268
269int message( string str )
270{
271 string pl;
272 object dest;
273
274 if( !secure() ) return FALSE;
275
276 if( str )
277 {
278 if( sscanf( str, "to %s", pl ) == 1 )
279 str = pl;
280 if( !(dest = find_player(str) ) )
281 {
282 write( capitalize(str) + " ist nicht eingeloggt.\n" );
283 return TRUE;
284 }
285 }
286 else
287 dest = 0;
288
289 do_msg( "<Mitteilung von "+PL->name(WEM)+">", dest );
290 write( "Mitteilung"
291 + ( dest ? " an " + dest->name(WEN) : "" )
292 + " kann mit '**' beendet werden.\n" );
293
294 input_to( "more_message", 0, dest );
295 return TRUE;
296}
297
298static void do_msg( string str, object obj )
299{
300 if( obj )
301 tell_object( obj, str + "\n" );
302 else
303 say( str + "\n" );
304}
305
306static int more_message( string str, object obj )
307{
308 if( str != "**" )
309 {
310 do_msg( str, obj );
311 input_to( "more_message", 0, obj );
312 }
313 else
314 do_msg( "<Ende der Mitteilung>", obj );
315 return TRUE;
316}
317
318// ----------------------------------------------------------------------
319// Parse-Funktionen
320// ----------------------------------------------------------------------
321int parse( string str )
322{
323 int i;
324 string arg, rest;
325
326 if( !secure() ) return FALSE;
327
328 // Die Hilfe faellt aus der allgemeinen Syntax heraus !
329 if( query_verb()[1..] == "hilfe" || query_verb()[1..] == "help" )
330 return zeige_hilfe( str );
331
332 if( str=this_player()->_unparsed_args() )
333 str = query_verb()[1..]+" "+str;
334 else
335 str = query_verb()[1..];
336
337 fehler_passiert = FALSE;
338 while( !fehler_passiert && str && str!="" )
339 str = parseNext( str, ({}), "-ROOT-" );
340
341 if( mit_say && !PL->QueryProp(P_INVIS) )
342 {
343 if( !fehler_passiert )
344 say( PL->name(WER)+" jongliert mit "
345 + PL->QPP(MALE,WEM,PLURAL)+" Tellern.\n" );
346 else
347 say( PL->name(WEM)+" faellt beim Jonglieren ein Teller herunter.\n" );
348 }
349 if( !fehler_passiert )
350 write( "OK.\n" );
351 return TRUE;
352}
353
354static string|int parseNext( string str, mixed auxstack, string funname )
355{
356 mixed *res;
357 string arg, rest;
358 bool mit_return;
359 int num;
360
361 while( str!="" && str[0]==' ' )
362 str = str[1..];
363 if( str=="" )
364 return FALSE;
365
366 switch( str[0] )
367 {
368 case ';': // ---------------------------------------- Kommandobeginn
369 case ',':
370 push( ";" );
371 return str[1..];
372 case '\"': // --------------------------------------- Stringkonstante
373 if( sscanf( str, "\"%s\"%s", arg, rest )==2 )
374 {
375 /* test auf numerisch fehlt hier noch */
376 push_str( arg );
377 return rest;
378 }
379 if( !sscanf( str, "\"%s\"", arg ) )
380 return error( "String ohne Ende" );
381 push_str( arg );
382 return FALSE;
383 case '#': // ---------------------------------------- Zahl
384 res = nextAlpha( str[1..] );
385 if( sscanf( res[0], "%d", num ) == 1 )
386 {
387 push( num );
388 return res[1];
389 }
390 return error( "'#': keine erlaubte Zahl" );
391 case '^': // ---------------------------------------- Hole env
392 if( !becomes_obj() )
393 return error( "'^': TOS ist kein Objekt" );
394 if( !environment(top()) )
395 return error( "'^': TOS hat kein Environment" );
396 push(environment(pop()));
397 return str[1..];
398 case '.': // ---------------------------------------- Hole aus inv
399 if( !becomes_obj() )
400 return error( "'.': TOS ist kein Objekt" );
401 res = nextAlpha( str[1..] );
402 calcinv( res[0] );
403 return res[1];
404 case '<': // ---------------------------------------- Recall
405 if( !sscanf( str, "<%s", arg ) || arg=="" )
406 return error( "'<': Variablenname fehlt" );
407 res = nextAlpha( str[1..] );
408 do_recall(res[0]);
409 return res[1];
410 case '>': // ---------------------------------------- Store
411 if( !sscanf( str, ">%s", arg ) || arg=="" )
412 return error( "'>': Variablenname fehlt" );
413 res = nextAlpha( str[1..] );
414 do_store(res[0]);
415 return res[1];
416 case '-': // ---------------------------------------- Call mit '-'
417 str = str[1..];
418 if( mit_return = (str[0] == '-') )
419 str = str[1..];
420 res = nextAlpha( str[1..] );
421 switch( str[0] )
422 {
423 case '>':
424 if( do_call( res[0], mit_return ) )
425 return res[1];
426 break;
427 case '*':
428 if( do_call_efun( res[0], mit_return ) )
429 return res[1];
430 break;
431 default:
432 return error( "'-': '>' oder '*' erwartet" );
433 }
434 return FALSE;
435 case '\'': // --------------------------------------- Call
436 str = str[1..];
437 if( mit_return = (str[0] == '\'') )
438 str = str[1..];
439 res = nextAlpha( str );
440 if( do_call( res[0], mit_return ) )
441 return res[1];
442 return FALSE;
443 case '`': // --------------------------------------- Call Efun
444 str = str[1..];
445 if( mit_return = (str[0] == '`') )
446 str = str[1..];
447 res = nextAlpha( str );
448 if( do_call_efun( res[0], mit_return ) )
449 return res[1];
450 return FALSE;
451 case '@': // --------------------------------------- Evaluate
452 str = str[1..];
453 if( mit_return = (str[0] == '@') )
454 str = str[1..];
455 if( do_lpc( str, mit_return ) )
456 return FALSE;
457 return FALSE;
458 case '!': // ------------------------------------------- META
459 if( sscanf(str,"!%d%s",num,arg)==2 )
460 {
461 if( num>=sizeof(auxstack) )
462 return error( "'"+funname+"': zu weing Argumente" );
463 push( auxstack[num] );
464 }
465 else
466 {
467 res = nextAlpha( str[1..] );
468 memory += ([ res[0]: res[1]; 1 ]);
469 return FALSE;
470 }
471 return arg;
472 default: // ----------------------------------------- default
473 res = nextAlpha( str );
474 do_cmd(res[0]);
475 return res[1];
476 }
477 return memo( "Etwas Seltsames ist passiert" );
478}
479
480static int do_cmd( string str )
481{
482 string fun, filename, *spl;
483 mixed* oldstack;
484 int i,max,num;
485
486 if( member(memory,str) )
487 {
488 fun = memory[str,0];
489 if( !memory[str,1] ) // normale Variablen
490 {
491 push( fun );
492 return TRUE;
493 }
494 oldstack = stack;
495 stack = ({});
496 spl = regexplode( fun, "![0-9][0-9]*" );
497 max = -1;
498 for( i=1; i<sizeof(spl); i+=2 )
499 if( sscanf(spl[i],"!%d",num) && max<num ) max = num;
500
501 while( !fehler_passiert && fun && fun!="" )
502 fun = parseNext( fun, oldstack, str );
503 if( fehler_passiert )
504 {
505 stack = oldstack;
506 return FALSE;
507 }
508 stack = stack + oldstack[(max+1)..];
509 return TRUE;
510 }
511 else if (fun=tcommands[str])
512 return call_other(ME,"cmd_"+fun);
513
514 if( sscanf( str, "%d", i ) )
515 push( i );
516 else
517 {
518 filename = MASTER->_get_path(str,getuid());
519 if( filename[<1] == '.' )
520 filename = filename[0..<2];
521 if( file_size( filename+".c" ) != -1 )
522 push( filename );
523 else
524 push( str );
525 }
526 return TRUE;
527}
528
529static mixed nextAlpha( string str )
530{
531 int pos;
532
533 for(
534 pos=0;
535 pos<sizeof(str) && member( " #\";,^.><", str[pos] ) == -1;
536 pos++
537 )
538 ;
539
540 if( pos==sizeof(str) )
541 return ({ str, 0 });
542 else
543 return ({ str[0..pos-1], str[pos..] });
544}
545
546static varargs void restore_stack( string* argv, int args )
547{
548 int i;
549 if( !args )
550 args = sizeof(argv);
551 if( sizeof(stack) ) push( ";" );
552 for( i=0; i<args; i++ )
553 push(argv[i]);
554}
555
556static int do_call( string fun, int mit_return )
557{
558 int args;
559 string err;
560 mixed result;
561 mixed arg, *argv;
562
563 argv = ({});
564 while( sizeof(stack) && (arg=pop())!=";" )
565 argv = ({arg}) + argv;
566 if( !becomes_obj(argv) )
567 {
568 restore_stack( argv );
569 return error( "call: Funktion nicht an Objekt gerichtet" );
570 }
571 if( !function_exists(fun,argv[0]) )
572 {
573 restore_stack(argv);
574 return error( "call: Funktion nicht gefunden" );
575 }
576
577 args = sizeof(argv);
578 argv += ({ 0,0,0,0,0 });
579 err=(catch(result=call_other(argv[0],fun,
580 argv[1],argv[2],argv[3],argv[4],argv[5])));
581 if( err )
582 {
583 restore_stack( argv, args );
584 return error( "call: "+err[1..<2] );
585 }
586 else
587 {
588 write( "=> " );
589 dump_obj( result, 3 );
590 if( mit_return )
591 push( result );
592 }
593 return TRUE;
594}
595
596static int do_call_efun( string fun, int mit_return )
597{
598 int args;
599 string err;
600 mixed result;
601 mixed arg, *argv;
602
603 argv = ({});
604 while( sizeof(stack) && (arg=pop())!=";" )
605 argv = ({arg}) + argv;
606
607 if( !function_exists( "efun_"+fun ) )
608 return error( "call efun: \""+fun+"\" nicht benutzbar" );
609 fun = "efun_"+fun;
610
611 args = sizeof(argv);
612 argv += ({ 0,0,0,0,0 });
613 err=(catch(result=call_other(ME,fun,
614 argv[0],argv[1],argv[2],argv[3],argv[4])));
615 if( err )
616 {
617 restore_stack( argv, args );
618 return error( "call efun: "+err[1..<2] );
619 }
620 else
621 {
622 write( "=> " );
623 dump_obj( result, 3 );
624 if( mit_return )
625 push( result );
626 }
627 return TRUE;
628}
629
630static int do_lpc( string str, int mit_return )
631{
632 int args, val;
633 string err;
634 string file, cmd, pre, post;
635 mixed result;
636 mixed arg, *argv;
637
638 argv = ({});
639 while( sizeof(stack) && (arg=pop())!=";" )
640 argv = argv + ({arg});
641
642 file = "/players/"+getuid()+"/.teller";
643 cmd = "#include <language.h>\n#include <properties.h>\n"
644 + "#include <moving.h>\n#include <defines.h>\n#include <terminal.h>\n"
645 + "#include <wizlevels.h>\n#include <ansi.h>\ncreate(){}doit(){";
646
647 while( str!="" && sscanf( str, "%s@%s", pre, post ) == 2 )
648 {
649 if( sscanf( str, "%s@%d@%s", pre, val, post ) == 3 )
650 {
651 if( sizeof(argv)<=val || val<0 )
652 {
653 restore_stack( argv, args );
654 return error( "lpc: Illegaler Index auf den Stack" );
655 }
656 cmd += pre + DumpObj(argv[val]);
657 str = post;
658 }
659 else
660 if( sscanf( str, "%s@%s", pre, post ) == 2 )
661 {
662 cmd += pre + "@";
663 str = post;
664 }
665 }
666 cmd += str;
667 rm( file+".c" );
668 write_file( file+".c" , cmd+";}\n" );
669 if( find_object(file) ) destruct( find_object(file) );
670 err=(catch(result=call_other(file,"doit")));
671 if( err )
672 {
673 //rm( file+".c" );
674 restore_stack( argv, args );
675 return error( "lpc: "+err[1..<2] );
676 }
677 else
678 {
679 //rm( file+".c" );
680 write( "=> " );
681 dump_obj( result, 3 );
682 if( mit_return )
683 push( result );
684 }
685 return TRUE;
686}