using System;
using OpenTK;

namespace SharpQuake
{
	internal static class server
	{
		public static server_t sv
		{
			get
			{
				return server._Server;
			}
		}

		public static server_static_t svs
		{
			get
			{
				return server._ServerStatic;
			}
		}

		public static bool IsActive
		{
			get
			{
				return server._Server.active;
			}
		}

		public static float Gravity
		{
			get
			{
				return server._Gravity.Value;
			}
		}

		public static bool IsLoading
		{
			get
			{
				return server._Server.state == server_state_t.Loading;
			}
		}

		public static float Aim
		{
			get
			{
				return server._Aim.Value;
			}
		}

		public static edict_t EdictNum(int n)
		{
			if (n < 0 || n >= server._Server.max_edicts)
			{
				sys.Error("EDICT_NUM: bad number {0}", new object[]
				{
					n
				});
			}
			return server._Server.edicts[n];
		}

		public static edict_t AllocEdict()
		{
			int i;
			edict_t edict_t;
			for (i = server.svs.maxclients + 1; i < server.sv.num_edicts; i++)
			{
				edict_t = server.EdictNum(i);
				if (edict_t.free && (edict_t.freetime < 2f || server.sv.time - (double)edict_t.freetime > 0.5))
				{
					edict_t.Clear();
					return edict_t;
				}
			}
			if (i == 600)
			{
				sys.Error("ED_Alloc: no free edicts", Array.Empty<object>());
			}
			server.sv.num_edicts++;
			edict_t = server.EdictNum(i);
			edict_t.Clear();
			return edict_t;
		}

		public static void FreeEdict(edict_t ed)
		{
			server.UnlinkEdict(ed);
			ed.free = true;
			ed.v.model = 0;
			ed.v.takedamage = 0f;
			ed.v.modelindex = 0f;
			ed.v.colormap = 0f;
			ed.v.skin = 0f;
			ed.v.frame = 0f;
			ed.v.origin = default(v3f);
			ed.v.angles = default(v3f);
			ed.v.nextthink = -1f;
			ed.v.solid = 0f;
			ed.freetime = (float)server.sv.time;
		}

		public static int EdictToProg(edict_t e)
		{
			return Array.IndexOf<edict_t>(server._Server.edicts, e);
		}

		public static edict_t ProgToEdict(int e)
		{
			if (e < 0 || e > server.sv.edicts.Length)
			{
				sys.Error("ProgToEdict: Bad prog!", Array.Empty<object>());
			}
			return server.sv.edicts[e];
		}

		public static int NumForEdict(edict_t e)
		{
			int num = Array.IndexOf<edict_t>(server.sv.edicts, e);
			if (num < 0)
			{
				sys.Error("NUM_FOR_EDICT: bad pointer", Array.Empty<object>());
			}
			return num;
		}

		static server()
		{
			server._Server = new server_t();
			server._ServerStatic = new server_static_t();
		}

		public static void Init()
		{
			for (int i = 0; i < server._BoxClipNodes.Length; i++)
			{
				server._BoxClipNodes[i].children = new short[2];
			}
			for (int j = 0; j < server._BoxPlanes.Length; j++)
			{
				server._BoxPlanes[j] = new mplane_t();
			}
			for (int k = 0; k < server._AreaNodes.Length; k++)
			{
				server._AreaNodes[k] = new areanode_t();
			}
			if (server._Friction == null)
			{
				server._Friction = new cvar("sv_friction", "4", false, true);
				server._EdgeFriction = new cvar("edgefriction", "2");
				server._StopSpeed = new cvar("sv_stopspeed", "100");
				server._Gravity = new cvar("sv_gravity", "800", false, true);
				server._MaxVelocity = new cvar("sv_maxvelocity", "2000");
				server._NoStep = new cvar("sv_nostep", "0");
				server._MaxSpeed = new cvar("sv_maxspeed", "320", false, true);
				server._Accelerate = new cvar("sv_accelerate", "10");
				server._Aim = new cvar("sv_aim", "0.93");
				server._IdealPitchScale = new cvar("sv_idealpitchscale", "0.8");
			}
			for (int l = 0; l < 256; l++)
			{
				server._LocalModels[l] = "*" + l.ToString();
			}
		}

		public static void StartParticle(ref Vector3 org, ref Vector3 dir, int color, int count)
		{
			if (server.sv.datagram.Length > 1008)
			{
				return;
			}
			server.sv.datagram.WriteByte(18);
			server.sv.datagram.WriteCoord(org.X);
			server.sv.datagram.WriteCoord(org.Y);
			server.sv.datagram.WriteCoord(org.Z);
			Vector3 max = Vector3.One * 127f;
			Vector3 min = Vector3.One * -128f;
			Vector3 vector = Vector3.Clamp(dir * 16f, min, max);
			server.sv.datagram.WriteChar((int)vector.X);
			server.sv.datagram.WriteChar((int)vector.Y);
			server.sv.datagram.WriteChar((int)vector.Z);
			server.sv.datagram.WriteByte(count);
			server.sv.datagram.WriteByte(color);
		}

		public static void StartSound(edict_t entity, int channel, string sample, int volume, float attenuation)
		{
			if (volume < 0 || volume > 255)
			{
				sys.Error("SV_StartSound: volume = {0}", new object[]
				{
					volume
				});
			}
			if (attenuation < 0f || attenuation > 4f)
			{
				sys.Error("SV_StartSound: attenuation = {0}", new object[]
				{
					attenuation
				});
			}
			if (channel < 0 || channel > 7)
			{
				sys.Error("SV_StartSound: channel = {0}", new object[]
				{
					channel
				});
			}
			if (server.sv.datagram.Length > 1008)
			{
				return;
			}
			int num = 1;
			while (num < 256 && server.sv.sound_precache[num] != null && !(sample == server.sv.sound_precache[num]))
			{
				num++;
			}
			if (num == 256 || string.IsNullOrEmpty(server.sv.sound_precache[num]))
			{
				Con.Print("SV_StartSound: {0} not precacheed\n", new object[]
				{
					sample
				});
				return;
			}
			channel = (server.NumForEdict(entity) << 3 | channel);
			int num2 = 0;
			if (volume != 255)
			{
				num2 |= 1;
			}
			if (attenuation != 1f)
			{
				num2 |= 2;
			}
			server.sv.datagram.WriteByte(6);
			server.sv.datagram.WriteByte(num2);
			if ((num2 & 1) != 0)
			{
				server.sv.datagram.WriteByte(volume);
			}
			if ((num2 & 2) != 0)
			{
				server.sv.datagram.WriteByte((int)(attenuation * 64f));
			}
			server.sv.datagram.WriteShort(channel);
			server.sv.datagram.WriteByte(num);
			v3f v3f;
			mathlib.VectorAdd(ref entity.v.mins, ref entity.v.maxs, out v3f);
			mathlib.VectorMA(ref entity.v.origin, 0.5f, ref v3f, out v3f);
			server.sv.datagram.WriteCoord(v3f.x);
			server.sv.datagram.WriteCoord(v3f.y);
			server.sv.datagram.WriteCoord(v3f.z);
		}

		public static void DropClient(bool crash)
		{
			client_t hostClient = host.HostClient;
			if (!crash)
			{
				if (net.CanSendMessage(hostClient.netconnection))
				{
					MsgWriter message = hostClient.message;
					message.WriteByte(2);
					net.SendMessage(hostClient.netconnection, message);
				}
				if (hostClient.edict != null && hostClient.spawned)
				{
					int self = progs.GlobalStruct.self;
					progs.GlobalStruct.self = server.EdictToProg(hostClient.edict);
					progs.Execute(progs.GlobalStruct.ClientDisconnect);
					progs.GlobalStruct.self = self;
				}
				Con.DPrint("Client {0} removed\n", new object[]
				{
					hostClient.name
				});
			}
			net.Close(hostClient.netconnection);
			hostClient.netconnection = null;
			hostClient.active = false;
			hostClient.name = null;
			hostClient.old_frags = -999999;
			net.ActiveConnections--;
			for (int i = 0; i < server.svs.maxclients; i++)
			{
				client_t client_t = server.svs.clients[i];
				if (client_t.active)
				{
					client_t.message.WriteByte(13);
					client_t.message.WriteByte(host.ClientNum);
					client_t.message.WriteString("");
					client_t.message.WriteByte(14);
					client_t.message.WriteByte(host.ClientNum);
					client_t.message.WriteShort(0);
					client_t.message.WriteByte(17);
					client_t.message.WriteByte(host.ClientNum);
					client_t.message.WriteByte(0);
				}
			}
		}

		public static void SendClientMessages()
		{
			server.UpdateToReliableMessages();
			for (int i = 0; i < server.svs.maxclients; i++)
			{
				host.HostClient = server.svs.clients[i];
				if (host.HostClient.active)
				{
					if (host.HostClient.spawned)
					{
						if (!server.SendClientDatagram(host.HostClient))
						{
							goto IL_13C;
						}
					}
					else if (!host.HostClient.sendsignon)
					{
						if (host.RealTime - host.HostClient.last_message > 5.0)
						{
							server.SendNop(host.HostClient);
							goto IL_13C;
						}
						goto IL_13C;
					}
					if (host.HostClient.message.IsOveflowed)
					{
						server.DropClient(true);
						host.HostClient.message.IsOveflowed = false;
					}
					else if ((host.HostClient.message.Length > 0 || host.HostClient.dropasap) && net.CanSendMessage(host.HostClient.netconnection))
					{
						if (host.HostClient.dropasap)
						{
							server.DropClient(false);
						}
						else
						{
							if (net.SendMessage(host.HostClient.netconnection, host.HostClient.message) == -1)
							{
								server.DropClient(true);
							}
							host.HostClient.message.Clear();
							host.HostClient.last_message = host.RealTime;
							host.HostClient.sendsignon = false;
						}
					}
				}
				IL_13C:;
			}
			server.CleanupEnts();
		}

		public static void ClearDatagram()
		{
			server.sv.datagram.Clear();
		}

		public static int ModelIndex(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return 0;
			}
			int num = 0;
			while (num < 256 && server.sv.model_precache[num] != null)
			{
				if (server.sv.model_precache[num] == name)
				{
					return num;
				}
				num++;
			}
			if (num == 256 || string.IsNullOrEmpty(server.sv.model_precache[num]))
			{
				sys.Error("SV_ModelIndex: model {0} not precached", new object[]
				{
					name
				});
			}
			return num;
		}

		public static void ClientPrint(string fmt, params object[] args)
		{
			string s = string.Format(fmt, args);
			host.HostClient.message.WriteByte(8);
			host.HostClient.message.WriteString(s);
		}

		public static void BroadcastPrint(string fmt, params object[] args)
		{
			string s = (args.Length != 0) ? string.Format(fmt, args) : fmt;
			for (int i = 0; i < server.svs.maxclients; i++)
			{
				if (server.svs.clients[i].active && server.svs.clients[i].spawned)
				{
					MsgWriter message = server.svs.clients[i].message;
					message.WriteByte(8);
					message.WriteString(s);
				}
			}
		}

		public static void WriteClientDataToMessage(edict_t ent, MsgWriter msg)
		{
			if (ent.v.dmg_take != 0f || ent.v.dmg_save != 0f)
			{
				edict_t edict_t = server.ProgToEdict(ent.v.dmg_inflictor);
				msg.WriteByte(19);
				msg.WriteByte((int)ent.v.dmg_save);
				msg.WriteByte((int)ent.v.dmg_take);
				msg.WriteCoord(edict_t.v.origin.x + 0.5f * (edict_t.v.mins.x + edict_t.v.maxs.x));
				msg.WriteCoord(edict_t.v.origin.y + 0.5f * (edict_t.v.mins.y + edict_t.v.maxs.y));
				msg.WriteCoord(edict_t.v.origin.z + 0.5f * (edict_t.v.mins.z + edict_t.v.maxs.z));
				ent.v.dmg_take = 0f;
				ent.v.dmg_save = 0f;
			}
			server.SetIdealPitch();
			if (ent.v.fixangle != 0f)
			{
				msg.WriteByte(10);
				msg.WriteAngle(ent.v.angles.x);
				msg.WriteAngle(ent.v.angles.y);
				msg.WriteAngle(ent.v.angles.z);
				ent.v.fixangle = 0f;
			}
			int num = 0;
			if (ent.v.view_ofs.z != 22f)
			{
				num |= 1;
			}
			if (ent.v.idealpitch != 0f)
			{
				num |= 2;
			}
			float edictFieldFloat = progs.GetEdictFieldFloat(ent, "items2", 0f);
			int c;
			if (edictFieldFloat != 0f)
			{
				c = ((int)ent.v.items | (int)edictFieldFloat << 23);
			}
			else
			{
				c = ((int)ent.v.items | (int)progs.GlobalStruct.serverflags << 28);
			}
			num |= 512;
			if (((int)ent.v.flags & 512) != 0)
			{
				num |= 1024;
			}
			if (ent.v.waterlevel >= 2f)
			{
				num |= 2048;
			}
			if (ent.v.punchangle.x != 0f)
			{
				num |= 4;
			}
			if (ent.v.punchangle.y != 0f)
			{
				num |= 8;
			}
			if (ent.v.punchangle.z != 0f)
			{
				num |= 16;
			}
			if (ent.v.velocity.x != 0f)
			{
				num |= 32;
			}
			if (ent.v.velocity.y != 0f)
			{
				num |= 64;
			}
			if (ent.v.velocity.z != 0f)
			{
				num |= 128;
			}
			if (ent.v.weaponframe != 0f)
			{
				num |= 4096;
			}
			if (ent.v.armorvalue != 0f)
			{
				num |= 8192;
			}
			num |= 16384;
			msg.WriteByte(15);
			msg.WriteShort(num);
			if ((num & 1) != 0)
			{
				msg.WriteChar((int)ent.v.view_ofs.z);
			}
			if ((num & 2) != 0)
			{
				msg.WriteChar((int)ent.v.idealpitch);
			}
			if ((num & 4) != 0)
			{
				msg.WriteChar((int)ent.v.punchangle.x);
			}
			if ((num & 32) != 0)
			{
				msg.WriteChar((int)(ent.v.velocity.x / 16f));
			}
			if ((num & 8) != 0)
			{
				msg.WriteChar((int)ent.v.punchangle.y);
			}
			if ((num & 64) != 0)
			{
				msg.WriteChar((int)(ent.v.velocity.y / 16f));
			}
			if ((num & 16) != 0)
			{
				msg.WriteChar((int)ent.v.punchangle.z);
			}
			if ((num & 128) != 0)
			{
				msg.WriteChar((int)(ent.v.velocity.z / 16f));
			}
			msg.WriteLong(c);
			if ((num & 4096) != 0)
			{
				msg.WriteByte((int)ent.v.weaponframe);
			}
			if ((num & 8192) != 0)
			{
				msg.WriteByte((int)ent.v.armorvalue);
			}
			if ((num & 16384) != 0)
			{
				msg.WriteByte(server.ModelIndex(progs.GetString(ent.v.weaponmodel)));
			}
			msg.WriteShort((int)ent.v.health);
			msg.WriteByte((int)ent.v.currentammo);
			msg.WriteByte((int)ent.v.ammo_shells);
			msg.WriteByte((int)ent.v.ammo_nails);
			msg.WriteByte((int)ent.v.ammo_rockets);
			msg.WriteByte((int)ent.v.ammo_cells);
			if (common.GameKind == GameKind.StandardQuake)
			{
				msg.WriteByte((int)ent.v.weapon);
				return;
			}
			for (int i = 0; i < 32; i++)
			{
				if (((int)ent.v.weapon & 1 << i) != 0)
				{
					msg.WriteByte(i);
					return;
				}
			}
		}

		public static void CheckForNewClients()
		{
			for (;;)
			{
				qsocket_t qsocket_t = net.CheckNewConnections();
				if (qsocket_t == null)
				{
					break;
				}
				int num = 0;
				while (num < server.svs.maxclients && server.svs.clients[num].active)
				{
					num++;
				}
				if (num == server.svs.maxclients)
				{
					sys.Error("Host_CheckForNewClients: no free clients", Array.Empty<object>());
				}
				server.svs.clients[num].netconnection = qsocket_t;
				server.ConnectClient(num);
				net.ActiveConnections++;
			}
		}

		public static void SaveSpawnparms()
		{
			server.svs.serverflags = (int)progs.GlobalStruct.serverflags;
			for (int i = 0; i < server.svs.maxclients; i++)
			{
				host.HostClient = server.svs.clients[i];
				if (host.HostClient.active)
				{
					progs.GlobalStruct.self = server.EdictToProg(host.HostClient.edict);
					progs.Execute(progs.GlobalStruct.SetChangeParms);
					server.AssignGlobalSpawnparams(host.HostClient);
				}
			}
		}

		public static void SpawnServer(string server)
		{
			if (string.IsNullOrEmpty(net.HostName))
			{
				cvar.Set("hostname", "UNNAMED");
			}
			Scr.CenterTimeOff = 0f;
			Con.DPrint("SpawnServer: {0}\n", new object[]
			{
				server
			});
			server.svs.changelevel_issued = false;
			if (server.sv.active)
			{
				server.SendReconnect();
			}
			if (host.IsCoop)
			{
				cvar.Set("deathmatch", 0f);
			}
			host.CurrentSkill = (int)((double)host.Skill + 0.5);
			if (host.CurrentSkill < 0)
			{
				host.CurrentSkill = 0;
			}
			if (host.CurrentSkill > 3)
			{
				host.CurrentSkill = 3;
			}
			cvar.Set("skill", (float)host.CurrentSkill);
			host.ClearMemory();
			server.sv.Clear();
			server.sv.name = server;
			progs.LoadProgs();
			server.sv.max_edicts = 600;
			server.sv.edicts = new edict_t[server.sv.max_edicts];
			for (int i = 0; i < server.sv.edicts.Length; i++)
			{
				server.sv.edicts[i] = new edict_t();
			}
			server.sv.num_edicts = server.svs.maxclients + 1;
			edict_t edict_t;
			for (int j = 0; j < server.svs.maxclients; j++)
			{
				edict_t = server.EdictNum(j + 1);
				server.svs.clients[j].edict = edict_t;
			}
			server.sv.state = server_state_t.Loading;
			server.sv.paused = false;
			server.sv.time = 1.0;
			server.sv.modelname = string.Format("maps/{0}.bsp", server);
			server.sv.worldmodel = Mod.ForName(server.sv.modelname, false);
			if (server.sv.worldmodel == null)
			{
				Con.Print("Couldn't spawn server {0}\n", new object[]
				{
					server.sv.modelname
				});
				server.sv.active = false;
				return;
			}
			server.sv.models[1] = server.sv.worldmodel;
			server.ClearWorld();
			server.sv.sound_precache[0] = string.Empty;
			server.sv.model_precache[0] = string.Empty;
			server.sv.model_precache[1] = server.sv.modelname;
			for (int k = 1; k < server.sv.worldmodel.numsubmodels; k++)
			{
				server.sv.model_precache[1 + k] = server._LocalModels[k];
				server.sv.models[k + 1] = Mod.ForName(server._LocalModels[k], false);
			}
			edict_t = server.EdictNum(0);
			edict_t.Clear();
			edict_t.v.model = progs.StringOffset(server.sv.worldmodel.name);
			if (edict_t.v.model == -1)
			{
				edict_t.v.model = progs.NewString(server.sv.worldmodel.name);
			}
			edict_t.v.modelindex = 1f;
			edict_t.v.solid = 4f;
			edict_t.v.movetype = 7f;
			if (host.IsCoop)
			{
				progs.GlobalStruct.coop = 1f;
			}
			else
			{
				progs.GlobalStruct.deathmatch = host.Deathmatch;
			}
			int mapname = progs.NewString(server.sv.name);
			progs.GlobalStruct.mapname = mapname;
			progs.GlobalStruct.serverflags = (float)server.svs.serverflags;
			progs.LoadFromFile(server.sv.worldmodel.entities);
			server.sv.active = true;
			server.sv.state = server_state_t.Active;
			host.FrameTime = 0.1;
			server.Physics();
			server.Physics();
			server.CreateBaseline();
			for (int l = 0; l < server.svs.maxclients; l++)
			{
				host.HostClient = server.svs.clients[l];
				if (host.HostClient.active)
				{
					server.SendServerInfo(host.HostClient);
				}
			}
			GC.Collect();
			Con.DPrint("Server spawned.\n", Array.Empty<object>());
		}

		private static void CleanupEnts()
		{
			for (int i = 1; i < server.sv.num_edicts; i++)
			{
				edict_t edict_t = server.sv.edicts[i];
				edict_t.v.effects = (float)((int)edict_t.v.effects & ~(float)EntityEffects.EF_MUZZLEFLASH);
			}
		}

		private static void SendNop(client_t client)
		{
			MsgWriter msgWriter = new MsgWriter(4);
			msgWriter.WriteChar(1);
			if (net.SendUnreliableMessage(client.netconnection, msgWriter) == -1)
			{
				server.DropClient(true);
			}
			client.last_message = host.RealTime;
		}

		private static bool SendClientDatagram(client_t client)
		{
			MsgWriter msgWriter = new MsgWriter(1024);
			msgWriter.WriteByte(7);
			msgWriter.WriteFloat((float)server.sv.time);
			server.WriteClientDataToMessage(client.edict, msgWriter);
			server.WriteEntitiesToClient(client.edict, msgWriter);
			if (msgWriter.Length + server.sv.datagram.Length < msgWriter.Capacity)
			{
				msgWriter.Write(server.sv.datagram.Data, 0, server.sv.datagram.Length);
			}
			if (net.SendUnreliableMessage(client.netconnection, msgWriter) == -1)
			{
				server.DropClient(true);
				return false;
			}
			return true;
		}

		private static void WriteEntitiesToClient(edict_t clent, MsgWriter msg)
		{
			Vector3 vector = common.ToVector(ref clent.v.origin) + common.ToVector(ref clent.v.view_ofs);
			byte[] array = server.FatPVS(ref vector);
			int i = 1;
			while (i < server.sv.num_edicts)
			{
				edict_t edict_t = server.sv.edicts[i];
				if (edict_t == clent)
				{
					goto IL_A2;
				}
				if (!string.IsNullOrEmpty(progs.GetString(edict_t.v.model)))
				{
					int num = 0;
					while (num < edict_t.num_leafs && ((int)array[edict_t.leafnums[num] >> 3] & 1 << (int)(edict_t.leafnums[num] & 7)) == 0)
					{
						num++;
					}
					if (num != edict_t.num_leafs)
					{
						goto IL_A2;
					}
				}
				IL_422:
				i++;
				continue;
				IL_A2:
				if (msg.Capacity - msg.Length < 16)
				{
					Con.Print("packet overflow\n", Array.Empty<object>());
					return;
				}
				int num2 = 0;
				v3f v3f;
				mathlib.VectorSubtract(ref edict_t.v.origin, ref edict_t.baseline.origin, out v3f);
				if (v3f.x < -0.1f || v3f.x > 0.1f)
				{
					num2 |= 2;
				}
				if (v3f.y < -0.1f || v3f.y > 0.1f)
				{
					num2 |= 4;
				}
				if (v3f.z < -0.1f || v3f.z > 0.1f)
				{
					num2 |= 8;
				}
				if (edict_t.v.angles.x != edict_t.baseline.angles.x)
				{
					num2 |= 256;
				}
				if (edict_t.v.angles.y != edict_t.baseline.angles.y)
				{
					num2 |= 16;
				}
				if (edict_t.v.angles.z != edict_t.baseline.angles.z)
				{
					num2 |= 512;
				}
				if (edict_t.v.movetype == 4f)
				{
					num2 |= 32;
				}
				if ((float)edict_t.baseline.colormap != edict_t.v.colormap)
				{
					num2 |= 2048;
				}
				if ((float)edict_t.baseline.skin != edict_t.v.skin)
				{
					num2 |= 4096;
				}
				if ((float)edict_t.baseline.frame != edict_t.v.frame)
				{
					num2 |= 64;
				}
				if ((float)edict_t.baseline.effects != edict_t.v.effects)
				{
					num2 |= 8192;
				}
				if ((float)edict_t.baseline.modelindex != edict_t.v.modelindex)
				{
					num2 |= 1024;
				}
				if (i >= 256)
				{
					num2 |= 16384;
				}
				if (num2 >= 256)
				{
					num2 |= 1;
				}
				msg.WriteByte(num2 | 128);
				if ((num2 & 1) != 0)
				{
					msg.WriteByte(num2 >> 8);
				}
				if ((num2 & 16384) != 0)
				{
					msg.WriteShort(i);
				}
				else
				{
					msg.WriteByte(i);
				}
				if ((num2 & 1024) != 0)
				{
					msg.WriteByte((int)edict_t.v.modelindex);
				}
				if ((num2 & 64) != 0)
				{
					msg.WriteByte((int)edict_t.v.frame);
				}
				if ((num2 & 2048) != 0)
				{
					msg.WriteByte((int)edict_t.v.colormap);
				}
				if ((num2 & 4096) != 0)
				{
					msg.WriteByte((int)edict_t.v.skin);
				}
				if ((num2 & 8192) != 0)
				{
					msg.WriteByte((int)edict_t.v.effects);
				}
				if ((num2 & 2) != 0)
				{
					msg.WriteCoord(edict_t.v.origin.x);
				}
				if ((num2 & 256) != 0)
				{
					msg.WriteAngle(edict_t.v.angles.x);
				}
				if ((num2 & 4) != 0)
				{
					msg.WriteCoord(edict_t.v.origin.y);
				}
				if ((num2 & 16) != 0)
				{
					msg.WriteAngle(edict_t.v.angles.y);
				}
				if ((num2 & 8) != 0)
				{
					msg.WriteCoord(edict_t.v.origin.z);
				}
				if ((num2 & 512) != 0)
				{
					msg.WriteAngle(edict_t.v.angles.z);
					goto IL_422;
				}
				goto IL_422;
			}
		}

		private static byte[] FatPVS(ref Vector3 org)
		{
			server._FatBytes = server.sv.worldmodel.numleafs + 31 >> 3;
			Array.Clear(server._FatPvs, 0, server._FatPvs.Length);
			server.AddToFatPVS(ref org, server.sv.worldmodel.nodes[0]);
			return server._FatPvs;
		}

		private static void AddToFatPVS(ref Vector3 org, mnodebase_t node)
		{
			while (node.contents >= 0)
			{
				mnode_t mnode_t = (mnode_t)node;
				mplane_t plane = mnode_t.plane;
				float num = Vector3.Dot(org, plane.normal) - plane.dist;
				if (num > 8f)
				{
					node = mnode_t.children[0];
				}
				else if (num < -8f)
				{
					node = mnode_t.children[1];
				}
				else
				{
					server.AddToFatPVS(ref org, mnode_t.children[0]);
					node = mnode_t.children[1];
				}
			}
			if (node.contents != -2)
			{
				byte[] array = Mod.LeafPVS((mleaf_t)node, server.sv.worldmodel);
				for (int i = 0; i < server._FatBytes; i++)
				{
					byte[] fatPvs = server._FatPvs;
					int num2 = i;
					fatPvs[num2] |= array[i];
				}
			}
		}

		private static void UpdateToReliableMessages()
		{
			for (int i = 0; i < server.svs.maxclients; i++)
			{
				host.HostClient = server.svs.clients[i];
				if ((float)host.HostClient.old_frags != host.HostClient.edict.v.frags)
				{
					for (int j = 0; j < server.svs.maxclients; j++)
					{
						client_t client_t = server.svs.clients[j];
						if (client_t.active)
						{
							client_t.message.WriteByte(14);
							client_t.message.WriteByte(i);
							client_t.message.WriteShort((int)host.HostClient.edict.v.frags);
						}
					}
					host.HostClient.old_frags = (int)host.HostClient.edict.v.frags;
				}
			}
			for (int k = 0; k < server.svs.maxclients; k++)
			{
				client_t client_t2 = server.svs.clients[k];
				if (client_t2.active)
				{
					client_t2.message.Write(server.sv.reliable_datagram.Data, 0, server.sv.reliable_datagram.Length);
				}
			}
			server.sv.reliable_datagram.Clear();
		}

		private static void ConnectClient(int clientnum)
		{
			client_t client_t = server.svs.clients[clientnum];
			Con.DPrint("Client {0} connected\n", new object[]
			{
				client_t.netconnection.address
			});
			edict_t edict = server.EdictNum(clientnum + 1);
			qsocket_t netconnection = client_t.netconnection;
			float[] array = new float[16];
			if (server.sv.loadgame)
			{
				Array.Copy(client_t.spawn_parms, array, array.Length);
			}
			client_t.Clear();
			client_t.netconnection = netconnection;
			client_t.name = "unconnected";
			client_t.active = true;
			client_t.spawned = false;
			client_t.edict = edict;
			client_t.message.AllowOverflow = true;
			client_t.privileged = false;
			if (server.sv.loadgame)
			{
				Array.Copy(array, client_t.spawn_parms, array.Length);
			}
			else
			{
				progs.Execute(progs.GlobalStruct.SetNewParms);
				server.AssignGlobalSpawnparams(client_t);
			}
			server.SendServerInfo(client_t);
		}

		private static void AssignGlobalSpawnparams(client_t client)
		{
			client.spawn_parms[0] = progs.GlobalStruct.parm1;
			client.spawn_parms[1] = progs.GlobalStruct.parm2;
			client.spawn_parms[2] = progs.GlobalStruct.parm3;
			client.spawn_parms[3] = progs.GlobalStruct.parm4;
			client.spawn_parms[4] = progs.GlobalStruct.parm5;
			client.spawn_parms[5] = progs.GlobalStruct.parm6;
			client.spawn_parms[6] = progs.GlobalStruct.parm7;
			client.spawn_parms[7] = progs.GlobalStruct.parm8;
			client.spawn_parms[8] = progs.GlobalStruct.parm9;
			client.spawn_parms[9] = progs.GlobalStruct.parm10;
			client.spawn_parms[10] = progs.GlobalStruct.parm11;
			client.spawn_parms[11] = progs.GlobalStruct.parm12;
			client.spawn_parms[12] = progs.GlobalStruct.parm13;
			client.spawn_parms[13] = progs.GlobalStruct.parm14;
			client.spawn_parms[14] = progs.GlobalStruct.parm15;
			client.spawn_parms[15] = progs.GlobalStruct.parm16;
		}

		private static void SendServerInfo(client_t client)
		{
			MsgWriter message = client.message;
			message.WriteByte(8);
			message.WriteString(string.Format("{0}\nVERSION {1,4:F2} SERVER ({2} CRC)", '\u0002', 1.09f, progs.Crc));
			message.WriteByte(11);
			message.WriteLong(15);
			message.WriteByte(server.svs.maxclients);
			if (!host.IsCoop && host.Deathmatch != 0f)
			{
				message.WriteByte(1);
			}
			else
			{
				message.WriteByte(0);
			}
			string @string = progs.GetString(server.sv.edicts[0].v.message);
			message.WriteString(@string);
			for (int i = 1; i < server.sv.model_precache.Length; i++)
			{
				string text = server.sv.model_precache[i];
				if (string.IsNullOrEmpty(text))
				{
					break;
				}
				message.WriteString(text);
			}
			message.WriteByte(0);
			for (int j = 1; j < server.sv.sound_precache.Length; j++)
			{
				string text2 = server.sv.sound_precache[j];
				if (text2 == null)
				{
					break;
				}
				message.WriteString(text2);
			}
			message.WriteByte(0);
			message.WriteByte(32);
			message.WriteByte((int)server.sv.edicts[0].v.sounds);
			message.WriteByte((int)server.sv.edicts[0].v.sounds);
			message.WriteByte(5);
			message.WriteShort(server.NumForEdict(client.edict));
			message.WriteByte(25);
			message.WriteByte(1);
			client.sendsignon = true;
			client.spawned = false;
		}

		private static void SendReconnect()
		{
			MsgWriter msgWriter = new MsgWriter(128);
			msgWriter.WriteChar(9);
			msgWriter.WriteString("reconnect\n");
			net.SendToAll(msgWriter, 5);
			if (client.cls.state != cactive_t.ca_dedicated)
			{
				cmd.ExecuteString("reconnect\n", cmd_source_t.src_command);
			}
		}

		private static void CreateBaseline()
		{
			for (int i = 0; i < server.sv.num_edicts; i++)
			{
				edict_t edict_t = server.EdictNum(i);
				if (!edict_t.free && (i <= server.svs.maxclients || edict_t.v.modelindex != 0f))
				{
					edict_t.baseline.origin = edict_t.v.origin;
					edict_t.baseline.angles = edict_t.v.angles;
					edict_t.baseline.frame = (int)edict_t.v.frame;
					edict_t.baseline.skin = (int)edict_t.v.skin;
					if (i > 0 && i <= server.svs.maxclients)
					{
						edict_t.baseline.colormap = i;
						edict_t.baseline.modelindex = server.ModelIndex("progs/player.mdl");
					}
					else
					{
						edict_t.baseline.colormap = 0;
						edict_t.baseline.modelindex = server.ModelIndex(progs.GetString(edict_t.v.model));
					}
					server.sv.signon.WriteByte(22);
					server.sv.signon.WriteShort(i);
					server.sv.signon.WriteByte(edict_t.baseline.modelindex);
					server.sv.signon.WriteByte(edict_t.baseline.frame);
					server.sv.signon.WriteByte(edict_t.baseline.colormap);
					server.sv.signon.WriteByte(edict_t.baseline.skin);
					server.sv.signon.WriteCoord(edict_t.baseline.origin.x);
					server.sv.signon.WriteAngle(edict_t.baseline.angles.x);
					server.sv.signon.WriteCoord(edict_t.baseline.origin.y);
					server.sv.signon.WriteAngle(edict_t.baseline.angles.y);
					server.sv.signon.WriteCoord(edict_t.baseline.origin.z);
					server.sv.signon.WriteAngle(edict_t.baseline.angles.z);
				}
			}
		}

		public static bool MoveStep(edict_t ent, ref v3f move, bool relink)
		{
			v3f origin = ent.v.origin;
			v3f v3f;
			mathlib.VectorAdd(ref ent.v.origin, ref move, out v3f);
			trace_t trace_t;
			if (((int)ent.v.flags & 3) != 0)
			{
				int i = 0;
				while (i < 2)
				{
					mathlib.VectorAdd(ref ent.v.origin, ref move, out v3f);
					edict_t edict_t = server.ProgToEdict(ent.v.enemy);
					if (i == 0 && edict_t != server.sv.edicts[0])
					{
						float num = ent.v.origin.z - edict_t.v.origin.z;
						if (num > 40f)
						{
							v3f.z -= 8f;
						}
						if (num < 30f)
						{
							v3f.z += 8f;
						}
					}
					trace_t = server.Move(ref ent.v.origin, ref ent.v.mins, ref ent.v.maxs, ref v3f, 0, ent);
					if (trace_t.fraction == 1f)
					{
						if (((int)ent.v.flags & 2) != 0 && server.PointContents(ref trace_t.endpos) == -1)
						{
							return false;
						}
						mathlib.Copy(ref trace_t.endpos, out ent.v.origin);
						if (relink)
						{
							server.LinkEdict(ent, true);
						}
						return true;
					}
					else
					{
						if (edict_t == server.sv.edicts[0])
						{
							break;
						}
						i++;
					}
				}
				return false;
			}
			v3f.z += 18f;
			v3f v3f2 = v3f;
			v3f2.z -= 36f;
			trace_t = server.Move(ref v3f, ref ent.v.mins, ref ent.v.maxs, ref v3f2, 0, ent);
			if (trace_t.allsolid)
			{
				return false;
			}
			if (trace_t.startsolid)
			{
				v3f.z -= 18f;
				trace_t = server.Move(ref v3f, ref ent.v.mins, ref ent.v.maxs, ref v3f2, 0, ent);
				if (trace_t.allsolid || trace_t.startsolid)
				{
					return false;
				}
			}
			if (trace_t.fraction == 1f)
			{
				if (((int)ent.v.flags & 1024) != 0)
				{
					mathlib.VectorAdd(ref ent.v.origin, ref move, out ent.v.origin);
					if (relink)
					{
						server.LinkEdict(ent, true);
					}
					ent.v.flags = (float)((int)ent.v.flags & -513);
					return true;
				}
				return false;
			}
			else
			{
				mathlib.Copy(ref trace_t.endpos, out ent.v.origin);
				if (server.CheckBottom(ent))
				{
					if (((int)ent.v.flags & 1024) != 0)
					{
						ent.v.flags = (float)((int)ent.v.flags & -1025);
					}
					ent.v.groundentity = server.EdictToProg(trace_t.ent);
					if (relink)
					{
						server.LinkEdict(ent, true);
					}
					return true;
				}
				if (((int)ent.v.flags & 1024) != 0)
				{
					if (relink)
					{
						server.LinkEdict(ent, true);
					}
					return true;
				}
				ent.v.origin = origin;
				return false;
			}
		}

		public static bool CheckBottom(edict_t ent)
		{
			v3f v3f;
			mathlib.VectorAdd(ref ent.v.origin, ref ent.v.mins, out v3f);
			v3f v3f2;
			mathlib.VectorAdd(ref ent.v.origin, ref ent.v.maxs, out v3f2);
			Vector3 vector;
			vector.Z = v3f.z - 1f;
			for (int i = 0; i <= 1; i++)
			{
				int j = 0;
				while (j <= 1)
				{
					vector.X = ((i != 0) ? v3f2.x : v3f.x);
					vector.Y = ((j != 0) ? v3f2.y : v3f.y);
					if (server.PointContents(ref vector) == -2)
					{
						j++;
					}
					else
					{
						vector.Z = v3f.z;
						vector.X = (v3f.x + v3f2.x) * 0.5f;
						vector.Y = (v3f.y + v3f2.y) * 0.5f;
						Vector3 vector2 = vector;
						vector2.Z -= 36f;
						trace_t trace_t = server.Move(ref vector, ref common.ZeroVector, ref common.ZeroVector, ref vector2, 1, ent);
						if ((double)trace_t.fraction == 1.0)
						{
							return false;
						}
						float z = trace_t.endpos.Z;
						float num = z;
						for (int k = 0; k <= 1; k++)
						{
							for (int l = 0; l <= 1; l++)
							{
								vector.X = (vector2.X = ((k != 0) ? v3f2.x : v3f.x));
								vector.Y = (vector2.Y = ((l != 0) ? v3f2.y : v3f.y));
								trace_t = server.Move(ref vector, ref common.ZeroVector, ref common.ZeroVector, ref vector2, 1, ent);
								if ((double)trace_t.fraction != 1.0 && trace_t.endpos.Z > num)
								{
									num = trace_t.endpos.Z;
								}
								if ((double)trace_t.fraction == 1.0 || z - trace_t.endpos.Z > 18f)
								{
									return false;
								}
							}
						}
						return true;
					}
				}
			}
			return true;
		}

		public static void MoveToGoal()
		{
			edict_t edict_t = server.ProgToEdict(progs.GlobalStruct.self);
			edict_t edict_t2 = server.ProgToEdict(edict_t.v.goalentity);
			float @float = QBuiltins.GetFloat(4);
			if (((int)edict_t.v.flags & 515) == 0)
			{
				QBuiltins.ReturnFloat(0f);
				return;
			}
			if (server.ProgToEdict(edict_t.v.enemy) != server.sv.edicts[0] && server.CloseEnough(edict_t, edict_t2, @float))
			{
				return;
			}
			if ((sys.Random() & 3) == 1 || !server.StepDirection(edict_t, edict_t.v.ideal_yaw, @float))
			{
				server.NewChaseDir(edict_t, edict_t2, @float);
			}
		}

		private static bool CloseEnough(edict_t ent, edict_t goal, float dist)
		{
			return goal.v.absmin.x <= ent.v.absmax.x + dist && goal.v.absmin.y <= ent.v.absmax.y + dist && goal.v.absmin.z <= ent.v.absmax.z + dist && goal.v.absmax.x >= ent.v.absmin.x - dist && goal.v.absmax.y >= ent.v.absmin.y - dist && goal.v.absmax.z >= ent.v.absmin.z - dist;
		}

		private static bool StepDirection(edict_t ent, float yaw, float dist)
		{
			ent.v.ideal_yaw = yaw;
			QBuiltins.PF_changeyaw();
			yaw = (float)((double)yaw * 3.1415926535897931 * 2.0 / 360.0);
			v3f v3f;
			v3f.x = (float)Math.Cos((double)yaw) * dist;
			v3f.y = (float)Math.Sin((double)yaw) * dist;
			v3f.z = 0f;
			v3f origin = ent.v.origin;
			if (server.MoveStep(ent, ref v3f, false))
			{
				float num = ent.v.angles.y - ent.v.ideal_yaw;
				if (num > 45f && num < 315f)
				{
					ent.v.origin = origin;
				}
				server.LinkEdict(ent, true);
				return true;
			}
			server.LinkEdict(ent, true);
			return false;
		}

		private static void NewChaseDir(edict_t actor, edict_t enemy, float dist)
		{
			float num = mathlib.AngleMod((double)((int)(actor.v.ideal_yaw / 45f) * 45));
			float num2 = mathlib.AngleMod((double)(num - 180f));
			float num3 = enemy.v.origin.x - actor.v.origin.x;
			float num4 = enemy.v.origin.y - actor.v.origin.y;
			v3f v3f;
			if (num3 > 10f)
			{
				v3f.y = 0f;
			}
			else if (num3 < -10f)
			{
				v3f.y = 180f;
			}
			else
			{
				v3f.y = -1f;
			}
			if (num4 < -10f)
			{
				v3f.z = 270f;
			}
			else if (num4 > 10f)
			{
				v3f.z = 90f;
			}
			else
			{
				v3f.z = -1f;
			}
			if (v3f.y != -1f && v3f.z != -1f)
			{
				float num5;
				if (v3f.y == 0f)
				{
					num5 = (float)((v3f.z == 90f) ? 45 : 315);
				}
				else
				{
					num5 = (float)((v3f.z == 90f) ? 135 : 215);
				}
				if (num5 != num2 && server.StepDirection(actor, num5, dist))
				{
					return;
				}
			}
			if ((sys.Random() & 3 & 1) != 0 || Math.Abs(num4) > Math.Abs(num3))
			{
				float num5 = v3f.y;
				v3f.y = v3f.z;
				v3f.z = num5;
			}
			if (v3f.y != -1f && v3f.y != num2 && server.StepDirection(actor, v3f.y, dist))
			{
				return;
			}
			if (v3f.z != -1f && v3f.z != num2 && server.StepDirection(actor, v3f.z, dist))
			{
				return;
			}
			if (num != -1f && server.StepDirection(actor, num, dist))
			{
				return;
			}
			if ((sys.Random() & 1) != 0)
			{
				for (float num5 = 0f; num5 <= 315f; num5 += 45f)
				{
					if (num5 != num2 && server.StepDirection(actor, num5, dist))
					{
						return;
					}
				}
			}
			else
			{
				for (float num5 = 315f; num5 >= 0f; num5 -= 45f)
				{
					if (num5 != num2 && server.StepDirection(actor, num5, dist))
					{
						return;
					}
				}
			}
			if (num2 != -1f && server.StepDirection(actor, num2, dist))
			{
				return;
			}
			actor.v.ideal_yaw = num;
			if (!server.CheckBottom(actor))
			{
				server.FixCheckBottom(actor);
			}
		}

		private static void FixCheckBottom(edict_t ent)
		{
			ent.v.flags = (float)((int)ent.v.flags | 1024);
		}

		public static void Physics()
		{
			progs.GlobalStruct.self = server.EdictToProg(server.sv.edicts[0]);
			progs.GlobalStruct.other = progs.GlobalStruct.self;
			progs.GlobalStruct.time = (float)server.sv.time;
			progs.Execute(progs.GlobalStruct.StartFrame);
			for (int i = 0; i < server.sv.num_edicts; i++)
			{
				edict_t edict_t = server.sv.edicts[i];
				if (!edict_t.free)
				{
					if (progs.GlobalStruct.force_retouch != 0f)
					{
						server.LinkEdict(edict_t, true);
					}
					if (i > 0 && i <= server.svs.maxclients)
					{
						server.Physics_Client(edict_t, i);
					}
					else
					{
						switch ((int)edict_t.v.movetype)
						{
						case 0:
							server.Physics_None(edict_t);
							goto IL_134;
						case 4:
							server.Physics_Step(edict_t);
							goto IL_134;
						case 5:
						case 6:
						case 9:
						case 10:
							server.Physics_Toss(edict_t);
							goto IL_134;
						case 7:
							server.Physics_Pusher(edict_t);
							goto IL_134;
						case 8:
							server.Physics_Noclip(edict_t);
							goto IL_134;
						}
						sys.Error("SV_Physics: bad movetype {0}", new object[]
						{
							(int)edict_t.v.movetype
						});
					}
				}
				IL_134:;
			}
			if (progs.GlobalStruct.force_retouch != 0f)
			{
				progs.GlobalStruct.force_retouch -= 1f;
			}
			server.sv.time += host.FrameTime;
		}

		private static void Physics_Toss(edict_t ent)
		{
			if (!server.RunThink(ent))
			{
				return;
			}
			if (((int)ent.v.flags & 512) != 0)
			{
				return;
			}
			server.CheckVelocity(ent);
			if (ent.v.movetype != 5f && ent.v.movetype != 9f)
			{
				server.AddGravity(ent);
			}
			mathlib.VectorMA(ref ent.v.angles, (float)host.FrameTime, ref ent.v.avelocity, out ent.v.angles);
			v3f v3f;
			mathlib.VectorScale(ref ent.v.velocity, (float)host.FrameTime, out v3f);
			trace_t trace_t = server.PushEntity(ent, ref v3f);
			if (trace_t.fraction == 1f)
			{
				return;
			}
			if (ent.free)
			{
				return;
			}
			float overbounce;
			if (ent.v.movetype == 10f)
			{
				overbounce = 1.5f;
			}
			else
			{
				overbounce = 1f;
			}
			server.ClipVelocity(ref ent.v.velocity, ref trace_t.plane.normal, out ent.v.velocity, overbounce);
			if (trace_t.plane.normal.Z > 0.7f && (ent.v.velocity.z < 60f || ent.v.movetype != 10f))
			{
				ent.v.flags = (float)((int)ent.v.flags | 512);
				ent.v.groundentity = server.EdictToProg(trace_t.ent);
				ent.v.velocity = default(v3f);
				ent.v.avelocity = default(v3f);
			}
			server.CheckWaterTransition(ent);
		}

		private static int ClipVelocity(ref v3f src, ref Vector3 normal, out v3f dest, float overbounce)
		{
			int num = 0;
			if (normal.Z > 0f)
			{
				num |= 1;
			}
			if (normal.Z == 0f)
			{
				num |= 2;
			}
			float num2 = (src.x * normal.X + src.y * normal.Y + src.z * normal.Z) * overbounce;
			dest.x = src.x - normal.X * num2;
			dest.y = src.y - normal.Y * num2;
			dest.z = src.z - normal.Z * num2;
			if (dest.x > -0.1f && dest.x < 0.1f)
			{
				dest.x = 0f;
			}
			if (dest.y > -0.1f && dest.y < 0.1f)
			{
				dest.y = 0f;
			}
			if (dest.z > -0.1f && dest.z < 0.1f)
			{
				dest.z = 0f;
			}
			return num;
		}

		private static trace_t PushEntity(edict_t ent, ref v3f push)
		{
			v3f v3f;
			mathlib.VectorAdd(ref ent.v.origin, ref push, out v3f);
			trace_t trace_t;
			if (ent.v.movetype == 9f)
			{
				trace_t = server.Move(ref ent.v.origin, ref ent.v.mins, ref ent.v.maxs, ref v3f, 2, ent);
			}
			else if (ent.v.solid == 1f || ent.v.solid == 0f)
			{
				trace_t = server.Move(ref ent.v.origin, ref ent.v.mins, ref ent.v.maxs, ref v3f, 1, ent);
			}
			else
			{
				trace_t = server.Move(ref ent.v.origin, ref ent.v.mins, ref ent.v.maxs, ref v3f, 0, ent);
			}
			mathlib.Copy(ref trace_t.endpos, out ent.v.origin);
			server.LinkEdict(ent, true);
			if (trace_t.ent != null)
			{
				server.Impact(ent, trace_t.ent);
			}
			return trace_t;
		}

		private static void CheckWaterTransition(edict_t ent)
		{
			Vector3 vector = common.ToVector(ref ent.v.origin);
			int num = server.PointContents(ref vector);
			if (ent.v.watertype == 0f)
			{
				ent.v.watertype = (float)num;
				ent.v.waterlevel = 1f;
				return;
			}
			if (num <= -3)
			{
				if (ent.v.watertype == -1f)
				{
					server.StartSound(ent, 0, "misc/h2ohit1.wav", 255, 1f);
				}
				ent.v.watertype = (float)num;
				ent.v.waterlevel = 1f;
				return;
			}
			if (ent.v.watertype != -1f)
			{
				server.StartSound(ent, 0, "misc/h2ohit1.wav", 255, 1f);
			}
			ent.v.watertype = -1f;
			ent.v.waterlevel = (float)num;
		}

		private static void AddGravity(edict_t ent)
		{
			float num = progs.GetEdictFieldFloat(ent, "gravity", 0f);
			if (num == 0f)
			{
				num = 1f;
			}
			ent.v.velocity.z = ent.v.velocity.z - (float)((double)(num * server._Gravity.Value) * host.FrameTime);
		}

		private static void Physics_Step(edict_t ent)
		{
			if (((int)ent.v.flags & 515) == 0)
			{
				bool flag = (double)ent.v.velocity.z < (double)server._Gravity.Value * -0.1;
				server.AddGravity(ent);
				server.CheckVelocity(ent);
				server.FlyMove(ent, (float)host.FrameTime, null);
				server.LinkEdict(ent, true);
				if (((int)ent.v.flags & 512) != 0 && flag)
				{
					server.StartSound(ent, 0, "demon/dland2.wav", 255, 1f);
				}
			}
			server.RunThink(ent);
			server.CheckWaterTransition(ent);
		}

		private static void Physics_Noclip(edict_t ent)
		{
			if (!server.RunThink(ent))
			{
				return;
			}
			mathlib.VectorMA(ref ent.v.angles, (float)host.FrameTime, ref ent.v.avelocity, out ent.v.angles);
			mathlib.VectorMA(ref ent.v.origin, (float)host.FrameTime, ref ent.v.velocity, out ent.v.origin);
			server.LinkEdict(ent, false);
		}

		private static void Physics_None(edict_t ent)
		{
			server.RunThink(ent);
		}

		private static void Physics_Pusher(edict_t ent)
		{
			float ltime = ent.v.ltime;
			float nextthink = ent.v.nextthink;
			float num;
			if ((double)nextthink < (double)ent.v.ltime + host.FrameTime)
			{
				num = nextthink - ent.v.ltime;
				if (num < 0f)
				{
					num = 0f;
				}
			}
			else
			{
				num = (float)host.FrameTime;
			}
			if (num != 0f)
			{
				server.PushMove(ent, num);
			}
			if (nextthink > ltime && nextthink <= ent.v.ltime)
			{
				ent.v.nextthink = 0f;
				progs.GlobalStruct.time = (float)server.sv.time;
				progs.GlobalStruct.self = server.EdictToProg(ent);
				progs.GlobalStruct.other = server.EdictToProg(server.sv.edicts[0]);
				progs.Execute(ent.v.think);
				bool free = ent.free;
				return;
			}
		}

		private static void Physics_Client(edict_t ent, int num)
		{
			if (!server.svs.clients[num - 1].active)
			{
				return;
			}
			progs.GlobalStruct.time = (float)server.sv.time;
			progs.GlobalStruct.self = server.EdictToProg(ent);
			progs.Execute(progs.GlobalStruct.PlayerPreThink);
			server.CheckVelocity(ent);
			switch ((int)ent.v.movetype)
			{
			case 0:
				if (!server.RunThink(ent))
				{
					return;
				}
				goto IL_155;
			case 3:
				if (!server.RunThink(ent))
				{
					return;
				}
				if (!server.CheckWater(ent) && ((int)ent.v.flags & 2048) == 0)
				{
					server.AddGravity(ent);
				}
				server.CheckStuck(ent);
				server.WalkMove(ent);
				goto IL_155;
			case 5:
				if (!server.RunThink(ent))
				{
					return;
				}
				server.FlyMove(ent, (float)host.FrameTime, null);
				goto IL_155;
			case 6:
			case 10:
				server.Physics_Toss(ent);
				goto IL_155;
			case 8:
				if (!server.RunThink(ent))
				{
					return;
				}
				mathlib.VectorMA(ref ent.v.origin, (float)host.FrameTime, ref ent.v.velocity, out ent.v.origin);
				goto IL_155;
			}
			sys.Error("SV_Physics_client: bad movetype {0}", new object[]
			{
				(int)ent.v.movetype
			});
			IL_155:
			server.LinkEdict(ent, true);
			progs.GlobalStruct.time = (float)server.sv.time;
			progs.GlobalStruct.self = server.EdictToProg(ent);
			progs.Execute(progs.GlobalStruct.PlayerPostThink);
		}

		private static void WalkMove(edict_t ent)
		{
			int num = (int)ent.v.flags & 512;
			ent.v.flags = (float)((int)ent.v.flags & -513);
			v3f origin = ent.v.origin;
			v3f velocity = ent.v.velocity;
			trace_t trace_t = new trace_t();
			int num2 = server.FlyMove(ent, (float)host.FrameTime, trace_t);
			if ((num2 & 2) == 0)
			{
				return;
			}
			if (num == 0 && ent.v.waterlevel == 0f)
			{
				return;
			}
			if (ent.v.movetype != 3f)
			{
				return;
			}
			if (server._NoStep.Value != 0f)
			{
				return;
			}
			if (((int)server._Player.v.flags & 2048) != 0)
			{
				return;
			}
			v3f origin2 = ent.v.origin;
			v3f velocity2 = ent.v.velocity;
			ent.v.origin = origin;
			v3f zeroVector3f = common.ZeroVector3f;
			v3f v3f = zeroVector3f;
			zeroVector3f.z = 18f;
			v3f.z = (float)(-18.0 + (double)velocity.z * host.FrameTime);
			server.PushEntity(ent, ref zeroVector3f);
			ent.v.velocity.x = velocity.x;
			ent.v.velocity.y = velocity.y;
			ent.v.velocity.z = 0f;
			num2 = server.FlyMove(ent, (float)host.FrameTime, trace_t);
			if (num2 != 0 && (double)Math.Abs(origin.y - ent.v.origin.y) < 0.03125 && (double)Math.Abs(origin.x - ent.v.origin.x) < 0.03125)
			{
				num2 = server.TryUnstick(ent, ref velocity);
			}
			if ((num2 & 2) != 0)
			{
				server.WallFriction(ent, trace_t);
			}
			trace_t trace_t2 = server.PushEntity(ent, ref v3f);
			if ((double)trace_t2.plane.normal.Z > 0.7)
			{
				if (ent.v.solid == 4f)
				{
					ent.v.flags = (float)((int)ent.v.flags | 512);
					ent.v.groundentity = server.EdictToProg(trace_t2.ent);
					return;
				}
			}
			else
			{
				ent.v.origin = origin2;
				ent.v.velocity = velocity2;
			}
		}

		private static int TryUnstick(edict_t ent, ref v3f oldvel)
		{
			v3f origin = ent.v.origin;
			v3f zeroVector3f = common.ZeroVector3f;
			trace_t steptrace = new trace_t();
			for (int i = 0; i < 8; i++)
			{
				switch (i)
				{
				case 0:
					zeroVector3f.x = 2f;
					zeroVector3f.y = 0f;
					break;
				case 1:
					zeroVector3f.x = 0f;
					zeroVector3f.y = 2f;
					break;
				case 2:
					zeroVector3f.x = -2f;
					zeroVector3f.y = 0f;
					break;
				case 3:
					zeroVector3f.x = 0f;
					zeroVector3f.y = -2f;
					break;
				case 4:
					zeroVector3f.x = 2f;
					zeroVector3f.y = 2f;
					break;
				case 5:
					zeroVector3f.x = -2f;
					zeroVector3f.y = 2f;
					break;
				case 6:
					zeroVector3f.x = 2f;
					zeroVector3f.y = -2f;
					break;
				case 7:
					zeroVector3f.x = -2f;
					zeroVector3f.y = -2f;
					break;
				}
				server.PushEntity(ent, ref zeroVector3f);
				ent.v.velocity.x = oldvel.x;
				ent.v.velocity.y = oldvel.y;
				ent.v.velocity.z = 0f;
				int result = server.FlyMove(ent, 0.1f, steptrace);
				if (Math.Abs(origin.y - ent.v.origin.y) > 4f || Math.Abs(origin.x - ent.v.origin.x) > 4f)
				{
					return result;
				}
				ent.v.origin = origin;
			}
			ent.v.velocity = common.ZeroVector3f;
			return 7;
		}

		private static void WallFriction(edict_t ent, trace_t trace)
		{
			Vector3 vector = common.ToVector(ref ent.v.v_angle);
			Vector3 right;
			Vector3 vector2;
			Vector3 vector3;
			mathlib.AngleVectors(ref vector, out right, out vector2, out vector3);
			float num = Vector3.Dot(trace.plane.normal, right);
			num += 0.5f;
			if (num >= 0f)
			{
				return;
			}
			Vector3 vector4 = common.ToVector(ref ent.v.velocity);
			float scale = Vector3.Dot(trace.plane.normal, vector4);
			Vector3 right2 = trace.plane.normal * scale;
			Vector3 vector5 = vector4 - right2;
			ent.v.velocity.x = vector5.X * (1f + num);
			ent.v.velocity.y = vector5.Y * (1f + num);
		}

		private static void CheckStuck(edict_t ent)
		{
			if (server.TestEntityPosition(ent) == null)
			{
				ent.v.oldorigin = ent.v.origin;
				return;
			}
			v3f origin = ent.v.origin;
			ent.v.origin = ent.v.oldorigin;
			if (server.TestEntityPosition(ent) == null)
			{
				Con.DPrint("Unstuck.\n", Array.Empty<object>());
				server.LinkEdict(ent, true);
				return;
			}
			for (int i = 0; i < 18; i++)
			{
				for (int j = -1; j <= 1; j++)
				{
					for (int k = -1; k <= 1; k++)
					{
						ent.v.origin.x = origin.x + (float)j;
						ent.v.origin.y = origin.y + (float)k;
						ent.v.origin.z = origin.z + (float)i;
						if (server.TestEntityPosition(ent) == null)
						{
							Con.DPrint("Unstuck.\n", Array.Empty<object>());
							server.LinkEdict(ent, true);
							return;
						}
					}
				}
			}
			ent.v.origin = origin;
			Con.DPrint("player is stuck.\n", Array.Empty<object>());
		}

		private static bool CheckWater(edict_t ent)
		{
			Vector3 vector;
			vector.X = ent.v.origin.x;
			vector.Y = ent.v.origin.y;
			vector.Z = ent.v.origin.z + ent.v.mins.z + 1f;
			ent.v.waterlevel = 0f;
			ent.v.watertype = -1f;
			int num = server.PointContents(ref vector);
			if (num <= -3)
			{
				ent.v.watertype = (float)num;
				ent.v.waterlevel = 1f;
				vector.Z = ent.v.origin.z + (ent.v.mins.z + ent.v.maxs.z) * 0.5f;
				num = server.PointContents(ref vector);
				if (num <= -3)
				{
					ent.v.waterlevel = 2f;
					vector.Z = ent.v.origin.z + ent.v.view_ofs.z;
					num = server.PointContents(ref vector);
					if (num <= -3)
					{
						ent.v.waterlevel = 3f;
					}
				}
			}
			return ent.v.waterlevel > 1f;
		}

		private static bool RunThink(edict_t ent)
		{
			float num = ent.v.nextthink;
			if (num <= 0f || (double)num > server.sv.time + host.FrameTime)
			{
				return true;
			}
			if ((double)num < server.sv.time)
			{
				num = (float)server.sv.time;
			}
			ent.v.nextthink = 0f;
			progs.GlobalStruct.time = num;
			progs.GlobalStruct.self = server.EdictToProg(ent);
			progs.GlobalStruct.other = server.EdictToProg(server.sv.edicts[0]);
			progs.Execute(ent.v.think);
			return !ent.free;
		}

		private static void CheckVelocity(edict_t ent)
		{
			if (mathlib.CheckNaN(ref ent.v.velocity, 0f))
			{
				Con.Print("Got a NaN velocity on {0}\n", new object[]
				{
					progs.GetString(ent.v.classname)
				});
			}
			if (mathlib.CheckNaN(ref ent.v.origin, 0f))
			{
				Con.Print("Got a NaN origin on {0}\n", new object[]
				{
					progs.GetString(ent.v.classname)
				});
			}
			Vector3 vector = Vector3.One * server._MaxVelocity.Value;
			Vector3 vector2 = -Vector3.One * server._MaxVelocity.Value;
			mathlib.Clamp(ref ent.v.velocity, ref vector2, ref vector, out ent.v.velocity);
		}

		private static int FlyMove(edict_t ent, float time, trace_t steptrace)
		{
			v3f velocity = ent.v.velocity;
			v3f velocity2 = ent.v.velocity;
			int num = 4;
			int num2 = 0;
			Vector3[] array = new Vector3[5];
			int num3 = 0;
			float num4 = time;
			int num5 = 0;
			while (num5 < num && !ent.v.velocity.IsEmpty)
			{
				v3f v3f;
				mathlib.VectorMA(ref ent.v.origin, num4, ref ent.v.velocity, out v3f);
				trace_t trace_t = server.Move(ref ent.v.origin, ref ent.v.mins, ref ent.v.maxs, ref v3f, 0, ent);
				if (trace_t.allsolid)
				{
					ent.v.velocity = default(v3f);
					return 3;
				}
				if (trace_t.fraction > 0f)
				{
					mathlib.Copy(ref trace_t.endpos, out ent.v.origin);
					velocity = ent.v.velocity;
					num3 = 0;
				}
				if (trace_t.fraction == 1f)
				{
					break;
				}
				if (trace_t.ent == null)
				{
					sys.Error("SV_FlyMove: !trace.ent", Array.Empty<object>());
				}
				if ((double)trace_t.plane.normal.Z > 0.7)
				{
					num2 |= 1;
					if (trace_t.ent.v.solid == 4f)
					{
						ent.v.flags = (float)((int)ent.v.flags | 512);
						ent.v.groundentity = server.EdictToProg(trace_t.ent);
					}
				}
				if (trace_t.plane.normal.Z == 0f)
				{
					num2 |= 2;
					if (steptrace != null)
					{
						steptrace.CopyFrom(trace_t);
					}
				}
				server.Impact(ent, trace_t.ent);
				if (ent.free)
				{
					break;
				}
				num4 -= num4 * trace_t.fraction;
				if (num3 >= 5)
				{
					ent.v.velocity = default(v3f);
					return 3;
				}
				array[num3] = trace_t.plane.normal;
				num3++;
				v3f v3f2 = default(v3f);
				int i;
				for (i = 0; i < num3; i++)
				{
					server.ClipVelocity(ref velocity, ref array[i], out v3f2, 1f);
					int num6 = 0;
					while (num6 < num3 && (num6 == i || v3f2.x * array[num6].X + v3f2.y * array[num6].Y + v3f2.z * array[num6].Z >= 0f))
					{
						num6++;
					}
					if (num6 == num3)
					{
						break;
					}
				}
				if (i != num3)
				{
					ent.v.velocity = v3f2;
				}
				else
				{
					if (num3 != 2)
					{
						ent.v.velocity = default(v3f);
						return 7;
					}
					Vector3 vector = Vector3.Cross(array[0], array[1]);
					float scale = vector.X * ent.v.velocity.x + vector.Y * ent.v.velocity.y + vector.Z * ent.v.velocity.z;
					mathlib.Copy(ref vector, out ent.v.velocity);
					mathlib.VectorScale(ref ent.v.velocity, scale, out ent.v.velocity);
				}
				if (mathlib.DotProduct(ref ent.v.velocity, ref velocity2) <= 0f)
				{
					ent.v.velocity = default(v3f);
					return num2;
				}
				num5++;
			}
			return num2;
		}

		private static trace_t Move(ref v3f start, ref v3f mins, ref v3f maxs, ref v3f end, int type, edict_t passedict)
		{
			Vector3 vector;
			mathlib.Copy(ref start, out vector);
			Vector3 vector2;
			mathlib.Copy(ref mins, out vector2);
			Vector3 vector3;
			mathlib.Copy(ref maxs, out vector3);
			Vector3 vector4;
			mathlib.Copy(ref end, out vector4);
			return server.Move(ref vector, ref vector2, ref vector3, ref vector4, type, passedict);
		}

		private static void Impact(edict_t e1, edict_t e2)
		{
			int self = progs.GlobalStruct.self;
			int other = progs.GlobalStruct.other;
			progs.GlobalStruct.time = (float)server.sv.time;
			if (e1.v.touch != 0 && e1.v.solid != 0f)
			{
				progs.GlobalStruct.self = server.EdictToProg(e1);
				progs.GlobalStruct.other = server.EdictToProg(e2);
				progs.Execute(e1.v.touch);
			}
			if (e2.v.touch != 0 && e2.v.solid != 0f)
			{
				progs.GlobalStruct.self = server.EdictToProg(e2);
				progs.GlobalStruct.other = server.EdictToProg(e1);
				progs.Execute(e2.v.touch);
			}
			progs.GlobalStruct.self = self;
			progs.GlobalStruct.other = other;
		}

		private static void PushMove(edict_t pusher, float movetime)
		{
			if (pusher.v.velocity.IsEmpty)
			{
				pusher.v.ltime = pusher.v.ltime + movetime;
				return;
			}
			v3f v3f;
			mathlib.VectorScale(ref pusher.v.velocity, movetime, out v3f);
			v3f v3f2;
			mathlib.VectorAdd(ref pusher.v.absmin, ref v3f, out v3f2);
			v3f v3f3;
			mathlib.VectorAdd(ref pusher.v.absmax, ref v3f, out v3f3);
			v3f origin = pusher.v.origin;
			edict_t[] array = new edict_t[600];
			v3f[] array2 = new v3f[600];
			mathlib.VectorAdd(ref pusher.v.origin, ref v3f, out pusher.v.origin);
			pusher.v.ltime = pusher.v.ltime + movetime;
			server.LinkEdict(pusher, false);
			int num = 0;
			for (int i = 1; i < server.sv.num_edicts; i++)
			{
				edict_t edict_t = server.sv.edicts[i];
				if (!edict_t.free && edict_t.v.movetype != 7f && edict_t.v.movetype != 0f && edict_t.v.movetype != 8f && ((((int)edict_t.v.flags & 512) != 0 && server.ProgToEdict(edict_t.v.groundentity) == pusher) || (edict_t.v.absmin.x < v3f3.x && edict_t.v.absmin.y < v3f3.y && edict_t.v.absmin.z < v3f3.z && edict_t.v.absmax.x > v3f2.x && edict_t.v.absmax.y > v3f2.y && edict_t.v.absmax.z > v3f2.z && server.TestEntityPosition(edict_t) != null)))
				{
					if (edict_t.v.movetype != 3f)
					{
						edict_t.v.flags = (float)((int)edict_t.v.flags & -513);
					}
					v3f origin2 = edict_t.v.origin;
					array2[num] = origin2;
					array[num] = edict_t;
					num++;
					pusher.v.solid = 0f;
					server.PushEntity(edict_t, ref v3f);
					pusher.v.solid = 4f;
					if (server.TestEntityPosition(edict_t) != null && edict_t.v.mins.x != edict_t.v.maxs.x)
					{
						if (edict_t.v.solid != 0f && edict_t.v.solid != 1f)
						{
							edict_t.v.origin = origin2;
							server.LinkEdict(edict_t, true);
							pusher.v.origin = origin;
							server.LinkEdict(pusher, false);
							pusher.v.ltime = pusher.v.ltime - movetime;
							if (pusher.v.blocked != 0)
							{
								progs.GlobalStruct.self = server.EdictToProg(pusher);
								progs.GlobalStruct.other = server.EdictToProg(edict_t);
								progs.Execute(pusher.v.blocked);
							}
							for (int j = 0; j < num; j++)
							{
								array[j].v.origin = array2[j];
								server.LinkEdict(array[j], false);
							}
							return;
						}
						edict_t.v.mins.x = (edict_t.v.mins.y = 0f);
						edict_t.v.maxs = edict_t.v.mins;
					}
				}
			}
		}

		public static edict_t Player
		{
			get
			{
				return server._Player;
			}
		}

		public static void RunClients()
		{
			for (int i = 0; i < server.svs.maxclients; i++)
			{
				host.HostClient = server.svs.clients[i];
				if (host.HostClient.active)
				{
					server._Player = host.HostClient.edict;
					if (!server.ReadClientMessage())
					{
						server.DropClient(false);
					}
					else if (!host.HostClient.spawned)
					{
						host.HostClient.cmd.Clear();
					}
					else if (!server.sv.paused && (server.svs.maxclients > 1 || Key.Destination == keydest_t.key_game))
					{
						server.ClientThink();
					}
				}
			}
		}

		public static void SetIdealPitch()
		{
			if (((int)server._Player.v.flags & 512) == 0)
			{
				return;
			}
			double num = (double)server._Player.v.angles.y * 3.1415926535897931 * 2.0 / 360.0;
			double num2 = Math.Sin(num);
			double num3 = Math.Cos(num);
			float[] array = new float[6];
			for (int i = 0; i < 6; i++)
			{
				v3f origin = server._Player.v.origin;
				origin.x += (float)(num3 * (double)(i + 3) * 12.0);
				origin.y += (float)(num2 * (double)(i + 3) * 12.0);
				origin.z += server._Player.v.view_ofs.z;
				v3f v3f = origin;
				v3f.z -= 160f;
				trace_t trace_t = server.Move(ref origin, ref common.ZeroVector3f, ref common.ZeroVector3f, ref v3f, 1, server._Player);
				if (trace_t.allsolid)
				{
					return;
				}
				if (trace_t.fraction == 1f)
				{
					return;
				}
				array[i] = origin.z + trace_t.fraction * (v3f.z - origin.z);
			}
			float num4 = 0f;
			int num5 = 0;
			for (int j = 1; j < 6; j++)
			{
				float num6 = array[j] - array[j - 1];
				if (num6 <= -0.1f || num6 >= 0.1f)
				{
					if (num4 != 0f && (num6 - num4 > 0.1f || num6 - num4 < -0.1f))
					{
						return;
					}
					num5++;
					num4 = num6;
				}
			}
			if (num4 == 0f)
			{
				server._Player.v.idealpitch = 0f;
				return;
			}
			if (num5 < 2)
			{
				return;
			}
			server._Player.v.idealpitch = -num4 * server._IdealPitchScale.Value;
		}

		private static bool ReadClientMessage()
		{
			for (;;)
			{
				int num = net.GetMessage(host.HostClient.netconnection);
				if (num == -1)
				{
					break;
				}
				if (num == 0)
				{
					return true;
				}
				net.Reader.Reset();
				bool flag = true;
				while (flag)
				{
					if (!host.HostClient.active)
					{
						return false;
					}
					if (net.Reader.IsBadRead)
					{
						goto Block_3;
					}
					switch (net.Reader.ReadChar())
					{
					case -1:
						flag = false;
						num = 1;
						continue;
					case 1:
						continue;
					case 2:
						return false;
					case 3:
						server.ReadClientMove(ref host.HostClient.cmd);
						continue;
					case 4:
					{
						string text = net.Reader.ReadString();
						if (host.HostClient.privileged)
						{
							num = 2;
						}
						else
						{
							num = 0;
						}
						if (common.SameText(text, "status", 6))
						{
							num = 1;
						}
						else if (common.SameText(text, "god", 3))
						{
							num = 1;
						}
						else if (common.SameText(text, "notarget", 8))
						{
							num = 1;
						}
						else if (common.SameText(text, "fly", 3))
						{
							num = 1;
						}
						else if (common.SameText(text, "name", 4))
						{
							num = 1;
						}
						else if (common.SameText(text, "noclip", 6))
						{
							num = 1;
						}
						else if (common.SameText(text, "say", 3))
						{
							num = 1;
						}
						else if (common.SameText(text, "say_team", 8))
						{
							num = 1;
						}
						else if (common.SameText(text, "tell", 4))
						{
							num = 1;
						}
						else if (common.SameText(text, "color", 5))
						{
							num = 1;
						}
						else if (common.SameText(text, "kill", 4))
						{
							num = 1;
						}
						else if (common.SameText(text, "pause", 5))
						{
							num = 1;
						}
						else if (common.SameText(text, "spawn", 5))
						{
							num = 1;
						}
						else if (common.SameText(text, "begin", 5))
						{
							num = 1;
						}
						else if (common.SameText(text, "prespawn", 8))
						{
							num = 1;
						}
						else if (common.SameText(text, "kick", 4))
						{
							num = 1;
						}
						else if (common.SameText(text, "ping", 4))
						{
							num = 1;
						}
						else if (common.SameText(text, "give", 4))
						{
							num = 1;
						}
						else if (common.SameText(text, "ban", 3))
						{
							num = 1;
						}
						if (num == 2)
						{
							Cbuf.InsertText(text);
							continue;
						}
						if (num == 1)
						{
							cmd.ExecuteString(text, cmd_source_t.src_client);
							continue;
						}
						Con.DPrint("{0} tried to {1}\n", new object[]
						{
							host.HostClient.name,
							text
						});
						continue;
					}
					}
					goto Block_4;
				}
				if (num != 1)
				{
					return true;
				}
			}
			Con.DPrint("SV_ReadClientMessage: NET_GetMessage failed\n", Array.Empty<object>());
			return false;
			Block_3:
			Con.DPrint("SV_ReadClientMessage: badread\n", Array.Empty<object>());
			return false;
			Block_4:
			Con.DPrint("SV_ReadClientMessage: unknown command char\n", Array.Empty<object>());
			return false;
		}

		private static void ReadClientMove(ref usercmd_t move)
		{
			client_t hostClient = host.HostClient;
			hostClient.ping_times[hostClient.num_pings % 16] = (float)(server.sv.time - (double)net.Reader.ReadFloat());
			hostClient.num_pings++;
			Vector3 vector = net.Reader.ReadAngles();
			mathlib.Copy(ref vector, out hostClient.edict.v.v_angle);
			move.forwardmove = (float)net.Reader.ReadShort();
			move.sidemove = (float)net.Reader.ReadShort();
			move.upmove = (float)net.Reader.ReadShort();
			int num = net.Reader.ReadByte();
			hostClient.edict.v.button0 = (float)(num & 1);
			hostClient.edict.v.button2 = (float)((num & 2) >> 1);
			int num2 = net.Reader.ReadByte();
			if (num2 != 0)
			{
				hostClient.edict.v.impulse = (float)num2;
			}
		}

		private static void ClientThink()
		{
			if (server._Player.v.movetype == 0f)
			{
				return;
			}
			server._OnGround = (((int)server._Player.v.flags & 512) != 0);
			server.DropPunchAngle();
			if (server._Player.v.health <= 0f)
			{
				return;
			}
			server._Cmd = host.HostClient.cmd;
			v3f v3f;
			mathlib.VectorAdd(ref server._Player.v.v_angle, ref server._Player.v.punchangle, out v3f);
			Vector3 vector = common.ToVector(ref server._Player.v.angles);
			Vector3 vector2 = common.ToVector(ref server._Player.v.velocity);
			server._Player.v.angles.z = view.CalcRoll(ref vector, ref vector2) * 4f;
			if (server._Player.v.fixangle == 0f)
			{
				server._Player.v.angles.x = -v3f.x / 3f;
				server._Player.v.angles.y = v3f.y;
			}
			if (((int)server._Player.v.flags & 2048) != 0)
			{
				server.WaterJump();
				return;
			}
			if (server._Player.v.waterlevel >= 2f && server._Player.v.movetype != 8f)
			{
				server.WaterMove();
				return;
			}
			server.AirMove();
		}

		private static void DropPunchAngle()
		{
			Vector3 vec = common.ToVector(ref server._Player.v.punchangle);
			double num = (double)mathlib.Normalize(ref vec) - 10.0 * host.FrameTime;
			if (num < 0.0)
			{
				num = 0.0;
			}
			vec *= (float)num;
			mathlib.Copy(ref vec, out server._Player.v.punchangle);
		}

		private static void WaterJump()
		{
			if (server.sv.time > (double)server._Player.v.teleport_time || server._Player.v.waterlevel == 0f)
			{
				server._Player.v.flags = (float)((int)server._Player.v.flags & -2049);
				server._Player.v.teleport_time = 0f;
			}
			server._Player.v.velocity.x = server._Player.v.movedir.x;
			server._Player.v.velocity.y = server._Player.v.movedir.y;
		}

		private static void WaterMove()
		{
			Vector3 vector = common.ToVector(ref server._Player.v.v_angle);
			mathlib.AngleVectors(ref vector, out server._Forward, out server._Right, out server._Up);
			Vector3 vector2 = server._Forward * server._Cmd.forwardmove + server._Right * server._Cmd.sidemove;
			if (server._Cmd.forwardmove == 0f && server._Cmd.sidemove == 0f && server._Cmd.upmove == 0f)
			{
				vector2.Z -= 60f;
			}
			else
			{
				vector2.Z += server._Cmd.upmove;
			}
			float num = vector2.Length;
			if (num > server._MaxSpeed.Value)
			{
				vector2 *= server._MaxSpeed.Value / num;
				num = server._MaxSpeed.Value;
			}
			num *= 0.7f;
			float num2 = mathlib.Length(ref server._Player.v.velocity);
			float num3;
			if (num2 != 0f)
			{
				num3 = (float)((double)num2 - host.FrameTime * (double)num2 * (double)server._Friction.Value);
				if (num3 < 0f)
				{
					num3 = 0f;
				}
				mathlib.VectorScale(ref server._Player.v.velocity, num3 / num2, out server._Player.v.velocity);
			}
			else
			{
				num3 = 0f;
			}
			if (num == 0f)
			{
				return;
			}
			float num4 = num - num3;
			if (num4 <= 0f)
			{
				return;
			}
			mathlib.Normalize(ref vector2);
			float num5 = (float)((double)(server._Accelerate.Value * num) * host.FrameTime);
			if (num5 > num4)
			{
				num5 = num4;
			}
			vector2 *= num5;
			edict_t player = server._Player;
			player.v.velocity.x = player.v.velocity.x + vector2.X;
			edict_t player2 = server._Player;
			player2.v.velocity.y = player2.v.velocity.y + vector2.Y;
			edict_t player3 = server._Player;
			player3.v.velocity.z = player3.v.velocity.z + vector2.Z;
		}

		private static void AirMove()
		{
			Vector3 vector = common.ToVector(ref server._Player.v.angles);
			mathlib.AngleVectors(ref vector, out server._Forward, out server._Right, out server._Up);
			float num = server._Cmd.forwardmove;
			float sidemove = server._Cmd.sidemove;
			if (server.sv.time < (double)server._Player.v.teleport_time && num < 0f)
			{
				num = 0f;
			}
			Vector3 vector2 = server._Forward * num + server._Right * sidemove;
			if ((int)server._Player.v.movetype != 3)
			{
				vector2.Z = server._Cmd.upmove;
			}
			else
			{
				vector2.Z = 0f;
			}
			server._WishDir = vector2;
			server._WishSpeed = mathlib.Normalize(ref server._WishDir);
			if (server._WishSpeed > server._MaxSpeed.Value)
			{
				vector2 *= server._MaxSpeed.Value / server._WishSpeed;
				server._WishSpeed = server._MaxSpeed.Value;
			}
			if (server._Player.v.movetype == 8f)
			{
				mathlib.Copy(ref vector2, out server._Player.v.velocity);
				return;
			}
			if (server._OnGround)
			{
				server.UserFriction();
				server.Accelerate();
				return;
			}
			server.AirAccelerate(vector2);
		}

		private static void UserFriction()
		{
			float num = mathlib.LengthXY(ref server._Player.v.velocity);
			if (num == 0f)
			{
				return;
			}
			Vector3 vector;
			Vector3 vector2;
			vector.X = (vector2.X = server._Player.v.origin.x + server._Player.v.velocity.x / num * 16f);
			vector.Y = (vector2.Y = server._Player.v.origin.y + server._Player.v.velocity.y / num * 16f);
			vector.Z = server._Player.v.origin.z + server._Player.v.mins.z;
			vector2.Z = vector.Z - 34f;
			trace_t trace_t = server.Move(ref vector, ref common.ZeroVector, ref common.ZeroVector, ref vector2, 1, server._Player);
			float num2 = server._Friction.Value;
			if ((double)trace_t.fraction == 1.0)
			{
				num2 *= server._EdgeFriction.Value;
			}
			float num3 = (num < server._StopSpeed.Value) ? server._StopSpeed.Value : num;
			float num4 = (float)((double)num - host.FrameTime * (double)num3 * (double)num2);
			if (num4 < 0f)
			{
				num4 = 0f;
			}
			num4 /= num;
			mathlib.VectorScale(ref server._Player.v.velocity, num4, out server._Player.v.velocity);
		}

		private static void Accelerate()
		{
			float num = Vector3.Dot(common.ToVector(ref server._Player.v.velocity), server._WishDir);
			float num2 = server._WishSpeed - num;
			if (num2 <= 0f)
			{
				return;
			}
			float num3 = (float)((double)server._Accelerate.Value * host.FrameTime * (double)server._WishSpeed);
			if (num3 > num2)
			{
				num3 = num2;
			}
			edict_t player = server._Player;
			player.v.velocity.x = player.v.velocity.x + server._WishDir.X * num3;
			edict_t player2 = server._Player;
			player2.v.velocity.y = player2.v.velocity.y + server._WishDir.Y * num3;
			edict_t player3 = server._Player;
			player3.v.velocity.z = player3.v.velocity.z + server._WishDir.Z * num3;
		}

		private static void AirAccelerate(Vector3 wishveloc)
		{
			float num = mathlib.Normalize(ref wishveloc);
			if (num > 30f)
			{
				num = 30f;
			}
			float num2 = Vector3.Dot(common.ToVector(ref server._Player.v.velocity), wishveloc);
			float num3 = num - num2;
			if (num3 <= 0f)
			{
				return;
			}
			float num4 = (float)((double)(server._Accelerate.Value * server._WishSpeed) * host.FrameTime);
			if (num4 > num3)
			{
				num4 = num3;
			}
			wishveloc *= num4;
			edict_t player = server._Player;
			player.v.velocity.x = player.v.velocity.x + wishveloc.X;
			edict_t player2 = server._Player;
			player2.v.velocity.y = player2.v.velocity.y + wishveloc.Y;
			edict_t player3 = server._Player;
			player3.v.velocity.z = player3.v.velocity.z + wishveloc.Z;
		}

		public static void ClearWorld()
		{
			server.InitBoxHull();
			areanode_t[] areaNodes = server._AreaNodes;
			for (int i = 0; i < areaNodes.Length; i++)
			{
				areaNodes[i].Clear();
			}
			server._NumAreaNodes = 0;
			server.CreateAreaNode(0, ref server.sv.worldmodel.mins, ref server.sv.worldmodel.maxs);
		}

		public static void UnlinkEdict(edict_t ent)
		{
			if (ent.area.Prev == null)
			{
				return;
			}
			ent.area.Remove();
		}

		public static void LinkEdict(edict_t ent, bool touch_triggers)
		{
			if (ent.area.Prev != null)
			{
				server.UnlinkEdict(ent);
			}
			if (ent == server.sv.edicts[0])
			{
				return;
			}
			if (ent.free)
			{
				return;
			}
			mathlib.VectorAdd(ref ent.v.origin, ref ent.v.mins, out ent.v.absmin);
			mathlib.VectorAdd(ref ent.v.origin, ref ent.v.maxs, out ent.v.absmax);
			if (((int)ent.v.flags & 256) != 0)
			{
				ent.v.absmin.x = ent.v.absmin.x - 15f;
				ent.v.absmin.y = ent.v.absmin.y - 15f;
				ent.v.absmax.x = ent.v.absmax.x + 15f;
				ent.v.absmax.y = ent.v.absmax.y + 15f;
			}
			else
			{
				ent.v.absmin.x = ent.v.absmin.x - 1f;
				ent.v.absmin.y = ent.v.absmin.y - 1f;
				ent.v.absmin.z = ent.v.absmin.z - 1f;
				ent.v.absmax.x = ent.v.absmax.x + 1f;
				ent.v.absmax.y = ent.v.absmax.y + 1f;
				ent.v.absmax.z = ent.v.absmax.z + 1f;
			}
			ent.num_leafs = 0;
			if (ent.v.modelindex != 0f)
			{
				server.FindTouchedLeafs(ent, server.sv.worldmodel.nodes[0]);
			}
			if (ent.v.solid == 0f)
			{
				return;
			}
			areanode_t areanode_t = server._AreaNodes[0];
			while (areanode_t.axis != -1)
			{
				if (mathlib.Comp(ref ent.v.absmin, areanode_t.axis) > areanode_t.dist)
				{
					areanode_t = areanode_t.children[0];
				}
				else
				{
					if (mathlib.Comp(ref ent.v.absmax, areanode_t.axis) >= areanode_t.dist)
					{
						break;
					}
					areanode_t = areanode_t.children[1];
				}
			}
			if (ent.v.solid == 1f)
			{
				ent.area.InsertBefore(areanode_t.trigger_edicts);
			}
			else
			{
				ent.area.InsertBefore(areanode_t.solid_edicts);
			}
			if (touch_triggers)
			{
				server.TouchLinks(ent, server._AreaNodes[0]);
			}
		}

		public static int PointContents(ref Vector3 p)
		{
			int num = server.HullPointContents(server.sv.worldmodel.hulls[0], 0, ref p);
			if (num <= -9 && num >= -14)
			{
				num = -3;
			}
			return num;
		}

		public static trace_t Move(ref Vector3 start, ref Vector3 mins, ref Vector3 maxs, ref Vector3 end, int type, edict_t passedict)
		{
			server.moveclip_t moveclip_t = new server.moveclip_t();
			moveclip_t.trace = server.ClipMoveToEntity(server.sv.edicts[0], ref start, ref mins, ref maxs, ref end);
			moveclip_t.start = start;
			moveclip_t.end = end;
			moveclip_t.mins = mins;
			moveclip_t.maxs = maxs;
			moveclip_t.type = type;
			moveclip_t.passedict = passedict;
			if (type == 2)
			{
				moveclip_t.mins2 = Vector3.One * -15f;
				moveclip_t.maxs2 = Vector3.One * 15f;
			}
			else
			{
				moveclip_t.mins2 = mins;
				moveclip_t.maxs2 = maxs;
			}
			server.MoveBounds(ref start, ref moveclip_t.mins2, ref moveclip_t.maxs2, ref end, out moveclip_t.boxmins, out moveclip_t.boxmaxs);
			server.ClipToLinks(server._AreaNodes[0], moveclip_t);
			return moveclip_t.trace;
		}

		public static bool RecursiveHullCheck(hull_t hull, int num, float p1f, float p2f, ref Vector3 p1, ref Vector3 p2, trace_t trace)
		{
			if (num < 0)
			{
				if (num != -2)
				{
					trace.allsolid = false;
					if (num == -1)
					{
						trace.inopen = true;
					}
					else
					{
						trace.inwater = true;
					}
				}
				else
				{
					trace.startsolid = true;
				}
				return true;
			}
			if (num < hull.firstclipnode || num > hull.lastclipnode)
			{
				sys.Error("SV_RecursiveHullCheck: bad node number", Array.Empty<object>());
			}
			short[] children = hull.clipnodes[num].children;
			mplane_t mplane_t = hull.planes[hull.clipnodes[num].planenum];
			float num2;
			float num3;
			if (mplane_t.type < 3)
			{
				num2 = mathlib.Comp(ref p1, (int)mplane_t.type) - mplane_t.dist;
				num3 = mathlib.Comp(ref p2, (int)mplane_t.type) - mplane_t.dist;
			}
			else
			{
				num2 = Vector3.Dot(mplane_t.normal, p1) - mplane_t.dist;
				num3 = Vector3.Dot(mplane_t.normal, p2) - mplane_t.dist;
			}
			if (num2 >= 0f && num3 >= 0f)
			{
				return server.RecursiveHullCheck(hull, (int)children[0], p1f, p2f, ref p1, ref p2, trace);
			}
			if (num2 < 0f && num3 < 0f)
			{
				return server.RecursiveHullCheck(hull, (int)children[1], p1f, p2f, ref p1, ref p2, trace);
			}
			float num4;
			if (num2 < 0f)
			{
				num4 = (num2 + 0.03125f) / (num2 - num3);
			}
			else
			{
				num4 = (num2 - 0.03125f) / (num2 - num3);
			}
			if (num4 < 0f)
			{
				num4 = 0f;
			}
			if (num4 > 1f)
			{
				num4 = 1f;
			}
			float num5 = p1f + (p2f - p1f) * num4;
			Vector3 endpos = p1 + (p2 - p1) * num4;
			int num6 = (num2 < 0f) ? 1 : 0;
			if (!server.RecursiveHullCheck(hull, (int)children[num6], p1f, num5, ref p1, ref endpos, trace))
			{
				return false;
			}
			if (server.HullPointContents(hull, (int)children[num6 ^ 1], ref endpos) != -2)
			{
				return server.RecursiveHullCheck(hull, (int)children[num6 ^ 1], num5, p2f, ref endpos, ref p2, trace);
			}
			if (trace.allsolid)
			{
				return false;
			}
			if (num6 == 0)
			{
				trace.plane.normal = mplane_t.normal;
				trace.plane.dist = mplane_t.dist;
			}
			else
			{
				trace.plane.normal = -mplane_t.normal;
				trace.plane.dist = -mplane_t.dist;
			}
			while (server.HullPointContents(hull, hull.firstclipnode, ref endpos) == -2)
			{
				num4 -= 0.1f;
				if (num4 < 0f)
				{
					trace.fraction = num5;
					trace.endpos = endpos;
					Con.DPrint("backup past 0\n", Array.Empty<object>());
					return false;
				}
				num5 = p1f + (p2f - p1f) * num4;
				endpos = p1 + (p2 - p1) * num4;
			}
			trace.fraction = num5;
			trace.endpos = endpos;
			return false;
		}

		private static areanode_t CreateAreaNode(int depth, ref Vector3 mins, ref Vector3 maxs)
		{
			areanode_t areanode_t = server._AreaNodes[server._NumAreaNodes];
			server._NumAreaNodes++;
			areanode_t.trigger_edicts.Clear();
			areanode_t.solid_edicts.Clear();
			if (depth == 4)
			{
				areanode_t.axis = -1;
				areanode_t.children[0] = (areanode_t.children[1] = null);
				return areanode_t;
			}
			Vector3 vector = maxs - mins;
			Vector3 vector2 = mins;
			Vector3 vector3 = mins;
			Vector3 vector4 = maxs;
			Vector3 vector5 = maxs;
			if (vector.X > vector.Y)
			{
				areanode_t.axis = 0;
				areanode_t.dist = 0.5f * (maxs.X + mins.X);
				vector4.X = (vector3.X = areanode_t.dist);
			}
			else
			{
				areanode_t.axis = 1;
				areanode_t.dist = 0.5f * (maxs.Y + mins.Y);
				vector4.Y = (vector3.Y = areanode_t.dist);
			}
			areanode_t.children[0] = server.CreateAreaNode(depth + 1, ref vector3, ref vector5);
			areanode_t.children[1] = server.CreateAreaNode(depth + 1, ref vector2, ref vector4);
			return areanode_t;
		}

		private static edict_t TestEntityPosition(edict_t ent)
		{
			if (server.Move(ref ent.v.origin, ref ent.v.mins, ref ent.v.maxs, ref ent.v.origin, 0, ent).startsolid)
			{
				return server.sv.edicts[0];
			}
			return null;
		}

		private static void InitBoxHull()
		{
			server._BoxHull.clipnodes = server._BoxClipNodes;
			server._BoxHull.planes = server._BoxPlanes;
			server._BoxHull.firstclipnode = 0;
			server._BoxHull.lastclipnode = 5;
			for (int i = 0; i < 6; i++)
			{
				server._BoxClipNodes[i].planenum = i;
				int num = i & 1;
				server._BoxClipNodes[i].children[num] = -1;
				if (i != 5)
				{
					server._BoxClipNodes[i].children[num ^ 1] = (short)(i + 1);
				}
				else
				{
					server._BoxClipNodes[i].children[num ^ 1] = -2;
				}
				server._BoxPlanes[i].type = (byte)(i >> 1);
				switch (i >> 1)
				{
				case 0:
					server._BoxPlanes[i].normal.X = 1f;
					break;
				case 1:
					server._BoxPlanes[i].normal.Y = 1f;
					break;
				case 2:
					server._BoxPlanes[i].normal.Z = 1f;
					break;
				}
			}
		}

		private static hull_t HullForBox(ref Vector3 mins, ref Vector3 maxs)
		{
			server._BoxPlanes[0].dist = maxs.X;
			server._BoxPlanes[1].dist = mins.X;
			server._BoxPlanes[2].dist = maxs.Y;
			server._BoxPlanes[3].dist = mins.Y;
			server._BoxPlanes[4].dist = maxs.Z;
			server._BoxPlanes[5].dist = mins.Z;
			return server._BoxHull;
		}

		private static hull_t HullForEntity(edict_t ent, ref Vector3 mins, ref Vector3 maxs, out Vector3 offset)
		{
			hull_t hull_t;
			if (ent.v.solid == 4f)
			{
				if (ent.v.movetype != 7f)
				{
					sys.Error("SOLID_BSP without MOVETYPE_PUSH", Array.Empty<object>());
				}
				model_t model_t = server.sv.models[(int)ent.v.modelindex];
				if (model_t == null || model_t.type != modtype_t.mod_brush)
				{
					sys.Error("MOVETYPE_PUSH with a non bsp model", Array.Empty<object>());
				}
				Vector3 vector = maxs - mins;
				if (vector.X < 3f)
				{
					hull_t = model_t.hulls[0];
				}
				else if (vector.X <= 32f)
				{
					hull_t = model_t.hulls[1];
				}
				else
				{
					hull_t = model_t.hulls[2];
				}
				offset = hull_t.clip_mins - mins;
				offset += common.ToVector(ref ent.v.origin);
			}
			else
			{
				Vector3 vector2 = common.ToVector(ref ent.v.mins) - maxs;
				Vector3 vector3 = common.ToVector(ref ent.v.maxs) - mins;
				hull_t = server.HullForBox(ref vector2, ref vector3);
				offset = common.ToVector(ref ent.v.origin);
			}
			return hull_t;
		}

		private static void FindTouchedLeafs(edict_t ent, mnodebase_t node)
		{
			if (node.contents == -2)
			{
				return;
			}
			if (node.contents >= 0)
			{
				mnode_t mnode_t = (mnode_t)node;
				mplane_t plane = mnode_t.plane;
				int num = mathlib.BoxOnPlaneSide(ref ent.v.absmin, ref ent.v.absmax, plane);
				if ((num & 1) != 0)
				{
					server.FindTouchedLeafs(ent, mnode_t.children[0]);
				}
				if ((num & 2) != 0)
				{
					server.FindTouchedLeafs(ent, mnode_t.children[1]);
				}
				return;
			}
			if (ent.num_leafs == 16)
			{
				return;
			}
			mleaf_t value = (mleaf_t)node;
			int num2 = Array.IndexOf<mleaf_t>(server.sv.worldmodel.leafs, value) - 1;
			ent.leafnums[ent.num_leafs] = (short)num2;
			ent.num_leafs++;
		}

		private static void TouchLinks(edict_t ent, areanode_t node)
		{
			link_t next;
			for (link_t link_t = node.trigger_edicts.Next; link_t != node.trigger_edicts; link_t = next)
			{
				next = link_t.Next;
				edict_t edict_t = (edict_t)link_t.Owner;
				if (edict_t != ent && edict_t.v.touch != 0 && edict_t.v.solid == 1f && ent.v.absmin.x <= edict_t.v.absmax.x && ent.v.absmin.y <= edict_t.v.absmax.y && ent.v.absmin.z <= edict_t.v.absmax.z && ent.v.absmax.x >= edict_t.v.absmin.x && ent.v.absmax.y >= edict_t.v.absmin.y && ent.v.absmax.z >= edict_t.v.absmin.z)
				{
					int self = progs.GlobalStruct.self;
					int other = progs.GlobalStruct.other;
					progs.GlobalStruct.self = server.EdictToProg(edict_t);
					progs.GlobalStruct.other = server.EdictToProg(ent);
					progs.GlobalStruct.time = (float)server.sv.time;
					progs.Execute(edict_t.v.touch);
					progs.GlobalStruct.self = self;
					progs.GlobalStruct.other = other;
				}
			}
			if (node.axis == -1)
			{
				return;
			}
			if (mathlib.Comp(ref ent.v.absmax, node.axis) > node.dist)
			{
				server.TouchLinks(ent, node.children[0]);
			}
			if (mathlib.Comp(ref ent.v.absmin, node.axis) < node.dist)
			{
				server.TouchLinks(ent, node.children[1]);
			}
		}

		private static trace_t ClipMoveToEntity(edict_t ent, ref Vector3 start, ref Vector3 mins, ref Vector3 maxs, ref Vector3 end)
		{
			trace_t trace_t = new trace_t();
			trace_t.fraction = 1f;
			trace_t.allsolid = true;
			trace_t.endpos = end;
			Vector3 right;
			hull_t hull_t = server.HullForEntity(ent, ref mins, ref maxs, out right);
			Vector3 vector = start - right;
			Vector3 vector2 = end - right;
			server.RecursiveHullCheck(hull_t, hull_t.firstclipnode, 0f, 1f, ref vector, ref vector2, trace_t);
			if (trace_t.fraction != 1f)
			{
				trace_t.endpos += right;
			}
			if (trace_t.fraction < 1f || trace_t.startsolid)
			{
				trace_t.ent = ent;
			}
			return trace_t;
		}

		private static void MoveBounds(ref Vector3 start, ref Vector3 mins, ref Vector3 maxs, ref Vector3 end, out Vector3 boxmins, out Vector3 boxmaxs)
		{
			boxmins = Vector3.ComponentMin(start, end) + mins - Vector3.One;
			boxmaxs = Vector3.ComponentMax(start, end) + maxs + Vector3.One;
		}

		private static void ClipToLinks(areanode_t node, server.moveclip_t clip)
		{
			link_t next;
			for (link_t link_t = node.solid_edicts.Next; link_t != node.solid_edicts; link_t = next)
			{
				next = link_t.Next;
				edict_t edict_t = (edict_t)link_t.Owner;
				if (edict_t.v.solid != 0f && edict_t != clip.passedict)
				{
					if (edict_t.v.solid == 1f)
					{
						sys.Error("Trigger in clipping list", Array.Empty<object>());
					}
					if ((clip.type != 1 || edict_t.v.solid == 4f) && clip.boxmins.X <= edict_t.v.absmax.x && clip.boxmins.Y <= edict_t.v.absmax.y && clip.boxmins.Z <= edict_t.v.absmax.z && clip.boxmaxs.X >= edict_t.v.absmin.x && clip.boxmaxs.Y >= edict_t.v.absmin.y && clip.boxmaxs.Z >= edict_t.v.absmin.z && (clip.passedict == null || clip.passedict.v.size.x == 0f || edict_t.v.size.x != 0f))
					{
						if (clip.trace.allsolid)
						{
							return;
						}
						if (clip.passedict == null || (server.ProgToEdict(edict_t.v.owner) != clip.passedict && server.ProgToEdict(clip.passedict.v.owner) != edict_t))
						{
							trace_t trace_t;
							if (((int)edict_t.v.flags & 32) != 0)
							{
								trace_t = server.ClipMoveToEntity(edict_t, ref clip.start, ref clip.mins2, ref clip.maxs2, ref clip.end);
							}
							else
							{
								trace_t = server.ClipMoveToEntity(edict_t, ref clip.start, ref clip.mins, ref clip.maxs, ref clip.end);
							}
							if (trace_t.allsolid || trace_t.startsolid || trace_t.fraction < clip.trace.fraction)
							{
								trace_t.ent = edict_t;
								if (clip.trace.startsolid)
								{
									clip.trace = trace_t;
									clip.trace.startsolid = true;
								}
								else
								{
									clip.trace = trace_t;
								}
							}
							else if (trace_t.startsolid)
							{
								clip.trace.startsolid = true;
							}
						}
					}
				}
			}
			if (node.axis == -1)
			{
				return;
			}
			if (mathlib.Comp(ref clip.boxmaxs, node.axis) > node.dist)
			{
				server.ClipToLinks(node.children[0], clip);
			}
			if (mathlib.Comp(ref clip.boxmins, node.axis) < node.dist)
			{
				server.ClipToLinks(node.children[1], clip);
			}
		}

		private static int HullPointContents(hull_t hull, int num, ref Vector3 p)
		{
			while (num >= 0)
			{
				if (num < hull.firstclipnode || num > hull.lastclipnode)
				{
					sys.Error("SV_HullPointContents: bad node number", Array.Empty<object>());
				}
				short[] children = hull.clipnodes[num].children;
				mplane_t mplane_t = hull.planes[hull.clipnodes[num].planenum];
				float num2;
				if (mplane_t.type < 3)
				{
					num2 = mathlib.Comp(ref p, (int)mplane_t.type) - mplane_t.dist;
				}
				else
				{
					num2 = Vector3.Dot(mplane_t.normal, p) - mplane_t.dist;
				}
				if (num2 < 0f)
				{
					num = (int)children[1];
				}
				else
				{
					num = (int)children[0];
				}
			}
			return num;
		}

		public const int NUM_PING_TIMES = 16;

		public const int NUM_SPAWN_PARMS = 16;

		private static cvar _Friction;

		private static cvar _EdgeFriction;

		private static cvar _StopSpeed;

		private static cvar _Gravity;

		private static cvar _MaxVelocity;

		private static cvar _NoStep;

		private static cvar _MaxSpeed;

		private static cvar _Accelerate;

		private static cvar _Aim;

		private static cvar _IdealPitchScale;

		private static server_t _Server;

		private static server_static_t _ServerStatic;

		private static string[] _LocalModels = new string[256];

		private static int _FatBytes;

		private static byte[] _FatPvs = new byte[1024];

		private const float DI_NODIR = -1f;

		private const float STOP_EPSILON = 0.1f;

		private const int MAX_CLIP_PLANES = 5;

		private const float STEPSIZE = 18f;

		private const int MAX_FORWARD = 6;

		private static edict_t _Player;

		private static bool _OnGround;

		private static usercmd_t _Cmd;

		private static Vector3 _Forward;

		private static Vector3 _Right;

		private static Vector3 _Up;

		private static Vector3 _WishDir;

		private static float _WishSpeed;

		private const float DIST_EPSILON = 0.03125f;

		private const int MOVE_NORMAL = 0;

		private const int MOVE_NOMONSTERS = 1;

		private const int MOVE_MISSILE = 2;

		private const int AREA_DEPTH = 4;

		private const int AREA_NODES = 32;

		private static areanode_t[] _AreaNodes = new areanode_t[32];

		private static int _NumAreaNodes;

		private static hull_t _BoxHull = new hull_t();

		private static dclipnode_t[] _BoxClipNodes = new dclipnode_t[6];

		private static mplane_t[] _BoxPlanes = new mplane_t[6];

		private class moveclip_t
		{
			public Vector3 boxmins;

			public Vector3 boxmaxs;

			public Vector3 mins;

			public Vector3 maxs;

			public Vector3 mins2;

			public Vector3 maxs2;

			public Vector3 start;

			public Vector3 end;

			public trace_t trace;

			public int type;

			public edict_t passedict;
		}
	}
}
