예제 #1
0
        /// <inheritdoc />
        protected override Task HandleMessage(IPeerSessionMessageContext <GameServerPacketPayload> context, ClientMovementDataUpdateRequest payload, NetworkEntityGuid guid)
        {
            try
            {
                IMovementGenerator <GameObject> generator = MovementGenerator.RetrieveEntity(guid);
                IMovementData movementData = MovementDataMap.RetrieveEntity(guid);
                PositionChangeMovementData changeMovementData = BuildPositionChangeMovementData(payload, generator, movementData);
                MovementDataMap.ReplaceObject(guid, changeMovementData);

                IActorRef playerActorRef = ActorReferenceMappable.RetrieveEntity(guid);

                playerActorRef.TellSelf(new PlayerMovementStateChangedMessage(changeMovementData.Direction));

                //If the generator is running, we should use its initial position instead of the last movement data's position.
                MovementGenerator.ReplaceObject(guid, BuildCharacterControllerMovementGenerator(guid, changeMovementData, generator, movementData));
            }
            catch (Exception e)
            {
                if (Logger.IsErrorEnabled)
                {
                    Logger.Error($"Failed to update MovementData for GUID: {guid} Reason: {e.Message}");
                }

                throw;
            }

            return(Task.CompletedTask);
        }
예제 #2
0
        void Mutate(MovementGenerator m, MovementSlot _slot)
        {
            int slot = (int)_slot;
            MovementGenerator curr = Impl[slot];

            if (curr != null)
            {
                Impl[slot] = null; // in case a new one is generated in this slot during directdelete
                if (_top == slot && Convert.ToBoolean(_cleanFlag & MMCleanFlag.UPDATE))
                {
                    DelayedDelete(curr);
                }
                else
                {
                    DirectDelete(curr);
                }
            }
            else if (_top < slot)
            {
                _top = slot;
            }

            Impl[slot] = m;
            if (_top > slot)
            {
                _needInit[slot] = true;
            }
            else
            {
                _needInit[slot] = false;
                m.Initialize(_owner);
            }
        }
예제 #3
0
        /// <inheritdoc />
        protected override Task HandleMessage(IPeerSessionMessageContext <GameServerPacketPayload> context, ClientRotationDataUpdateRequest payload, NetworkEntityGuid guid)
        {
            try
            {
                IMovementGenerator <GameObject> generator = MovementGenerator.RetrieveEntity(guid);
                IMovementData movementData = MovementDataMap.RetrieveEntity(guid);

                //TODO: This is a temporary hack, we nee d abetter solluition
                if (movementData is PositionChangeMovementData posChangeMoveDat)
                {
                    Vector2 direction = posChangeMoveDat.Direction;

                    //TODO: Sanity check position sent.
                    //TODO: Sanity check timestamp
                    MovementDataMap.ReplaceObject(guid, new PositionChangeMovementData(payload.TimeStamp, payload.ClientCurrentPosition, direction, payload.Rotation));
                }
                else
                {
                    throw new NotImplementedException($"TODO: Implement rotation when dealing with: {movementData.GetType().Name} type movement.");
                }

                OnPlayerRotationChanged?.Invoke(this, new PlayerRotiationChangeEventArgs(guid, payload.Rotation));
            }
            catch (Exception e)
            {
                if (Logger.IsErrorEnabled)
                {
                    Logger.Error($"Failed to update MovementData for GUID: {guid} Reason: {e.Message}");
                }

                throw;
            }

            return(Task.CompletedTask);
        }
예제 #4
0
        void DirectExpire(bool reset)
        {
            if (size() > 1)
            {
                MovementGenerator curr = top();
                pop();
                DirectDelete(curr);
            }

            while (top() == null)
            {
                --_top;
            }

            if (empty())
            {
                Initialize();
            }
            else if (needInitTop())
            {
                InitTop();
            }
            else if (reset)
            {
                top().Reset(_owner);
            }
        }
예제 #5
0
        public void GeneratesRandomMovement()
        {
            MovementGenerator cpu = new MovementGenerator();
            Movement          generatedMovement = cpu.GenerateMovement();

            Assert.IsNotNull(generatedMovement);
            Assert.IsInstanceOf <Movement> (generatedMovement);
        }
예제 #6
0
 void DirectDelete(MovementGenerator curr)
 {
     if (isStatic(curr))
     {
         return;
     }
     curr.Finalize(_owner);
 }
예제 #7
0
        public void SetUp()
        {
            ui        = new MyUITest();
            displayer = Substitute.For <ScoreDisplayer> ();

            cpu = Substitute.For <MovementGenerator> ();
            cpu.GenerateMovement().Returns(new Rock());

            game = new Game(ui, displayer, cpu);
        }
예제 #8
0
        public void UpdateMotion(uint diff)
        {
            lock (locker)
            {
                if (_owner == null)
                {
                    return;
                }

                if (_owner.HasUnitState(UnitState.Root | UnitState.Stunned)) // what about UNIT_STATE_DISTRACTED? Why is this not included?
                {
                    return;
                }

                _cleanFlag |= MMCleanFlag.UPDATE;
                if (top() != null && !top().Update(_owner, diff))
                {
                    _cleanFlag &= ~MMCleanFlag.UPDATE;
                    MovementExpired();
                }
                else
                {
                    _cleanFlag &= ~MMCleanFlag.UPDATE;
                }

                if (_expList != null)
                {
                    for (var i = 0; i < _expList.Count; ++i)
                    {
                        MovementGenerator mg = _expList[i];
                        DirectDelete(mg);
                    }

                    _expList = null;

                    if (empty())
                    {
                        Initialize();
                    }
                    else if (needInitTop())
                    {
                        InitTop();
                    }
                    else if (Convert.ToBoolean(_cleanFlag & MMCleanFlag.RESET))
                    {
                        top().Reset(_owner);
                    }

                    _cleanFlag &= ~MMCleanFlag.RESET;
                }
            }
            // probably not the best place to pu this but im not really sure where else to put it.
            //_owner->UpdateUnderwaterState(_owner->GetMap(), _owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ());
        }
예제 #9
0
 void DelayedClean()
 {
     while (size() > 1)
     {
         MovementGenerator curr = top();
         pop();
         if (curr != null)
         {
             DelayedDelete(curr);
         }
     }
 }
예제 #10
0
 public MotionMaster(Unit unit)
 {
     Impl       = new MovementGenerator[(int)MovementSlot.Max];
     _needInit  = new bool[(int)MovementSlot.Max];
     _expList   = null;
     _top       = -1;
     _cleanFlag = MMCleanFlag.NONE;
     _owner     = unit;
     for (byte i = 0; i < (int)MovementSlot.Max; ++i)
     {
         Impl[i]      = null;
         _needInit[i] = true;
     }
 }
예제 #11
0
        void DelayedExpire()
        {
            if (size() > 1)
            {
                MovementGenerator curr = top();
                pop();
                DelayedDelete(curr);
            }

            while (top() == null)
            {
                --_top;
            }
        }
예제 #12
0
 void DelayedDelete(MovementGenerator curr)
 {
     Log.outError("Unit (Entry {0}) is trying to delete its updating MG (Type {1})!", _owner.GetEntry(),
                  curr.GetMovementGeneratorType());
     if (isStatic(curr))
     {
         return;
     }
     if (_expList == null)
     {
         _expList = new List <MovementGenerator>();
     }
     _expList.Add(curr);
 }
예제 #13
0
        public void Initialize()
        {
            // clear ALL movement generators (including default)
            while (!empty())
            {
                MovementGenerator curr = top();
                pop();
                if (curr != null)
                {
                    DirectDelete(curr);
                }
            }

            InitDefault();
        }
예제 #14
0
        void DirectClean(bool reset)
        {
            while (size() > 1)
            {
                MovementGenerator curr = top();
                pop();
                if (curr != null)
                {
                    DirectDelete(curr);
                }
            }

            if (needInitTop())
            {
                InitTop();
            }
            else if (reset)
            {
                top().Reset(_owner);
            }
        }
예제 #15
0
        public void SetEscortPaused(bool on)
        {
            if (!HasEscortState(EscortState.Escorting))
            {
                return;
            }

            if (on)
            {
                AddEscortState(EscortState.Paused);
                MovementGenerator movementGenerator = me.GetMotionMaster().GetCurrentMovementGenerator(MovementSlot.Default);
                if (movementGenerator != null)
                {
                    movementGenerator.Pause(0);
                }
            }
            else
            {
                RemoveEscortState(EscortState.Paused);
                _resume = true;
            }
        }
예제 #16
0
        /// <inheritdoc />
        protected override Task HandleMessage(IPeerSessionMessageContext <GameServerPacketPayload> context, ClientSetClickToMovePathRequestPayload payload, NetworkEntityGuid guid)
        {
            try
            {
                IMovementGenerator <GameObject> generator = MovementGenerator.RetrieveEntity(guid);

                IMovementData         movementData       = MovementDataMap.RetrieveEntity(guid);
                PathBasedMovementData changeMovementData = BuildPathData(payload, generator, movementData, guid);

                //If it doesn't have more one point reject it
                if (changeMovementData.MovementPath.Count < 2)
                {
                    return(Task.CompletedTask);
                }

                MovementDataMap.ReplaceObject(guid, changeMovementData);

                IActorRef playerActorRef = ActorReferenceMappable.RetrieveEntity(guid);

                Vector3 direction3D = (changeMovementData.MovementPath[1] - changeMovementData.MovementPath[0]);
                Vector2 direction2D = new Vector2(direction3D.x, direction3D.z).normalized;
                playerActorRef.TellSelf(new PlayerMovementStateChangedMessage(direction2D));

                //If the generator is running, we should use its initial position instead of the last movement data's position.
                MovementGenerator.ReplaceObject(guid, new PathMovementGenerator(changeMovementData));
            }
            catch (Exception e)
            {
                if (Logger.IsErrorEnabled)
                {
                    Logger.Error($"Failed to update MovementData for GUID: {guid} Reason: {e.Message}");
                }

                throw;
            }

            return(Task.CompletedTask);
        }
예제 #17
0
 public Game(IUIEventDispatcher ui, ScoreDisplayer displayer, MovementGenerator cpu)
 {
     ui.PlayerMovementSelected += OnPlayerMovementSelected;
     movementGenerator          = cpu;
     this.displayer             = displayer;
 }
예제 #18
0
        public override void UpdateAI(uint diff)
        {
            //Waypoint Updating
            if (HasEscortState(EscortState.Escorting) && !me.IsEngaged() && !HasEscortState(EscortState.Returning))
            {
                if (_pauseTimer <= diff)
                {
                    if (!HasEscortState(EscortState.Paused))
                    {
                        _pauseTimer = 0;

                        if (_ended)
                        {
                            _ended = false;
                            me.GetMotionMaster().MoveIdle();

                            if (_despawnAtEnd)
                            {
                                Log.outDebug(LogFilter.ScriptsAi, $"EscortAI::UpdateAI: reached end of waypoints, despawning at end ({me.GetGUID()})");
                                if (_returnToStart)
                                {
                                    Position respawnPosition = new();
                                    float    orientation;
                                    me.GetRespawnPosition(out respawnPosition.posX, out respawnPosition.posY, out respawnPosition.posZ, out orientation);
                                    respawnPosition.SetOrientation(orientation);
                                    me.GetMotionMaster().MovePoint(EscortPointIds.Home, respawnPosition);
                                    Log.outDebug(LogFilter.ScriptsAi, $"EscortAI::UpdateAI: returning to spawn location: {respawnPosition} ({me.GetGUID()})");
                                }
                                else if (_instantRespawn)
                                {
                                    me.Respawn();
                                }
                                else
                                {
                                    me.DespawnOrUnsummon();
                                }
                            }

                            Log.outDebug(LogFilter.ScriptsAi, $"EscortAI::UpdateAI: reached end of waypoints ({me.GetGUID()})");
                            RemoveEscortState(EscortState.Escorting);
                            return;
                        }

                        if (!_started)
                        {
                            _started = true;
                            me.GetMotionMaster().MovePath(_path, false);
                        }
                        else if (_resume)
                        {
                            _resume = false;
                            MovementGenerator movementGenerator = me.GetMotionMaster().GetCurrentMovementGenerator(MovementSlot.Default);
                            if (movementGenerator != null)
                            {
                                movementGenerator.Resume(0);
                            }
                        }
                    }
                }
                else
                {
                    _pauseTimer -= diff;
                }
            }


            //Check if player or any member of his group is within range
            if (_despawnAtFar && HasEscortState(EscortState.Escorting) && !_playerGUID.IsEmpty() && !me.IsEngaged() && !HasEscortState(EscortState.Returning))
            {
                if (_playerCheckTimer <= diff)
                {
                    if (!IsPlayerOrGroupInRange())
                    {
                        Log.outDebug(LogFilter.ScriptsAi, $"EscortAI::UpdateAI: failed because player/group was to far away or not found ({me.GetGUID()})");

                        bool         isEscort     = false;
                        CreatureData creatureData = me.GetCreatureData();
                        if (creatureData != null)
                        {
                            isEscort = (WorldConfig.GetBoolValue(WorldCfg.RespawnDynamicEscortNpc) && creatureData.spawnGroupData.flags.HasAnyFlag(SpawnGroupFlags.EscortQuestNpc));
                        }

                        if (_instantRespawn)
                        {
                            if (!isEscort)
                            {
                                me.DespawnOrUnsummon(0, TimeSpan.FromSeconds(1));
                            }
                            else
                            {
                                me.GetMap().Respawn(SpawnObjectType.Creature, me.GetSpawnId());
                            }
                        }
                        else
                        {
                            me.DespawnOrUnsummon();
                        }

                        return;
                    }

                    _playerCheckTimer = 1000;
                }
                else
                {
                    _playerCheckTimer -= diff;
                }
            }

            UpdateEscortAI(diff);
        }
예제 #19
0
        void HandleMoveWorldportAck()
        {
            Player player = GetPlayer();

            // ignore unexpected far teleports
            if (!player.IsBeingTeleportedFar())
            {
                return;
            }

            bool seamlessTeleport = player.IsBeingTeleportedSeamlessly();

            player.SetSemaphoreTeleportFar(false);

            // get the teleport destination
            WorldLocation loc = player.GetTeleportDest();

            // possible errors in the coordinate validity check
            if (!GridDefines.IsValidMapCoord(loc))
            {
                LogoutPlayer(false);
                return;
            }

            // get the destination map entry, not the current one, this will fix homebind and reset greeting
            MapRecord        mapEntry  = CliDB.MapStorage.LookupByKey(loc.GetMapId());
            InstanceTemplate mInstance = Global.ObjectMgr.GetInstanceTemplate(loc.GetMapId());

            // reset instance validity, except if going to an instance inside an instance
            if (!player.m_InstanceValid && mInstance == null)
            {
                player.m_InstanceValid = true;
            }

            Map oldMap = player.GetMap();
            Map newMap = Global.MapMgr.CreateMap(loc.GetMapId(), player);

            if (player.IsInWorld)
            {
                Log.outError(LogFilter.Network, $"Player (Name {player.GetName()}) is still in world when teleported from map {oldMap.GetId()} to new map {loc.GetMapId()}");
                oldMap.RemovePlayerFromMap(player, false);
            }

            // relocate the player to the teleport destination
            // the CannotEnter checks are done in TeleporTo but conditions may change
            // while the player is in transit, for example the map may get full
            if (newMap == null || newMap.CannotEnter(player) != 0)
            {
                Log.outError(LogFilter.Network, $"Map {loc.GetMapId()} could not be created for {(newMap ? newMap.GetMapName() : "Unknown")} ({player.GetGUID()}), porting player to homebind");
                player.TeleportTo(player.GetHomebind());
                return;
            }

            float z = loc.GetPositionZ() + player.GetHoverOffset();

            player.Relocate(loc.GetPositionX(), loc.GetPositionY(), z, loc.GetOrientation());
            player.SetFallInformation(0, player.GetPositionZ());

            player.ResetMap();
            player.SetMap(newMap);

            ResumeToken resumeToken = new();

            resumeToken.SequenceIndex = player.m_movementCounter;
            resumeToken.Reason        = seamlessTeleport ? 2 : 1u;
            SendPacket(resumeToken);

            if (!seamlessTeleport)
            {
                player.SendInitialPacketsBeforeAddToMap();
            }

            if (!player.GetMap().AddPlayerToMap(player, !seamlessTeleport))
            {
                Log.outError(LogFilter.Network, $"WORLD: failed to teleport player {player.GetName()} ({player.GetGUID()}) to map {loc.GetMapId()} ({(newMap ? newMap.GetMapName() : "Unknown")}) because of unknown reason!");
                player.ResetMap();
                player.SetMap(oldMap);
                player.TeleportTo(player.GetHomebind());
                return;
            }

            // Battleground state prepare (in case join to BG), at relogin/tele player not invited
            // only add to bg group and object, if the player was invited (else he entered through command)
            if (player.InBattleground())
            {
                // cleanup setting if outdated
                if (!mapEntry.IsBattlegroundOrArena())
                {
                    // We're not in BG
                    player.SetBattlegroundId(0, BattlegroundTypeId.None);
                    // reset destination bg team
                    player.SetBGTeam(0);
                }
                // join to bg case
                else
                {
                    Battleground bg = player.GetBattleground();
                    if (bg)
                    {
                        if (player.IsInvitedForBattlegroundInstance(player.GetBattlegroundId()))
                        {
                            bg.AddPlayer(player);
                        }
                    }
                }
            }

            if (!seamlessTeleport)
            {
                player.SendInitialPacketsAfterAddToMap();
            }
            else
            {
                player.UpdateVisibilityForPlayer();
                Garrison garrison = player.GetGarrison();
                if (garrison != null)
                {
                    garrison.SendRemoteInfo();
                }
            }

            // flight fast teleport case
            if (player.IsInFlight())
            {
                if (!player.InBattleground())
                {
                    if (!seamlessTeleport)
                    {
                        // short preparations to continue flight
                        MovementGenerator movementGenerator = player.GetMotionMaster().GetCurrentMovementGenerator();
                        movementGenerator.Initialize(player);
                    }
                    return;
                }

                // Battlegroundstate prepare, stop flight
                player.FinishTaxiFlight();
            }

            if (!player.IsAlive() && player.GetTeleportOptions().HasAnyFlag(TeleportToOptions.ReviveAtTeleport))
            {
                player.ResurrectPlayer(0.5f);
            }

            // resurrect character at enter into instance where his corpse exist after add to map
            if (mapEntry.IsDungeon() && !player.IsAlive())
            {
                if (player.GetCorpseLocation().GetMapId() == mapEntry.Id)
                {
                    player.ResurrectPlayer(0.5f, false);
                    player.SpawnCorpseBones();
                }
            }

            if (mInstance != null)
            {
                // check if this instance has a reset time and send it to player if so
                Difficulty          diff    = newMap.GetDifficultyID();
                MapDifficultyRecord mapDiff = Global.DB2Mgr.GetMapDifficultyData(mapEntry.Id, diff);
                if (mapDiff != null)
                {
                    if (mapDiff.GetRaidDuration() != 0)
                    {
                        long timeReset = Global.InstanceSaveMgr.GetResetTimeFor(mapEntry.Id, diff);
                        if (timeReset != 0)
                        {
                            uint timeleft = (uint)(timeReset - GameTime.GetGameTime());
                            player.SendInstanceResetWarning(mapEntry.Id, diff, timeleft, true);
                        }
                    }
                }

                // check if instance is valid
                if (!player.CheckInstanceValidity(false))
                {
                    player.m_InstanceValid = false;
                }
            }

            // update zone immediately, otherwise leave channel will cause crash in mtmap
            player.GetZoneAndAreaId(out uint newzone, out uint newarea);
            player.UpdateZone(newzone, newarea);

            // honorless target
            if (player.pvpInfo.IsHostile)
            {
                player.CastSpell(player, 2479, true);
            }

            // in friendly area
            else if (player.IsPvP() && !player.HasPlayerFlag(PlayerFlags.InPVP))
            {
                player.UpdatePvP(false, false);
            }

            // resummon pet
            player.ResummonPetTemporaryUnSummonedIfAny();

            //lets process all delayed operations on successful teleport
            player.ProcessDelayedOperations();
        }
예제 #20
0
 bool isStatic(MovementGenerator mv)
 {
     return(false);                                 /*(mv == &si_idleMovement);*/
 }