DEADSOFTWARE

warnings for -O3
[d2df-sdl.git] / src / game / g_console.pas
1 unit g_console;
3 interface
5 procedure g_Console_Init();
6 procedure g_Console_Update();
7 procedure g_Console_Draw();
8 procedure g_Console_Switch();
9 procedure g_Console_Char(C: Char);
10 procedure g_Console_Control(K: Word);
11 procedure g_Console_Process(L: String; Quiet: Boolean = False);
12 procedure g_Console_Add(L: String; Show: Boolean = False);
13 procedure g_Console_Clear();
14 function g_Console_CommandBlacklisted(C: String): Boolean;
16 procedure g_Console_Chat_Switch(Team: Boolean = False);
18 var
19 gConsoleShow: Boolean; // True - êîíñîëü îòêðûòà èëè îòêðûâàåòñÿ
20 gChatShow: Boolean;
21 gChatTeam: Boolean = False;
22 gAllowConsoleMessages: Boolean = True;
23 gChatEnter: Boolean = True;
24 gJustChatted: Boolean = False; // ÷òîáû àäìèí â èíòåðå ÷àòÿñü íå ïðîìàòûâàë ñòàòèñòèêó
26 implementation
28 uses
29 g_textures, g_main, e_graphics, e_input, g_game,
30 SysUtils, g_basic, g_options, WADEDITOR, Math,
31 g_menu, g_language, g_net, g_netmsg;
33 type
34 TCmdProc = procedure (P: SArray);
36 TCommand = record
37 Cmd: String;
38 Proc: TCmdProc;
39 end;
41 TAlias = record
42 Name: String;
43 Commands: SArray;
44 end;
46 const
47 Step = 32;
48 Alpha = 25;
49 MsgTime = 144;
50 MaxScriptRecursion = 16;
52 DEBUG_STRING = 'DEBUG MODE';
54 var
55 ID: DWORD;
56 RecursionDepth: Word = 0;
57 RecursionLimitHit: Boolean = False;
58 Cons_Y: SmallInt;
59 Cons_Shown: Boolean; // Ðèñîâàòü ëè êîíñîëü?
60 Line: String;
61 CPos: Word;
62 ConsoleHistory: SArray;
63 CommandHistory: SArray;
64 Whitelist: SArray;
65 Commands: Array of TCommand;
66 Aliases: Array of TAlias;
67 CmdIndex: Word;
68 Offset: Word;
69 MsgArray: Array [0..4] of record
70 Msg: String;
71 Time: Word;
72 end;
74 function GetStrACmd(var Str: String): String;
75 var
76 a: Integer;
77 begin
78 Result := '';
79 for a := 1 to Length(Str) do
80 if (a = Length(Str)) or (Str[a+1] = ';') then
81 begin
82 Result := Copy(Str, 1, a);
83 Delete(Str, 1, a+1);
84 Str := Trim(Str);
85 Exit;
86 end;
87 end;
89 function ParseAlias(Str: String): SArray;
90 begin
91 Result := nil;
93 Str := Trim(Str);
95 if Str = '' then
96 Exit;
98 while Str <> '' do
99 begin
100 SetLength(Result, Length(Result)+1);
101 Result[High(Result)] := GetStrACmd(Str);
102 end;
103 end;
105 procedure ConsoleCommands(P: SArray);
106 var
107 Cmd, s: String;
108 a, b: Integer;
109 F: TextFile;
110 begin
111 Cmd := LowerCase(P[0]);
112 s := '';
114 if Cmd = 'clear' then
115 begin
116 ConsoleHistory := nil;
118 for a := 0 to High(MsgArray) do
119 with MsgArray[a] do
120 begin
121 Msg := '';
122 Time := 0;
123 end;
124 end;
126 if Cmd = 'clearhistory' then
127 CommandHistory := nil;
129 if Cmd = 'showhistory' then
130 if CommandHistory <> nil then
131 begin
132 g_Console_Add('');
133 for a := 0 to High(CommandHistory) do
134 g_Console_Add(' '+CommandHistory[a]);
135 end;
137 if Cmd = 'commands' then
138 begin
139 g_Console_Add('');
140 g_Console_Add('Commands list:');
141 for a := High(Commands) downto 0 do
142 g_Console_Add(' '+Commands[a].Cmd);
143 end;
145 if Cmd = 'time' then
146 g_Console_Add(TimeToStr(Now), True);
148 if Cmd = 'date' then
149 g_Console_Add(DateToStr(Now), True);
151 if Cmd = 'echo' then
152 if Length(P) > 1 then
153 begin
154 if P[1] = 'ololo' then
155 gCheats := True
156 else
157 begin
158 s := '';
159 for a := 1 to High(P) do
160 s := s + P[a] + ' ';
161 g_Console_Add(b_Text_Format(s), True);
162 end;
163 end
164 else
165 g_Console_Add('');
167 if Cmd = 'dump' then
168 begin
169 if ConsoleHistory <> nil then
170 begin
171 if Length(P) > 1 then
172 s := P[1]
173 else
174 s := GameDir+'/console.txt';
176 {$I-}
177 AssignFile(F, s);
178 Rewrite(F);
179 if IOResult <> 0 then
180 begin
181 g_Console_Add(Format(_lc[I_CONSOLE_ERROR_WRITE], [s]));
182 CloseFile(F);
183 Exit;
184 end;
186 for a := 0 to High(ConsoleHistory) do
187 WriteLn(F, ConsoleHistory[a]);
189 CloseFile(F);
190 g_Console_Add(Format(_lc[I_CONSOLE_DUMPED], [s]));
191 {$I+}
192 end;
193 end;
195 if Cmd = 'exec' then
196 begin
197 // exec <filename>
198 if Length(P) > 1 then
199 begin
200 s := GameDir+'/'+P[1];
202 {$I-}
203 AssignFile(F, s);
204 Reset(F);
205 if IOResult <> 0 then
206 begin
207 g_Console_Add(Format(_lc[I_CONSOLE_ERROR_READ], [s]));
208 CloseFile(F);
209 Exit;
210 end;
211 g_Console_Add(Format(_lc[I_CONSOLE_EXEC], [s]));
213 while not EOF(F) do
214 begin
215 ReadLn(F, s);
216 if IOResult <> 0 then
217 begin
218 g_Console_Add(Format(_lc[I_CONSOLE_ERROR_READ], [s]));
219 CloseFile(F);
220 Exit;
221 end;
222 if Pos('#', s) <> 1 then // script comment
223 begin
224 // prevents endless loops
225 Inc(RecursionDepth);
226 RecursionLimitHit := (RecursionDepth > MaxScriptRecursion) or RecursionLimitHit;
227 if not RecursionLimitHit then
228 g_Console_Process(s, True);
229 Dec(RecursionDepth);
230 end;
231 end;
232 if (RecursionDepth = 0) and RecursionLimitHit then
233 begin
234 g_Console_Add(Format(_lc[I_CONSOLE_ERROR_CALL], [s]));
235 RecursionLimitHit := False;
236 end;
238 CloseFile(F);
239 {$I+}
240 end
241 else
242 g_Console_Add('exec <script file>');
243 end;
245 if Cmd = 'alias' then
246 begin
247 // alias [alias_name] [commands]
248 if Length(P) > 1 then
249 begin
250 for a := 0 to High(Aliases) do
251 if Aliases[a].Name = P[1] then
252 begin
253 if Length(P) > 2 then
254 Aliases[a].Commands := ParseAlias(P[2])
255 else
256 for b := 0 to High(Aliases[a].Commands) do
257 g_Console_Add(Aliases[a].Commands[b]);
258 Exit;
259 end;
260 SetLength(Aliases, Length(Aliases)+1);
261 a := High(Aliases);
262 Aliases[a].Name := P[1];
263 if Length(P) > 2 then
264 Aliases[a].Commands := ParseAlias(P[2])
265 else
266 for b := 0 to High(Aliases[a].Commands) do
267 g_Console_Add(Aliases[a].Commands[b]);
268 end else
269 for a := 0 to High(Aliases) do
270 if Aliases[a].Commands <> nil then
271 g_Console_Add(Aliases[a].Name);
272 end;
274 if Cmd = 'call' then
275 begin
276 // call <alias_name>
277 if Length(P) > 1 then
278 begin
279 if Aliases = nil then
280 Exit;
281 for a := 0 to High(Aliases) do
282 if Aliases[a].Name = P[1] then
283 begin
284 if Aliases[a].Commands <> nil then
285 begin
286 // with this system proper endless loop detection seems either impossible
287 // or very dirty to implement, so let's have this instead
288 // prevents endless loops
289 for b := 0 to High(Aliases[a].Commands) do
290 begin
291 Inc(RecursionDepth);
292 RecursionLimitHit := (RecursionDepth > MaxScriptRecursion) or RecursionLimitHit;
293 if not RecursionLimitHit then
294 g_Console_Process(Aliases[a].Commands[b], True);
295 Dec(RecursionDepth);
296 end;
297 if (RecursionDepth = 0) and RecursionLimitHit then
298 begin
299 g_Console_Add(Format(_lc[I_CONSOLE_ERROR_CALL], [s]));
300 RecursionLimitHit := False;
301 end;
302 end;
303 Exit;
304 end;
305 end
306 else
307 g_Console_Add('call <alias name>');
308 end;
309 end;
311 procedure WhitelistCommand(Cmd: string);
312 var
313 a: Integer;
314 begin
315 SetLength(Whitelist, Length(Whitelist)+1);
316 a := High(Whitelist);
317 Whitelist[a] := Cmd;
318 end;
320 procedure AddCommand(Cmd: String; Proc: TCmdProc);
321 var
322 a: Integer;
323 begin
324 SetLength(Commands, Length(Commands)+1);
325 a := High(Commands);
326 Commands[a].Cmd := Cmd;
327 Commands[a].Proc := Proc;
328 end;
330 procedure g_Console_Init();
331 var
332 a: Integer;
333 begin
334 g_Texture_CreateWAD(ID, GameWAD+':TEXTURES\CONSOLE');
335 Cons_Y := -(gScreenHeight div 2);
336 gConsoleShow := False;
337 gChatShow := False;
338 Cons_Shown := False;
339 CPos := 1;
341 for a := 0 to High(MsgArray) do
342 with MsgArray[a] do
343 begin
344 Msg := '';
345 Time := 0;
346 end;
348 AddCommand('clear', ConsoleCommands);
349 AddCommand('clearhistory', ConsoleCommands);
350 AddCommand('showhistory', ConsoleCommands);
351 AddCommand('commands', ConsoleCommands);
352 AddCommand('time', ConsoleCommands);
353 AddCommand('date', ConsoleCommands);
354 AddCommand('echo', ConsoleCommands);
355 AddCommand('dump', ConsoleCommands);
356 AddCommand('exec', ConsoleCommands);
357 AddCommand('alias', ConsoleCommands);
358 AddCommand('call', ConsoleCommands);
360 AddCommand('d_window', DebugCommands);
361 AddCommand('d_sounds', DebugCommands);
362 AddCommand('d_frames', DebugCommands);
363 AddCommand('d_winmsg', DebugCommands);
364 AddCommand('d_monoff', DebugCommands);
365 AddCommand('d_botoff', DebugCommands);
366 AddCommand('d_monster', DebugCommands);
367 AddCommand('d_health', DebugCommands);
368 AddCommand('d_player', DebugCommands);
369 AddCommand('d_joy', DebugCommands);
371 AddCommand('p1_name', GameCVars);
372 AddCommand('p2_name', GameCVars);
373 AddCommand('p1_color', GameCVars);
374 AddCommand('p2_color', GameCVars);
375 AddCommand('r_showfps', GameCVars);
376 AddCommand('r_showtime', GameCVars);
377 AddCommand('r_showscore', GameCVars);
378 AddCommand('r_showlives', GameCVars);
379 AddCommand('r_showstat', GameCVars);
380 AddCommand('r_showkillmsg', GameCVars);
381 AddCommand('r_showspect', GameCVars);
382 AddCommand('r_showping', GameCVars);
383 AddCommand('g_gamemode', GameCVars);
384 AddCommand('g_friendlyfire', GameCVars);
385 AddCommand('g_weaponstay', GameCVars);
386 AddCommand('g_allow_exit', GameCVars);
387 AddCommand('g_allow_monsters', GameCVars);
388 AddCommand('g_bot_vsmonsters', GameCVars);
389 AddCommand('g_bot_vsplayers', GameCVars);
390 AddCommand('g_scorelimit', GameCVars);
391 AddCommand('g_timelimit', GameCVars);
392 AddCommand('g_maxlives', GameCVars);
393 AddCommand('g_warmuptime', GameCVars);
394 AddCommand('net_interp', GameCVars);
395 AddCommand('net_forceplayerupdate', GameCVars);
396 AddCommand('net_predictself', GameCVars);
397 AddCommand('sv_name', GameCVars);
398 AddCommand('sv_passwd', GameCVars);
399 AddCommand('sv_maxplrs', GameCVars);
400 AddCommand('sv_public', GameCVars);
401 AddCommand('sv_intertime', GameCVars);
403 AddCommand('quit', GameCommands);
404 AddCommand('exit', GameCommands);
405 AddCommand('pause', GameCommands);
406 AddCommand('endgame', GameCommands);
407 AddCommand('restart', GameCommands);
408 AddCommand('addbot', GameCommands);
409 AddCommand('bot_add', GameCommands);
410 AddCommand('bot_addlist', GameCommands);
411 AddCommand('bot_addred', GameCommands);
412 AddCommand('bot_addblue', GameCommands);
413 AddCommand('bot_removeall', GameCommands);
414 AddCommand('chat', GameCommands);
415 AddCommand('teamchat', GameCommands);
416 AddCommand('game', GameCommands);
417 AddCommand('host', GameCommands);
418 AddCommand('map', GameCommands);
419 AddCommand('nextmap', GameCommands);
420 AddCommand('endmap', GameCommands);
421 AddCommand('goodbye', GameCommands);
422 AddCommand('suicide', GameCommands);
423 AddCommand('spectate', GameCommands);
424 AddCommand('ready', GameCommands);
425 AddCommand('kick', GameCommands);
426 AddCommand('kick_id', GameCommands);
427 AddCommand('ban', GameCommands);
428 AddCommand('permban', GameCommands);
429 AddCommand('ban_id', GameCommands);
430 AddCommand('permban_id', GameCommands);
431 AddCommand('unban', GameCommands);
432 AddCommand('connect', GameCommands);
433 AddCommand('disconnect', GameCommands);
434 AddCommand('reconnect', GameCommands);
435 AddCommand('say', GameCommands);
436 AddCommand('tell', GameCommands);
437 AddCommand('overtime', GameCommands);
438 AddCommand('rcon_password', GameCommands);
439 AddCommand('rcon', GameCommands);
440 AddCommand('callvote', GameCommands);
441 AddCommand('vote', GameCommands);
442 AddCommand('clientlist', GameCommands);
443 AddCommand('event', GameCommands);
445 WhitelistCommand('say');
446 WhitelistCommand('tell');
447 WhitelistCommand('overtime');
448 WhitelistCommand('ready');
449 WhitelistCommand('map');
450 WhitelistCommand('nextmap');
451 WhitelistCommand('endmap');
452 WhitelistCommand('restart');
453 WhitelistCommand('kick');
454 WhitelistCommand('ban');
456 WhitelistCommand('addbot');
457 WhitelistCommand('bot_add');
458 WhitelistCommand('bot_addred');
459 WhitelistCommand('bot_addblue');
460 WhitelistCommand('bot_removeall');
462 WhitelistCommand('g_gamemode');
463 WhitelistCommand('g_friendlyfire');
464 WhitelistCommand('g_weaponstay');
465 WhitelistCommand('g_allow_exit');
466 WhitelistCommand('g_allow_monsters');
467 WhitelistCommand('g_scorelimit');
468 WhitelistCommand('g_timelimit');
470 g_Console_Add(Format(_lc[I_CONSOLE_WELCOME], [GAME_VERSION]));
471 g_Console_Add('');
472 end;
474 procedure g_Console_Update();
475 var
476 a, b: Integer;
477 begin
478 if Cons_Shown then
479 begin
480 // Â ïðîöåññå îòêðûòèÿ:
481 if gConsoleShow and (Cons_Y < 0) then
482 begin
483 Cons_Y := Cons_Y+Step;
484 end;
486 // Â ïðîöåññå çàêðûòèÿ:
487 if (not gConsoleShow) and
488 (Cons_Y > -(gScreenHeight div 2)) then
489 Cons_Y := Cons_Y-Step;
491 // Îêîí÷àòåëüíî îòêðûëàñü:
492 if Cons_Y > 0 then
493 Cons_Y := 0;
495 // Îêîí÷àòåëüíî çàêðûëàñü:
496 if Cons_Y <= (-(gScreenHeight div 2)) then
497 begin
498 Cons_Y := -(gScreenHeight div 2);
499 Cons_Shown := False;
500 end;
501 end;
503 a := 0;
504 while a <= High(MsgArray) do
505 begin
506 if MsgArray[a].Time > 0 then
507 begin
508 if MsgArray[a].Time = 1 then
509 begin
510 if a < High(MsgArray) then
511 begin
512 for b := a to High(MsgArray)-1 do
513 MsgArray[b] := MsgArray[b+1];
515 MsgArray[High(MsgArray)].Time := 0;
517 a := a - 1;
518 end;
519 end
520 else
521 Dec(MsgArray[a].Time);
522 end;
524 a := a + 1;
525 end;
526 end;
528 procedure g_Console_Draw();
529 var
530 CWidth, CHeight: Byte;
531 mfW, mfH: Word;
532 a, b, c, d: Integer;
533 begin
534 e_TextureFontGetSize(gStdFont, CWidth, CHeight);
536 for a := 0 to High(MsgArray) do
537 if MsgArray[a].Time > 0 then
538 e_TextureFontPrintFmt(0, CHeight*a, MsgArray[a].Msg,
539 gStdFont, True);
541 if not Cons_Shown then
542 begin
543 if gChatShow then
544 begin
545 if gChatTeam then
546 begin
547 e_TextureFontPrintEx(0, gScreenHeight - CHeight - 1, 'say team> ' + Line,
548 gStdFont, 255, 255, 255, 1, True);
549 e_TextureFontPrintEx((CPos + 9)*CWidth, gScreenHeight - CHeight - 1, '_',
550 gStdFont, 255, 255, 255, 1, True);
551 end
552 else
553 begin
554 e_TextureFontPrintEx(0, gScreenHeight - CHeight - 1, 'say> ' + Line,
555 gStdFont, 255, 255, 255, 1, True);
556 e_TextureFontPrintEx((CPos + 4)*CWidth, gScreenHeight - CHeight - 1, '_',
557 gStdFont, 255, 255, 255, 1, True);
558 end;
559 end;
560 Exit;
561 end;
563 if gDebugMode then
564 begin
565 e_CharFont_GetSize(gMenuFont, DEBUG_STRING, mfW, mfH);
566 a := (gScreenWidth - 2*mfW) div 2;
567 b := Cons_Y + ((gScreenHeight div 2) - 2*mfH) div 2;
568 e_CharFont_PrintEx(gMenuFont, a div 2, b div 2, DEBUG_STRING,
569 _RGB(128, 0, 0), 2.0);
570 end;
572 e_DrawSize(ID, 0, Cons_Y, Alpha, False, False, gScreenWidth, gScreenHeight div 2);
573 e_TextureFontPrint(0, Cons_Y+(gScreenHeight div 2)-CHeight-4, '> '+Line, gStdFont);
575 if ConsoleHistory <> nil then
576 begin
577 b := 0;
578 if CHeight > 0 then
579 if Length(ConsoleHistory) > ((gScreenHeight div 2) div CHeight)-1 then
580 b := Length(ConsoleHistory)-((gScreenHeight div 2) div CHeight)+1;
582 b := Max(b-Offset, 0);
583 d := Max(High(ConsoleHistory)-Offset, 0);
585 c := 2;
586 for a := d downto b do
587 begin
588 e_TextureFontPrintFmt(0, (gScreenHeight div 2)-4-c*CHeight-Abs(Cons_Y), ConsoleHistory[a],
589 gStdFont, True);
590 c := c + 1;
591 end;
592 end;
594 e_TextureFontPrint((CPos+1)*CWidth, Cons_Y+(gScreenHeight div 2)-21, '_', gStdFont);
595 end;
597 procedure g_Console_Switch();
598 begin
599 if gChatShow then Exit;
600 gConsoleShow := not gConsoleShow;
601 Cons_Shown := True;
602 end;
604 procedure g_Console_Chat_Switch(Team: Boolean = False);
605 begin
606 if gConsoleShow then Exit;
607 if not g_Game_IsNet then Exit;
608 gChatShow := not gChatShow;
609 gChatTeam := Team;
610 if gChatShow then
611 gChatEnter := False;
612 Line := '';
613 CPos := 1;
614 end;
616 procedure g_Console_Char(C: Char);
617 begin
618 if gChatShow and (not gChatEnter) then
619 Exit;
620 Insert(C, Line, CPos);
621 CPos := CPos + 1;
622 end;
624 procedure Complete();
625 var
626 i: Integer;
627 t: Array of String;
628 begin
629 if Line = '' then
630 Exit;
632 t := nil;
634 for i := 0 to High(Commands) do
635 if LowerCase(Line) = LowerCase(Copy(Commands[i].Cmd, 0, Length(Line))) then
636 begin
637 SetLength(t, Length(t) + 1);
638 t[Length(t)-1] := Commands[i].Cmd;
639 end;
641 if t = nil then
642 Exit;
644 if Length(t) = 1 then
645 begin
646 Line := t[0]+' ';
647 CPos := Length(Line)+1;
648 end
649 else
650 begin
651 g_Console_Add('');
652 for i := 0 to High(t) do
653 g_Console_Add(' '+t[i]);
654 end;
655 end;
657 procedure g_Console_Control(K: Word);
658 begin
659 case K of
660 IK_BACKSPACE:
661 if (Length(Line) > 0) and (CPos > 1) then
662 begin
663 Delete(Line, CPos-1, 1);
664 CPos := CPos-1;
665 end;
666 IK_DELETE:
667 if (Length(Line) > 0) and (CPos <= Length(Line)) then
668 Delete(Line, CPos, 1);
669 IK_LEFT:
670 if CPos > 1 then
671 CPos := CPos - 1;
672 IK_RIGHT:
673 if CPos <= Length(Line) then
674 CPos := CPos + 1;
675 IK_RETURN:
676 begin
677 if Cons_Shown then
678 g_Console_Process(Line)
679 else
680 if gChatShow then
681 begin
682 if (Length(Line) > 0) and g_Game_IsNet then
683 begin
684 if gChatTeam then
685 begin
686 if g_Game_IsClient then
687 MC_SEND_Chat(b_Text_Format(Line), NET_CHAT_TEAM)
688 else
689 MH_SEND_Chat('[' + gPlayer1Settings.Name + ']: ' + b_Text_Format(Line),
690 NET_CHAT_TEAM, gPlayer1Settings.Team);
691 end
692 else
693 begin
694 if g_Game_IsClient then
695 MC_SEND_Chat(b_Text_Format(Line), NET_CHAT_PLAYER)
696 else
697 MH_SEND_Chat('[' + gPlayer1Settings.Name + ']: ' + b_Text_Format(Line),
698 NET_CHAT_PLAYER);
699 end;
700 end;
702 Line := '';
703 CPos := 1;
704 gChatShow := False;
705 gJustChatted := True;
706 end;
707 end;
708 IK_TAB:
709 if not gChatShow then
710 Complete();
711 IK_DOWN:
712 if not gChatShow then
713 if (CommandHistory <> nil) and
714 (CmdIndex < Length(CommandHistory)) then
715 begin
716 if CmdIndex < Length(CommandHistory)-1 then
717 CmdIndex := CmdIndex + 1;
718 Line := CommandHistory[CmdIndex];
719 CPos := Length(Line) + 1;
720 end;
721 IK_UP:
722 if not gChatShow then
723 if (CommandHistory <> nil) and
724 (CmdIndex <= Length(CommandHistory)) then
725 begin
726 if CmdIndex > 0 then
727 CmdIndex := CmdIndex - 1;
728 Line := CommandHistory[CmdIndex];
729 Cpos := Length(Line) + 1;
730 end;
731 IK_PAGEUP: // PgUp
732 if not gChatShow then
733 IncMax(OffSet, Length(ConsoleHistory)-1);
734 IK_PAGEDN: // PgDown
735 if not gChatShow then
736 DecMin(OffSet, 0);
737 IK_HOME:
738 CPos := 1;
739 IK_END:
740 CPos := Length(Line) + 1;
741 end;
742 end;
744 function GetStr(var Str: String): String;
745 var
746 a, b: Integer;
747 begin
748 Result := '';
749 if Str[1] = '"' then
750 begin
751 for b := 1 to Length(Str) do
752 if (b = Length(Str)) or (Str[b+1] = '"') then
753 begin
754 Result := Copy(Str, 2, b-1);
755 Delete(Str, 1, b+1);
756 Str := Trim(Str);
757 Exit;
758 end;
759 end;
761 for a := 1 to Length(Str) do
762 if (a = Length(Str)) or (Str[a+1] = ' ') then
763 begin
764 Result := Copy(Str, 1, a);
765 Delete(Str, 1, a+1);
766 Str := Trim(Str);
767 Exit;
768 end;
769 end;
771 function ParseString(Str: String): SArray;
772 begin
773 Result := nil;
775 Str := Trim(Str);
777 if Str = '' then
778 Exit;
780 while Str <> '' do
781 begin
782 SetLength(Result, Length(Result)+1);
783 Result[High(Result)] := GetStr(Str);
784 end;
785 end;
787 procedure g_Console_Add(L: String; Show: Boolean = False);
788 var
789 a: Integer;
790 begin
791 // Âûâîä ñòðîê ñ ïåðåíîñàìè ïî î÷åðåäè
792 while Pos(#10, L) > 0 do
793 begin
794 g_Console_Add(Copy(L, 1, Pos(#10, L) - 1), Show);
795 Delete(L, 1, Pos(#10, L));
796 end;
798 SetLength(ConsoleHistory, Length(ConsoleHistory)+1);
799 ConsoleHistory[High(ConsoleHistory)] := L;
801 Show := Show and gAllowConsoleMessages;
803 if Show and gShowMessages then
804 begin
805 for a := 0 to High(MsgArray) do
806 with MsgArray[a] do
807 if Time = 0 then
808 begin
809 Msg := L;
810 Time := MsgTime;
811 Exit;
812 end;
814 for a := 0 to High(MsgArray)-1 do
815 MsgArray[a] := MsgArray[a+1];
817 with MsgArray[High(MsgArray)] do
818 begin
819 Msg := L;
820 Time := MsgTime;
821 end;
822 end;
823 end;
825 procedure g_Console_Clear();
826 begin
827 ConsoleHistory := nil;
828 Offset := 0;
829 end;
831 procedure AddToHistory(L: String);
832 var
833 len: Integer;
834 begin
835 len := Length(CommandHistory);
837 if (len = 0) or
838 (LowerCase(CommandHistory[len-1]) <> LowerCase(L)) then
839 begin
840 SetLength(CommandHistory, len+1);
841 CommandHistory[len] := L;
842 end;
844 CmdIndex := Length(CommandHistory);
845 end;
847 function g_Console_CommandBlacklisted(C: String): Boolean;
848 var
849 Arr: SArray;
850 i: Integer;
851 begin
852 Result := True;
854 Arr := nil;
856 if Trim(C) = '' then
857 Exit;
859 Arr := ParseString(C);
860 if Arr = nil then
861 Exit;
863 for i := 0 to High(Whitelist) do
864 if Whitelist[i] = LowerCase(Arr[0]) then
865 Result := False;
866 end;
868 procedure g_Console_Process(L: String; Quiet: Boolean = False);
869 var
870 Arr: SArray;
871 i: Integer;
872 begin
873 Arr := nil;
875 if Trim(L) = '' then
876 Exit;
878 if not Quiet then
879 begin
880 g_Console_Add('> '+L);
881 Line := '';
882 CPos := 1;
883 end;
885 Arr := ParseString(L);
886 if Arr = nil then
887 Exit;
889 if Commands = nil then
890 Exit;
892 if not Quiet then
893 AddToHistory(L);
895 for i := 0 to High(Commands) do
896 if Commands[i].Cmd = LowerCase(Arr[0]) then
897 if @Commands[i].Proc <> nil then
898 begin
899 Commands[i].Proc(Arr);
900 Exit;
901 end;
903 g_Console_Add(Format(_lc[I_CONSOLE_UNKNOWN], [Arr[0]]));
904 end;
906 end.