diff options
Diffstat (limited to 'src/jake2/client/Console.java')
-rw-r--r-- | src/jake2/client/Console.java | 610 |
1 files changed, 610 insertions, 0 deletions
diff --git a/src/jake2/client/Console.java b/src/jake2/client/Console.java new file mode 100644 index 0000000..d37bf5c --- /dev/null +++ b/src/jake2/client/Console.java @@ -0,0 +1,610 @@ +/* + * Con.java + * Copyright (C) 2003 + * + * $Id: Console.java,v 1.1 2004-07-07 19:58:41 hzi Exp $ + */ +/* +Copyright (C) 1997-2001 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +package jake2.client; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Arrays; + +import jake2.Defines; +import jake2.Globals; +import jake2.game.Cmd; +import jake2.qcommon.*; +import jake2.util.Vargs; + +/** + * Console + */ +public final class Console extends Globals { + + public static xcommand_t ToggleConsole_f = new xcommand_t() { + public void execute() { + SCR.EndLoadingPlaque(); // get rid of loading plaque + + if (Globals.cl.attractloop) { + Cbuf.AddText("killserver\n"); + return; + } + + if (Globals.cls.state == Defines.ca_disconnected) { + // start the demo loop again + Cbuf.AddText("d1\n"); + return; + } + + Key.ClearTyping(); + Console.ClearNotify(); + + if (Globals.cls.key_dest == Defines.key_console) { + Menu.ForceMenuOff(); + Cvar.Set("paused", "0"); + } + else { + Menu.ForceMenuOff(); + Globals.cls.key_dest = Defines.key_console; + + if (Cvar.VariableValue("maxclients") == 1 && Com.ServerState()!= 0) + Cvar.Set("paused", "1"); + } + } + }; + + public static xcommand_t Clear_f = new xcommand_t() { + public void execute() { + Arrays.fill(Globals.con.text, (byte)' '); + } + }; + public static xcommand_t Dump_f = new xcommand_t() { + public void execute() { + + int l, x; + int line; + RandomAccessFile f; + byte[] buffer = new byte[1024]; + String name; + + if (Cmd.Argc() != 2) { + Com.Printf("usage: condump <filename>\n"); + return; + } + + //Com_sprintf (name, sizeof(name), "%s/%s.txt", FS_Gamedir(), Cmd_Argv(1)); + name = FS.Gamedir() + "/" + Cmd.Argv(1) + ".txt"; + + Com.Printf("Dumped console text to " + name + ".\n"); + FS.CreatePath(name); + f = fopen(name, "rw"); + if (f == null) { + Com.Printf("ERROR: couldn't open.\n"); + return; + } + + // skip empty lines + for (l = con.current - con.totallines + 1; l <= con.current; l++) { + line = (l % con.totallines) * con.linewidth; + for (x = 0; x < con.linewidth; x++) + if (con.text[line + x] != ' ') + break; + if (x != con.linewidth) + break; + } + + // write the remaining lines + buffer[con.linewidth] = 0; + for (; l <= con.current; l++) { + line = (l % con.totallines) * con.linewidth; + //strncpy (buffer, line, con.linewidth); + System.arraycopy(con.text, line, buffer, 0, con.linewidth); + for (x = con.linewidth - 1; x >= 0; x--) { + if (buffer[x] == ' ') + buffer[x] = 0; + else + break; + } + for (x = 0; buffer[x] != 0; x++) + buffer[x] &= 0x7f; + + buffer[x] = '\n'; + // fprintf (f, "%s\n", buffer); + try { + f.write(buffer, 0, x+1); + } catch (IOException e) {} + } + + fclose(f); + + } + }; + + /** + * + */ + public static void Init() { + Globals.con.linewidth = -1; + + CheckResize(); + + Com.Printf("Console initialized.\n"); + + // + // register our commands + // + Globals.con_notifytime = Cvar.Get("con_notifytime", "3", 0); + + Cmd.AddCommand("toggleconsole", ToggleConsole_f); + Cmd.AddCommand("togglechat", ToggleChat_f); + Cmd.AddCommand("messagemode", MessageMode_f); + Cmd.AddCommand("messagemode2", MessageMode2_f); + Cmd.AddCommand("clear", Clear_f); + Cmd.AddCommand("condump", Dump_f); + Globals.con.initialized = true; + } + + /** + * If the line width has changed, reformat the buffer. + */ + public static void CheckResize() { + int i, j, width, oldwidth, oldtotallines, numlines, numchars; + byte[] tbuf = new byte[Defines.CON_TEXTSIZE]; + + width = (Globals.viddef.width >> 3) - 2; + + if (width == Globals.con.linewidth) + return; + + if (width < 1) { // video hasn't been initialized yet + width = 38; + Globals.con.linewidth = width; + Globals.con.totallines = Defines.CON_TEXTSIZE / Globals.con.linewidth; + Arrays.fill(Globals.con.text, (byte)' '); + } + else { + oldwidth = Globals.con.linewidth; + Globals.con.linewidth = width; + oldtotallines = Globals.con.totallines; + Globals.con.totallines = Defines.CON_TEXTSIZE / Globals.con.linewidth; + numlines = oldtotallines; + + if (Globals.con.totallines < numlines) + numlines = Globals.con.totallines; + + numchars = oldwidth; + + if (Globals.con.linewidth < numchars) + numchars = Globals.con.linewidth; + + System.arraycopy(Globals.con.text, 0, tbuf, 0, Defines.CON_TEXTSIZE); + Arrays.fill(Globals.con.text, (byte)' '); + + for (i=0 ; i<numlines ; i++) { + for (j=0 ; j<numchars ; j++) { + Globals.con.text[(Globals.con.totallines - 1 - i) * Globals.con.linewidth + j] = + tbuf[((Globals.con.current - i + oldtotallines) % oldtotallines) * oldwidth + j]; + } + } + + Console.ClearNotify(); + } + + Globals.con.current = Globals.con.totallines - 1; + Globals.con.display = Globals.con.current; + } + + public static void ClearNotify() { + int i; + for (i=0 ; i<Defines.NUM_CON_TIMES ; i++) + Globals.con.times[i] = 0; + } + + static void DrawString(int x, int y, String s) { + for (int i = 0; i < s.length(); i++) { + Globals.re.DrawChar(x, y, s.charAt(i)); + x+=8; + } + } + + static void DrawAltString(int x, int y, String s) { + for (int i = 0; i < s.length(); i++) { + Globals.re.DrawChar(x, y, s.charAt(i) ^ 0x80); + x+=8; + } + } + + + /* + ================ + Con_ToggleChat_f + ================ + */ + static xcommand_t ToggleChat_f = new xcommand_t() { + public void execute() { + Key.ClearTyping(); + + if (cls.key_dest == key_console) { + if (cls.state == ca_active) { + Menu.ForceMenuOff(); + cls.key_dest = key_game; + } + } else + cls.key_dest = key_console; + + ClearNotify(); + } + }; + + /* + ================ + Con_MessageMode_f + ================ + */ + static xcommand_t MessageMode_f = new xcommand_t() { + public void execute() { + chat_team = false; + cls.key_dest = key_message; + } + }; + + /* + ================ + Con_MessageMode2_f + ================ + */ + static xcommand_t MessageMode2_f = new xcommand_t() { + public void execute() { + chat_team = true; + cls.key_dest = key_message; + } + }; + + /* + =============== + Con_Linefeed + =============== + */ + static void Linefeed() { + Globals.con.x = 0; + if (Globals.con.display == Globals.con.current) + Globals.con.display++; + Globals.con.current++; + int i = (Globals.con.current%Globals.con.totallines)*Globals.con.linewidth; + int e = i + Globals.con.linewidth; + while (i++ < e) Globals.con.text[i] = ' '; + } + + /* + ================ + Con_Print + + Handles cursor positioning, line wrapping, etc + All console printing must go through this in order to be logged to disk + If no console is visible, the text will appear at the top of the game window + ================ + */ + private static int cr; + public static void Print(String txt) { + int y; + int c, l; + int mask; + int txtpos = 0; + + if (!con.initialized) return; + + if (txt.charAt(0) == 1 || txt.charAt(0) == 2) { + mask = 128; // go to colored text + txtpos++; + } else mask = 0; + + while ( txtpos < txt.length() ) { + c = txt.charAt(txtpos); + // count word length + for (l=0 ; l < con.linewidth && l < (txt.length() - txtpos) ; l++) + if ( txt.charAt(l + txtpos) <= ' ') break; + + // word wrap + if (l != con.linewidth && (con.x + l > con.linewidth) ) + con.x = 0; + + txtpos++; + + if (cr != 0) { + con.current--; + cr = 0; + } + + if (con.x == 0) { + Console.Linefeed(); + // mark time for transparent overlay + if (con.current >= 0) + con.times[con.current % NUM_CON_TIMES] = cls.realtime; + } + + switch (c) { + case '\n': + con.x = 0; + break; + + case '\r': + con.x = 0; + cr = 1; + break; + + default: // display character and advance + y = con.current % con.totallines; + con.text[y*con.linewidth+con.x] = (byte)(c | mask | con.ormask); + con.x++; + if (con.x >= con.linewidth) + con.x = 0; + break; + } + } + } + + /* + ============== + Con_CenteredPrint + ============== + */ + static void CenteredPrint(String text) { + int l = text.length(); + l = (con.linewidth-l)/2; + if (l < 0) l = 0; + + StringBuffer sb = new StringBuffer(1024); + for (int i = 0; i < l; i++) sb.append(' '); + sb.append(text); + sb.append('\n'); + + sb.setLength(1024); + + Console.Print(sb.toString()); + } + + /* + ============================================================================== + + DRAWING + + ============================================================================== + */ + + /* + ================ + Con_DrawInput + + The input line scrolls horizontally if typing goes beyond the right edge + ================ + */ + static void DrawInput() { + int y; + int i; + byte[] text; + int start = 0; + + if (cls.key_dest == key_menu) + return; + if (cls.key_dest != key_console && cls.state == ca_active) + return; // don't draw anything (always draw if not active) + + text = key_lines[edit_line]; + + // add the cursor frame + text[key_linepos] = (byte)(10+((int)(cls.realtime>>8)&1)); + + // fill out remainder with spaces + for (i=key_linepos+1 ; i< con.linewidth ; i++) + text[i] = ' '; + + // prestep if horizontally scrolling + if (key_linepos >= con.linewidth) + start += 1 + key_linepos - con.linewidth; + + // draw it + y = con.vislines-16; + + for (i=0 ; i<con.linewidth ; i++) + re.DrawChar ( (i+1)<<3, con.vislines - 22, text[i]); + + // remove cursor + key_lines[edit_line][key_linepos] = 0; + } + + + /* + ================ + Con_DrawNotify + + Draws the last few lines of output transparently over the game top + ================ + */ + static void DrawNotify() { + int x, v; + int text; + int i; + int time; + String s; + int skip; + + v = 0; + for (i= con.current-NUM_CON_TIMES+1 ; i<=con.current ; i++) { + if (i < 0) continue; + + time = (int)con.times[i % NUM_CON_TIMES]; + if (time == 0) continue; + + time = (int)(cls.realtime - time); + if (time > con_notifytime.value*1000) continue; + + text = (i % con.totallines)*con.linewidth; + + for (x = 0 ; x < con.linewidth ; x++) + re.DrawChar( (x+1)<<3, v, con.text[text+x]); + + v += 8; + } + + if (cls.key_dest == key_message) { + if (chat_team) { + DrawString(8, v, "say_team:"); + skip = 11; + } else { + DrawString (8, v, "say:"); + skip = 5; + } + + s = chat_buffer; + if (chat_bufferlen > (viddef.width>>3)-(skip+1)) + s = s.substring(chat_bufferlen - ((viddef.width>>3)-(skip+1))); + + for (x = 0; x < s.length(); x++) { + re.DrawChar( (x+skip)<<3, v, s.charAt(x)); + } + re.DrawChar( (x+skip)<<3, v, (int)(10+((cls.realtime>>8)&1))); + v += 8; + } + + if (v != 0) { + SCR.AddDirtyPoint(0,0); + SCR.AddDirtyPoint(viddef.width-1, v); + } + } + + /* + ================ + Con_DrawConsole + + Draws the console with the solid background + ================ + */ + static void DrawConsole(float frac) { + int i, j, x, y, n; + int rows; + int text; + int row; + int lines; + String version; + String dlbar; + + lines = (int)(viddef.height * frac); + if (lines <= 0) + return; + + if (lines > viddef.height) + lines = viddef.height; + + // draw the background + re.DrawStretchPic(0, -viddef.height+lines, viddef.width, viddef.height, "conback"); + SCR.AddDirtyPoint(0,0); + SCR.AddDirtyPoint(viddef.width-1,lines-1); + + version = Com.sprintf("v%4.2f", new Vargs(1).add(VERSION)); + for (x=0 ; x<5 ; x++) + re.DrawChar (viddef.width-44+x*8, lines-12, 128 + version.charAt(x)); + + // draw the text + con.vislines = lines; + + rows = (lines-22)>>3; // rows of text to draw + + y = lines - 30; + + // draw from the bottom up + if (con.display != con.current) { + // draw arrows to show the buffer is backscrolled + for (x=0 ; x<con.linewidth ; x+=4) + re.DrawChar ( (x+1)<<3, y, '^'); + + y -= 8; + rows--; + } + + row = con.display; + for (i=0 ; i<rows ; i++, y-=8, row--) { + if (row < 0) + break; + if (con.current - row >= con.totallines) + break; // past scrollback wrap point + + int first = (row % con.totallines)*con.linewidth; + + for (x=0 ; x<con.linewidth ; x++) + re.DrawChar( (x+1)<<3, y, con.text[x+first]); + } + + //ZOID + // draw the download bar + // figure out width + if (cls.download != null) { + if ((text = cls.downloadname.lastIndexOf('/')) != 0) + text++; + else + text = 0; + + x = con.linewidth - ((con.linewidth * 7) / 40); + y = x - (cls.downloadname.length()-text) - 8; + i = con.linewidth/3; + if (cls.downloadname.length()-text > i) { + y = x - i - 11; + int end = text + i - 1;; + dlbar = cls.downloadname.substring(text, end); + dlbar += "..."; + } else { + dlbar = cls.downloadname.substring(text); + } + dlbar += ": "; + i = strlen(dlbar); + dlbar += (char)0x80; + i++; + + // where's the dot go? + if (cls.downloadpercent == 0) + n = 0; + else + n = y * cls.downloadpercent / 100; + + StringBuffer sb = new StringBuffer(dlbar); + sb.ensureCapacity(1024); + for (j = 0; j < y; j++) { + if (j == n) + sb.append((char)0x83); + else + sb.append((char)0x81); + } + sb.append((char)0x82); + + dlbar = sb.toString(); + dlbar += Com.sprintf(" %02d%%", new Vargs(1).add(cls.downloadpercent)); + + // draw it + y = con.vislines-12; + for (i = 0; i < dlbar.length(); i++) + re.DrawChar ( (i+1)<<3, y, dlbar.charAt(i)); + } + //ZOID + + // draw the input prompt, user text, and cursor if desired + DrawInput(); + } +} |