aboutsummaryrefslogtreecommitdiffstats
path: root/src/jake2/client/CL.java
diff options
context:
space:
mode:
authorRene Stoeckel <[email protected]>2004-09-22 19:22:16 +0000
committerRene Stoeckel <[email protected]>2004-09-22 19:22:16 +0000
commitc4fcffe436fbfb5b0f3b7be2e5ee103ec74932f7 (patch)
tree7c9439ab1d9f5a4fd61bd57c755069007b23e0b6 /src/jake2/client/CL.java
parentbcb4ac6eefb425d5b0a90009da506361d5739e75 (diff)
major refactoring in game, server and client package
Diffstat (limited to 'src/jake2/client/CL.java')
-rw-r--r--src/jake2/client/CL.java3207
1 files changed, 1625 insertions, 1582 deletions
diff --git a/src/jake2/client/CL.java b/src/jake2/client/CL.java
index 3170112..dcdf7db 100644
--- a/src/jake2/client/CL.java
+++ b/src/jake2/client/CL.java
@@ -2,36 +2,39 @@
* CL.java
* Copyright (C) 2004
*
- * $Id: CL.java,v 1.10 2004-09-08 09:37:39 hzi Exp $
+ * $Id: CL.java,v 1.11 2004-09-22 19:22:08 salomo Exp $
*/
/*
-Copyright (C) 1997-2001 Id Software, Inc.
+ 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 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.
+ 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.
+ 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.
+ 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 jake2.Defines;
import jake2.Globals;
import jake2.game.*;
import jake2.qcommon.*;
+import jake2.qcommon.qfiles.dmdl_t;
import jake2.server.SV_MAIN;
import jake2.sound.*;
import jake2.sys.*;
+import jake2.util.Lib;
+import jake2.util.Math3D;
import jake2.util.Vargs;
import java.io.IOException;
@@ -42,1590 +45,1630 @@ import java.nio.ByteOrder;
/**
* CL
*/
-public final class CL extends CL_pred {
-
- /*
- ====================
- CL_WriteDemoMessage
-
- Dumps the current net message, prefixed by the length
- ====================
- */
- static void WriteDemoMessage() {
- int swlen;
-
- // the first eight bytes are just packet sequencing stuff
- swlen = net_message.cursize - 8;
-
- try {
- cls.demofile.writeInt(swlen);
- //fwrite (&swlen, 4, 1, cls.demofile);
- cls.demofile.write(net_message.data, 8, swlen);
- //fwrite (net_message.data+8, len, 1, cls.demofile);
- } catch (IOException e) {}
-
- }
-
- /*
- ====================
- CL_Stop_f
-
- stop recording a demo
- ====================
- */
- static xcommand_t Stop_f = new xcommand_t() {
- public void execute() {
- try {
-
- int len;
-
- if (!cls.demorecording) {
- Com.Printf("Not recording a demo.\n");
- return;
- }
-
- // finish up
- len = -1;
- cls.demofile.writeInt(len);
- cls.demofile.close();
- cls.demofile = null;
- cls.demorecording = false;
- Com.Printf("Stopped demo.\n");
- }
- catch (IOException e) {
- }
- }
- };
-
- /*
- ====================
- CL_Record_f
-
- record <demoname>
-
- Begins recording a demo from the current position
- ====================
- */
- static entity_state_t nullstate = new entity_state_t(null);
-
- static xcommand_t Record_f = new xcommand_t() {
- public void execute() {
- try {
- String name;
- byte buf_data[] = new byte[MAX_MSGLEN];
- sizebuf_t buf = new sizebuf_t();
- int i;
- entity_state_t ent;
-
- if (Cmd.Argc() != 2) {
- Com.Printf("record <demoname>\n");
- return;
- }
-
- if (cls.demorecording) {
- Com.Printf("Already recording.\n");
- return;
- }
-
- if (cls.state != ca_active) {
- Com.Printf("You must be in a level to record.\n");
- return;
- }
-
- //
- // open the demo file
- //
- name = FS.Gamedir() + "/demos/" + Cmd.Argv(1) + ".dm2";
-
- Com.Printf("recording to " + name + ".\n");
- FS.CreatePath(name);
- cls.demofile = new RandomAccessFile(name, "rw");
- if (cls.demofile == null) {
- Com.Printf("ERROR: couldn't open.\n");
- return;
- }
- cls.demorecording = true;
-
- // don't start saving messages until a non-delta compressed message is received
- cls.demowaiting = true;
-
- //
- // write out messages to hold the startup information
- //
- SZ.Init(buf, buf_data, MAX_MSGLEN);
-
- // send the serverdata
- MSG.WriteByte(buf, svc_serverdata);
- MSG.WriteInt(buf, PROTOCOL_VERSION);
- MSG.WriteInt(buf, 0x10000 + cl.servercount);
- MSG.WriteByte(buf, 1); // demos are always attract loops
- MSG.WriteString(buf, cl.gamedir);
- MSG.WriteShort(buf, cl.playernum);
-
- MSG.WriteString(buf, cl.configstrings[CS_NAME]);
-
- // configstrings
- for (i = 0; i < MAX_CONFIGSTRINGS; i++) {
- if (cl.configstrings[i].length()>0) {
- if (buf.cursize + cl.configstrings[i].length() + 32 > buf.maxsize) { // write it out
- //len = LittleLong(buf.cursize);
- //fwrite(& len, 4, 1, cls.demofile);
- cls.demofile.writeInt(buf.cursize);
- //fwrite(buf.data, buf.cursize, 1, cls.demofile);
- cls.demofile.write(buf.data, 0, buf.cursize);
- buf.cursize = 0;
- }
-
- MSG.WriteByte(buf, svc_configstring);
- MSG.WriteShort(buf, i);
- MSG.WriteString(buf, cl.configstrings[i]);
- }
-
- }
-
- // baselines
- //memset( nullstate, 0, sizeof(nullstate));
- for (i = 0; i < MAX_EDICTS; i++) {
- ent = cl_entities[i].baseline;
- if (ent.modelindex == 0)
- continue;
-
- if (buf.cursize + 64 > buf.maxsize) { // write it out
- //len = LittleLong(buf.cursize);
- //fwrite(& len, 4, 1, cls.demofile);
- cls.demofile.writeInt(buf.cursize);
- //fwrite(buf.data, buf.cursize, 1, cls.demofile);
- cls.demofile.write(buf.data, 0, buf.cursize);
- buf.cursize = 0;
- }
-
- MSG.WriteByte(buf, svc_spawnbaseline);
- MSG.WriteDeltaEntity(nullstate, cl_entities[i].baseline, buf, true, true);
- }
-
- MSG.WriteByte(buf, svc_stufftext);
- MSG.WriteString(buf, "precache\n");
-
- // write it to the demo file
-
- //len = LittleLong(buf.cursize);
- //fwrite(& len, 4, 1, cls.demofile);
- cls.demofile.writeInt(buf.cursize);
- //fwrite(buf.data, buf.cursize, 1, cls.demofile);
- cls.demofile.write(buf.data, 0, buf.cursize);
- // the rest of the demo file will be individual frames
-
- }
- catch (IOException e) {
- }
- }
- };
-
- /*
- ==================
- CL_ForwardToServer_f
- ==================
- */
- static xcommand_t ForwardToServer_f = new xcommand_t() {
- public void execute() {
- if (cls.state != ca_connected && cls.state != ca_active) {
- Com.Printf("Can't \"" + Cmd.Argv(0) + "\", not connected\n");
- return;
- }
-
- // don't forward the first argument
- if (Cmd.Argc() > 1) {
- MSG.WriteByte(cls.netchan.message, clc_stringcmd);
- SZ.Print(cls.netchan.message, Cmd.Args());
- }
- }
- };
-
- /*
- ==================
- CL_Pause_f
- ==================
- */
- static xcommand_t Pause_f = new xcommand_t() {
- public void execute() {
- // never pause in multiplayer
-
- if (Cvar.VariableValue("maxclients") > 1 || Globals.server_state == 0) {
- Cvar.SetValue("paused", 0);
- return;
- }
-
- Cvar.SetValue("paused", cl_paused.value);
- }
- };
-
- /*
- ==================
- CL_Quit_f
- ==================
- */
- static xcommand_t Quit_f = new xcommand_t() {
- public void execute() {
- Disconnect();
- Com.Quit();
- }
- };
-
- /*
- =======================
- CL_SendConnectPacket
-
- We have gotten a challenge from the server, so try and
- connect.
- ======================
- */
- static void SendConnectPacket() {
- netadr_t adr = new netadr_t();
- int port;
-
- if (!NET.StringToAdr(cls.servername, adr)) {
- Com.Printf("Bad server address\n");
- cls.connect_time = 0;
- return;
- }
- if (adr.port == 0)
- adr.port = PORT_SERVER;
- // adr.port = BigShort(PORT_SERVER);
-
- port = (int) Cvar.VariableValue("qport");
- userinfo_modified = false;
-
- Netchan.OutOfBandPrint(
- NS_CLIENT,
- adr,
- "connect " + PROTOCOL_VERSION + " " + port + " " + cls.challenge + " \"" + Cvar.Userinfo() + "\"\n");
- }
-
- /*
- =================
- CL_CheckForResend
-
- Resend a connect message if the last one has timed out
- =================
- */
- static void CheckForResend() {
- netadr_t adr = new netadr_t();
-
- // if the local server is running and we aren't
- // then connect
- if (cls.state == ca_disconnected && Globals.server_state != 0) {
- cls.state = ca_connecting;
- cls.servername = "localhost";
- // we don't need a challenge on the localhost
- CL.SendConnectPacket();
- return;
- }
-
- // resend if we haven't gotten a reply yet
- if (cls.state != ca_connecting)
- return;
-
- if (cls.realtime - cls.connect_time < 3000)
- return;
-
- if (!NET.StringToAdr(cls.servername, adr)) {
- Com.Printf("Bad server address\n");
- cls.state = ca_disconnected;
- return;
- }
- if (adr.port == 0)
- // adr.port = BigShort(PORT_SERVER);
- adr.port = PORT_SERVER;
-
- cls.connect_time = cls.realtime; // for retransmit requests
-
- Com.Printf("Connecting to " + cls.servername + "...\n");
-
- Netchan.OutOfBandPrint(NS_CLIENT, adr, "getchallenge\n");
- }
-
- /*
- ================
- CL_Connect_f
-
- ================
- */
- static xcommand_t Connect_f = new xcommand_t() {
- public void execute() {
- String server;
-
- if (Cmd.Argc() != 2) {
- Com.Printf("usage: connect <server>\n");
- return;
- }
-
- if (Globals.server_state != 0) {
- // if running a local server, kill it and reissue
- SV_MAIN.SV_Shutdown("Server quit\n", false);
- } else {
- CL.Disconnect();
- }
-
- server = Cmd.Argv(1);
-
- NET.Config(true); // allow remote
-
- CL.Disconnect();
-
- cls.state = ca_connecting;
- //strncpy (cls.servername, server, sizeof(cls.servername)-1);
- cls.servername = server;
- cls.connect_time = -99999;
- // CL_CheckForResend() will fire immediately
- }
- };
-
- /*
- =====================
- CL_Rcon_f
-
- Send the rest of the command line over as
- an unconnected command.
- =====================
- */
- static xcommand_t Rcon_f = new xcommand_t() {
- public void execute() {
- StringBuffer message = new StringBuffer(1024);
- int i;
- netadr_t to = new netadr_t();
-
- if (rcon_client_password.string == null) {
- Com.Printf("You must set 'rcon_password' before\nissuing an rcon command.\n");
- return;
- }
-
- message.append((char)255);
- message.append((char)255);
- message.append((char)255);
- message.append((char)255);
-
- NET.Config(true); // allow remote
-
- //strcat (message, "rcon ");
- message.append("rcon ");
-
- //strcat (message, rcon_client_password.string);
- message.append(rcon_client_password.string);
- //strcat (message, " ");
- message.append(" ");
-
- for (i = 1; i < Cmd.Argc(); i++) {
- //strcat (message, Cmd.Argv(i));
- message.append(Cmd.Argv(i));
- //strcat (message, " ");
- message.append(" ");
- }
-
- if (cls.state >= ca_connected)
- to = cls.netchan.remote_address;
- else {
- if (rcon_address.string.length() == 0) {
- Com.Printf(
- "You must either be connected,\nor set the 'rcon_address' cvar\nto issue rcon commands\n");
-
- return;
- }
- NET.StringToAdr(rcon_address.string, to);
- if (to.port == 0)
- //to.port = BigShort (PORT_SERVER);
- to.port = PORT_SERVER;
- }
- message.append('\0');
- String b = message.toString();
- NET.SendPacket(NS_CLIENT, b.length(), b.getBytes(), to);
- }
- };
-
- /*
- =====================
- CL_ClearState
-
- =====================
- */
-
- static void ClearState() {
- S.StopAllSounds();
- CL.ClearEffects();
- CL.ClearTEnts();
-
- // wipe the entire cl structure
-
- cl = new client_state_t();
- for (int i = 0; i < cl_entities.length; i++) {
- cl_entities[i] = new centity_t();
- }
-
- SZ.Clear(cls.netchan.message);
- }
-
- /*
- =====================
- CL_Disconnect
-
- Goes from a connected state to full screen console state
- Sends a disconnect message to the server
- This is also called on Com_Error, so it shouldn't cause any errors
- =====================
- */
-
- static void Disconnect() {
-
- String fin;
-
- if (cls.state == ca_disconnected)
- return;
-
- if (cl_timedemo != null && cl_timedemo.value != 0.0f) {
- int time;
-
- time = (int) (Sys.Milliseconds() - cl.timedemo_start);
- if (time > 0)
- Com.Printf(
- "%i frames, %3.1f seconds: %3.1f fps\n",
- new Vargs(3).add(cl.timedemo_frames).add(time / 1000.0).add(cl.timedemo_frames * 1000.0 / time));
- }
-
- VectorClear(cl.refdef.blend);
- //re.CinematicSetPalette(null);
-
- Menu.ForceMenuOff();
-
- cls.connect_time = 0;
-
- // SCR.StopCinematic();
-
- if (cls.demorecording)
- CL.Stop_f.execute();
-
- // send a disconnect message to the server
- fin = (char) clc_stringcmd + "disconnect";
- Netchan.Transmit(cls.netchan, fin.length(), fin.getBytes());
- Netchan.Transmit(cls.netchan, fin.length(), fin.getBytes());
- Netchan.Transmit(cls.netchan, fin.length(), fin.getBytes());
-
- CL.ClearState();
-
- // stop download
- if (cls.download != null) {
- fclose(cls.download);
- cls.download = null;
- // fclose(cls.download);
- // cls.download = NULL;
- }
-
- cls.state = ca_disconnected;
- }
-
- static xcommand_t Disconnect_f = new xcommand_t() {
- public void execute() {
- Com.Error(ERR_DROP, "Disconnected from server");
- }
- };
-
- /*
- =================
- CL_Changing_f
-
- Just sent as a hint to the client that they should
- drop to full console
- =================
- */
- static xcommand_t Changing_f = new xcommand_t() {
- public void execute() {
- //ZOID
- //if we are downloading, we don't change!
- // This so we don't suddenly stop downloading a map
-
- if (cls.download != null)
- return;
-
- SCR.BeginLoadingPlaque();
- cls.state = ca_connected; // not active anymore, but not disconnected
- Com.Printf("\nChanging map...\n");
- }
- };
-
- /*
- =================
- CL_Reconnect_f
-
- The server is changing levels
- =================
- */
- static xcommand_t Reconnect_f = new xcommand_t() {
- public void execute() {
- //ZOID
- //if we are downloading, we don't change! This so we don't suddenly stop downloading a map
- if (cls.download != null)
- return;
-
- S.StopAllSounds();
- if (cls.state == ca_connected) {
- Com.Printf("reconnecting...\n");
- cls.state = ca_connected;
- MSG.WriteChar(cls.netchan.message, clc_stringcmd);
- MSG.WriteString(cls.netchan.message, "new");
- return;
- }
-
- if (cls.servername != null) {
- if (cls.state >= ca_connected) {
- CL.Disconnect();
- cls.connect_time = cls.realtime - 1500;
- } else
- cls.connect_time = -99999; // fire immediately
-
- cls.state = ca_connecting;
- Com.Printf("reconnecting...\n");
- }
- }
- };
-
- /*
- =================
- CL_ParseStatusMessage
-
- Handle a reply from a ping
- =================
- */
- static void ParseStatusMessage() {
- String s;
-
- s = MSG.ReadString(net_message);
-
- Com.Printf(s + "\n");
- Menu.AddToServerList(net_from, s);
- }
-
- /*
- =================
- CL_PingServers_f
- =================
- */
- static xcommand_t PingServers_f = new xcommand_t() {
- public void execute() {
- int i;
- netadr_t adr = new netadr_t();
- //char name[32];
- String name;
- String adrstring;
- cvar_t noudp;
- cvar_t noipx;
-
- NET.Config(true); // allow remote
-
- // send a broadcast packet
- Com.Printf("pinging broadcast...\n");
-
- noudp = Cvar.Get("noudp", "0", CVAR_NOSET);
- if (noudp.value == 0.0f) {
- adr.type = NA_BROADCAST;
- adr.port = PORT_SERVER;
- //adr.port = BigShort(PORT_SERVER);
- Netchan.OutOfBandPrint(NS_CLIENT, adr, "info " + PROTOCOL_VERSION);
- }
-
- // we use no IPX
- noipx = Cvar.Get("noipx", "1", CVAR_NOSET);
- if (noipx.value == 0.0f) {
- adr.type = NA_BROADCAST_IPX;
- //adr.port = BigShort(PORT_SERVER);
- adr.port = PORT_SERVER;
- Netchan.OutOfBandPrint(NS_CLIENT, adr, "info " + PROTOCOL_VERSION);
- }
-
- // send a packet to each address book entry
- for (i = 0; i < 16; i++) {
- //Com_sprintf (name, sizeof(name), "adr%i", i);
- name = "adr" + i;
- adrstring = Cvar.VariableString(name);
- if (adrstring == null || adrstring.length() == 0)
- continue;
-
- Com.Printf("pinging " + adrstring + "...\n");
- if (!NET.StringToAdr(adrstring, adr)) {
- Com.Printf("Bad address: " + adrstring + "\n");
- continue;
- }
- if (adr.port == 0)
- //adr.port = BigShort(PORT_SERVER);
- adr.port = PORT_SERVER;
- Netchan.OutOfBandPrint(NS_CLIENT, adr, "info " + PROTOCOL_VERSION);
- }
- }
- };
-
-
- /*
- =================
- CL_Skins_f
-
- Load or download any custom player skins and models
- =================
- */
- static xcommand_t Skins_f = new xcommand_t() {
- public void execute() {
- int i;
-
- for (i = 0; i < MAX_CLIENTS; i++) {
- if (cl.configstrings[CS_PLAYERSKINS + i] == null)
- continue;
- Com.Printf("client " + i + ": " + cl.configstrings[CS_PLAYERSKINS + i] + "\n");
- SCR.UpdateScreen();
- Sys.SendKeyEvents(); // pump message loop
- CL.ParseClientinfo(i);
- }
- }
- };
-
- /*
- =================
- CL_ConnectionlessPacket
-
- Responses to broadcasts, etc
- =================
- */
- static void ConnectionlessPacket() {
- String s;
- String c;
-
- MSG.BeginReading(net_message);
- MSG.ReadLong(net_message); // skip the -1
-
- s = MSG.ReadStringLine(net_message);
-
- Cmd.TokenizeString(s.toCharArray(), false);
-
- c = Cmd.Argv(0);
-
- Com.Printf(NET.AdrToString(net_from) + ": " + c + "\n");
-
- // server connection
- if (c.equals("client_connect")) {
- if (cls.state == ca_connected) {
- Com.Printf("Dup connect received. Ignored.\n");
- return;
- }
- Netchan.Setup(NS_CLIENT, cls.netchan, net_from, cls.quakePort);
- MSG.WriteChar(cls.netchan.message, clc_stringcmd);
- MSG.WriteString(cls.netchan.message, "new");
- cls.state = ca_connected;
- return;
- }
-
- // server responding to a status broadcast
- if (c.equals("info")) {
- CL.ParseStatusMessage();
- return;
- }
-
- // remote command from gui front end
- if (c.equals ("cmd")) {
- if (!NET.IsLocalAddress(net_from)) {
- Com.Printf("Command packet from remote host. Ignored.\n");
- return;
- }
- s = MSG.ReadString(net_message);
- Cbuf.AddText(s);
- Cbuf.AddText("\n");
- return;
- }
- // print command from somewhere
- if (c.equals("print")) {
- s = MSG.ReadString(net_message);
- Com.Printf(s);
- return;
- }
-
- // ping from somewhere
- if (c.equals("ping")) {
- Netchan.OutOfBandPrint(NS_CLIENT, net_from, "ack");
- return;
- }
-
- // challenge from the server we are connecting to
- if (c.equals("challenge")) {
- cls.challenge = Integer.parseInt(Cmd.Argv(1));
- CL.SendConnectPacket();
- return;
- }
-
- // echo request from server
- if (c.equals("echo")) {
- Netchan.OutOfBandPrint(NS_CLIENT, net_from, Cmd.Argv(1));
- return;
- }
-
- Com.Printf("Unknown command.\n");
- }
-
- /*
- =================
- CL_DumpPackets
-
- A vain attempt to help bad TCP stacks that cause problems
- when they overflow
- =================
- */
- static void DumpPackets() {
- while (NET.GetPacket(NS_CLIENT, net_from, net_message)) {
- Com.Printf("dumping a packet\n");
- }
- }
-
- /*
- =================
- CL_ReadPackets
- =================
- */
- static void ReadPackets() {
- while (NET.GetPacket(NS_CLIENT, net_from, net_message)) {
-
- //
- // remote command packet
- //
- if (net_message.data[0] == -1 && net_message.data[1] == -1
- && net_message.data[2] == -1 && net_message.data[3] == -1) {
- // if (*(int *)net_message.data == -1)
- CL.ConnectionlessPacket();
- continue;
- }
-
- if (cls.state == ca_disconnected || cls.state == ca_connecting)
- continue; // dump it if not connected
-
- if (net_message.cursize < 8) {
- Com.Printf(NET.AdrToString(net_from) + ": Runt packet\n");
- continue;
- }
-
- //
- // packet from server
- //
- if (!NET.CompareAdr(net_from, cls.netchan.remote_address)) {
- Com.DPrintf(NET.AdrToString(net_from) + ":sequenced packet without connection\n");
- continue;
- }
- if (!Netchan.Process(cls.netchan, net_message))
- continue; // wasn't accepted for some reason
- ParseServerMessage();
- }
-
- //
- // check timeout
- //
- if (cls.state >= ca_connected && cls.realtime - cls.netchan.last_received > cl_timeout.value * 1000) {
- if (++cl.timeoutcount > 5) // timeoutcount saves debugger
- {
- Com.Printf("\nServer connection timed out.\n");
- CL.Disconnect();
- return;
- }
- }
- else
- cl.timeoutcount = 0;
- }
-
- // =============================================================================
-
- /*
- ==============
- CL_FixUpGender_f
- ==============
- */
- static void FixUpGender() {
-
- String sk;
-
- if (gender_auto.value != 0.0f) {
-
- if (gender.modified) {
- // was set directly, don't override the user
- gender.modified = false;
- return;
- }
-
- sk = skin.string;
- if (sk.startsWith("male") || sk.startsWith("cyborg"))
- Cvar.Set("gender", "male");
- else if (sk.startsWith("female") || sk.startsWith("crackhor"))
- Cvar.Set("gender", "female");
- else
- Cvar.Set("gender", "none");
- gender.modified = false;
- }
- }
-
- /*
- ==============
- CL_Userinfo_f
- ==============
- */
- static xcommand_t Userinfo_f = new xcommand_t() {
- public void execute() {
- Com.Printf("User info settings:\n");
- Info.Print(Cvar.Userinfo());
- }
- };
-
- /*
- =================
- CL_Snd_Restart_f
-
- Restart the sound subsystem so it can pick up
- new parameters and flush all sounds
- =================
- */
- static xcommand_t Snd_Restart_f = new xcommand_t() {
- public void execute() {
- S.Shutdown();
- S.Init();
- CL.RegisterSounds();
- }
- };
-
- static int precache_check; // for autodownload of precache items
- static int precache_spawncount;
- static int precache_tex;
- static int precache_model_skin;
-
- static byte precache_model[]; // used for skin checking in alias models
-
- public static final int PLAYER_MULT = 5;
-
- // ENV_CNT is map load, ENV_CNT+1 is first env map
- public static final int ENV_CNT = (CS_PLAYERSKINS + MAX_CLIENTS * PLAYER_MULT);
- public static final int TEXTURE_CNT = (ENV_CNT + 13);
-
- static String env_suf[] = { "rt", "bk", "lf", "ft", "up", "dn" };
-
- public static void RequestNextDownload() {
- int map_checksum = 0; // for detecting cheater maps
- //char fn[MAX_OSPATH];
- String fn;
-
- qfiles.dmdl_t pheader;
-
- if (cls.state != ca_connected)
- return;
-
- if (SV_MAIN.allow_download.value == 0 && precache_check < ENV_CNT)
- precache_check = ENV_CNT;
-
- // ZOID
- if (precache_check == CS_MODELS) { // confirm map
- precache_check = CS_MODELS + 2; // 0 isn't used
- if (SV_MAIN.allow_download_maps.value != 0)
- if (!CheckOrDownloadFile(cl.configstrings[CS_MODELS + 1]))
- return; // started a download
- }
- if (precache_check >= CS_MODELS && precache_check < CS_MODELS + MAX_MODELS) {
- if (SV_MAIN.allow_download_models.value != 0) {
- while (precache_check < CS_MODELS + MAX_MODELS && cl.configstrings[precache_check].length() > 0) {
- if (cl.configstrings[precache_check].charAt(0) == '*' || cl.configstrings[precache_check].charAt(0) == '#') {
- precache_check++;
- continue;
- }
- if (precache_model_skin == 0) {
- if (!CheckOrDownloadFile(cl.configstrings[precache_check])) {
- precache_model_skin = 1;
- return; // started a download
- }
- precache_model_skin = 1;
- }
-
- // checking for skins in the model
- if (precache_model == null) {
-
- precache_model = FS.LoadFile(cl.configstrings[precache_check]);
- if (precache_model == null) {
- precache_model_skin = 0;
- precache_check++;
- continue; // couldn't load it
- }
- ByteBuffer bb = ByteBuffer.wrap(precache_model);
- bb.order(ByteOrder.LITTLE_ENDIAN);
-
- int header = bb.getInt();
-
- if (header != qfiles.IDALIASHEADER) {
- // not an alias model
- FS.FreeFile(precache_model);
- precache_model = null;
- precache_model_skin = 0;
- precache_check++;
- continue;
- }
- pheader = new qfiles.dmdl_t(ByteBuffer.wrap(precache_model).order(ByteOrder.LITTLE_ENDIAN));
- if (pheader.version != ALIAS_VERSION) {
- precache_check++;
- precache_model_skin = 0;
- continue; // couldn't load it
- }
- }
-
- pheader = new qfiles.dmdl_t(ByteBuffer.wrap(precache_model).order(ByteOrder.LITTLE_ENDIAN));
-
- int num_skins = pheader.num_skins;
-
- while (precache_model_skin - 1 < num_skins) {
- //Com.Printf("critical code section because of endian mess!\n");
-
- String name =
- new String(
- precache_model,
- pheader.ofs_skins + (precache_model_skin - 1) * MAX_SKINNAME,
- MAX_SKINNAME * num_skins);
-
- if (!CheckOrDownloadFile(name)) {
- precache_model_skin++;
- return; // started a download
- }
- precache_model_skin++;
- }
- if (precache_model != null) {
- FS.FreeFile(precache_model);
- precache_model = null;
- }
- precache_model_skin = 0;
- precache_check++;
- }
- }
- precache_check = CS_SOUNDS;
- }
- if (precache_check >= CS_SOUNDS && precache_check < CS_SOUNDS + MAX_SOUNDS) {
- if (SV_MAIN.allow_download_sounds.value != 0) {
- if (precache_check == CS_SOUNDS)
- precache_check++; // zero is blank
- while (precache_check < CS_SOUNDS + MAX_SOUNDS && cl.configstrings[precache_check].length() > 0) {
- if (cl.configstrings[precache_check].charAt(0) == '*') {
- precache_check++;
- continue;
- }
- fn = "sound/" + cl.configstrings[precache_check++];
- if (!CheckOrDownloadFile(fn))
- return; // started a download
- }
- }
- precache_check = CS_IMAGES;
- }
- if (precache_check >= CS_IMAGES && precache_check < CS_IMAGES + MAX_IMAGES) {
- if (precache_check == CS_IMAGES)
- precache_check++; // zero is blank
-
- while (precache_check < CS_IMAGES + MAX_IMAGES && cl.configstrings[precache_check].length() > 0) {
- fn = "pics/" + cl.configstrings[precache_check++] + ".pcx";
- if (!CheckOrDownloadFile(fn))
- return; // started a download
- }
- precache_check = CS_PLAYERSKINS;
- }
- // skins are special, since a player has three things to download:
- // model, weapon model and skin
- // so precache_check is now *3
- if (precache_check >= CS_PLAYERSKINS && precache_check < CS_PLAYERSKINS + MAX_CLIENTS * PLAYER_MULT) {
- if (SV_MAIN.allow_download_players.value != 0) {
- while (precache_check < CS_PLAYERSKINS + MAX_CLIENTS * PLAYER_MULT) {
-
- int i, n;
- //char model[MAX_QPATH], skin[MAX_QPATH], * p;
- String model, skin;
-
- i = (precache_check - CS_PLAYERSKINS) / PLAYER_MULT;
- n = (precache_check - CS_PLAYERSKINS) % PLAYER_MULT;
-
- if (cl.configstrings[CS_PLAYERSKINS + i].length() == 0) {
- precache_check = CS_PLAYERSKINS + (i + 1) * PLAYER_MULT;
- continue;
- }
-
- int pos = cl.configstrings[CS_PLAYERSKINS + i].indexOf('\\');
- if (pos != -1)
- pos++;
- else
- pos = 0;
-
- model = cl.configstrings[CS_PLAYERSKINS + i].substring(pos);
-
- pos = model.indexOf('/');
-
- if (pos == -1)
- pos = model.indexOf('\\');
-
- if (pos != -1) {
- skin = model.substring(pos + 1);
- }
- else
- skin = "";
-
- switch (n) {
- case 0 : // model
- fn = "players/" + model + "/tris.md2";
- if (!CheckOrDownloadFile(fn)) {
- precache_check = CS_PLAYERSKINS + i * PLAYER_MULT + 1;
- return; // started a download
- }
- n++;
- /*FALL THROUGH*/
-
- case 1 : // weapon model
- fn = "players/" + model + "/weapon.md2";
- if (!CheckOrDownloadFile(fn)) {
- precache_check = CS_PLAYERSKINS + i * PLAYER_MULT + 2;
- return; // started a download
- }
- n++;
- /*FALL THROUGH*/
-
- case 2 : // weapon skin
- fn = "players/" + model + "/weapon.pcx";
- if (!CheckOrDownloadFile(fn)) {
- precache_check = CS_PLAYERSKINS + i * PLAYER_MULT + 3;
- return; // started a download
- }
- n++;
- /*FALL THROUGH*/
-
- case 3 : // skin
- fn = "players/" + model + "/" + skin + ".pcx";
- if (!CheckOrDownloadFile(fn)) {
- precache_check = CS_PLAYERSKINS + i * PLAYER_MULT + 4;
- return; // started a download
- }
- n++;
- /*FALL THROUGH*/
-
- case 4 : // skin_i
- fn = "players/" + model + "/" + skin + "_i.pcx";
- if (!CheckOrDownloadFile(fn)) {
- precache_check = CS_PLAYERSKINS + i * PLAYER_MULT + 5;
- return; // started a download
- }
- // move on to next model
- precache_check = CS_PLAYERSKINS + (i + 1) * PLAYER_MULT;
- }
- }
- }
- // precache phase completed
- precache_check = ENV_CNT;
- }
-
- if (precache_check == ENV_CNT) {
- precache_check = ENV_CNT + 1;
-
- int iw[] = {map_checksum};
-
- CM.CM_LoadMap(cl.configstrings[CS_MODELS + 1], true, iw);
- map_checksum = iw[0];
-
- if ((map_checksum ^ atoi(cl.configstrings[CS_MAPCHECKSUM])) != 0) {
- Com.Error(
- ERR_DROP,
- "Local map version differs from server: " + map_checksum + " != '" + cl.configstrings[CS_MAPCHECKSUM] + "'\n");
- return;
- }
- }
-
- if (precache_check > ENV_CNT && precache_check < TEXTURE_CNT) {
- if (SV_MAIN.allow_download.value != 0 && SV_MAIN.allow_download_maps.value != 0) {
- while (precache_check < TEXTURE_CNT) {
- int n = precache_check++ -ENV_CNT - 1;
-
- if ((n & 1) != 0)
- fn = "env/" + cl.configstrings[CS_SKY] + env_suf[n / 2] + ".pcx";
- else
- fn = "env/" + cl.configstrings[CS_SKY] + env_suf[n / 2] + ".tga";
- if (!CheckOrDownloadFile(fn))
- return; // started a download
- }
- }
- precache_check = TEXTURE_CNT;
- }
-
- if (precache_check == TEXTURE_CNT) {
- precache_check = TEXTURE_CNT + 1;
- precache_tex = 0;
- }
-
- // confirm existance of textures, download any that don't exist
- if (precache_check == TEXTURE_CNT + 1) {
- // from qcommon/cmodel.c
- // extern int numtexinfo;
- // extern mapsurface_t map_surfaces[];
-
- if (SV_MAIN.allow_download.value != 0 && SV_MAIN.allow_download_maps.value != 0) {
- while (precache_tex < CM.numtexinfo) {
- //char fn[MAX_OSPATH];
-
- fn = "textures/" + CM.map_surfaces[precache_tex++].rname + ".wal";
- if (!CheckOrDownloadFile(fn))
- return; // started a download
- }
- }
- precache_check = TEXTURE_CNT + 999;
- }
-
- // ZOID
- CL.RegisterSounds();
- PrepRefresh();
-
- MSG.WriteByte(cls.netchan.message, clc_stringcmd);
- MSG.WriteString(cls.netchan.message, "begin " + precache_spawncount + "\n");
- }
-
- /*
- =================
- CL_Precache_f
-
- The server will send this command right
- before allowing the client into the server
- =================
- */
- static xcommand_t Precache_f = new xcommand_t() {
- public void execute() {
- /* Yet another hack to let old demos work
- the old precache sequence */
-
- if (Cmd.Argc() < 2) {
-
- int iw[] ={0};// for detecting cheater maps
-
-
- CM.CM_LoadMap(cl.configstrings[CS_MODELS + 1], true, iw);
- int mapchecksum = iw[0] ;
- CL.RegisterSounds();
- CL.PrepRefresh();
- return;
- }
-
- precache_check = CS_MODELS;
- precache_spawncount = atoi(Cmd.Argv(1));
- precache_model = null;
- precache_model_skin = 0;
-
- RequestNextDownload();
- }
- };
-
- /*
- =================
- CL_InitLocal
- =================
- */
- public static void InitLocal() {
- cls.state = Defines.ca_disconnected;
- cls.realtime = Sys.Milliseconds();
-
- InitInput();
-
- // never used !!
-// adr0 = Cvar.Get("adr0", "", CVAR_ARCHIVE);
-// adr1 = Cvar.Get("adr1", "", CVAR_ARCHIVE);
-// adr2 = Cvar.Get("adr2", "", CVAR_ARCHIVE);
-// adr3 = Cvar.Get("adr3", "", CVAR_ARCHIVE);
-// adr4 = Cvar.Get("adr4", "", CVAR_ARCHIVE);
-// adr5 = Cvar.Get("adr5", "", CVAR_ARCHIVE);
-// adr6 = Cvar.Get("adr6", "", CVAR_ARCHIVE);
-// adr7 = Cvar.Get("adr7", "", CVAR_ARCHIVE);
-// adr8 = Cvar.Get("adr8", "", CVAR_ARCHIVE);
-
- //
- // register our variables
- //
- cl_stereo_separation = Cvar.Get("cl_stereo_separation", "0.4", CVAR_ARCHIVE);
- cl_stereo = Cvar.Get("cl_stereo", "0", 0);
-
- cl_add_blend = Cvar.Get("cl_blend", "1", 0);
- cl_add_lights = Cvar.Get("cl_lights", "1", 0);
- cl_add_particles = Cvar.Get("cl_particles", "1", 0);
- cl_add_entities = Cvar.Get("cl_entities", "1", 0);
- cl_gun = Cvar.Get("cl_gun", "1", 0);
- cl_footsteps = Cvar.Get("cl_footsteps", "1", 0);
- cl_noskins = Cvar.Get("cl_noskins", "0", 0);
- cl_autoskins = Cvar.Get("cl_autoskins", "0", 0);
- cl_predict = Cvar.Get("cl_predict", "1", 0);
-
- cl_maxfps = Cvar.Get("cl_maxfps", "90", 0);
-
- cl_upspeed = Cvar.Get("cl_upspeed", "200", 0);
- cl_forwardspeed = Cvar.Get("cl_forwardspeed", "200", 0);
- cl_sidespeed = Cvar.Get("cl_sidespeed", "200", 0);
- cl_yawspeed = Cvar.Get("cl_yawspeed", "140", 0);
- cl_pitchspeed = Cvar.Get("cl_pitchspeed", "150", 0);
- cl_anglespeedkey = Cvar.Get("cl_anglespeedkey", "1.5", 0);
-
- cl_run = Cvar.Get("cl_run", "0", CVAR_ARCHIVE);
- lookspring = Cvar.Get("lookspring", "0", CVAR_ARCHIVE);
- lookstrafe = Cvar.Get("lookstrafe", "0", CVAR_ARCHIVE);
- sensitivity = Cvar.Get("sensitivity", "3", CVAR_ARCHIVE);
-
- m_pitch = Cvar.Get("m_pitch", "0.022", CVAR_ARCHIVE);
- m_yaw = Cvar.Get("m_yaw", "0.022", 0);
- m_forward = Cvar.Get("m_forward", "1", 0);
- m_side = Cvar.Get("m_side", "1", 0);
-
- cl_shownet = Cvar.Get("cl_shownet", "0", 0);
- cl_showmiss = Cvar.Get("cl_showmiss", "0", 0);
- cl_showclamp = Cvar.Get("showclamp", "0", 0);
- cl_timeout = Cvar.Get("cl_timeout", "120", 0);
- cl_paused = Cvar.Get("paused", "0", 0);
- cl_timedemo = Cvar.Get("timedemo", "0", 0);
-
- rcon_client_password = Cvar.Get("rcon_password", "", 0);
- rcon_address = Cvar.Get("rcon_address", "", 0);
-
- cl_lightlevel = Cvar.Get("r_lightlevel", "0", 0);
-
- //
- // userinfo
- //
- info_password = Cvar.Get("password", "", CVAR_USERINFO);
- info_spectator = Cvar.Get("spectator", "0", CVAR_USERINFO);
- name = Cvar.Get("name", "unnamed", CVAR_USERINFO | CVAR_ARCHIVE);
- skin = Cvar.Get("skin", "male/grunt", CVAR_USERINFO | CVAR_ARCHIVE);
- rate = Cvar.Get("rate", "25000", CVAR_USERINFO | CVAR_ARCHIVE); // FIXME
- msg = Cvar.Get("msg", "1", CVAR_USERINFO | CVAR_ARCHIVE);
- hand = Cvar.Get("hand", "0", CVAR_USERINFO | CVAR_ARCHIVE);
- fov = Cvar.Get("fov", "90", CVAR_USERINFO | CVAR_ARCHIVE);
- gender = Cvar.Get("gender", "male", CVAR_USERINFO | CVAR_ARCHIVE);
- gender_auto = Cvar.Get("gender_auto", "1", CVAR_ARCHIVE);
- gender.modified = false; // clear this so we know when user sets it manually
-
- cl_vwep = Cvar.Get("cl_vwep", "1", CVAR_ARCHIVE);
-
- //
- // register our commands
- //
- Cmd.AddCommand("cmd", ForwardToServer_f);
- Cmd.AddCommand("pause", Pause_f);
- Cmd.AddCommand("pingservers", PingServers_f);
- Cmd.AddCommand("skins", Skins_f);
-
- Cmd.AddCommand("userinfo", Userinfo_f);
- Cmd.AddCommand("snd_restart", Snd_Restart_f);
-
- Cmd.AddCommand("changing", Changing_f);
- Cmd.AddCommand("disconnect", Disconnect_f);
- Cmd.AddCommand("record", Record_f);
- Cmd.AddCommand("stop", Stop_f);
-
- Cmd.AddCommand("quit", Quit_f);
-
- Cmd.AddCommand("connect", Connect_f);
- Cmd.AddCommand("reconnect", Reconnect_f);
-
- Cmd.AddCommand("rcon", Rcon_f);
-
- Cmd.AddCommand("precache", Precache_f);
-
- Cmd.AddCommand("download", Download_f);
-
- //
- // forward to server commands
- //
- // the only thing this does is allow command completion
- // to work -- all unknown commands are automatically
- // forwarded to the server
- Cmd.AddCommand("wave", null);
- Cmd.AddCommand("inven", null);
- Cmd.AddCommand("kill", null);
- Cmd.AddCommand("use", null);
- Cmd.AddCommand("drop", null);
- Cmd.AddCommand("say", null);
- Cmd.AddCommand("say_team", null);
- Cmd.AddCommand("info", null);
- Cmd.AddCommand("prog", null);
- Cmd.AddCommand("give", null);
- Cmd.AddCommand("god", null);
- Cmd.AddCommand("notarget", null);
- Cmd.AddCommand("noclip", null);
- Cmd.AddCommand("invuse", null);
- Cmd.AddCommand("invprev", null);
- Cmd.AddCommand("invnext", null);
- Cmd.AddCommand("invdrop", null);
- Cmd.AddCommand("weapnext", null);
- Cmd.AddCommand("weapprev", null);
-
- }
-
- /*
- ===============
- CL_WriteConfiguration
-
- Writes key bindings and archived cvars to config.cfg
- ===============
- */
- static void WriteConfiguration() {
- RandomAccessFile f;
- String path;
-
- if (cls.state == ca_uninitialized)
- return;
-
- path = FS.Gamedir() + "/config.cfg";
- f = fopen(path, "rw");
- if (f == null) {
- Com.Printf("Couldn't write config.cfg.\n");
- return;
- }
- try
- {
- f.seek(0);
- f.setLength(0);
- }
- catch (IOException e1)
- {}
- try {
- f.writeBytes("// generated by quake, do not modify\n");
- }
- catch (IOException e) {}
-
- Key.WriteBindings(f);
- fclose(f);
- Cvar.WriteVariables(path);
- }
-
- /*
- ==================
- CL_FixCvarCheats
-
- ==================
- */
- public static class cheatvar_t {
- String name;
- String value;
- cvar_t var;
- }
-
- public static String cheatvarsinfo[][] = { { "timescale", "1" }, {
- "timedemo", "0" }, {
- "r_drawworld", "1" }, {
- "cl_testlights", "0" }, {
- "r_fullbright", "0" }, {
- "r_drawflat", "0" }, {
- "paused", "0" }, {
- "fixedtime", "0" }, {
- "sw_draworder", "0" }, {
- "gl_lightmap", "0" }, {
- "gl_saturatelighting", "0" }, {
- null, null }
- };
- public static cheatvar_t cheatvars[];
-
- static {
- cheatvars = new cheatvar_t[cheatvarsinfo.length];
- for (int n = 0; n < cheatvarsinfo.length; n++) {
- cheatvars[n] = new cheatvar_t();
- cheatvars[n].name = cheatvarsinfo[n][0];
- cheatvars[n].value = cheatvarsinfo[n][1];
- }
- }
-
- static int numcheatvars;
-
- public static void FixCvarCheats() {
- int i;
- cheatvar_t var;
-
- if ("1".equals(cl.configstrings[CS_MAXCLIENTS]) || 0 == cl.configstrings[CS_MAXCLIENTS].length())
- return; // single player can cheat
-
- // find all the cvars if we haven't done it yet
- if (0 == numcheatvars) {
- while (cheatvars[numcheatvars].name != null) {
- cheatvars[numcheatvars].var = Cvar.Get(cheatvars[numcheatvars].name, cheatvars[numcheatvars].value, 0);
- numcheatvars++;
- }
- }
-
- // make sure they are all set to the proper values
- for (i = 0; i < numcheatvars; i++) {
- var = cheatvars[i];
- if (!var.var.string.equals(var.value)) {
- Cvar.Set(var.name, var.value);
- }
- }
- }
-
- // ============================================================================
-
- /*
- ==================
- CL_SendCommand
-
- ==================
- */
- public static void SendCommand() {
- // get new key events
- Sys.SendKeyEvents();
-
- // allow mice or other external controllers to add commands
- IN.Commands();
-
- // process console commands
- Cbuf.Execute();
-
- // fix any cheating cvars
- FixCvarCheats();
-
- // send intentions now
- SendCmd();
-
- // resend a connection request if necessary
- CheckForResend();
- }
-
- /*
- ==================
- CL_Frame
-
- ==================
- */
- private static int extratime;
-// private static int lasttimecalled;
-
- public static void Frame(int msec) {
-
- extratime += msec;
-
- if (cl_timedemo.value == 0.0f) {
- if (cls.state == ca_connected && extratime < 100) {
- return; // don't flood packets out while connecting
- }
- if (extratime < 1000 / cl_maxfps.value) {
- return; // framerate is too high
- }
- }
-
- // let the mouse activate or deactivate
- IN.Frame();
-
- // decide the simulation time
- cls.frametime = extratime / 1000.0f;
- cl.time += extratime;
- cls.realtime = curtime;
-
- extratime = 0;
-
- if (cls.frametime > (1.0f / 5))
- cls.frametime = (1.0f / 5);
-
- // if in the debugger last frame, don't timeout
- if (msec > 5000)
- cls.netchan.last_received = Sys.Milliseconds();
-
- // fetch results from server
- CL.ReadPackets();
-
- // send a new command message to the server
- SendCommand();
-
- // predict all unacknowledged movements
- CL.PredictMovement();
-
- // allow rendering DLL change
- VID.CheckChanges();
- if (!cl.refresh_prepped && cls.state == ca_active) {
- CL.PrepRefresh();
- // force GC after level loading
- System.gc();
- }
-
- SCR.UpdateScreen();
-
- // update audio
- S.Update(cl.refdef.vieworg, cl.v_forward, cl.v_right, cl.v_up);
-
- // advance local effects for next frame
- CL.RunDLights();
- CL.RunLightStyles();
-
- SCR.RunConsole();
-
- cls.framecount++;
- if (cls.state != ca_active || cls.key_dest != key_game) {
- try {
- Thread.sleep(20);
- } catch (InterruptedException e) {}
- }
- }
-
- // ============================================================================
+public final class CL {
+
+ static int precache_check; // for autodownload of precache items
+
+ static int precache_spawncount;
+
+ static int precache_tex;
+
+ static int precache_model_skin;
+
+ static byte precache_model[]; // used for skin checking in alias models
+
+ public static final int PLAYER_MULT = 5;
+
+ /*
+ * ================== CL_FixCvarCheats
+ *
+ * ==================
+ */
+ public static class cheatvar_t {
+ String name;
+
+ String value;
+
+ cvar_t var;
+ }
+
+ public static String cheatvarsinfo[][] = { { "timescale", "1" },
+ { "timedemo", "0" }, { "r_drawworld", "1" },
+ { "cl_testlights", "0" }, { "r_fullbright", "0" },
+ { "r_drawflat", "0" }, { "paused", "0" }, { "fixedtime", "0" },
+ { "sw_draworder", "0" }, { "gl_lightmap", "0" },
+ { "gl_saturatelighting", "0" }, { null, null } };
+
+ public static cheatvar_t cheatvars[];
+
+ static {
+ cheatvars = new cheatvar_t[cheatvarsinfo.length];
+ for (int n = 0; n < cheatvarsinfo.length; n++) {
+ cheatvars[n] = new cheatvar_t();
+ cheatvars[n].name = cheatvarsinfo[n][0];
+ cheatvars[n].value = cheatvarsinfo[n][1];
+ }
+ }
+
+ static int numcheatvars;
+
+ /*
+ * ==================== CL_Stop_f
+ *
+ * stop recording a demo ====================
+ */
+ static xcommand_t Stop_f = new xcommand_t() {
+ public void execute() {
+ try {
+
+ int len;
+
+ if (!Globals.cls.demorecording) {
+ Com.Printf("Not recording a demo.\n");
+ return;
+ }
+
+ // finish up
+ len = -1;
+ Globals.cls.demofile.writeInt(len);
+ Globals.cls.demofile.close();
+ Globals.cls.demofile = null;
+ Globals.cls.demorecording = false;
+ Com.Printf("Stopped demo.\n");
+ } catch (IOException e) {
+ }
+ }
+ };
+
+ /*
+ * ==================== CL_Record_f
+ *
+ * record <demoname>
+ *
+ * Begins recording a demo from the current position ====================
+ */
+ static entity_state_t nullstate = new entity_state_t(null);
+
+ static xcommand_t Record_f = new xcommand_t() {
+ public void execute() {
+ try {
+ String name;
+ byte buf_data[] = new byte[Defines.MAX_MSGLEN];
+ sizebuf_t buf = new sizebuf_t();
+ int i;
+ entity_state_t ent;
+
+ if (Cmd.Argc() != 2) {
+ Com.Printf("record <demoname>\n");
+ return;
+ }
+
+ if (Globals.cls.demorecording) {
+ Com.Printf("Already recording.\n");
+ return;
+ }
+
+ if (Globals.cls.state != Defines.ca_active) {
+ Com.Printf("You must be in a level to record.\n");
+ return;
+ }
+
+ //
+ // open the demo file
+ //
+ name = FS.Gamedir() + "/demos/" + Cmd.Argv(1) + ".dm2";
+
+ Com.Printf("recording to " + name + ".\n");
+ FS.CreatePath(name);
+ Globals.cls.demofile = new RandomAccessFile(name, "rw");
+ if (Globals.cls.demofile == null) {
+ Com.Printf("ERROR: couldn't open.\n");
+ return;
+ }
+ Globals.cls.demorecording = true;
+
+ // don't start saving messages until a non-delta compressed
+ // message is received
+ Globals.cls.demowaiting = true;
+
+ //
+ // write out messages to hold the startup information
+ //
+ SZ.Init(buf, buf_data, Defines.MAX_MSGLEN);
+
+ // send the serverdata
+ MSG.WriteByte(buf, Defines.svc_serverdata);
+ MSG.WriteInt(buf, Defines.PROTOCOL_VERSION);
+ MSG.WriteInt(buf, 0x10000 + Globals.cl.servercount);
+ MSG.WriteByte(buf, 1); // demos are always attract loops
+ MSG.WriteString(buf, Globals.cl.gamedir);
+ MSG.WriteShort(buf, Globals.cl.playernum);
+
+ MSG.WriteString(buf, Globals.cl.configstrings[Defines.CS_NAME]);
+
+ // configstrings
+ for (i = 0; i < Defines.MAX_CONFIGSTRINGS; i++) {
+ if (Globals.cl.configstrings[i].length() > 0) {
+ if (buf.cursize + Globals.cl.configstrings[i].length()
+ + 32 > buf.maxsize) { // write it out
+ //len = LittleLong(buf.cursize);
+ //fwrite(& len, 4, 1, cls.demofile);
+ Globals.cls.demofile.writeInt(buf.cursize);
+ //fwrite(buf.data, buf.cursize, 1, cls.demofile);
+ Globals.cls.demofile
+ .write(buf.data, 0, buf.cursize);
+ buf.cursize = 0;
+ }
+
+ MSG.WriteByte(buf, Defines.svc_configstring);
+ MSG.WriteShort(buf, i);
+ MSG.WriteString(buf, Globals.cl.configstrings[i]);
+ }
+
+ }
+
+ // baselines
+ //memset( nullstate, 0, sizeof(nullstate));
+ for (i = 0; i < Defines.MAX_EDICTS; i++) {
+ ent = Globals.cl_entities[i].baseline;
+ if (ent.modelindex == 0)
+ continue;
+
+ if (buf.cursize + 64 > buf.maxsize) { // write it out
+ //len = LittleLong(buf.cursize);
+ //fwrite(& len, 4, 1, cls.demofile);
+ Globals.cls.demofile.writeInt(buf.cursize);
+ //fwrite(buf.data, buf.cursize, 1, cls.demofile);
+ Globals.cls.demofile.write(buf.data, 0, buf.cursize);
+ buf.cursize = 0;
+ }
+
+ MSG.WriteByte(buf, Defines.svc_spawnbaseline);
+ MSG.WriteDeltaEntity(nullstate,
+ Globals.cl_entities[i].baseline, buf, true, true);
+ }
+
+ MSG.WriteByte(buf, Defines.svc_stufftext);
+ MSG.WriteString(buf, "precache\n");
+
+ // write it to the demo file
+
+ //len = LittleLong(buf.cursize);
+ //fwrite(& len, 4, 1, cls.demofile);
+ Globals.cls.demofile.writeInt(buf.cursize);
+ //fwrite(buf.data, buf.cursize, 1, cls.demofile);
+ Globals.cls.demofile.write(buf.data, 0, buf.cursize);
+ // the rest of the demo file will be individual frames
+
+ } catch (IOException e) {
+ }
+ }
+ };
+
+ /*
+ * ================== CL_ForwardToServer_f ==================
+ */
+ static xcommand_t ForwardToServer_f = new xcommand_t() {
+ public void execute() {
+ if (Globals.cls.state != Defines.ca_connected
+ && Globals.cls.state != Defines.ca_active) {
+ Com.Printf("Can't \"" + Cmd.Argv(0) + "\", not connected\n");
+ return;
+ }
+
+ // don't forward the first argument
+ if (Cmd.Argc() > 1) {
+ MSG.WriteByte(Globals.cls.netchan.message,
+ Defines.clc_stringcmd);
+ SZ.Print(Globals.cls.netchan.message, Cmd.Args());
+ }
+ }
+ };
+
+ /*
+ * ================== CL_Pause_f ==================
+ */
+ static xcommand_t Pause_f = new xcommand_t() {
+ public void execute() {
+ // never pause in multiplayer
+
+ if (Cvar.VariableValue("maxclients") > 1
+ || Globals.server_state == 0) {
+ Cvar.SetValue("paused", 0);
+ return;
+ }
+
+ Cvar.SetValue("paused", Globals.cl_paused.value);
+ }
+ };
+
+ /*
+ * ================== CL_Quit_f ==================
+ */
+ static xcommand_t Quit_f = new xcommand_t() {
+ public void execute() {
+ Disconnect();
+ Com.Quit();
+ }
+ };
+
+ /*
+ * ================ CL_Connect_f
+ *
+ * ================
+ */
+ static xcommand_t Connect_f = new xcommand_t() {
+ public void execute() {
+ String server;
+
+ if (Cmd.Argc() != 2) {
+ Com.Printf("usage: connect <server>\n");
+ return;
+ }
+
+ if (Globals.server_state != 0) {
+ // if running a local server, kill it and reissue
+ SV_MAIN.SV_Shutdown("Server quit\n", false);
+ } else {
+ Disconnect();
+ }
+
+ server = Cmd.Argv(1);
+
+ NET.Config(true); // allow remote
+
+ Disconnect();
+
+ Globals.cls.state = Defines.ca_connecting;
+ //strncpy (cls.servername, server, sizeof(cls.servername)-1);
+ Globals.cls.servername = server;
+ Globals.cls.connect_time = -99999;
+ // CL_CheckForResend() will fire immediately
+ }
+ };
+
+ /*
+ * ===================== CL_Rcon_f
+ *
+ * Send the rest of the command line over as an unconnected command.
+ * =====================
+ */
+ static xcommand_t Rcon_f = new xcommand_t() {
+ public void execute() {
+ StringBuffer message = new StringBuffer(1024);
+ int i;
+ netadr_t to = new netadr_t();
+
+ if (Globals.rcon_client_password.string == null) {
+ Com
+ .Printf("You must set 'rcon_password' before\nissuing an rcon command.\n");
+ return;
+ }
+
+ message.append((char) 255);
+ message.append((char) 255);
+ message.append((char) 255);
+ message.append((char) 255);
+
+ NET.Config(true); // allow remote
+
+ //strcat (message, "rcon ");
+ message.append("rcon ");
+
+ //strcat (message, rcon_client_password.string);
+ message.append(Globals.rcon_client_password.string);
+ //strcat (message, " ");
+ message.append(" ");
+
+ for (i = 1; i < Cmd.Argc(); i++) {
+ //strcat (message, Cmd.Argv(i));
+ message.append(Cmd.Argv(i));
+ //strcat (message, " ");
+ message.append(" ");
+ }
+
+ if (Globals.cls.state >= Defines.ca_connected)
+ to = Globals.cls.netchan.remote_address;
+ else {
+ if (Globals.rcon_address.string.length() == 0) {
+ Com
+ .Printf("You must either be connected,\nor set the 'rcon_address' cvar\nto issue rcon commands\n");
+
+ return;
+ }
+ NET.StringToAdr(Globals.rcon_address.string, to);
+ if (to.port == 0)
+ //to.port = BigShort (PORT_SERVER);
+ to.port = Defines.PORT_SERVER;
+ }
+ message.append('\0');
+ String b = message.toString();
+ NET.SendPacket(Defines.NS_CLIENT, b.length(), b.getBytes(), to);
+ }
+ };
+
+ static xcommand_t Disconnect_f = new xcommand_t() {
+ public void execute() {
+ Com.Error(Defines.ERR_DROP, "Disconnected from server");
+ }
+ };
+
+ /*
+ * ================= CL_Changing_f
+ *
+ * Just sent as a hint to the client that they should drop to full console
+ * =================
+ */
+ static xcommand_t Changing_f = new xcommand_t() {
+ public void execute() {
+ //ZOID
+ //if we are downloading, we don't change!
+ // This so we don't suddenly stop downloading a map
+
+ if (Globals.cls.download != null)
+ return;
+
+ SCR.BeginLoadingPlaque();
+ Globals.cls.state = Defines.ca_connected; // not active anymore, but
+ // not disconnected
+ Com.Printf("\nChanging map...\n");
+ }
+ };
+
+ /*
+ * ================= CL_Reconnect_f
+ *
+ * The server is changing levels =================
+ */
+ static xcommand_t Reconnect_f = new xcommand_t() {
+ public void execute() {
+ //ZOID
+ //if we are downloading, we don't change! This so we don't suddenly
+ // stop downloading a map
+ if (Globals.cls.download != null)
+ return;
+
+ S.StopAllSounds();
+ if (Globals.cls.state == Defines.ca_connected) {
+ Com.Printf("reconnecting...\n");
+ Globals.cls.state = Defines.ca_connected;
+ MSG.WriteChar(Globals.cls.netchan.message,
+ Defines.clc_stringcmd);
+ MSG.WriteString(Globals.cls.netchan.message, "new");
+ return;
+ }
+
+ if (Globals.cls.servername != null) {
+ if (Globals.cls.state >= Defines.ca_connected) {
+ Disconnect();
+ Globals.cls.connect_time = Globals.cls.realtime - 1500;
+ } else
+ Globals.cls.connect_time = -99999; // fire immediately
+
+ Globals.cls.state = Defines.ca_connecting;
+ Com.Printf("reconnecting...\n");
+ }
+ }
+ };
+
+ /*
+ * ================= CL_PingServers_f =================
+ */
+ static xcommand_t PingServers_f = new xcommand_t() {
+ public void execute() {
+ int i;
+ netadr_t adr = new netadr_t();
+ //char name[32];
+ String name;
+ String adrstring;
+ cvar_t noudp;
+ cvar_t noipx;
+
+ NET.Config(true); // allow remote
+
+ // send a broadcast packet
+ Com.Printf("pinging broadcast...\n");
+
+ noudp = Cvar.Get("noudp", "0", Defines.CVAR_NOSET);
+ if (noudp.value == 0.0f) {
+ adr.type = Defines.NA_BROADCAST;
+ adr.port = Defines.PORT_SERVER;
+ //adr.port = BigShort(PORT_SERVER);
+ Netchan.OutOfBandPrint(Defines.NS_CLIENT, adr, "info "
+ + Defines.PROTOCOL_VERSION);
+ }
+
+ // we use no IPX
+ noipx = Cvar.Get("noipx", "1", Defines.CVAR_NOSET);
+ if (noipx.value == 0.0f) {
+ adr.type = Defines.NA_BROADCAST_IPX;
+ //adr.port = BigShort(PORT_SERVER);
+ adr.port = Defines.PORT_SERVER;
+ Netchan.OutOfBandPrint(Defines.NS_CLIENT, adr, "info "
+ + Defines.PROTOCOL_VERSION);
+ }
+
+ // send a packet to each address book entry
+ for (i = 0; i < 16; i++) {
+ //Com_sprintf (name, sizeof(name), "adr%i", i);
+ name = "adr" + i;
+ adrstring = Cvar.VariableString(name);
+ if (adrstring == null || adrstring.length() == 0)
+ continue;
+
+ Com.Printf("pinging " + adrstring + "...\n");
+ if (!NET.StringToAdr(adrstring, adr)) {
+ Com.Printf("Bad address: " + adrstring + "\n");
+ continue;
+ }
+ if (adr.port == 0)
+ //adr.port = BigShort(PORT_SERVER);
+ adr.port = Defines.PORT_SERVER;
+ Netchan.OutOfBandPrint(Defines.NS_CLIENT, adr, "info "
+ + Defines.PROTOCOL_VERSION);
+ }
+ }
+ };
+
+ /*
+ * ================= CL_Skins_f
+ *
+ * Load or download any custom player skins and models =================
+ */
+ static xcommand_t Skins_f = new xcommand_t() {
+ public void execute() {
+ int i;
+
+ for (i = 0; i < Defines.MAX_CLIENTS; i++) {
+ if (Globals.cl.configstrings[Defines.CS_PLAYERSKINS + i] == null)
+ continue;
+ Com.Printf("client " + i + ": "
+ + Globals.cl.configstrings[Defines.CS_PLAYERSKINS + i]
+ + "\n");
+ SCR.UpdateScreen();
+ Sys.SendKeyEvents(); // pump message loop
+ CL_parse.ParseClientinfo(i);
+ }
+ }
+ };
+
+ /*
+ * ============== CL_Userinfo_f ==============
+ */
+ static xcommand_t Userinfo_f = new xcommand_t() {
+ public void execute() {
+ Com.Printf("User info settings:\n");
+ Info.Print(Cvar.Userinfo());
+ }
+ };
+
+ /*
+ * ================= CL_Snd_Restart_f
+ *
+ * Restart the sound subsystem so it can pick up new parameters and flush
+ * all sounds =================
+ */
+ static xcommand_t Snd_Restart_f = new xcommand_t() {
+ public void execute() {
+ S.Shutdown();
+ S.Init();
+ CL_parse.RegisterSounds();
+ }
+ };
+
+ // ENV_CNT is map load, ENV_CNT+1 is first env map
+ public static final int ENV_CNT = (Defines.CS_PLAYERSKINS + Defines.MAX_CLIENTS
+ * CL.PLAYER_MULT);
+
+ public static final int TEXTURE_CNT = (ENV_CNT + 13);
+
+ static String env_suf[] = { "rt", "bk", "lf", "ft", "up", "dn" };
+
+ /*
+ * ================= CL_Precache_f
+ *
+ * The server will send this command right before allowing the client into
+ * the server =================
+ */
+ static xcommand_t Precache_f = new xcommand_t() {
+ public void execute() {
+ /*
+ * Yet another hack to let old demos work the old precache sequence
+ */
+
+ if (Cmd.Argc() < 2) {
+
+ int iw[] = { 0 }; // for detecting cheater maps
+
+ CM.CM_LoadMap(Globals.cl.configstrings[Defines.CS_MODELS + 1],
+ true, iw);
+ int mapchecksum = iw[0];
+ CL_parse.RegisterSounds();
+ CL_view.PrepRefresh();
+ return;
+ }
+
+ CL.precache_check = Defines.CS_MODELS;
+ CL.precache_spawncount = Lib.atoi(Cmd.Argv(1));
+ CL.precache_model = null;
+ CL.precache_model_skin = 0;
+
+ RequestNextDownload();
+ }
+ };
+
+ /*
+ * ================== CL_Frame
+ *
+ * ==================
+ */
+ private static int extratime;
+
+ // ============================================================================
+
+ /*
+ * =============== CL_Shutdown
+ *
+ * FIXME: this is a callback from Sys_Quit and Com_Error. It would be better
+ * to run quit through here before the final handoff to the sys code.
+ * ===============
+ */
+ static boolean isdown = false;
+
+ /*
+ * ==================== CL_WriteDemoMessage
+ *
+ * Dumps the current net message, prefixed by the length
+ * ====================
+ */
+ static void WriteDemoMessage() {
+ int swlen;
+
+ // the first eight bytes are just packet sequencing stuff
+ swlen = Globals.net_message.cursize - 8;
+
+ try {
+ Globals.cls.demofile.writeInt(swlen);
+ //fwrite (&swlen, 4, 1, cls.demofile);
+ Globals.cls.demofile.write(Globals.net_message.data, 8, swlen);
+ //fwrite (net_message.data+8, len, 1, cls.demofile);
+ } catch (IOException e) {
+ }
+
+ }
+
+ /*
+ * ======================= CL_SendConnectPacket
+ *
+ * We have gotten a challenge from the server, so try and connect.
+ * ======================
+ */
+ static void SendConnectPacket() {
+ netadr_t adr = new netadr_t();
+ int port;
+
+ if (!NET.StringToAdr(Globals.cls.servername, adr)) {
+ Com.Printf("Bad server address\n");
+ Globals.cls.connect_time = 0;
+ return;
+ }
+ if (adr.port == 0)
+ adr.port = Defines.PORT_SERVER;
+ // adr.port = BigShort(PORT_SERVER);
+
+ port = (int) Cvar.VariableValue("qport");
+ Globals.userinfo_modified = false;
+
+ Netchan.OutOfBandPrint(Defines.NS_CLIENT, adr, "connect "
+ + Defines.PROTOCOL_VERSION + " " + port + " "
+ + Globals.cls.challenge + " \"" + Cvar.Userinfo() + "\"\n");
+ }
+
+ /*
+ * ================= CL_CheckForResend
+ *
+ * Resend a connect message if the last one has timed out =================
+ */
+ static void CheckForResend() {
+ netadr_t adr = new netadr_t();
+
+ // if the local server is running and we aren't
+ // then connect
+ if (Globals.cls.state == Defines.ca_disconnected
+ && Globals.server_state != 0) {
+ Globals.cls.state = Defines.ca_connecting;
+ Globals.cls.servername = "localhost";
+ // we don't need a challenge on the localhost
+ SendConnectPacket();
+ return;
+ }
+
+ // resend if we haven't gotten a reply yet
+ if (Globals.cls.state != Defines.ca_connecting)
+ return;
+
+ if (Globals.cls.realtime - Globals.cls.connect_time < 3000)
+ return;
+
+ if (!NET.StringToAdr(Globals.cls.servername, adr)) {
+ Com.Printf("Bad server address\n");
+ Globals.cls.state = Defines.ca_disconnected;
+ return;
+ }
+ if (adr.port == 0)
+ // adr.port = BigShort(PORT_SERVER);
+ adr.port = Defines.PORT_SERVER;
+
+ Globals.cls.connect_time = Globals.cls.realtime; // for retransmit
+ // requests
+
+ Com.Printf("Connecting to " + Globals.cls.servername + "...\n");
+
+ Netchan.OutOfBandPrint(Defines.NS_CLIENT, adr, "getchallenge\n");
+ }
+
+ /*
+ * ===================== CL_ClearState
+ *
+ * =====================
+ */
+
+ static void ClearState() {
+ S.StopAllSounds();
+ CL_fx.ClearEffects();
+ CL_tent.ClearTEnts();
+
+ // wipe the entire cl structure
+
+ Globals.cl = new client_state_t();
+ for (int i = 0; i < Globals.cl_entities.length; i++) {
+ Globals.cl_entities[i] = new centity_t();
+ }
+
+ SZ.Clear(Globals.cls.netchan.message);
+ }
+
+ /*
+ * ===================== CL_Disconnect
+ *
+ * Goes from a connected state to full screen console state Sends a
+ * disconnect message to the server This is also called on Com_Error, so it
+ * shouldn't cause any errors =====================
+ */
+
+ static void Disconnect() {
+
+ String fin;
+
+ if (Globals.cls.state == Defines.ca_disconnected)
+ return;
+
+ if (Globals.cl_timedemo != null && Globals.cl_timedemo.value != 0.0f) {
+ int time;
+
+ time = (int) (Sys.Milliseconds() - Globals.cl.timedemo_start);
+ if (time > 0)
+ Com.Printf("%i frames, %3.1f seconds: %3.1f fps\n",
+ new Vargs(3).add(Globals.cl.timedemo_frames).add(
+ time / 1000.0).add(
+ Globals.cl.timedemo_frames * 1000.0 / time));
+ }
+
+ Math3D.VectorClear(Globals.cl.refdef.blend);
+ //re.CinematicSetPalette(null);
+
+ Menu.ForceMenuOff();
+
+ Globals.cls.connect_time = 0;
+
+ // SCR.StopCinematic();
+
+ if (Globals.cls.demorecording)
+ Stop_f.execute();
+
+ // send a disconnect message to the server
+ fin = (char) Defines.clc_stringcmd + "disconnect";
+ Netchan.Transmit(Globals.cls.netchan, fin.length(), fin.getBytes());
+ Netchan.Transmit(Globals.cls.netchan, fin.length(), fin.getBytes());
+ Netchan.Transmit(Globals.cls.netchan, fin.length(), fin.getBytes());
+
+ ClearState();
+
+ // stop download
+ if (Globals.cls.download != null) {
+ Lib.fclose(Globals.cls.download);
+ Globals.cls.download = null;
+ // fclose(cls.download);
+ // cls.download = NULL;
+ }
+
+ Globals.cls.state = Defines.ca_disconnected;
+ }
+
+ /*
+ * ================= CL_ParseStatusMessage
+ *
+ * Handle a reply from a ping =================
+ */
+ static void ParseStatusMessage() {
+ String s;
+
+ s = MSG.ReadString(Globals.net_message);
+
+ Com.Printf(s + "\n");
+ Menu.AddToServerList(Globals.net_from, s);
+ }
+
+ /*
+ * ================= CL_ConnectionlessPacket
+ *
+ * Responses to broadcasts, etc =================
+ */
+ static void ConnectionlessPacket() {
+ String s;
+ String c;
+
+ MSG.BeginReading(Globals.net_message);
+ MSG.ReadLong(Globals.net_message); // skip the -1
+
+ s = MSG.ReadStringLine(Globals.net_message);
+
+ Cmd.TokenizeString(s.toCharArray(), false);
+
+ c = Cmd.Argv(0);
+
+ Com.Printf(NET.AdrToString(Globals.net_from) + ": " + c + "\n");
+
+ // server connection
+ if (c.equals("client_connect")) {
+ if (Globals.cls.state == Defines.ca_connected) {
+ Com.Printf("Dup connect received. Ignored.\n");
+ return;
+ }
+ Netchan.Setup(Defines.NS_CLIENT, Globals.cls.netchan,
+ Globals.net_from, Globals.cls.quakePort);
+ MSG.WriteChar(Globals.cls.netchan.message, Defines.clc_stringcmd);
+ MSG.WriteString(Globals.cls.netchan.message, "new");
+ Globals.cls.state = Defines.ca_connected;
+ return;
+ }
+
+ // server responding to a status broadcast
+ if (c.equals("info")) {
+ ParseStatusMessage();
+ return;
+ }
+
+ // remote command from gui front end
+ if (c.equals("cmd")) {
+ if (!NET.IsLocalAddress(Globals.net_from)) {
+ Com.Printf("Command packet from remote host. Ignored.\n");
+ return;
+ }
+ s = MSG.ReadString(Globals.net_message);
+ Cbuf.AddText(s);
+ Cbuf.AddText("\n");
+ return;
+ }
+ // print command from somewhere
+ if (c.equals("print")) {
+ s = MSG.ReadString(Globals.net_message);
+ Com.Printf(s);
+ return;
+ }
+
+ // ping from somewhere
+ if (c.equals("ping")) {
+ Netchan.OutOfBandPrint(Defines.NS_CLIENT, Globals.net_from, "ack");
+ return;
+ }
+
+ // challenge from the server we are connecting to
+ if (c.equals("challenge")) {
+ Globals.cls.challenge = Integer.parseInt(Cmd.Argv(1));
+ SendConnectPacket();
+ return;
+ }
+
+ // echo request from server
+ if (c.equals("echo")) {
+ Netchan.OutOfBandPrint(Defines.NS_CLIENT, Globals.net_from, Cmd
+ .Argv(1));
+ return;
+ }
+
+ Com.Printf("Unknown command.\n");
+ }
+
+ /*
+ * ================= CL_DumpPackets
+ *
+ * A vain attempt to help bad TCP stacks that cause problems when they
+ * overflow =================
+ */
+ static void DumpPackets() {
+ while (NET.GetPacket(Defines.NS_CLIENT, Globals.net_from,
+ Globals.net_message)) {
+ Com.Printf("dumping a packet\n");
+ }
+ }
+
+ /*
+ * ================= CL_ReadPackets =================
+ */
+ static void ReadPackets() {
+ while (NET.GetPacket(Defines.NS_CLIENT, Globals.net_from,
+ Globals.net_message)) {
+
+ //
+ // remote command packet
+ //
+ if (Globals.net_message.data[0] == -1
+ && Globals.net_message.data[1] == -1
+ && Globals.net_message.data[2] == -1
+ && Globals.net_message.data[3] == -1) {
+ // if (*(int *)net_message.data == -1)
+ ConnectionlessPacket();
+ continue;
+ }
+
+ if (Globals.cls.state == Defines.ca_disconnected
+ || Globals.cls.state == Defines.ca_connecting)
+ continue; // dump it if not connected
+
+ if (Globals.net_message.cursize < 8) {
+ Com.Printf(NET.AdrToString(Globals.net_from)
+ + ": Runt packet\n");
+ continue;
+ }
+
+ //
+ // packet from server
+ //
+ if (!NET.CompareAdr(Globals.net_from,
+ Globals.cls.netchan.remote_address)) {
+ Com.DPrintf(NET.AdrToString(Globals.net_from)
+ + ":sequenced packet without connection\n");
+ continue;
+ }
+ if (!Netchan.Process(Globals.cls.netchan, Globals.net_message))
+ continue; // wasn't accepted for some reason
+ CL_parse.ParseServerMessage();
+ }
+
+ //
+ // check timeout
+ //
+ if (Globals.cls.state >= Defines.ca_connected
+ && Globals.cls.realtime - Globals.cls.netchan.last_received > Globals.cl_timeout.value * 1000) {
+ if (++Globals.cl.timeoutcount > 5) // timeoutcount saves debugger
+ {
+ Com.Printf("\nServer connection timed out.\n");
+ Disconnect();
+ return;
+ }
+ } else
+ Globals.cl.timeoutcount = 0;
+ }
+
+ // =============================================================================
+
+ /*
+ * ============== CL_FixUpGender_f ==============
+ */
+ static void FixUpGender() {
+
+ String sk;
+
+ if (Globals.gender_auto.value != 0.0f) {
+
+ if (Globals.gender.modified) {
+ // was set directly, don't override the user
+ Globals.gender.modified = false;
+ return;
+ }
+
+ sk = Globals.skin.string;
+ if (sk.startsWith("male") || sk.startsWith("cyborg"))
+ Cvar.Set("gender", "male");
+ else if (sk.startsWith("female") || sk.startsWith("crackhor"))
+ Cvar.Set("gender", "female");
+ else
+ Cvar.Set("gender", "none");
+ Globals.gender.modified = false;
+ }
+ }
+
+ public static void RequestNextDownload() {
+ int map_checksum = 0; // for detecting cheater maps
+ //char fn[MAX_OSPATH];
+ String fn;
+
+ qfiles.dmdl_t pheader;
+
+ if (Globals.cls.state != Defines.ca_connected)
+ return;
+
+ if (SV_MAIN.allow_download.value == 0 && CL.precache_check < ENV_CNT)
+ CL.precache_check = ENV_CNT;
+
+ // ZOID
+ if (CL.precache_check == Defines.CS_MODELS) { // confirm map
+ CL.precache_check = Defines.CS_MODELS + 2; // 0 isn't used
+ if (SV_MAIN.allow_download_maps.value != 0)
+ if (!CL_parse
+ .CheckOrDownloadFile(Globals.cl.configstrings[Defines.CS_MODELS + 1]))
+ return; // started a download
+ }
+ if (CL.precache_check >= Defines.CS_MODELS
+ && CL.precache_check < Defines.CS_MODELS + Defines.MAX_MODELS) {
+ if (SV_MAIN.allow_download_models.value != 0) {
+ while (CL.precache_check < Defines.CS_MODELS
+ + Defines.MAX_MODELS
+ && Globals.cl.configstrings[CL.precache_check].length() > 0) {
+ if (Globals.cl.configstrings[CL.precache_check].charAt(0) == '*'
+ || Globals.cl.configstrings[CL.precache_check]
+ .charAt(0) == '#') {
+ CL.precache_check++;
+ continue;
+ }
+ if (CL.precache_model_skin == 0) {
+ if (!CL_parse
+ .CheckOrDownloadFile(Globals.cl.configstrings[CL.precache_check])) {
+ CL.precache_model_skin = 1;
+ return; // started a download
+ }
+ CL.precache_model_skin = 1;
+ }
+
+ // checking for skins in the model
+ if (CL.precache_model == null) {
+
+ CL.precache_model = FS
+ .LoadFile(Globals.cl.configstrings[CL.precache_check]);
+ if (CL.precache_model == null) {
+ CL.precache_model_skin = 0;
+ CL.precache_check++;
+ continue; // couldn't load it
+ }
+ ByteBuffer bb = ByteBuffer.wrap(CL.precache_model);
+ bb.order(ByteOrder.LITTLE_ENDIAN);
+
+ int header = bb.getInt();
+
+ if (header != qfiles.IDALIASHEADER) {
+ // not an alias model
+ FS.FreeFile(CL.precache_model);
+ CL.precache_model = null;
+ CL.precache_model_skin = 0;
+ CL.precache_check++;
+ continue;
+ }
+ pheader = new qfiles.dmdl_t(ByteBuffer.wrap(
+ CL.precache_model).order(
+ ByteOrder.LITTLE_ENDIAN));
+ if (pheader.version != Defines.ALIAS_VERSION) {
+ CL.precache_check++;
+ CL.precache_model_skin = 0;
+ continue; // couldn't load it
+ }
+ }
+
+ pheader = new qfiles.dmdl_t(ByteBuffer.wrap(
+ CL.precache_model).order(ByteOrder.LITTLE_ENDIAN));
+
+ int num_skins = pheader.num_skins;
+
+ while (CL.precache_model_skin - 1 < num_skins) {
+ //Com.Printf("critical code section because of endian
+ // mess!\n");
+
+ String name = new String(CL.precache_model,
+ pheader.ofs_skins
+ + (CL.precache_model_skin - 1)
+ * Defines.MAX_SKINNAME,
+ Defines.MAX_SKINNAME * num_skins);
+
+ if (!CL_parse.CheckOrDownloadFile(name)) {
+ CL.precache_model_skin++;
+ return; // started a download
+ }
+ CL.precache_model_skin++;
+ }
+ if (CL.precache_model != null) {
+ FS.FreeFile(CL.precache_model);
+ CL.precache_model = null;
+ }
+ CL.precache_model_skin = 0;
+ CL.precache_check++;
+ }
+ }
+ CL.precache_check = Defines.CS_SOUNDS;
+ }
+ if (CL.precache_check >= Defines.CS_SOUNDS
+ && CL.precache_check < Defines.CS_SOUNDS + Defines.MAX_SOUNDS) {
+ if (SV_MAIN.allow_download_sounds.value != 0) {
+ if (CL.precache_check == Defines.CS_SOUNDS)
+ CL.precache_check++; // zero is blank
+ while (CL.precache_check < Defines.CS_SOUNDS
+ + Defines.MAX_SOUNDS
+ && Globals.cl.configstrings[CL.precache_check].length() > 0) {
+ if (Globals.cl.configstrings[CL.precache_check].charAt(0) == '*') {
+ CL.precache_check++;
+ continue;
+ }
+ fn = "sound/"
+ + Globals.cl.configstrings[CL.precache_check++];
+ if (!CL_parse.CheckOrDownloadFile(fn))
+ return; // started a download
+ }
+ }
+ CL.precache_check = Defines.CS_IMAGES;
+ }
+ if (CL.precache_check >= Defines.CS_IMAGES
+ && CL.precache_check < Defines.CS_IMAGES + Defines.MAX_IMAGES) {
+ if (CL.precache_check == Defines.CS_IMAGES)
+ CL.precache_check++; // zero is blank
+
+ while (CL.precache_check < Defines.CS_IMAGES + Defines.MAX_IMAGES
+ && Globals.cl.configstrings[CL.precache_check].length() > 0) {
+ fn = "pics/" + Globals.cl.configstrings[CL.precache_check++]
+ + ".pcx";
+ if (!CL_parse.CheckOrDownloadFile(fn))
+ return; // started a download
+ }
+ CL.precache_check = Defines.CS_PLAYERSKINS;
+ }
+ // skins are special, since a player has three things to download:
+ // model, weapon model and skin
+ // so precache_check is now *3
+ if (CL.precache_check >= Defines.CS_PLAYERSKINS
+ && CL.precache_check < Defines.CS_PLAYERSKINS
+ + Defines.MAX_CLIENTS * CL.PLAYER_MULT) {
+ if (SV_MAIN.allow_download_players.value != 0) {
+ while (CL.precache_check < Defines.CS_PLAYERSKINS
+ + Defines.MAX_CLIENTS * CL.PLAYER_MULT) {
+
+ int i, n;
+ //char model[MAX_QPATH], skin[MAX_QPATH], * p;
+ String model, skin;
+
+ i = (CL.precache_check - Defines.CS_PLAYERSKINS)
+ / CL.PLAYER_MULT;
+ n = (CL.precache_check - Defines.CS_PLAYERSKINS)
+ % CL.PLAYER_MULT;
+
+ if (Globals.cl.configstrings[Defines.CS_PLAYERSKINS + i]
+ .length() == 0) {
+ CL.precache_check = Defines.CS_PLAYERSKINS + (i + 1)
+ * CL.PLAYER_MULT;
+ continue;
+ }
+
+ int pos = Globals.cl.configstrings[Defines.CS_PLAYERSKINS
+ + i].indexOf('\\');
+ if (pos != -1)
+ pos++;
+ else
+ pos = 0;
+
+ model = Globals.cl.configstrings[Defines.CS_PLAYERSKINS + i]
+ .substring(pos);
+
+ pos = model.indexOf('/');
+
+ if (pos == -1)
+ pos = model.indexOf('\\');
+
+ if (pos != -1) {
+ skin = model.substring(pos + 1);
+ } else
+ skin = "";
+
+ switch (n) {
+ case 0: // model
+ fn = "players/" + model + "/tris.md2";
+ if (!CL_parse.CheckOrDownloadFile(fn)) {
+ CL.precache_check = Defines.CS_PLAYERSKINS + i
+ * CL.PLAYER_MULT + 1;
+ return; // started a download
+ }
+ n++;
+ /* FALL THROUGH */
+
+ case 1: // weapon model
+ fn = "players/" + model + "/weapon.md2";
+ if (!CL_parse.CheckOrDownloadFile(fn)) {
+ CL.precache_check = Defines.CS_PLAYERSKINS + i
+ * CL.PLAYER_MULT + 2;
+ return; // started a download
+ }
+ n++;
+ /* FALL THROUGH */
+
+ case 2: // weapon skin
+ fn = "players/" + model + "/weapon.pcx";
+ if (!CL_parse.CheckOrDownloadFile(fn)) {
+ CL.precache_check = Defines.CS_PLAYERSKINS + i
+ * CL.PLAYER_MULT + 3;
+ return; // started a download
+ }
+ n++;
+ /* FALL THROUGH */
+
+ case 3: // skin
+ fn = "players/" + model + "/" + skin + ".pcx";
+ if (!CL_parse.CheckOrDownloadFile(fn)) {
+ CL.precache_check = Defines.CS_PLAYERSKINS + i
+ * CL.PLAYER_MULT + 4;
+ return; // started a download
+ }
+ n++;
+ /* FALL THROUGH */
+
+ case 4: // skin_i
+ fn = "players/" + model + "/" + skin + "_i.pcx";
+ if (!CL_parse.CheckOrDownloadFile(fn)) {
+ CL.precache_check = Defines.CS_PLAYERSKINS + i
+ * CL.PLAYER_MULT + 5;
+ return; // started a download
+ }
+ // move on to next model
+ CL.precache_check = Defines.CS_PLAYERSKINS + (i + 1)
+ * CL.PLAYER_MULT;
+ }
+ }
+ }
+ // precache phase completed
+ CL.precache_check = ENV_CNT;
+ }
+
+ if (CL.precache_check == ENV_CNT) {
+ CL.precache_check = ENV_CNT + 1;
+
+ int iw[] = { map_checksum };
+
+ CM.CM_LoadMap(Globals.cl.configstrings[Defines.CS_MODELS + 1],
+ true, iw);
+ map_checksum = iw[0];
+
+ if ((map_checksum ^ Lib
+ .atoi(Globals.cl.configstrings[Defines.CS_MAPCHECKSUM])) != 0) {
+ Com
+ .Error(
+ Defines.ERR_DROP,
+ "Local map version differs from server: "
+ + map_checksum
+ + " != '"
+ + Globals.cl.configstrings[Defines.CS_MAPCHECKSUM]
+ + "'\n");
+ return;
+ }
+ }
+
+ if (CL.precache_check > ENV_CNT && CL.precache_check < TEXTURE_CNT) {
+ if (SV_MAIN.allow_download.value != 0
+ && SV_MAIN.allow_download_maps.value != 0) {
+ while (CL.precache_check < TEXTURE_CNT) {
+ int n = CL.precache_check++ - ENV_CNT - 1;
+
+ if ((n & 1) != 0)
+ fn = "env/" + Globals.cl.configstrings[Defines.CS_SKY]
+ + env_suf[n / 2] + ".pcx";
+ else
+ fn = "env/" + Globals.cl.configstrings[Defines.CS_SKY]
+ + env_suf[n / 2] + ".tga";
+ if (!CL_parse.CheckOrDownloadFile(fn))
+ return; // started a download
+ }
+ }
+ CL.precache_check = TEXTURE_CNT;
+ }
+
+ if (CL.precache_check == TEXTURE_CNT) {
+ CL.precache_check = TEXTURE_CNT + 1;
+ CL.precache_tex = 0;
+ }
+
+ // confirm existance of textures, download any that don't exist
+ if (CL.precache_check == TEXTURE_CNT + 1) {
+ // from qcommon/cmodel.c
+ // extern int numtexinfo;
+ // extern mapsurface_t map_surfaces[];
+
+ if (SV_MAIN.allow_download.value != 0
+ && SV_MAIN.allow_download_maps.value != 0) {
+ while (CL.precache_tex < CM.numtexinfo) {
+ //char fn[MAX_OSPATH];
+
+ fn = "textures/" + CM.map_surfaces[CL.precache_tex++].rname
+ + ".wal";
+ if (!CL_parse.CheckOrDownloadFile(fn))
+ return; // started a download
+ }
+ }
+ CL.precache_check = TEXTURE_CNT + 999;
+ }
+
+ // ZOID
+ CL_parse.RegisterSounds();
+ CL_view.PrepRefresh();
+
+ MSG.WriteByte(Globals.cls.netchan.message, Defines.clc_stringcmd);
+ MSG.WriteString(Globals.cls.netchan.message, "begin "
+ + CL.precache_spawncount + "\n");
+ }
+
+ /*
+ * ================= CL_InitLocal =================
+ */
+ public static void InitLocal() {
+ Globals.cls.state = Defines.ca_disconnected;
+ Globals.cls.realtime = Sys.Milliseconds();
+
+ CL_input.InitInput();
+
+ // never used !!
+ // adr0 = Cvar.Get("adr0", "", CVAR_ARCHIVE);
+ // adr1 = Cvar.Get("adr1", "", CVAR_ARCHIVE);
+ // adr2 = Cvar.Get("adr2", "", CVAR_ARCHIVE);
+ // adr3 = Cvar.Get("adr3", "", CVAR_ARCHIVE);
+ // adr4 = Cvar.Get("adr4", "", CVAR_ARCHIVE);
+ // adr5 = Cvar.Get("adr5", "", CVAR_ARCHIVE);
+ // adr6 = Cvar.Get("adr6", "", CVAR_ARCHIVE);
+ // adr7 = Cvar.Get("adr7", "", CVAR_ARCHIVE);
+ // adr8 = Cvar.Get("adr8", "", CVAR_ARCHIVE);
+
+ //
+ // register our variables
+ //
+ Globals.cl_stereo_separation = Cvar.Get("cl_stereo_separation", "0.4",
+ Defines.CVAR_ARCHIVE);
+ Globals.cl_stereo = Cvar.Get("cl_stereo", "0", 0);
+
+ Globals.cl_add_blend = Cvar.Get("cl_blend", "1", 0);
+ Globals.cl_add_lights = Cvar.Get("cl_lights", "1", 0);
+ Globals.cl_add_particles = Cvar.Get("cl_particles", "1", 0);
+ Globals.cl_add_entities = Cvar.Get("cl_entities", "1", 0);
+ Globals.cl_gun = Cvar.Get("cl_gun", "1", 0);
+ Globals.cl_footsteps = Cvar.Get("cl_footsteps", "1", 0);
+ Globals.cl_noskins = Cvar.Get("cl_noskins", "0", 0);
+ Globals.cl_autoskins = Cvar.Get("cl_autoskins", "0", 0);
+ Globals.cl_predict = Cvar.Get("cl_predict", "1", 0);
+
+ Globals.cl_maxfps = Cvar.Get("cl_maxfps", "90", 0);
+
+ Globals.cl_upspeed = Cvar.Get("cl_upspeed", "200", 0);
+ Globals.cl_forwardspeed = Cvar.Get("cl_forwardspeed", "200", 0);
+ Globals.cl_sidespeed = Cvar.Get("cl_sidespeed", "200", 0);
+ Globals.cl_yawspeed = Cvar.Get("cl_yawspeed", "140", 0);
+ Globals.cl_pitchspeed = Cvar.Get("cl_pitchspeed", "150", 0);
+ Globals.cl_anglespeedkey = Cvar.Get("cl_anglespeedkey", "1.5", 0);
+
+ Globals.cl_run = Cvar.Get("cl_run", "0", Defines.CVAR_ARCHIVE);
+ Globals.lookspring = Cvar.Get("lookspring", "0", Defines.CVAR_ARCHIVE);
+ Globals.lookstrafe = Cvar.Get("lookstrafe", "0", Defines.CVAR_ARCHIVE);
+ Globals.sensitivity = Cvar
+ .Get("sensitivity", "3", Defines.CVAR_ARCHIVE);
+
+ Globals.m_pitch = Cvar.Get("m_pitch", "0.022", Defines.CVAR_ARCHIVE);
+ Globals.m_yaw = Cvar.Get("m_yaw", "0.022", 0);
+ Globals.m_forward = Cvar.Get("m_forward", "1", 0);
+ Globals.m_side = Cvar.Get("m_side", "1", 0);
+
+ Globals.cl_shownet = Cvar.Get("cl_shownet", "0", 0);
+ Globals.cl_showmiss = Cvar.Get("cl_showmiss", "0", 0);
+ Globals.cl_showclamp = Cvar.Get("showclamp", "0", 0);
+ Globals.cl_timeout = Cvar.Get("cl_timeout", "120", 0);
+ Globals.cl_paused = Cvar.Get("paused", "0", 0);
+ Globals.cl_timedemo = Cvar.Get("timedemo", "0", 0);
+
+ Globals.rcon_client_password = Cvar.Get("rcon_password", "", 0);
+ Globals.rcon_address = Cvar.Get("rcon_address", "", 0);
+
+ Globals.cl_lightlevel = Cvar.Get("r_lightlevel", "0", 0);
+
+ //
+ // userinfo
+ //
+ Globals.info_password = Cvar.Get("password", "", Defines.CVAR_USERINFO);
+ Globals.info_spectator = Cvar.Get("spectator", "0",
+ Defines.CVAR_USERINFO);
+ Globals.name = Cvar.Get("name", "unnamed", Defines.CVAR_USERINFO
+ | Defines.CVAR_ARCHIVE);
+ Globals.skin = Cvar.Get("skin", "male/grunt", Defines.CVAR_USERINFO
+ | Defines.CVAR_ARCHIVE);
+ Globals.rate = Cvar.Get("rate", "25000", Defines.CVAR_USERINFO
+ | Defines.CVAR_ARCHIVE); // FIXME
+ Globals.msg = Cvar.Get("msg", "1", Defines.CVAR_USERINFO
+ | Defines.CVAR_ARCHIVE);
+ Globals.hand = Cvar.Get("hand", "0", Defines.CVAR_USERINFO
+ | Defines.CVAR_ARCHIVE);
+ Globals.fov = Cvar.Get("fov", "90", Defines.CVAR_USERINFO
+ | Defines.CVAR_ARCHIVE);
+ Globals.gender = Cvar.Get("gender", "male", Defines.CVAR_USERINFO
+ | Defines.CVAR_ARCHIVE);
+ Globals.gender_auto = Cvar
+ .Get("gender_auto", "1", Defines.CVAR_ARCHIVE);
+ Globals.gender.modified = false; // clear this so we know when user sets
+ // it manually
+
+ Globals.cl_vwep = Cvar.Get("cl_vwep", "1", Defines.CVAR_ARCHIVE);
+
+ //
+ // register our commands
+ //
+ Cmd.AddCommand("cmd", ForwardToServer_f);
+ Cmd.AddCommand("pause", Pause_f);
+ Cmd.AddCommand("pingservers", PingServers_f);
+ Cmd.AddCommand("skins", Skins_f);
+
+ Cmd.AddCommand("userinfo", Userinfo_f);
+ Cmd.AddCommand("snd_restart", Snd_Restart_f);
+
+ Cmd.AddCommand("changing", Changing_f);
+ Cmd.AddCommand("disconnect", Disconnect_f);
+ Cmd.AddCommand("record", Record_f);
+ Cmd.AddCommand("stop", Stop_f);
+
+ Cmd.AddCommand("quit", Quit_f);
+
+ Cmd.AddCommand("connect", Connect_f);
+ Cmd.AddCommand("reconnect", Reconnect_f);
+
+ Cmd.AddCommand("rcon", Rcon_f);
+
+ Cmd.AddCommand("precache", Precache_f);
+
+ Cmd.AddCommand("download", CL_parse.Download_f);
+
+ //
+ // forward to server commands
+ //
+ // the only thing this does is allow command completion
+ // to work -- all unknown commands are automatically
+ // forwarded to the server
+ Cmd.AddCommand("wave", null);
+ Cmd.AddCommand("inven", null);
+ Cmd.AddCommand("kill", null);
+ Cmd.AddCommand("use", null);
+ Cmd.AddCommand("drop", null);
+ Cmd.AddCommand("say", null);
+ Cmd.AddCommand("say_team", null);
+ Cmd.AddCommand("info", null);
+ Cmd.AddCommand("prog", null);
+ Cmd.AddCommand("give", null);
+ Cmd.AddCommand("god", null);
+ Cmd.AddCommand("notarget", null);
+ Cmd.AddCommand("noclip", null);
+ Cmd.AddCommand("invuse", null);
+ Cmd.AddCommand("invprev", null);
+ Cmd.AddCommand("invnext", null);
+ Cmd.AddCommand("invdrop", null);
+ Cmd.AddCommand("weapnext", null);
+ Cmd.AddCommand("weapprev", null);
+
+ }
+
+ /*
+ * =============== CL_WriteConfiguration
+ *
+ * Writes key bindings and archived cvars to config.cfg ===============
+ */
+ static void WriteConfiguration() {
+ RandomAccessFile f;
+ String path;
+
+ if (Globals.cls.state == Defines.ca_uninitialized)
+ return;
+
+ path = FS.Gamedir() + "/config.cfg";
+ f = Lib.fopen(path, "rw");
+ if (f == null) {
+ Com.Printf("Couldn't write config.cfg.\n");
+ return;
+ }
+ try {
+ f.seek(0);
+ f.setLength(0);
+ } catch (IOException e1) {
+ }
+ try {
+ f.writeBytes("// generated by quake, do not modify\n");
+ } catch (IOException e) {
+ }
+
+ Key.WriteBindings(f);
+ Lib.fclose(f);
+ Cvar.WriteVariables(path);
+ }
+
+ public static void FixCvarCheats() {
+ int i;
+ CL.cheatvar_t var;
+
+ if ("1".equals(Globals.cl.configstrings[Defines.CS_MAXCLIENTS])
+ || 0 == Globals.cl.configstrings[Defines.CS_MAXCLIENTS]
+ .length())
+ return; // single player can cheat
+
+ // find all the cvars if we haven't done it yet
+ if (0 == CL.numcheatvars) {
+ while (CL.cheatvars[CL.numcheatvars].name != null) {
+ CL.cheatvars[CL.numcheatvars].var = Cvar.Get(
+ CL.cheatvars[CL.numcheatvars].name,
+ CL.cheatvars[CL.numcheatvars].value, 0);
+ CL.numcheatvars++;
+ }
+ }
+
+ // make sure they are all set to the proper values
+ for (i = 0; i < CL.numcheatvars; i++) {
+ var = CL.cheatvars[i];
+ if (!var.var.string.equals(var.value)) {
+ Cvar.Set(var.name, var.value);
+ }
+ }
+ }
+
+ // ============================================================================
+
+ /*
+ * ================== CL_SendCommand
+ *
+ * ==================
+ */
+ public static void SendCommand() {
+ // get new key events
+ Sys.SendKeyEvents();
+
+ // allow mice or other external controllers to add commands
+ IN.Commands();
+
+ // process console commands
+ Cbuf.Execute();
+
+ // fix any cheating cvars
+ FixCvarCheats();
+
+ // send intentions now
+ CL_input.SendCmd();
+
+ // resend a connection request if necessary
+ CheckForResend();
+ }
+
+ // private static int lasttimecalled;
+
+ public static void Frame(int msec) {
+
+ extratime += msec;
+
+ if (Globals.cl_timedemo.value == 0.0f) {
+ if (Globals.cls.state == Defines.ca_connected && extratime < 100) {
+ return; // don't flood packets out while connecting
+ }
+ if (extratime < 1000 / Globals.cl_maxfps.value) {
+ return; // framerate is too high
+ }
+ }
+
+ // let the mouse activate or deactivate
+ IN.Frame();
+
+ // decide the simulation time
+ Globals.cls.frametime = extratime / 1000.0f;
+ Globals.cl.time += extratime;
+ Globals.cls.realtime = Globals.curtime;
+
+ extratime = 0;
+
+ if (Globals.cls.frametime > (1.0f / 5))
+ Globals.cls.frametime = (1.0f / 5);
+
+ // if in the debugger last frame, don't timeout
+ if (msec > 5000)
+ Globals.cls.netchan.last_received = Sys.Milliseconds();
+
+ // fetch results from server
+ ReadPackets();
+
+ // send a new command message to the server
+ SendCommand();
+
+ // predict all unacknowledged movements
+ CL_pred.PredictMovement();
+
+ // allow rendering DLL change
+ VID.CheckChanges();
+ if (!Globals.cl.refresh_prepped
+ && Globals.cls.state == Defines.ca_active) {
+ CL_view.PrepRefresh();
+ // force GC after level loading
+ System.gc();
+ }
+
+ SCR.UpdateScreen();
+
+ // update audio
+ S.Update(Globals.cl.refdef.vieworg, Globals.cl.v_forward,
+ Globals.cl.v_right, Globals.cl.v_up);
+
+ // advance local effects for next frame
+ CL_fx.RunDLights();
+ CL_fx.RunLightStyles();
- /*
- ===============
- CL_Shutdown
+ SCR.RunConsole();
- FIXME: this is a callback from Sys_Quit and Com_Error. It would be better
- to run quit through here before the final handoff to the sys code.
- ===============
- */
- static boolean isdown = false;
- public static void Shutdown() {
+ Globals.cls.framecount++;
+ if (Globals.cls.state != Defines.ca_active
+ || Globals.cls.key_dest != Defines.key_game) {
+ try {
+ Thread.sleep(20);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
- if (isdown) {
- System.out.print("recursive shutdown\n");
- return;
- }
- isdown = true;
+ public static void Shutdown() {
- WriteConfiguration();
+ if (isdown) {
+ System.out.print("recursive shutdown\n");
+ return;
+ }
+ isdown = true;
- S.Shutdown();
- IN.Shutdown();
- VID.Shutdown();
- }
+ WriteConfiguration();
- /**
- * initialize client subsystem
- */
- public static void Init() {
- if (Globals.dedicated.value != 0.0f)
- return; // nothing running on the client
+ S.Shutdown();
+ IN.Shutdown();
+ VID.Shutdown();
+ }
- // all archived variables will now be loaded
+ /**
+ * initialize client subsystem
+ */
+ public static void Init() {
+ if (Globals.dedicated.value != 0.0f)
+ return; // nothing running on the client
- Console.Init(); //ok
+ // all archived variables will now be loaded
- S.Init(); //empty
- VID.Init();
+ Console.Init(); //ok
- V.Init();
+ S.Init(); //empty
+ VID.Init();
- Globals.net_message.data = Globals.net_message_buffer;
- Globals.net_message.maxsize = Globals.net_message_buffer.length;
+ V.Init();
- Menu.Init();
+ Globals.net_message.data = Globals.net_message_buffer;
+ Globals.net_message.maxsize = Globals.net_message_buffer.length;
- SCR.Init();
- //Globals.cls.disable_screen = 1.0f; // don't draw yet
+ Menu.Init();
- CL.InitLocal();
- IN.Init();
+ SCR.Init();
+ //Globals.cls.disable_screen = 1.0f; // don't draw yet
- FS.ExecAutoexec();
- Cbuf.Execute();
- }
+ InitLocal();
+ IN.Init();
- /**
- * Called after an ERR_DROP was thrown.
- */
- public static void Drop() {
- if (Globals.cls.state == Defines.ca_uninitialized)
- return;
- if (Globals.cls.state == Defines.ca_disconnected)
- return;
+ FS.ExecAutoexec();
+ Cbuf.Execute();
+ }
- CL.Disconnect();
+ /**
+ * Called after an ERR_DROP was thrown.
+ */
+ public static void Drop() {
+ if (Globals.cls.state == Defines.ca_uninitialized)
+ return;
+ if (Globals.cls.state == Defines.ca_disconnected)
+ return;
- // drop loading plaque unless this is the initial game start
- if (Globals.cls.disable_servercount != -1)
- SCR.EndLoadingPlaque(); // get rid of loading plaque
- }
+ Disconnect();
-}
+ // drop loading plaque unless this is the initial game start
+ if (Globals.cls.disable_servercount != -1)
+ SCR.EndLoadingPlaque(); // get rid of loading plaque
+ }
+} \ No newline at end of file