aboutsummaryrefslogtreecommitdiffstats
path: root/src/jake2/client/CL_input.java
diff options
context:
space:
mode:
authorHolger Zickner <[email protected]>2004-07-07 19:59:59 +0000
committerHolger Zickner <[email protected]>2004-07-07 19:59:59 +0000
commit6e23fc1074d1f0c2c2812f4c2e663f5a21a43c20 (patch)
tree46ecc6d0255c874ba4cd26dc3d0733f785019896 /src/jake2/client/CL_input.java
import of Jake2 version sunrisesunrise
Diffstat (limited to 'src/jake2/client/CL_input.java')
-rw-r--r--src/jake2/client/CL_input.java564
1 files changed, 564 insertions, 0 deletions
diff --git a/src/jake2/client/CL_input.java b/src/jake2/client/CL_input.java
new file mode 100644
index 0000000..1b6233c
--- /dev/null
+++ b/src/jake2/client/CL_input.java
@@ -0,0 +1,564 @@
+/*
+ * CL_input.java
+ * Copyright (C) 2004
+ *
+ * $Id: CL_input.java,v 1.1 2004-07-07 19:58:37 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 jake2.game.*;
+import jake2.game.Cmd;
+import jake2.game.usercmd_t;
+import jake2.qcommon.*;
+import jake2.qcommon.Cvar;
+import jake2.qcommon.xcommand_t;
+import jake2.sys.IN;
+
+/**
+ * CL_input
+ */
+public class CL_input extends CL_ents {
+
+ static long frame_msec;
+ static long old_sys_frame_time;
+
+ static cvar_t cl_nodelta;
+
+ /*
+ ===============================================================================
+
+ KEY BUTTONS
+
+ Continuous button event tracking is complicated by the fact that two different
+ input sources (say, mouse button 1 and the control key) can both press the
+ same button, but the button should only be released when both of the
+ pressing key have been released.
+
+ When a key event issues a button command (+forward, +attack, etc), it appends
+ its key number as a parameter to the command so it can be matched up with
+ the release.
+
+ state bit 0 is the current state of the key
+ state bit 1 is edge triggered on the up to down transition
+ state bit 2 is edge triggered on the down to up transition
+
+
+ Key_Event (int key, qboolean down, unsigned time);
+
+ +mlook src time
+
+ ===============================================================================
+ */
+
+ static kbutton_t in_klook = new kbutton_t();
+ static kbutton_t in_left = new kbutton_t();
+ static kbutton_t in_right = new kbutton_t();
+ static kbutton_t in_forward = new kbutton_t();
+ static kbutton_t in_back = new kbutton_t();
+ static kbutton_t in_lookup = new kbutton_t();
+ static kbutton_t in_lookdown = new kbutton_t();
+ static kbutton_t in_moveleft = new kbutton_t();
+ static kbutton_t in_moveright = new kbutton_t();
+ public static kbutton_t in_strafe = new kbutton_t();
+ static kbutton_t in_speed = new kbutton_t();
+ static kbutton_t in_use = new kbutton_t();
+ static kbutton_t in_attack = new kbutton_t();
+ static kbutton_t in_up = new kbutton_t();
+ static kbutton_t in_down = new kbutton_t();
+
+ static int in_impulse;
+
+ static void KeyDown(kbutton_t b) {
+ int k;
+ String c;
+
+ c = Cmd.Argv(1);
+ if (c.length() > 0)
+ k = Integer.parseInt(c);
+ else
+ k = -1; // typed manually at the console for continuous down
+
+ if (k == b.down[0] || k == b.down[1])
+ return; // repeating key
+
+ if (b.down[0] == 0)
+ b.down[0] = k;
+ else if (b.down[1] == 0)
+ b.down[1] = k;
+ else {
+ Com.Printf("Three keys down for a button!\n");
+ return;
+ }
+
+ if ((b.state & 1) != 0)
+ return; // still down
+
+ // save timestamp
+ c = Cmd.Argv(2);
+ b.downtime = Long.parseLong(c);
+ if (b.downtime == 0)
+ b.downtime = sys_frame_time - 100;
+
+ b.state |= 3; // down + impulse down
+ }
+
+ static void KeyUp(kbutton_t b) {
+ int k;
+ String c;
+ long uptime;
+
+ c = Cmd.Argv(1);
+ if (c.length() > 0)
+ k = Integer.parseInt(c);
+ else {
+ // typed manually at the console, assume for unsticking, so clear all
+ b.down[0] = b.down[1] = 0;
+ b.state = 4; // impulse up
+ return;
+ }
+
+ if (b.down[0] == k)
+ b.down[0] = 0;
+ else if (b.down[1] == k)
+ b.down[1] = 0;
+ else
+ return; // key up without coresponding down (menu pass through)
+ if (b.down[0] != 0 || b.down[1] != 0)
+ return; // some other key is still holding it down
+
+ if ((b.state & 1) == 0)
+ return; // still up (this should not happen)
+
+ // save timestamp
+ c = Cmd.Argv(2);
+ uptime = Long.parseLong(c);
+ if (uptime != 0)
+ b.msec += uptime - b.downtime;
+ else
+ b.msec += 10;
+
+ b.state &= ~1; // now up
+ b.state |= 4; // impulse up
+ }
+
+ static void IN_KLookDown() {KeyDown(in_klook);}
+ static void IN_KLookUp() {KeyUp(in_klook);}
+ static void IN_UpDown() {KeyDown(in_up);}
+ static void IN_UpUp() {KeyUp(in_up);}
+ static void IN_DownDown() {KeyDown(in_down);}
+ static void IN_DownUp() {KeyUp(in_down);}
+ static void IN_LeftDown() {KeyDown(in_left);}
+ static void IN_LeftUp() {KeyUp(in_left);}
+ static void IN_RightDown() {KeyDown(in_right);}
+ static void IN_RightUp() {KeyUp(in_right);}
+ static void IN_ForwardDown() {KeyDown(in_forward);}
+ static void IN_ForwardUp() {KeyUp(in_forward);}
+ static void IN_BackDown() {KeyDown(in_back);}
+ static void IN_BackUp() {KeyUp(in_back);}
+ static void IN_LookupDown() {KeyDown(in_lookup);}
+ static void IN_LookupUp() {KeyUp(in_lookup);}
+ static void IN_LookdownDown() {KeyDown(in_lookdown);}
+ static void IN_LookdownUp() {KeyUp(in_lookdown);}
+ static void IN_MoveleftDown() {KeyDown(in_moveleft);}
+ static void IN_MoveleftUp() {KeyUp(in_moveleft);}
+ static void IN_MoverightDown() {KeyDown(in_moveright);}
+ static void IN_MoverightUp() {KeyUp(in_moveright);}
+
+ static void IN_SpeedDown() {KeyDown(in_speed);}
+ static void IN_SpeedUp() {KeyUp(in_speed);}
+ static void IN_StrafeDown() {KeyDown(in_strafe);}
+ static void IN_StrafeUp() {KeyUp(in_strafe);}
+
+ static void IN_AttackDown() {KeyDown(in_attack);}
+ static void IN_AttackUp() {KeyUp(in_attack);}
+
+ static void IN_UseDown () {KeyDown(in_use);}
+ static void IN_UseUp () {KeyUp(in_use);}
+
+ static void IN_Impulse () {in_impulse=Integer.parseInt(Cmd.Argv(1));}
+
+ /*
+ ===============
+ CL_KeyState
+
+ Returns the fraction of the frame that the key was down
+ ===============
+ */
+ static float KeyState(kbutton_t key) {
+ float val;
+ long msec;
+
+ key.state &= 1; // clear impulses
+
+ msec = key.msec;
+ key.msec = 0;
+
+ if (key.state != 0) {
+ // still down
+ msec += sys_frame_time - key.downtime;
+ key.downtime = sys_frame_time;
+ }
+
+ val = (float)msec / frame_msec;
+ if (val < 0)
+ val = 0;
+ if (val > 1)
+ val = 1;
+
+ return val;
+ }
+
+// ==========================================================================
+
+ /*
+ ================
+ CL_AdjustAngles
+
+ Moves the local angle positions
+ ================
+ */
+ static void AdjustAngles() {
+ float speed;
+ float up, down;
+
+ if ((in_speed.state & 1) != 0)
+ speed = cls.frametime * cl_anglespeedkey.value;
+ else
+ speed = cls.frametime;
+
+ if ((in_strafe.state & 1) == 0) {
+ cl.viewangles[YAW] -= speed * cl_yawspeed.value * CL.KeyState(in_right);
+ cl.viewangles[YAW] += speed * cl_yawspeed.value * CL.KeyState(in_left);
+ }
+ if ((in_klook.state & 1) != 0) {
+ cl.viewangles[PITCH] -= speed * cl_pitchspeed.value * CL.KeyState(in_forward);
+ cl.viewangles[PITCH] += speed * cl_pitchspeed.value * CL.KeyState(in_back);
+ }
+
+ up = CL.KeyState(in_lookup);
+ down = CL.KeyState(in_lookdown);
+
+ cl.viewangles[PITCH] -= speed * cl_pitchspeed.value * up;
+ cl.viewangles[PITCH] += speed * cl_pitchspeed.value * down;
+ }
+
+ /*
+ ================
+ CL_BaseMove
+
+ Send the intended movement message to the server
+ ================
+ */
+ static void BaseMove(usercmd_t cmd) {
+ CL.AdjustAngles();
+
+ //memset (cmd, 0, sizeof(*cmd));
+ cmd.reset();
+
+ VectorCopy(cl.viewangles, cmd.angles);
+ if ((in_strafe.state & 1) != 0) {
+ cmd.sidemove += cl_sidespeed.value * CL.KeyState(in_right);
+ cmd.sidemove -= cl_sidespeed.value * CL.KeyState(in_left);
+ }
+
+ cmd.sidemove += cl_sidespeed.value * CL.KeyState(in_moveright);
+ cmd.sidemove -= cl_sidespeed.value * CL.KeyState(in_moveleft);
+
+ cmd.upmove += cl_upspeed.value * CL.KeyState(in_up);
+ cmd.upmove -= cl_upspeed.value * CL.KeyState(in_down);
+
+ if ((in_klook.state & 1) == 0) {
+ cmd.forwardmove += cl_forwardspeed.value * CL.KeyState(in_forward);
+ cmd.forwardmove -= cl_forwardspeed.value * CL.KeyState(in_back);
+ }
+
+ //
+ // adjust for speed key / running
+ //
+ if (((in_speed.state & 1) ^ (int) (cl_run.value)) != 0) {
+ cmd.forwardmove *= 2;
+ cmd.sidemove *= 2;
+ cmd.upmove *= 2;
+ }
+
+ }
+
+ static void ClampPitch() {
+
+ float pitch;
+
+ pitch = SHORT2ANGLE(cl.frame.playerstate.pmove.delta_angles[PITCH]);
+ if (pitch > 180)
+ pitch -= 360;
+
+ if (cl.viewangles[PITCH] + pitch < -360)
+ cl.viewangles[PITCH] += 360; // wrapped
+ if (cl.viewangles[PITCH] + pitch > 360)
+ cl.viewangles[PITCH] -= 360; // wrapped
+
+ if (cl.viewangles[PITCH] + pitch > 89)
+ cl.viewangles[PITCH] = 89 - pitch;
+ if (cl.viewangles[PITCH] + pitch < -89)
+ cl.viewangles[PITCH] = -89 - pitch;
+ }
+
+ /*
+ ==============
+ CL_FinishMove
+ ==============
+ */
+ static void FinishMove(usercmd_t cmd) {
+ int ms;
+ int i;
+
+ //
+ // figure button bits
+ //
+ if ((in_attack.state & 3) != 0)
+ cmd.buttons |= BUTTON_ATTACK;
+ in_attack.state &= ~2;
+
+ if ((in_use.state & 3) != 0)
+ cmd.buttons |= BUTTON_USE;
+ in_use.state &= ~2;
+
+ if (anykeydown != 0 && cls.key_dest == key_game)
+ cmd.buttons |= BUTTON_ANY;
+
+ // send milliseconds of time to apply the move
+ ms = (int)(cls.frametime * 1000);
+ if (ms > 250)
+ ms = 100; // time was unreasonable
+ cmd.msec = (byte)ms;
+
+ CL.ClampPitch();
+ for (i = 0; i < 3; i++)
+ cmd.angles[i] = (short)ANGLE2SHORT(cl.viewangles[i]);
+
+ cmd.impulse = (byte)in_impulse;
+ in_impulse = 0;
+
+ // send the ambient light level at the player's current position
+ cmd.lightlevel = (byte)cl_lightlevel.value;
+ }
+
+ /*
+ =================
+ CL_CreateCmd
+ =================
+ */
+ static usercmd_t CreateCmd() {
+ usercmd_t cmd = new usercmd_t();
+
+ frame_msec = sys_frame_time - old_sys_frame_time;
+ if (frame_msec < 1)
+ frame_msec = 1;
+ if (frame_msec > 200)
+ frame_msec = 200;
+
+ // get basic movement from keyboard
+ CL.BaseMove(cmd);
+
+ // allow mice or other external controllers to add to the move
+ IN.Move(cmd);
+
+ CL.FinishMove(cmd);
+
+ old_sys_frame_time = sys_frame_time;
+
+ return cmd;
+ }
+
+ /*
+ ============
+ CL_InitInput
+ ============
+ */
+ static void InitInput() {
+ Cmd.AddCommand("centerview", new xcommand_t() {
+ public void execute() {IN.CenterView();}});
+
+ Cmd.AddCommand("+moveup", new xcommand_t() {
+ public void execute() {IN_UpDown();}});
+ Cmd.AddCommand("-moveup", new xcommand_t() {
+ public void execute() {IN_UpUp();}});
+ Cmd.AddCommand("+movedown", new xcommand_t() {
+ public void execute() {IN_DownDown();}});
+ Cmd.AddCommand("-movedown", new xcommand_t() {
+ public void execute() {IN_DownUp();}});
+ Cmd.AddCommand("+left", new xcommand_t() {
+ public void execute() {IN_LeftDown();}});
+ Cmd.AddCommand("-left", new xcommand_t() {
+ public void execute() {IN_LeftUp();}});
+ Cmd.AddCommand("+right", new xcommand_t() {
+ public void execute() {IN_RightDown();}});
+ Cmd.AddCommand("-right", new xcommand_t() {
+ public void execute() {IN_RightUp();}});
+ Cmd.AddCommand("+forward", new xcommand_t() {
+ public void execute() {IN_ForwardDown();}});
+ Cmd.AddCommand("-forward", new xcommand_t() {
+ public void execute() {IN_ForwardUp();}});
+ Cmd.AddCommand("+back", new xcommand_t() {
+ public void execute() {IN_BackDown();}});
+ Cmd.AddCommand("-back", new xcommand_t() {
+ public void execute() {IN_BackUp();}});
+ Cmd.AddCommand("+lookup", new xcommand_t() {
+ public void execute() {IN_LookupDown();}});
+ Cmd.AddCommand("-lookup", new xcommand_t() {
+ public void execute() {IN_LookupUp();}});
+ Cmd.AddCommand("+lookdown", new xcommand_t() {
+ public void execute() {IN_LookdownDown();}});
+ Cmd.AddCommand("-lookdown", new xcommand_t() {
+ public void execute() {IN_LookdownUp();}});
+ Cmd.AddCommand("+strafe", new xcommand_t() {
+ public void execute() {IN_StrafeDown();}});
+ Cmd.AddCommand("-strafe", new xcommand_t() {
+ public void execute() {IN_StrafeUp();}});
+ Cmd.AddCommand("+moveleft", new xcommand_t() {
+ public void execute() {IN_MoveleftDown();}});
+ Cmd.AddCommand("-moveleft", new xcommand_t() {
+ public void execute() {IN_MoveleftUp();}});
+ Cmd.AddCommand("+moveright", new xcommand_t() {
+ public void execute() {IN_MoverightDown();}});
+ Cmd.AddCommand("-moveright", new xcommand_t() {
+ public void execute() {IN_MoverightUp();}});
+ Cmd.AddCommand("+speed", new xcommand_t() {
+ public void execute() {IN_SpeedDown();}});
+ Cmd.AddCommand("-speed", new xcommand_t() {
+ public void execute() {IN_SpeedUp();}});
+ Cmd.AddCommand("+attack", new xcommand_t() {
+ public void execute() {IN_AttackDown();}});
+ Cmd.AddCommand("-attack", new xcommand_t() {
+ public void execute() {IN_AttackUp();}});
+ Cmd.AddCommand("+use", new xcommand_t() {
+ public void execute() {IN_UseDown();}});
+ Cmd.AddCommand("-use", new xcommand_t() {
+ public void execute() {IN_UseUp();}});
+ Cmd.AddCommand("impulse", new xcommand_t() {
+ public void execute() {IN_Impulse();}});
+ Cmd.AddCommand("+klook", new xcommand_t() {
+ public void execute() {IN_KLookDown();}});
+ Cmd.AddCommand("-klook", new xcommand_t() {
+ public void execute() {IN_KLookUp();}});
+
+ // TODO nodelta
+ cl_nodelta = Cvar.Get("cl_nodelta", "1",0);
+ }
+
+ /*
+ =================
+ CL_SendCmd
+ =================
+ */
+ static void SendCmd() {
+ sizebuf_t buf = new sizebuf_t();
+ byte[] data = new byte[128];
+ int i;
+ usercmd_t cmd, oldcmd;
+ usercmd_t nullcmd = new usercmd_t();
+ int checksumIndex;
+
+ // build a command even if not connected
+
+ // save this command off for prediction
+ i = cls.netchan.outgoing_sequence & (CMD_BACKUP - 1);
+ cmd = cl.cmds[i];
+ cl.cmd_time[i] = (int)cls.realtime; // for netgraph ping calculation
+
+ cmd.set(CL.CreateCmd());
+
+ cl.cmd.set(cmd);
+
+ if (cls.state == ca_disconnected || cls.state == ca_connecting)
+ return;
+
+ if (cls.state == ca_connected) {
+ if (cls.netchan.message.cursize != 0 || curtime - cls.netchan.last_sent > 1000)
+ Netchan.Transmit(cls.netchan, 0, new byte[0]);
+ return;
+ }
+
+ // send a userinfo update if needed
+ if (userinfo_modified) {
+ CL.FixUpGender();
+ userinfo_modified = false;
+ MSG.WriteByte(cls.netchan.message, clc_userinfo);
+ MSG.WriteString(cls.netchan.message, Cvar.Userinfo());
+ }
+
+ SZ.Init(buf, data, data.length);
+
+ if (cmd.buttons != 0
+ && cl.cinematictime > 0
+ && !cl.attractloop
+ && cls.realtime - cl.cinematictime > 1000) { // skip the rest of the cinematic
+ SCR.FinishCinematic();
+ }
+
+ // begin a client move command
+ MSG.WriteByte(buf, clc_move);
+
+ // save the position for a checksum byte
+ checksumIndex = buf.cursize;
+ MSG.WriteByte(buf, 0);
+
+ // let the server know what the last frame we
+ // got was, so the next message can be delta compressed
+ if (cl_nodelta.value != 0.0f || !cl.frame.valid || cls.demowaiting)
+ MSG.WriteLong(buf, -1); // no compression
+ else
+ MSG.WriteLong(buf, cl.frame.serverframe);
+
+ // send this and the previous cmds in the message, so
+ // if the last packet was dropped, it can be recovered
+ i = (cls.netchan.outgoing_sequence - 2) & (CMD_BACKUP - 1);
+ cmd = cl.cmds[i];
+ //memset (nullcmd, 0, sizeof(nullcmd));
+ nullcmd.reset();
+
+ MSG.WriteDeltaUsercmd(buf, nullcmd, cmd);
+ oldcmd = cmd;
+
+ i = (cls.netchan.outgoing_sequence - 1) & (CMD_BACKUP - 1);
+ cmd = cl.cmds[i];
+
+ MSG.WriteDeltaUsercmd(buf, oldcmd, cmd);
+ oldcmd = cmd;
+
+ i = (cls.netchan.outgoing_sequence) & (CMD_BACKUP - 1);
+ cmd = cl.cmds[i];
+
+ MSG.WriteDeltaUsercmd(buf, oldcmd, cmd);
+
+ // calculate a checksum over the move commands
+ buf.data[checksumIndex] = 0;
+ /*COM_BlockSequenceCRCByte(
+ buf.data + checksumIndex + 1, buf.cursize - checksumIndex - 1,
+ cls.netchan.outgoing_sequence);*/
+
+ //
+ // deliver the message
+ //
+ Netchan.Transmit(cls.netchan, buf.cursize, buf.data);
+ }
+
+}