DEADSOFTWARE

initial commit:
[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 for a := 1 to Length(Str) do
79 if (a = Length(Str)) or (Str[a+1] = ';') then
80 begin
81 Result := Copy(Str, 1, a);
82 Delete(Str, 1, a+1);
83 Str := Trim(Str);
84 Exit;
85 end;
86 end;
88 function ParseAlias(Str: String): SArray;
89 begin
90 Result := nil;
92 Str := Trim(Str);
94 if Str = '' then
95 Exit;
97 while Str <> '' do
98 begin
99 SetLength(Result, Length(Result)+1);
100 Result[High(Result)] := GetStrACmd(Str);
101 end;
102 end;
104 procedure ConsoleCommands(P: SArray);
105 var
106 Cmd, s: String;
107 a, b: Integer;
108 F: TextFile;
109 begin
110 Cmd := LowerCase(P[0]);
112 if Cmd = 'clear' then
113 begin
114 ConsoleHistory := nil;
116 for a := 0 to High(MsgArray) do
117 with MsgArray[a] do
118 begin
119 Msg := '';
120 Time := 0;
121 end;
122 end;
124 if Cmd = 'clearhistory' then
125 CommandHistory := nil;
127 if Cmd = 'showhistory' then
128 if CommandHistory <> nil then
129 begin
130 g_Console_Add('');
131 for a := 0 to High(CommandHistory) do
132 g_Console_Add(' '+CommandHistory[a]);
133 end;
135 if Cmd = 'commands' then
136 begin
137 g_Console_Add('');
138 g_Console_Add('Commands list:');
139 for a := High(Commands) downto 0 do
140 g_Console_Add(' '+Commands[a].Cmd);
141 end;
143 if Cmd = 'time' then
144 g_Console_Add(TimeToStr(Now), True);
146 if Cmd = 'date' then
147 g_Console_Add(DateToStr(Now), True);
149 if Cmd = 'echo' then
150 if Length(P) > 1 then
151 begin
152 if P[1] = 'ololo' then
153 gCheats := True
154 else
155 begin
156 s := '';
157 for a := 1 to High(P) do
158 s := s + P[a] + ' ';
159 g_Console_Add(b_Text_Format(s), True);
160 end;
161 end
162 else
163 g_Console_Add('');
165 if Cmd = 'dump' then
166 begin
167 if ConsoleHistory <> nil then
168 begin
169 if Length(P) > 1 then
170 s := P[1]
171 else
172 s := GameDir+'/console.txt';
174 {$I-}
175 AssignFile(F, s);
176 Rewrite(F);
177 if IOResult <> 0 then
178 begin
179 g_Console_Add(Format(_lc[I_CONSOLE_ERROR_WRITE], [s]));
180 CloseFile(F);
181 Exit;
182 end;
184 for a := 0 to High(ConsoleHistory) do
185 WriteLn(F, ConsoleHistory[a]);
187 CloseFile(F);
188 g_Console_Add(Format(_lc[I_CONSOLE_DUMPED], [s]));
189 {$I+}
190 end;
191 end;
193 if Cmd = 'exec' then
194 begin
195 // exec <filename>
196 if Length(P) > 1 then
197 begin
198 s := GameDir+'/'+P[1];
200 {$I-}
201 AssignFile(F, s);
202 Reset(F);
203 if IOResult <> 0 then
204 begin
205 g_Console_Add(Format(_lc[I_CONSOLE_ERROR_READ], [s]));
206 CloseFile(F);
207 Exit;
208 end;
209 g_Console_Add(Format(_lc[I_CONSOLE_EXEC], [s]));
211 while not EOF(F) do
212 begin
213 ReadLn(F, s);
214 if IOResult <> 0 then
215 begin
216 g_Console_Add(Format(_lc[I_CONSOLE_ERROR_READ], [s]));
217 CloseFile(F);
218 Exit;
219 end;
220 if Pos('#', s) <> 1 then // script comment
221 begin
222 // prevents endless loops
223 Inc(RecursionDepth);
224 RecursionLimitHit := (RecursionDepth > MaxScriptRecursion) or RecursionLimitHit;
225 if not RecursionLimitHit then
226 g_Console_Process(s, True);
227 Dec(RecursionDepth);
228 end;
229 end;
230 if (RecursionDepth = 0) and RecursionLimitHit then
231 begin
232 g_Console_Add(Format(_lc[I_CONSOLE_ERROR_CALL], [s]));
233 RecursionLimitHit := False;
234 end;
236 CloseFile(F);
237 {$I+}
238 end
239 else
240 g_Console_Add('exec <script file>');
241 end;
243 if Cmd = 'alias' then
244 begin
245 // alias [alias_name] [commands]
246 if Length(P) > 1 then
247 begin
248 for a := 0 to High(Aliases) do
249 if Aliases[a].Name = P[1] then
250 begin
251 if Length(P) > 2 then
252 Aliases[a].Commands := ParseAlias(P[2])
253 else
254 for b := 0 to High(Aliases[a].Commands) do
255 g_Console_Add(Aliases[a].Commands[b]);
256 Exit;
257 end;
258 SetLength(Aliases, Length(Aliases)+1);
259 a := High(Aliases);
260 Aliases[a].Name := P[1];
261 if Length(P) > 2 then
262 Aliases[a].Commands := ParseAlias(P[2])
263 else
264 for b := 0 to High(Aliases[a].Commands) do
265 g_Console_Add(Aliases[a].Commands[b]);
266 end else
267 for a := 0 to High(Aliases) do
268 if Aliases[a].Commands <> nil then
269 g_Console_Add(Aliases[a].Name);
270 end;
272 if Cmd = 'call' then
273 begin
274 // call <alias_name>
275 if Length(P) > 1 then
276 begin
277 if Aliases = nil then
278 Exit;
279 for a := 0 to High(Aliases) do
280 if Aliases[a].Name = P[1] then
281 begin
282 if Aliases[a].Commands <> nil then
283 begin
284 // with this system proper endless loop detection seems either impossible
285 // or very dirty to implement, so let's have this instead
286 // prevents endless loops
287 for b := 0 to High(Aliases[a].Commands) do
288 begin
289 Inc(RecursionDepth);
290 RecursionLimitHit := (RecursionDepth > MaxScriptRecursion) or RecursionLimitHit;
291 if not RecursionLimitHit then
292 g_Console_Process(Aliases[a].Commands[b], True);
293 Dec(RecursionDepth);
294 end;
295 if (RecursionDepth = 0) and RecursionLimitHit then
296 begin
297 g_Console_Add(Format(_lc[I_CONSOLE_ERROR_CALL], [s]));
298 RecursionLimitHit := False;
299 end;
300 end;
301 Exit;
302 end;
303 end
304 else
305 g_Console_Add('call <alias name>');
306 end;
307 end;
309 procedure WhitelistCommand(Cmd: string);
310 var
311 a: Integer;
312 begin
313 SetLength(Whitelist, Length(Whitelist)+1);
314 a := High(Whitelist);
315 Whitelist[a] := Cmd;
316 end;
318 procedure AddCommand(Cmd: String; Proc: TCmdProc);
319 var
320 a: Integer;
321 begin
322 SetLength(Commands, Length(Commands)+1);
323 a := High(Commands);
324 Commands[a].Cmd := Cmd;
325 Commands[a].Proc := Proc;
326 end;
328 procedure g_Console_Init();
329 var
330 a: Integer;
331 begin
332 g_Texture_CreateWAD(ID, GameWAD+':TEXTURES\CONSOLE');
333 Cons_Y := -(gScreenHeight div 2);
334 gConsoleShow := False;
335 gChatShow := False;
336 Cons_Shown := False;
337 CPos := 1;
339 for a := 0 to High(MsgArray) do
340 with MsgArray[a] do
341 begin
342 Msg := '';
343 Time := 0;
344 end;
346 AddCommand('clear', ConsoleCommands);
347 AddCommand('clearhistory', ConsoleCommands);
348 AddCommand('showhistory', ConsoleCommands);
349 AddCommand('commands', ConsoleCommands);
350 AddCommand('time', ConsoleCommands);
351 AddCommand('date', ConsoleCommands);
352 AddCommand('echo', ConsoleCommands);
353 AddCommand('dump', ConsoleCommands);
354 AddCommand('exec', ConsoleCommands);
355 AddCommand('alias', ConsoleCommands);
356 AddCommand('call', ConsoleCommands);
358 AddCommand('d_window', DebugCommands);
359 AddCommand('d_sounds', DebugCommands);
360 AddCommand('d_frames', DebugCommands);
361 AddCommand('d_winmsg', DebugCommands);
362 AddCommand('d_monoff', DebugCommands);
363 AddCommand('d_botoff', DebugCommands);
364 AddCommand('d_monster', DebugCommands);
365 AddCommand('d_health', DebugCommands);
366 AddCommand('d_player', DebugCommands);
367 AddCommand('d_joy', DebugCommands);
369 AddCommand('p1_name', GameCVars);
370 AddCommand('p2_name', GameCVars);
371 AddCommand('p1_color', GameCVars);
372 AddCommand('p2_color', GameCVars);
373 AddCommand('r_showfps', GameCVars);
374 AddCommand('r_showtime', GameCVars);
375 AddCommand('r_showscore', GameCVars);
376 AddCommand('r_showlives', GameCVars);
377 AddCommand('r_showstat', GameCVars);
378 AddCommand('r_showkillmsg', GameCVars);
379 AddCommand('r_showspect', GameCVars);
380 AddCommand('r_showping', GameCVars);
381 AddCommand('g_gamemode', GameCVars);
382 AddCommand('g_friendlyfire', GameCVars);
383 AddCommand('g_weaponstay', GameCVars);
384 AddCommand('g_allow_exit', GameCVars);
385 AddCommand('g_allow_monsters', GameCVars);
386 AddCommand('g_bot_vsmonsters', GameCVars);
387 AddCommand('g_bot_vsplayers', GameCVars);
388 AddCommand('g_scorelimit', GameCVars);
389 AddCommand('g_timelimit', GameCVars);
390 AddCommand('g_maxlives', GameCVars);
391 AddCommand('g_warmuptime', GameCVars);
392 AddCommand('net_interp', GameCVars);
393 AddCommand('net_forceplayerupdate', GameCVars);
394 AddCommand('net_predictself', GameCVars);
395 AddCommand('sv_name', GameCVars);
396 AddCommand('sv_passwd', GameCVars);
397 AddCommand('sv_maxplrs', GameCVars);
398 AddCommand('sv_public', GameCVars);
399 AddCommand('sv_intertime', GameCVars);
401 AddCommand('quit', GameCommands);
402 AddCommand('exit', GameCommands);
403 AddCommand('pause', GameCommands);
404 AddCommand('endgame', GameCommands);
405 AddCommand('restart', GameCommands);
406 AddCommand('addbot', GameCommands);
407 AddCommand('bot_add', GameCommands);
408 AddCommand('bot_addlist', GameCommands);
409 AddCommand('bot_addred', GameCommands);
410 AddCommand('bot_addblue', GameCommands);
411 AddCommand('bot_removeall', GameCommands);
412 AddCommand('chat', GameCommands);
413 AddCommand('teamchat', GameCommands);
414 AddCommand('game', GameCommands);
415 AddCommand('host', GameCommands);
416 AddCommand('map', GameCommands);
417 AddCommand('nextmap', GameCommands);
418 AddCommand('endmap', GameCommands);
419 AddCommand('goodbye', GameCommands);
420 AddCommand('suicide', GameCommands);
421 AddCommand('spectate', GameCommands);
422 AddCommand('ready', GameCommands);
423 AddCommand('kick', GameCommands);
424 AddCommand('kick_id', GameCommands);
425 AddCommand('ban', GameCommands);
426 AddCommand('permban', GameCommands);
427 AddCommand('ban_id', GameCommands);
428 AddCommand('permban_id', GameCommands);
429 AddCommand('unban', GameCommands);
430 AddCommand('connect', GameCommands);
431 AddCommand('disconnect', GameCommands);
432 AddCommand('reconnect', GameCommands);
433 AddCommand('say', GameCommands);
434 AddCommand('tell', GameCommands);
435 AddCommand('overtime', GameCommands);
436 AddCommand('rcon_password', GameCommands);
437 AddCommand('rcon', GameCommands);
438 AddCommand('callvote', GameCommands);
439 AddCommand('vote', GameCommands);
440 AddCommand('clientlist', GameCommands);
441 AddCommand('event', GameCommands);
443 WhitelistCommand('say');
444 WhitelistCommand('tell');
445 WhitelistCommand('overtime');
446 WhitelistCommand('ready');
447 WhitelistCommand('map');
448 WhitelistCommand('nextmap');
449 WhitelistCommand('endmap');
450 WhitelistCommand('restart');
451 WhitelistCommand('kick');
452 WhitelistCommand('ban');
454 WhitelistCommand('addbot');
455 WhitelistCommand('bot_add');
456 WhitelistCommand('bot_addred');
457 WhitelistCommand('bot_addblue');
458 WhitelistCommand('bot_removeall');
460 WhitelistCommand('g_gamemode');
461 WhitelistCommand('g_friendlyfire');
462 WhitelistCommand('g_weaponstay');
463 WhitelistCommand('g_allow_exit');
464 WhitelistCommand('g_allow_monsters');
465 WhitelistCommand('g_scorelimit');
466 WhitelistCommand('g_timelimit');
468 g_Console_Add(Format(_lc[I_CONSOLE_WELCOME], [GAME_VERSION]));
469 g_Console_Add('');
470 end;
472 procedure g_Console_Update();
473 var
474 a, b: Integer;
475 begin
476 if Cons_Shown then
477 begin
478 // Â ïðîöåññå îòêðûòèÿ:
479 if gConsoleShow and (Cons_Y < 0) then
480 begin
481 Cons_Y := Cons_Y+Step;
482 end;
484 // Â ïðîöåññå çàêðûòèÿ:
485 if (not gConsoleShow) and
486 (Cons_Y > -(gScreenHeight div 2)) then
487 Cons_Y := Cons_Y-Step;
489 // Îêîí÷àòåëüíî îòêðûëàñü:
490 if Cons_Y > 0 then
491 Cons_Y := 0;
493 // Îêîí÷àòåëüíî çàêðûëàñü:
494 if Cons_Y <= (-(gScreenHeight div 2)) then
495 begin
496 Cons_Y := -(gScreenHeight div 2);
497 Cons_Shown := False;
498 end;
499 end;
501 a := 0;
502 while a <= High(MsgArray) do
503 begin
504 if MsgArray[a].Time > 0 then
505 begin
506 if MsgArray[a].Time = 1 then
507 begin
508 if a < High(MsgArray) then
509 begin
510 for b := a to High(MsgArray)-1 do
511 MsgArray[b] := MsgArray[b+1];
513 MsgArray[High(MsgArray)].Time := 0;
515 a := a - 1;
516 end;
517 end
518 else
519 Dec(MsgArray[a].Time);
520 end;
522 a := a + 1;
523 end;
524 end;
526 procedure g_Console_Draw();
527 var
528 CWidth, CHeight: Byte;
529 mfW, mfH: Word;
530 a, b, c, d: Integer;
531 begin
532 e_TextureFontGetSize(gStdFont, CWidth, CHeight);
534 for a := 0 to High(MsgArray) do
535 if MsgArray[a].Time > 0 then
536 e_TextureFontPrintFmt(0, CHeight*a, MsgArray[a].Msg,
537 gStdFont, True);
539 if not Cons_Shown then
540 begin
541 if gChatShow then
542 begin
543 if gChatTeam then
544 begin
545 e_TextureFontPrintEx(0, gScreenHeight - CHeight - 1, 'say team> ' + Line,
546 gStdFont, 255, 255, 255, 1, True);
547 e_TextureFontPrintEx((CPos + 9)*CWidth, gScreenHeight - CHeight - 1, '_',
548 gStdFont, 255, 255, 255, 1, True);
549 end
550 else
551 begin
552 e_TextureFontPrintEx(0, gScreenHeight - CHeight - 1, 'say> ' + Line,
553 gStdFont, 255, 255, 255, 1, True);
554 e_TextureFontPrintEx((CPos + 4)*CWidth, gScreenHeight - CHeight - 1, '_',
555 gStdFont, 255, 255, 255, 1, True);
556 end;
557 end;
558 Exit;
559 end;
561 if gDebugMode then
562 begin
563 e_CharFont_GetSize(gMenuFont, DEBUG_STRING, mfW, mfH);
564 a := (gScreenWidth - 2*mfW) div 2;
565 b := Cons_Y + ((gScreenHeight div 2) - 2*mfH) div 2;
566 e_CharFont_PrintEx(gMenuFont, a div 2, b div 2, DEBUG_STRING,
567 _RGB(128, 0, 0), 2.0);
568 end;
570 e_DrawSize(ID, 0, Cons_Y, Alpha, False, False, gScreenWidth, gScreenHeight div 2);
571 e_TextureFontPrint(0, Cons_Y+(gScreenHeight div 2)-CHeight-4, '> '+Line, gStdFont);
573 if ConsoleHistory <> nil then
574 begin
575 b := 0;
576 if CHeight > 0 then
577 if Length(ConsoleHistory) > ((gScreenHeight div 2) div CHeight)-1 then
578 b := Length(ConsoleHistory)-((gScreenHeight div 2) div CHeight)+1;
580 b := Max(b-Offset, 0);
581 d := Max(High(ConsoleHistory)-Offset, 0);
583 c := 2;
584 for a := d downto b do
585 begin
586 e_TextureFontPrintFmt(0, (gScreenHeight div 2)-4-c*CHeight-Abs(Cons_Y), ConsoleHistory[a],
587 gStdFont, True);
588 c := c + 1;
589 end;
590 end;
592 e_TextureFontPrint((CPos+1)*CWidth, Cons_Y+(gScreenHeight div 2)-21, '_', gStdFont);
593 end;
595 procedure g_Console_Switch();
596 begin
597 if gChatShow then Exit;
598 gConsoleShow := not gConsoleShow;
599 Cons_Shown := True;
600 end;
602 procedure g_Console_Chat_Switch(Team: Boolean = False);
603 begin
604 if gConsoleShow then Exit;
605 if not g_Game_IsNet then Exit;
606 gChatShow := not gChatShow;
607 gChatTeam := Team;
608 if gChatShow then
609 gChatEnter := False;
610 Line := '';
611 CPos := 1;
612 end;
614 procedure g_Console_Char(C: Char);
615 begin
616 if gChatShow and (not gChatEnter) then
617 Exit;
618 Insert(C, Line, CPos);
619 CPos := CPos + 1;
620 end;
622 procedure Complete();
623 var
624 i: Integer;
625 t: Array of String;
626 begin
627 if Line = '' then
628 Exit;
630 t := nil;
632 for i := 0 to High(Commands) do
633 if LowerCase(Line) = LowerCase(Copy(Commands[i].Cmd, 0, Length(Line))) then
634 begin
635 SetLength(t, Length(t) + 1);
636 t[Length(t)-1] := Commands[i].Cmd;
637 end;
639 if t = nil then
640 Exit;
642 if Length(t) = 1 then
643 begin
644 Line := t[0]+' ';
645 CPos := Length(Line)+1;
646 end
647 else
648 begin
649 g_Console_Add('');
650 for i := 0 to High(t) do
651 g_Console_Add(' '+t[i]);
652 end;
653 end;
655 procedure g_Console_Control(K: Word);
656 begin
657 case K of
658 IK_BACKSPACE:
659 if (Length(Line) > 0) and (CPos > 1) then
660 begin
661 Delete(Line, CPos-1, 1);
662 CPos := CPos-1;
663 end;
664 IK_DELETE:
665 if (Length(Line) > 0) and (CPos <= Length(Line)) then
666 Delete(Line, CPos, 1);
667 IK_LEFT:
668 if CPos > 1 then
669 CPos := CPos - 1;
670 IK_RIGHT:
671 if CPos <= Length(Line) then
672 CPos := CPos + 1;
673 IK_RETURN:
674 begin
675 if Cons_Shown then
676 g_Console_Process(Line)
677 else
678 if gChatShow then
679 begin
680 if (Length(Line) > 0) and g_Game_IsNet then
681 begin
682 if gChatTeam then
683 begin
684 if g_Game_IsClient then
685 MC_SEND_Chat(b_Text_Format(Line), NET_CHAT_TEAM)
686 else
687 MH_SEND_Chat('[' + gPlayer1Settings.Name + ']: ' + b_Text_Format(Line),
688 NET_CHAT_TEAM, gPlayer1Settings.Team);
689 end
690 else
691 begin
692 if g_Game_IsClient then
693 MC_SEND_Chat(b_Text_Format(Line), NET_CHAT_PLAYER)
694 else
695 MH_SEND_Chat('[' + gPlayer1Settings.Name + ']: ' + b_Text_Format(Line),
696 NET_CHAT_PLAYER);
697 end;
698 end;
700 Line := '';
701 CPos := 1;
702 gChatShow := False;
703 gJustChatted := True;
704 end;
705 end;
706 IK_TAB:
707 if not gChatShow then
708 Complete();
709 IK_DOWN:
710 if not gChatShow then
711 if (CommandHistory <> nil) and
712 (CmdIndex < Length(CommandHistory)) then
713 begin
714 if CmdIndex < Length(CommandHistory)-1 then
715 CmdIndex := CmdIndex + 1;
716 Line := CommandHistory[CmdIndex];
717 CPos := Length(Line) + 1;
718 end;
719 IK_UP:
720 if not gChatShow then
721 if (CommandHistory <> nil) and
722 (CmdIndex <= Length(CommandHistory)) then
723 begin
724 if CmdIndex > 0 then
725 CmdIndex := CmdIndex - 1;
726 Line := CommandHistory[CmdIndex];
727 Cpos := Length(Line) + 1;
728 end;
729 IK_PAGEUP: // PgUp
730 if not gChatShow then
731 IncMax(OffSet, Length(ConsoleHistory)-1);
732 IK_PAGEDN: // PgDown
733 if not gChatShow then
734 DecMin(OffSet, 0);
735 IK_HOME:
736 CPos := 1;
737 IK_END:
738 CPos := Length(Line) + 1;
739 end;
740 end;
742 function GetStr(var Str: String): String;
743 var
744 a, b: Integer;
745 begin
746 if Str[1] = '"' then
747 begin
748 for b := 1 to Length(Str) do
749 if (b = Length(Str)) or (Str[b+1] = '"') then
750 begin
751 Result := Copy(Str, 2, b-1);
752 Delete(Str, 1, b+1);
753 Str := Trim(Str);
754 Exit;
755 end;
756 end;
758 for a := 1 to Length(Str) do
759 if (a = Length(Str)) or (Str[a+1] = ' ') then
760 begin
761 Result := Copy(Str, 1, a);
762 Delete(Str, 1, a+1);
763 Str := Trim(Str);
764 Exit;
765 end;
766 end;
768 function ParseString(Str: String): SArray;
769 begin
770 Result := nil;
772 Str := Trim(Str);
774 if Str = '' then
775 Exit;
777 while Str <> '' do
778 begin
779 SetLength(Result, Length(Result)+1);
780 Result[High(Result)] := GetStr(Str);
781 end;
782 end;
784 procedure g_Console_Add(L: String; Show: Boolean = False);
785 var
786 a: Integer;
787 begin
788 // Âûâîä ñòðîê ñ ïåðåíîñàìè ïî î÷åðåäè
789 while Pos(#10, L) > 0 do
790 begin
791 g_Console_Add(Copy(L, 1, Pos(#10, L) - 1), Show);
792 Delete(L, 1, Pos(#10, L));
793 end;
795 SetLength(ConsoleHistory, Length(ConsoleHistory)+1);
796 ConsoleHistory[High(ConsoleHistory)] := L;
798 Show := Show and gAllowConsoleMessages;
800 if Show and gShowMessages then
801 begin
802 for a := 0 to High(MsgArray) do
803 with MsgArray[a] do
804 if Time = 0 then
805 begin
806 Msg := L;
807 Time := MsgTime;
808 Exit;
809 end;
811 for a := 0 to High(MsgArray)-1 do
812 MsgArray[a] := MsgArray[a+1];
814 with MsgArray[High(MsgArray)] do
815 begin
816 Msg := L;
817 Time := MsgTime;
818 end;
819 end;
820 end;
822 procedure g_Console_Clear();
823 begin
824 ConsoleHistory := nil;
825 Offset := 0;
826 end;
828 procedure AddToHistory(L: String);
829 var
830 len: Integer;
831 begin
832 len := Length(CommandHistory);
834 if (len = 0) or
835 (LowerCase(CommandHistory[len-1]) <> LowerCase(L)) then
836 begin
837 SetLength(CommandHistory, len+1);
838 CommandHistory[len] := L;
839 end;
841 CmdIndex := Length(CommandHistory);
842 end;
844 function g_Console_CommandBlacklisted(C: String): Boolean;
845 var
846 Arr: SArray;
847 i: Integer;
848 begin
849 Result := True;
851 Arr := nil;
853 if Trim(C) = '' then
854 Exit;
856 Arr := ParseString(C);
857 if Arr = nil then
858 Exit;
860 for i := 0 to High(Whitelist) do
861 if Whitelist[i] = LowerCase(Arr[0]) then
862 Result := False;
863 end;
865 procedure g_Console_Process(L: String; Quiet: Boolean = False);
866 var
867 Arr: SArray;
868 i: Integer;
869 begin
870 Arr := nil;
872 if Trim(L) = '' then
873 Exit;
875 if not Quiet then
876 begin
877 g_Console_Add('> '+L);
878 Line := '';
879 CPos := 1;
880 end;
882 Arr := ParseString(L);
883 if Arr = nil then
884 Exit;
886 if Commands = nil then
887 Exit;
889 if not Quiet then
890 AddToHistory(L);
892 for i := 0 to High(Commands) do
893 if Commands[i].Cmd = LowerCase(Arr[0]) then
894 if @Commands[i].Proc <> nil then
895 begin
896 Commands[i].Proc(Arr);
897 Exit;
898 end;
900 g_Console_Add(Format(_lc[I_CONSOLE_UNKNOWN], [Arr[0]]));
901 end;
903 end.