public override void Tick() { if (!IsSpawned) { return; } if (TheRegion.Delta <= 0) { return; } base.Tick(); opstt += TheRegion.Delta; while (opstt > 1.0) { opstt -= 1.0; OncePerSecondTick(); } ItemStack cit = Items.GetItemForSlot(Items.cItem); if (GetVelocity().LengthSquared() > 1) // TODO: Move animation to CharacterEntity { // TODO: Replicate animation automation on client? SetAnimation("human/stand/run", 0); SetAnimation("human/stand/" + AnimToHold(cit), 1); SetAnimation("human/stand/run", 2); } else { SetAnimation("human/stand/idle01", 0); SetAnimation("human/stand/" + AnimToHold(cit), 1); SetAnimation("human/stand/idle01", 2); } if (Click) // TODO: Move clicking to CharacterEntity { cit.Info.Click(this, cit); LastClick = TheRegion.GlobalTickTime; WasClicking = true; } else if (WasClicking) { cit.Info.ReleaseClick(this, cit); WasClicking = false; } if (AltClick) { cit.Info.AltClick(this, cit); LastAltClick = TheRegion.GlobalTickTime; WasAltClicking = true; } else if (WasAltClicking) { cit.Info.ReleaseAltClick(this, cit); WasAltClicking = false; } cit.Info.Tick(this, cit); WasItemLefting = ItemLeft; WasItemUpping = ItemUp; WasItemRighting = ItemRight; Location pos = LoadRelPos; Vector3i cpos = TheRegion.ChunkLocFor(pos); if (cpos != pChunkLoc) { for (int x = -2; x <= 2; x++) { for (int y = -2; y <= 2; y++) { for (int z = -2; z <= 2; z++) { TryChunk(cpos + new Vector3i(x, y, z), 1); } } } } ChunkMarchAndSend(); if (cpos != pChunkLoc) { /* * // TODO: Better system -> async? * TrySet(pos, 1, 1, 0, 1, false); * TrySet(pos, ViewRadiusInChunks / 2, ViewRadiusInChunks / 2, 0, 1, false); * TrySet(pos, ViewRadiusInChunks, ViewRadiusInChunks, 0, 1, false); * TrySet(pos, ViewRadiusInChunks + 1, ViewRadiusInChunks, 15, 2, true); * TrySet(pos, ViewRadiusInChunks + ViewRadExtra2, ViewRadiusInChunks + ViewRadExtra2Height, 30, 2, true); * TrySet(pos, ViewRadiusInChunks + ViewRadExtra5, ViewRadiusInChunks + ViewRadExtra5Height, 60, 5, true); */ /* * if (!loadedInitially) * { * loadedInitially = true; * ChunkNetwork.SendPacket(new TeleportPacketOut(GetPosition())); * ChunkNetwork.SendPacket(new OperationStatusPacketOut(StatusOperation.CHUNK_LOAD, 1)); * } * else * { * ChunkNetwork.SendPacket(new OperationStatusPacketOut(StatusOperation.CHUNK_LOAD, 2)); * } */ foreach (ChunkAwarenessInfo ch in ChunksAwareOf.Values) { if (!ShouldLoadChunk(ch.ChunkPos)) { removes.Add(ch.ChunkPos); } else if (!ShouldSeeChunk(ch.ChunkPos) && ch.LOD <= BestLOD) { ch.LOD = Chunk.CHUNK_SIZE; } } foreach (Vector3i loc in removes) { Chunk ch = TheRegion.GetChunk(loc); if (ch != null) { ForgetChunk(ch, loc); } else { ChunksAwareOf.Remove(loc); } } removes.Clear(); pChunkLoc = cpos; } if (Breadcrumbs.Count > 0) { double dist = (GetPosition() - Breadcrumbs[Breadcrumbs.Count - 1]).LengthSquared(); if (dist > BreadcrumbRadius * BreadcrumbRadius) { Location one = Breadcrumbs[Breadcrumbs.Count - 1]; Location two = GetPosition().GetBlockLocation() + new Location(0.5f, 0.5f, 0.5f); Breadcrumbs.Add((two - one).Normalize() * BreadcrumbRadius + one); // TODO: Effect? } } // TODO: Move use to CharacterEntity if (Use) { Location forw = ForwardVector(); CollisionResult cr = TheRegion.Collision.RayTrace(GetEyePosition(), GetEyePosition() + forw * 5, IgnoreThis); if (cr.Hit && cr.HitEnt != null && cr.HitEnt.Tag is EntityUseable) { if (UsedNow != (EntityUseable)cr.HitEnt.Tag) { if (UsedNow != null && ((Entity)UsedNow).IsSpawned) { UsedNow.StopUse(this); } UsedNow = (EntityUseable)cr.HitEnt.Tag; UsedNow.StartUse(this); } } else if (UsedNow != null) { if (((Entity)UsedNow).IsSpawned) { UsedNow.StopUse(this); } UsedNow = null; } } else if (UsedNow != null) { if (((Entity)UsedNow).IsSpawned) { UsedNow.StopUse(this); } UsedNow = null; } if (!CanReach(GetPosition())) { Teleport(posClamp(GetPosition())); } }
void ChunkMarchAndSend() { // TODO: is this the most efficient it can be? int maxChunks = TheServer.CVars.n_chunkspertick.ValueI; int chunksFound = 0; if (LoadRelPos.IsNaN() || LoadRelDir.IsNaN() || LoadRelDir.LengthSquared() < 0.1f) { return; } Matrix proj = Matrix.CreatePerspectiveFieldOfViewRH(Max_FOV * (double)Utilities.PI180, 1, 0.5f, 3000f); Matrix view = Matrix.CreateLookAtRH((LoadRelPos - LoadRelDir * 8).ToBVector(), (LoadRelPos + LoadRelDir * 8).ToBVector(), new Vector3(0, 0, 1)); Matrix combined = view * proj; BFrustum bfs = new BFrustum(combined); Vector3i start = TheRegion.ChunkLocFor(LoadRelPos); HashSet <Vector3i> seen = new HashSet <Vector3i>(); Queue <Vector3i> toSee = new Queue <Vector3i>(); toSee.Enqueue(start); while (toSee.Count > 0) { Vector3i cur = toSee.Dequeue(); seen.Add(cur); if (Math.Abs(cur.X - start.X) > (ViewRadiusInChunks + ViewRadExtra5) || Math.Abs(cur.Y - start.Y) > (ViewRadiusInChunks + ViewRadExtra5) || Math.Abs(cur.Z - start.Z) > (ViewRadiusInChunks + ViewRadExtra5Height)) { continue; } if (Math.Abs(cur.X - start.X) <= ViewRadiusInChunks && Math.Abs(cur.Y - start.Y) <= ViewRadiusInChunks && Math.Abs(cur.Z - start.Z) <= ViewRadiusInChunks) { if (TryChunk(cur, 1)) { chunksFound++; if (chunksFound > maxChunks) { return; } } } else if (Math.Abs(cur.X - start.X) <= (ViewRadiusInChunks + ViewRadExtra2) && Math.Abs(cur.Y - start.Y) <= (ViewRadiusInChunks + ViewRadExtra2) && Math.Abs(cur.Z - start.Z) <= (ViewRadiusInChunks + ViewRadExtra2Height)) { if (TryChunk(cur, 2)) { chunksFound++; if (chunksFound > maxChunks) { return; } } } else { if (TryChunk(cur, 5)) { chunksFound++; if (chunksFound > maxChunks) { return; } } } for (int i = 0; i < MoveDirs.Length; i++) { Vector3i t = cur + MoveDirs[i]; if (!seen.Contains(t) && !toSee.Contains(t)) { //toSee.Enqueue(t); for (int j = 0; j < MoveDirs.Length; j++) { if (Vector3.Dot(MoveDirs[j].ToVector3(), LoadRelDir.ToBVector()) < -0.8f) // TODO: Wut? { continue; } Vector3i nt = cur + MoveDirs[j]; if (!seen.Contains(nt) && !toSee.Contains(nt)) { bool val = false; Chunk ch = TheRegion.GetChunk(t); if (ch == null) { val = true; } // TODO: Oh, come on! else if (MoveDirs[i].X == -1) { if (MoveDirs[j].X == -1) { val = ch.Reachability[(int)ChunkReachability.XP_XM]; } else if (MoveDirs[j].Y == -1) { val = ch.Reachability[(int)ChunkReachability.XP_YM]; } else if (MoveDirs[j].Y == 1) { val = ch.Reachability[(int)ChunkReachability.XP_YP]; } else if (MoveDirs[j].Z == -1) { val = ch.Reachability[(int)ChunkReachability.ZM_XP]; } else if (MoveDirs[j].Z == 1) { val = ch.Reachability[(int)ChunkReachability.ZP_XP]; } } else if (MoveDirs[i].X == 1) { if (MoveDirs[j].X == 1) { val = ch.Reachability[(int)ChunkReachability.XP_XM]; } else if (MoveDirs[j].Y == -1) { val = ch.Reachability[(int)ChunkReachability.XM_YM]; } else if (MoveDirs[j].Y == 1) { val = ch.Reachability[(int)ChunkReachability.XM_YP]; } else if (MoveDirs[j].Z == -1) { val = ch.Reachability[(int)ChunkReachability.ZM_XM]; } else if (MoveDirs[j].Z == 1) { val = ch.Reachability[(int)ChunkReachability.ZP_XM]; } } else if (MoveDirs[i].Y == -1) { if (MoveDirs[j].Y == 1) { val = ch.Reachability[(int)ChunkReachability.YP_YM]; } else if (MoveDirs[j].X == -1) { val = ch.Reachability[(int)ChunkReachability.XM_YP]; } else if (MoveDirs[j].X == 1) { val = ch.Reachability[(int)ChunkReachability.XP_YP]; } else if (MoveDirs[j].Z == -1) { val = ch.Reachability[(int)ChunkReachability.ZM_YP]; } else if (MoveDirs[j].Z == 1) { val = ch.Reachability[(int)ChunkReachability.ZP_YP]; } } else if (MoveDirs[i].Y == 1) { if (MoveDirs[j].Y == -1) { val = ch.Reachability[(int)ChunkReachability.YP_YM]; } else if (MoveDirs[j].X == -1) { val = ch.Reachability[(int)ChunkReachability.XM_YP]; } else if (MoveDirs[j].X == 1) { val = ch.Reachability[(int)ChunkReachability.XP_YP]; } else if (MoveDirs[j].Z == -1) { val = ch.Reachability[(int)ChunkReachability.ZM_YP]; } else if (MoveDirs[j].Z == 1) { val = ch.Reachability[(int)ChunkReachability.ZP_YP]; } } else if (MoveDirs[i].Z == -1) { if (MoveDirs[j].Z == 1) { val = ch.Reachability[(int)ChunkReachability.ZP_ZM]; } else if (MoveDirs[j].X == -1) { val = ch.Reachability[(int)ChunkReachability.ZP_XM]; } else if (MoveDirs[j].X == 1) { val = ch.Reachability[(int)ChunkReachability.ZP_XP]; } else if (MoveDirs[j].Y == -1) { val = ch.Reachability[(int)ChunkReachability.ZP_YM]; } else if (MoveDirs[j].Y == 1) { val = ch.Reachability[(int)ChunkReachability.ZP_YP]; } } else if (MoveDirs[i].Z == 1) { if (MoveDirs[j].Z == -1) { val = ch.Reachability[(int)ChunkReachability.ZP_ZM]; } else if (MoveDirs[j].X == -1) { val = ch.Reachability[(int)ChunkReachability.ZM_XM]; } else if (MoveDirs[j].X == 1) { val = ch.Reachability[(int)ChunkReachability.ZM_XP]; } else if (MoveDirs[j].Y == -1) { val = ch.Reachability[(int)ChunkReachability.ZM_YM]; } else if (MoveDirs[j].Y == 1) { val = ch.Reachability[(int)ChunkReachability.ZM_YP]; } } if (val) { Location min = nt.ToLocation() * Chunk.CHUNK_SIZE; if (bfs.ContainsBox(min, min + new Location(Chunk.CHUNK_SIZE))) { toSee.Enqueue(nt); } else { seen.Add(nt); } } } } } } } }
public void UpdateForPacketFromServer(double gtt, long ID, Location pos, Location vel, bool _pup) { ServerLocation = pos; if (ServerFlags.HasFlag(YourStatusFlags.INSECURE_MOVEMENT)) { return; } if (InVehicle) { return; } // TODO: big solid entities! double now = TheRegion.GlobalTickTimeLocal; if (TheClient.CVars.n_movemode.ValueI == 2) { // TODO: Remove outsider chunks! for (int x = -1; x <= 1; x++) { for (int y = -1; y <= 1; y++) { for (int z = -1; z <= 1; z++) { Vector3i ch = TheRegion.ChunkLocFor(pos) + new Vector3i(x, y, z); Chunk chunk = TheRegion.GetChunk(ch); if (chunk == null) { continue; } if (!NMTWOMeshes.ContainsKey(ch)) { if (chunk.FCO != null) { FullChunkObject im = new FullChunkObject(chunk.FCO.Position, chunk.FCO.ChunkShape); NMTWOWorld.Add(im); NMTWOMeshes[ch] = im; } } } } } AddUIS(); int xf = 0; double jumpback = gtt - lGTT; if (jumpback < 0) { return; } double target = TheRegion.GlobalTickTimeLocal - jumpback; UserInputSet past = null; while (xf < Input.Length) { UserInputSet uis = Input[xf]; if (uis.GlobalTimeLocal < target) { past = uis; Input.Pop(); continue; } else if (xf == 0) { double mult = Math.Max(Math.Min(jumpback / TheClient.CVars.n_movement_adjustment.ValueD, 1.0), 0.01); NMTWOSetPosition(uis.Position + (pos - uis.Position) * mult); NMTWOSetVelocity(uis.Velocity + (vel - uis.Velocity) * mult); } xf++; double delta; if (xf < 2) { if (past == null) { continue; } delta = uis.GlobalTimeLocal - target; SetBodyMovement(NMTWOCBody, past); } else { UserInputSet prev = Input[xf - 2]; delta = uis.GlobalTimeLocal - prev.GlobalTimeLocal; SetBodyMovement(NMTWOCBody, prev); } SetMoveSpeed(NMTWOCBody, uis); if (!_pup) { NMTWOTryToJump(uis); } lPT = uis.GlobalTimeLocal; NMTWOWorld.Update((float)delta); FlyForth(NMTWOCBody, uis, delta); // TODO: Entirely disregard NWTWOWorld if flying? } AddUIS(); SetPosition(NMTWOGetPosition()); SetVelocity(new Location(NMTWOCBody.Body.LinearVelocity)); pup = _pup; lGTT = gtt; } else { double delta = lPT - now; Location dir = pos - TheClient.Player.GetPosition(); if (dir.LengthSquared() < TheClient.CVars.n_movement_maxdistance.ValueF * TheClient.CVars.n_movement_maxdistance.ValueF) { SetPosition(GetPosition() + dir / Math.Max(TheClient.CVars.n_movement_adjustment.ValueF / delta, 1)); Location veldir = vel - GetVelocity(); SetVelocity(GetVelocity() + veldir / Math.Max(TheClient.CVars.n_movement_adjustment.ValueF / delta, 1)); } else { TheClient.Player.SetPosition(pos); TheClient.Player.SetVelocity(vel); } lPT = now; } }