/* * ================== * SV_RunClients * ================== */ public static void SV_RunClients() { int i; for (i = 0; i < svs.maxclients; i++) { host.host_client = svs.clients[i]; if (!host.host_client.active) { continue; } sv_player = host.host_client.edict; if (!SV_ReadClientMessage()) { continue; } if (!host.host_client.spawned) { continue; } // always pause in single player if in console or menus if (!sv.paused && (svs.maxclients > 1 || keys.key_dest == keys.keydest_t.key_game)) { SV_ClientThink(); } } }
/* ================== SV_RunClients ================== */ public static void SV_RunClients() { int i; for (i=0 ; i<svs.maxclients ; i++) { host.host_client = svs.clients[i]; if (!host.host_client.active) continue; sv_player = host.host_client.edict; if (!SV_ReadClientMessage ()) { continue; } if (!host.host_client.spawned) { continue; } // always pause in single player if in console or menus if (!sv.paused && (svs.maxclients > 1 || keys.key_dest == keys.keydest_t.key_game) ) SV_ClientThink (); } }
/* ============ SV_PushMove ============ */ static void SV_PushMove(prog.edict_t pusher, Double movetime) { int i, e; prog.edict_t check, block; double[] mins = new double[3] {0, 0, 0}, maxs = new double[3] {0, 0, 0}, move = new double[3] {0, 0, 0}; double[] entorig = new double[3] {0, 0, 0}, pushorig = new double[3] {0, 0, 0}; int num_moved; prog.edict_t[] moved_edict = new prog.edict_t[quakedef.MAX_EDICTS]; double[][] moved_from = new double[quakedef.MAX_EDICTS][]; if (pusher.v.velocity[0]==0 && pusher.v.velocity[1]==0 && pusher.v.velocity[2]==0) { pusher.v.ltime += movetime; return; } for (i=0 ; i<3 ; i++) { move[i] = pusher.v.velocity[i] * movetime; mins[i] = pusher.v.absmin[i] + move[i]; maxs[i] = pusher.v.absmax[i] + move[i]; } mathlib.VectorCopy (pusher.v.origin, pushorig); // move the pusher to it's final position mathlib.VectorAdd (pusher.v.origin, move, pusher.v.origin); pusher.v.ltime += movetime; world.SV_LinkEdict (pusher, false); // see if any solid entities are inside the final position num_moved = 0; check = prog.NEXT_EDICT(sv.edicts[0]); for (e=1 ; e<sv.num_edicts ; e++, check = prog.NEXT_EDICT(check)) { if (check.free) continue; //Debug.WriteLine(string.Format("e: {0} movetype:{1}", e, (int)check.v.movetype)); if (check.v.movetype == MOVETYPE_PUSH || check.v.movetype == MOVETYPE_NONE || check.v.movetype == MOVETYPE_NOCLIP) continue; // if the entity is standing on the pusher, it will definately be moved if ( ! ( ((int)check.v.flags & FL_ONGROUND) != 0 && prog.PROG_TO_EDICT(check.v.groundentity) == pusher) ) { if ( check.v.absmin[0] >= maxs[0] || check.v.absmin[1] >= maxs[1] || check.v.absmin[2] >= maxs[2] || check.v.absmax[0] <= mins[0] || check.v.absmax[1] <= mins[1] || check.v.absmax[2] <= mins[2] ) continue; // see if the ent's bbox is inside the pusher's final position if (world.SV_TestEntityPosition (check) != null) continue; } // remove the onground flag for non-players if (check.v.movetype != MOVETYPE_WALK) check.v.flags = (int)check.v.flags & ~FL_ONGROUND; for (int j = 0; j < moved_from.Length; j++) { moved_from[j] = new double[3] {0, 0, 0}; } mathlib.VectorCopy (check.v.origin, entorig); mathlib.VectorCopy (check.v.origin, moved_from[num_moved]); moved_edict[num_moved] = check; num_moved++; // try moving the contacted entity pusher.v.solid = SOLID_NOT; SV_PushEntity (check, move); pusher.v.solid = SOLID_BSP; // if it is still inside the pusher, block block = world.SV_TestEntityPosition (check); if (block != null) { // fail the move if (check.v.mins[0] == check.v.maxs[0]) continue; if (check.v.solid == SOLID_NOT || check.v.solid == SOLID_TRIGGER) { // corpse check.v.mins[0] = check.v.mins[1] = 0; mathlib.VectorCopy (check.v.mins, check.v.maxs); continue; } mathlib.VectorCopy (entorig, check.v.origin); world.SV_LinkEdict (check, true); mathlib.VectorCopy (pushorig, pusher.v.origin); world.SV_LinkEdict (pusher, false); pusher.v.ltime -= movetime; // if the pusher has a "blocked" function, call it // otherwise, just stay in place until the obstacle is gone if (pusher.v.blocked != null) { prog.pr_global_struct[0].self = prog.EDICT_TO_PROG(pusher); prog.pr_global_struct[0].other = prog.EDICT_TO_PROG(check); prog.PR_ExecuteProgram (prog.pr_functions[pusher.v.blocked]); } // move back any entities we already moved for (i=0 ; i<num_moved ; i++) { mathlib.VectorCopy (moved_from[i], moved_edict[i].v.origin); world.SV_LinkEdict (moved_edict[i], false); } return; } } }
/* * ================== * SV_WriteClientdataToMessage * * ================== */ public static void SV_WriteClientdataToMessage(prog.edict_t ent, common.sizebuf_t msg) { int bits; int i; prog.edict_t other; int items; // // send a damage message // if (ent.v.dmg_take != 0 || ent.v.dmg_save != 0) { other = prog.PROG_TO_EDICT(ent.v.dmg_inflictor); common.MSG_WriteByte(msg, net.svc_damage); common.MSG_WriteByte(msg, (int)ent.v.dmg_save); common.MSG_WriteByte(msg, (int)ent.v.dmg_take); for (i = 0; i < 3; i++) { common.MSG_WriteCoord(msg, other.v.origin[i] + 0.5 * (other.v.mins[i] + other.v.maxs[i])); } ent.v.dmg_take = 0; ent.v.dmg_save = 0; } // // send the current viewpos offset from the view entity // SV_SetIdealPitch(); // how much to look up / down ideally // a fixangle might get lost in a dropped packet. Oh well. if (ent.v.fixangle != 0) { common.MSG_WriteByte(msg, net.svc_setangle); for (i = 0; i < 3; i++) { common.MSG_WriteAngle(msg, ent.v.angles[i]); } ent.v.fixangle = 0; } bits = 0; if (ent.v.view_ofs[2] != net.DEFAULT_VIEWHEIGHT) { bits |= net.SU_VIEWHEIGHT; } if (ent.v.idealpitch != 0) { bits |= net.SU_IDEALPITCH; } // stuff the sigil bits into the high bits of items for sbar, or else // mix in items2 //val = GetEdictFieldValue(ent, "items2"); /*if (val) * items = (int)ent->v.items | ((int)val->_float << 23); * else*/ items = (int)ent.v.items | ((int)prog.pr_global_struct[0].serverflags << 28); bits |= net.SU_ITEMS; if (((int)ent.v.flags & FL_ONGROUND) != 0) { bits |= net.SU_ONGROUND; } if (ent.v.waterlevel >= 2) { bits |= net.SU_INWATER; } for (i = 0; i < 3; i++) { if (ent.v.punchangle[i] != 0) { bits |= (net.SU_PUNCH1 << i); } if (ent.v.velocity[i] != 0) { bits |= (net.SU_VELOCITY1 << i); } } if (ent.v.weaponframe != 0) { bits |= net.SU_WEAPONFRAME; } if (ent.v.armorvalue != 0) { bits |= net.SU_ARMOR; } // if (ent.v.weapon != 0) bits |= net.SU_WEAPON; // send the data common.MSG_WriteByte(msg, net.svc_clientdata); common.MSG_WriteShort(msg, bits); if ((bits & net.SU_VIEWHEIGHT) != 0) { common.MSG_WriteChar(msg, (int)ent.v.view_ofs[2]); } if ((bits & net.SU_IDEALPITCH) != 0) { common.MSG_WriteChar(msg, (int)ent.v.idealpitch); } for (i = 0; i < 3; i++) { if ((bits & (net.SU_PUNCH1 << i)) != 0) { common.MSG_WriteChar(msg, (int)ent.v.punchangle[i]); } if ((bits & (net.SU_VELOCITY1 << i)) != 0) { common.MSG_WriteChar(msg, (int)ent.v.velocity[i] / 16); } } // [always sent] if (bits & SU_ITEMS) common.MSG_WriteLong(msg, items); if ((bits & net.SU_WEAPONFRAME) != 0) { common.MSG_WriteByte(msg, (int)ent.v.weaponframe); } if ((bits & net.SU_ARMOR) != 0) { common.MSG_WriteByte(msg, (int)ent.v.armorvalue); } if ((bits & net.SU_WEAPON) != 0) { common.MSG_WriteByte(msg, SV_ModelIndex(prog.pr_string(ent.v.weaponmodel))); } common.MSG_WriteShort(msg, (int)ent.v.health); common.MSG_WriteByte(msg, (int)ent.v.currentammo); common.MSG_WriteByte(msg, (int)ent.v.ammo_shells); common.MSG_WriteByte(msg, (int)ent.v.ammo_nails); common.MSG_WriteByte(msg, (int)ent.v.ammo_rockets); common.MSG_WriteByte(msg, (int)ent.v.ammo_cells); if (common.standard_quake) { common.MSG_WriteByte(msg, (int)ent.v.weapon); } else { for (i = 0; i < 32; i++) { if ((((int)ent.v.weapon) & (1 << i)) != 0) { common.MSG_WriteByte(msg, i); break; } } } }
/* * ============= * SV_WriteEntitiesToClient * * ============= */ static void SV_WriteEntitiesToClient(prog.edict_t clent, common.sizebuf_t msg) { int e, i; int bits; double[] org = new double[3]; double miss; prog.edict_t ent; // send over all entities (excpet the client) that touch the pvs for (e = 1; e < sv.num_edicts; e++) { ent = sv.edicts[e]; // ignore if not touching a PV leaf if (ent != clent) // clent is ALLWAYS sent { // ignore ents without visible models if (ent.v.modelindex == 0 || prog.pr_string(ent.v.model) == null) { continue; } } if (msg.maxsize - msg.cursize < 16) { console.Con_Printf("packet overflow\n"); return; } // send an update bits = 0; for (i = 0; i < 3; i++) { miss = ent.v.origin[i] - ent.baseline.origin[i]; if (miss < -0.1 || miss > 0.1) { bits |= net.U_ORIGIN1 << i; } } if (ent.v.angles[0] != ent.baseline.angles[0]) { bits |= net.U_ANGLE1; } if (ent.v.angles[1] != ent.baseline.angles[1]) { bits |= net.U_ANGLE2; } if (ent.v.angles[2] != ent.baseline.angles[2]) { bits |= net.U_ANGLE3; } if (ent.v.movetype == MOVETYPE_STEP) { bits |= net.U_NOLERP; // don't mess up the step animation } if (ent.baseline.colormap != ent.v.colormap) { bits |= net.U_COLORMAP; } if (ent.baseline.skin != ent.v.skin) { bits |= net.U_SKIN; } if (ent.baseline.frame != ent.v.frame) { bits |= net.U_FRAME; } if (ent.baseline.effects != ent.v.effects) { bits |= net.U_EFFECTS; } if (ent.baseline.modelindex != ent.v.modelindex) { bits |= net.U_MODEL; } if (e >= 256) { bits |= net.U_LONGENTITY; } if (bits >= 256) { bits |= net.U_MOREBITS; } // // write the message // common.MSG_WriteByte(msg, bits | net.U_SIGNAL); if ((bits & net.U_MOREBITS) != 0) { common.MSG_WriteByte(msg, bits >> 8); } if ((bits & net.U_LONGENTITY) != 0) { common.MSG_WriteShort(msg, e); } else { common.MSG_WriteByte(msg, e); } if ((bits & net.U_MODEL) != 0) { common.MSG_WriteByte(msg, (int)ent.v.modelindex); } if ((bits & net.U_FRAME) != 0) { common.MSG_WriteByte(msg, (int)ent.v.frame); } if ((bits & net.U_COLORMAP) != 0) { common.MSG_WriteByte(msg, (int)ent.v.colormap); } if ((bits & net.U_SKIN) != 0) { common.MSG_WriteByte(msg, (int)ent.v.skin); } if ((bits & net.U_EFFECTS) != 0) { common.MSG_WriteByte(msg, (int)ent.v.effects); } if ((bits & net.U_ORIGIN1) != 0) { common.MSG_WriteCoord(msg, ent.v.origin[0]); } if ((bits & net.U_ANGLE1) != 0) { common.MSG_WriteAngle(msg, ent.v.angles[0]); } if ((bits & net.U_ORIGIN2) != 0) { common.MSG_WriteCoord(msg, ent.v.origin[1]); } if ((bits & net.U_ANGLE2) != 0) { common.MSG_WriteAngle(msg, ent.v.angles[1]); } if ((bits & net.U_ORIGIN3) != 0) { common.MSG_WriteCoord(msg, ent.v.origin[2]); } if ((bits & net.U_ANGLE3) != 0) { common.MSG_WriteAngle(msg, ent.v.angles[2]); } } }