X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_console.pas;h=d16d9d606b8fd637044548619cd9a04ae9972938;hb=96165a1a95f0ea18a20dd8578fade4b46ec23746;hp=6a5c9a411c9412b3c9d9536bf7928408d4e7005d;hpb=dd0d8ac4cc2a0aa774f25c8a1a774f7358acfae7;p=d2df-sdl.git diff --git a/src/game/g_console.pas b/src/game/g_console.pas index 6a5c9a4..d16d9d6 100644 --- a/src/game/g_console.pas +++ b/src/game/g_console.pas @@ -18,6 +18,9 @@ unit g_console; interface +uses + wadreader; // for SArray + procedure g_Console_Init(); procedure g_Console_Update(); procedure g_Console_Draw(); @@ -29,8 +32,17 @@ procedure g_Console_Add(L: String; Show: Boolean = False); procedure g_Console_Clear(); function g_Console_CommandBlacklisted(C: String): Boolean; +procedure conwriteln (const s: AnsiString; show: Boolean=false); +procedure conwritefln (const s: AnsiString; args: array of const; show: Boolean=false); + +// <0: no arg; 0/1: true/false +function conGetBoolArg (P: SArray; idx: Integer): Integer; + procedure g_Console_Chat_Switch(Team: Boolean = False); +procedure conRegVar (const conname: AnsiString; pvar: PBoolean; const ahelp: AnsiString; const amsg: AnsiString; acheat: Boolean=false); + + var gConsoleShow: Boolean; // True - êîíñîëü îòêðûòà èëè îòêðûâàåòñÿ gChatShow: Boolean; @@ -43,15 +55,24 @@ implementation uses g_textures, g_main, e_graphics, e_input, g_game, - SysUtils, g_basic, g_options, wadreader, Math, - g_menu, g_language, g_net, g_netmsg, e_log, conbuf; + SysUtils, g_basic, g_options, Math, + g_menu, g_language, g_net, g_netmsg, e_log, conbuf, utils; type + PCommand = ^TCommand; + TCmdProc = procedure (P: SArray); + TCmdProcEx = procedure (me: PCommand; P: SArray); TCommand = record Cmd: String; Proc: TCmdProc; + ProcEx: TCmdProcEx; + help: String; + hidden: Boolean; + ptr: Pointer; // various data + msg: AnsiString; // message for var changes + cheat: Boolean; end; TAlias = record @@ -59,6 +80,7 @@ type Commands: SArray; end; + const Step = 32; Alpha = 25; @@ -78,8 +100,8 @@ var //ConsoleHistory: SArray; CommandHistory: SArray; Whitelist: SArray; - Commands: Array of TCommand; - Aliases: Array of TAlias; + Commands: Array of TCommand = nil; + Aliases: Array of TAlias = nil; CmdIndex: Word; conSkipLines: Integer = 0; MsgArray: Array [0..4] of record @@ -87,6 +109,60 @@ var Time: Word; end; + +// <0: no arg; 0/1: true/false +function conGetBoolArg (P: SArray; idx: Integer): Integer; +begin + if (idx < 0) or (idx > High(P)) then begin result := -1; exit; end; + result := 0; + if (P[idx] = '1') or (CompareText(P[idx], 'on') = 0) or (CompareText(P[idx], 'true') = 0) or + (CompareText(P[idx], 'tan') = 0) or (CompareText(P[idx], 'yes') = 0) then result := 1; +end; + + +procedure boolVarHandler (me: PCommand; P: SArray); + + procedure binaryFlag (var flag: Boolean; msg: string); + begin + if (Length(p) > 2) then + begin + conwritefln('too many arguments to ''%s''', [P[0]]); + end + else + begin + case conGetBoolArg(P, 1) of + -1: begin end; + 0: if conIsCheatsEnabled then flag := false else begin conwriteln('not available'); exit; end; + 1: if conIsCheatsEnabled then flag := true else begin conwriteln('not available'); exit; end; + end; + if flag then conwritefln('%s: tan', [msg]) else conwritefln('%s: ona', [msg]); + end; + end; + +begin + binaryFlag(PBoolean(me.ptr)^, me.msg); +end; + + +procedure conRegVar (const conname: AnsiString; pvar: PBoolean; const ahelp: AnsiString; const amsg: AnsiString; acheat: Boolean=false); +var + f: Integer; + cp: PCommand; +begin + f := Length(Commands); + SetLength(Commands, f+1); + cp := @Commands[f]; + cp.Cmd := LowerCase(conname); + cp.Proc := nil; + cp.ProcEx := boolVarHandler; + cp.help := ahelp; + cp.hidden := false; + cp.ptr := pvar; + cp.msg := amsg; + cp.cheat := acheat; +end; + + function GetStrACmd(var Str: String): String; var a: Integer; @@ -157,7 +233,16 @@ begin g_Console_Add(''); g_Console_Add('Commands list:'); for a := High(Commands) downto 0 do - g_Console_Add(' '+Commands[a].Cmd); + begin + if (Length(Commands[a].help) > 0) then + begin + g_Console_Add(' '+Commands[a].Cmd+' -- '+Commands[a].help); + end + else + begin + g_Console_Add(' '+Commands[a].Cmd); + end; + end; end; if Cmd = 'time' then @@ -334,17 +419,25 @@ var begin SetLength(Whitelist, Length(Whitelist)+1); a := High(Whitelist); - Whitelist[a] := Cmd; + Whitelist[a] := LowerCase(Cmd); end; -procedure AddCommand(Cmd: String; Proc: TCmdProc); +procedure AddCommand(Cmd: String; Proc: TCmdProc; ahelp: String=''; ahidden: Boolean=false; acheat: Boolean=false); var a: Integer; + cp: PCommand; begin SetLength(Commands, Length(Commands)+1); a := High(Commands); - Commands[a].Cmd := Cmd; - Commands[a].Proc := Proc; + cp := @Commands[a]; + cp.Cmd := LowerCase(Cmd); + cp.Proc := Proc; + cp.ProcEx := nil; + cp.help := ahelp; + cp.hidden := ahidden; + cp.ptr := nil; + cp.msg := ''; + cp.cheat := acheat; end; procedure g_Console_Init(); @@ -365,7 +458,7 @@ begin Time := 0; end; - AddCommand('clear', ConsoleCommands); + AddCommand('clear', ConsoleCommands, 'clear console'); AddCommand('clearhistory', ConsoleCommands); AddCommand('showhistory', ConsoleCommands); AddCommand('commands', ConsoleCommands); @@ -712,39 +805,122 @@ begin CPos := CPos + 1; end; -procedure Complete(); + var - i: Integer; - t: Array of String; + tcomplist: array of string = nil; + tcompidx: array of Integer = nil; + +procedure Complete (); +var + i, c: Integer; + tused: Integer; + ll, lpfx, cmd: string; begin - if Line = '' then - Exit; + if (Length(Line) = 0) then + begin + g_Console_Add(''); + for i := 0 to High(Commands) do + begin + if not Commands[i].hidden then + begin + if (Length(Commands[i].help) > 0) then + begin + g_Console_Add(' '+Commands[i].Cmd+' -- '+Commands[i].help); + end + else + begin + g_Console_Add(' '+Commands[i].Cmd); + end; + end; + end; + exit; + end; - t := nil; + ll := LowerCase(Line); + lpfx := ''; + + if (Length(ll) > 1) and (ll[Length(ll)] = ' ') then + begin + ll := Copy(ll, 0, Length(ll)-1); + for i := 0 to High(Commands) do + begin + if Commands[i].hidden then continue; + if (Commands[i].Cmd = ll) then + begin + if (Length(Commands[i].help) > 0) then + begin + g_Console_Add(' '+Commands[i].Cmd+' -- '+Commands[i].help); + end; + end; + end; + exit; + end; + // build completion list + tused := 0; for i := 0 to High(Commands) do - if LowerCase(Line) = LowerCase(Copy(Commands[i].Cmd, 0, Length(Line))) then + begin + if Commands[i].hidden then continue; + cmd := Commands[i].Cmd; + if (Length(cmd) >= Length(ll)) and (ll = Copy(cmd, 0, Length(ll))) then + begin + if (tused = Length(tcomplist)) then + begin + SetLength(tcomplist, Length(tcomplist)+128); + SetLength(tcompidx, Length(tcompidx)+128); + end; + tcomplist[tused] := cmd; + tcompidx[tused] := i; + Inc(tused); + if (Length(cmd) > Length(lpfx)) then lpfx := cmd; + end; + end; + + // get longest prefix + for i := 0 to tused-1 do + begin + cmd := tcomplist[i]; + for c := 1 to Length(lpfx) do begin - SetLength(t, Length(t) + 1); - t[Length(t)-1] := Commands[i].Cmd; + if (c > Length(cmd)) then break; + if (cmd[c] <> lpfx[c]) then begin lpfx := Copy(lpfx, 0, c-1); break; end; end; + end; - if t = nil then - Exit; + if (tused = 0) then exit; - if Length(t) = 1 then + if (tused = 1) then + begin + Line := tcomplist[0]+' '; + CPos := Length(Line)+1; + end + else + begin + // has longest prefix? + if (Length(lpfx) > Length(ll)) then begin - Line := t[0]+' '; - CPos := Length(Line)+1; + Line := lpfx; + CPos:= Length(Line)+1; end - else + else begin g_Console_Add(''); - for i := 0 to High(t) do - g_Console_Add(' '+t[i]); + for i := 0 to tused-1 do + begin + if (Length(Commands[tcompidx[i]].help) > 0) then + begin + g_Console_Add(' '+tcomplist[i]+' -- '+Commands[tcompidx[i]].help); + end + else + begin + g_Console_Add(' '+tcomplist[i]); + end; + end; end; + end; end; + procedure g_Console_Control(K: Word); begin case K of @@ -931,6 +1107,58 @@ begin *) end; + +var + consolewriterLastWasEOL: Boolean = false; + +procedure consolewriter (constref buf; len: SizeUInt); +var + b: PByte; +begin + if (len < 1) then exit; + b := PByte(@buf); + consolewriterLastWasEOL := (b[len-1] = 13) or (b[len-1] = 10); + while (len > 0) do + begin + if (b[0] <> 13) and (b[0] <> 10) then + begin + cbufPut(Char(b[0])); + end + else + begin + if (len > 1) and (b[0] = 13) then begin len -= 1; b += 1; end; + cbufPut(#10); + end; + len -= 1; + b += 1; + end; +end; + + +// returns formatted string if `writerCB` is `nil`, empty string otherwise +//function formatstrf (const fmt: AnsiString; args: array of const; writerCB: TFormatStrFCallback=nil): AnsiString; +//TFormatStrFCallback = procedure (constref buf; len: SizeUInt); +procedure conwriteln (const s: AnsiString; show: Boolean=false); +begin + g_Console_Add(s, show); +end; + + +procedure conwritefln (const s: AnsiString; args: array of const; show: Boolean=false); +begin + if show then + begin + g_Console_Add(formatstrf(s, args), true); + end + else + begin + consolewriterLastWasEOL := false; + formatstrf(s, args, consolewriter); + if not consolewriterLastWasEOL then cbufPut(#10); + end; +end; + + procedure g_Console_Clear(); begin //ConsoleHistory := nil; @@ -1014,12 +1242,21 @@ begin AddToHistory(L); for i := 0 to High(Commands) do + begin if Commands[i].Cmd = LowerCase(Arr[0]) then - if @Commands[i].Proc <> nil then + begin + if assigned(Commands[i].ProcEx) then + begin + Commands[i].ProcEx(@Commands[i], Arr); + exit; + end; + if assigned(Commands[i].Proc) then begin Commands[i].Proc(Arr); - Exit; + exit; end; + end; + end; g_Console_Add(Format(_lc[I_CONSOLE_UNKNOWN], [Arr[0]])); end;