Example #1
0
        public bool IsVisibleIndoors(ObjCell cell)
        {
            var blockDist = PhysicsObj.GetBlockDist(ID, cell.ID);

            // if landblocks equal
            if (blockDist == 0)
            {
                // check env VisibleCells
                var cellID = cell.ID & 0xFFFF;
                if (VisibleCells.ContainsKey(cellID))
                {
                    return(true);
                }
            }
            return(SeenOutside && blockDist <= 1);
        }
Example #2
0
        /// <summary>
        /// Used by physics engine to actually update a player position
        /// Automatically notifies clients of updated position
        /// </summary>
        /// <param name="newPosition">The new position being requested, before verification through physics engine</param>
        /// <returns>TRUE if object moves to a different landblock</returns>
        public bool UpdatePlayerPosition(ACE.Entity.Position newPosition, bool forceUpdate = false)
        {
            //Console.WriteLine($"{Name}.UpdatePlayerPhysics({newPosition}, {forceUpdate}, {Teleporting})");
            bool verifyContact = false;

            // possible bug: while teleporting, client can still send AutoPos packets from old landblock
            if (Teleporting && !forceUpdate)
            {
                return(false);
            }

            // pre-validate movement
            if (!ValidateMovement(newPosition))
            {
                log.Error($"{Name}.UpdatePlayerPosition() - movement pre-validation failed from {Location} to {newPosition}");
                return(false);
            }

            try
            {
                if (!forceUpdate) // This is needed beacuse this function might be called recursively
                {
                    stopwatch.Restart();
                }

                var success = true;

                if (PhysicsObj != null)
                {
                    var distSq = Location.SquaredDistanceTo(newPosition);

                    if (distSq > PhysicsGlobals.EpsilonSq)
                    {
                        /*var p = new Physics.Common.Position(newPosition);
                         * var dist = PhysicsObj.Position.Distance(p);
                         * Console.WriteLine($"Dist: {dist}");*/

                        if (newPosition.Landblock == 0x18A && Location.Landblock != 0x18A)
                        {
                            log.Info($"{Name} is getting swanky");
                        }

                        if (!Teleporting)
                        {
                            var blockDist = PhysicsObj.GetBlockDist(Location.ObjCellID, newPosition.ObjCellID);

                            // verify movement
                            if (distSq > MaxSpeedSq && blockDist > 1)
                            {
                                //Session.Network.EnqueueSend(new GameMessageSystemChat("Movement error", ChatMessageType.Broadcast));
                                log.Warn($"MOVEMENT SPEED: {Name} trying to move from {Location} to {newPosition}, speed: {Math.Sqrt(distSq)}");
                                return(false);
                            }

                            // verify z-pos
                            if (blockDist == 0 && LastGroundPos != null && newPosition.Pos.Z - LastGroundPos.Pos.Z > 10 && DateTime.UtcNow - LastJumpTime > TimeSpan.FromSeconds(1) && GetCreatureSkill(Skill.Jump).Current < 1000)
                            {
                                verifyContact = true;
                            }
                        }

                        var curCell = LScape.get_landcell(newPosition.LongObjCellID);
                        if (curCell != null)
                        {
                            //if (PhysicsObj.CurCell == null || curCell.ID != PhysicsObj.CurCell.ID)
                            //PhysicsObj.change_cell_server(curCell);

                            PhysicsObj.set_request_pos(newPosition.Pos, newPosition.Rotation, newPosition.Instance, curCell, Location.ObjCellID);
                            if (FastTick)
                            {
                                success = PhysicsObj.update_object_server_new(true, newPosition.Instance);
                            }
                            else
                            {
                                success = PhysicsObj.update_object_server(true, newPosition.Instance);
                            }

                            if (PhysicsObj.CurCell == null && curCell.ID >> 16 != 0x18A)
                            {
                                PhysicsObj.CurCell = curCell;
                            }

                            if (verifyContact && IsJumping)
                            {
                                log.Warn($"z-pos hacking detected for {Name}, lastGroundPos: {LastGroundPos.ToLOCString()} - requestPos: {newPosition.ToLOCString()}");
                                Location = new ACE.Entity.Position(LastGroundPos);
                                Sequences.GetNextSequence(SequenceType.ObjectForcePosition);
                                SendUpdatePosition();
                                return(false);
                            }

                            CheckMonsters();
                        }
                    }
                    else
                    {
                        PhysicsObj.Position.Frame.Orientation = newPosition.Rotation;
                    }
                }

                // double update path: landblock physics update -> updateplayerphysics() -> update_object_server() -> Teleport() -> updateplayerphysics() -> return to end of original branch
                if (Teleporting && !forceUpdate)
                {
                    return(true);
                }

                if (!success)
                {
                    return(false);
                }

                var landblockUpdate = Location.Landblock != newPosition.Landblock;

                Location = newPosition;

                if (RecordCast.Enabled)
                {
                    RecordCast.Log($"CurPos: {Location.ToLOCString()}");
                }

                if (RequestedLocationBroadcast || DateTime.UtcNow - LastUpdatePosition >= MoveToState_UpdatePosition_Threshold)
                {
                    SendUpdatePosition();
                }
                else
                {
                    Session.Network.EnqueueSend(new GameMessageUpdatePosition(this));
                }

                if (!InUpdate)
                {
                    // todo: improve this logic

                    /*if (CurrentLandblock.Instance > 0)
                     * {
                     *  ClearInstance(CurrentLandblock.LongId);
                     * }*/

                    LandblockManager.RelocateObjectForPhysics(this, true);
                }

                return(landblockUpdate);
            }
            finally
            {
                if (!forceUpdate) // This is needed beacuse this function might be called recursively
                {
                    var elapsedSeconds = stopwatch.Elapsed.TotalSeconds;
                    ServerPerformanceMonitor.AddToCumulativeEvent(ServerPerformanceMonitor.CumulativeEventHistoryType.Player_Tick_UpdateObjectPhysics, elapsedSeconds);
                    if (elapsedSeconds >= 0.100) // Yea, that ain't good....
                    {
                        log.Warn($"[PERFORMANCE][PHYSICS] {Guid}:{Name} took {(elapsedSeconds * 1000):N1} ms to process UpdatePlayerPosition() at loc: {Location}");
                    }
                    else if (elapsedSeconds >= 0.010)
                    {
                        log.Debug($"[PERFORMANCE][PHYSICS] {Guid}:{Name} took {(elapsedSeconds * 1000):N1} ms to process UpdatePlayerPosition() at loc: {Location}");
                    }
                }
            }
        }
Example #3
0
        public bool IsVisibleOutdoors(ObjCell cell)
        {
            var blockDist = PhysicsObj.GetBlockDist(ID, cell.ID);

            return(blockDist <= 1);
        }