Exemplo n.º 1
0
        public void PerformUpdate(object state)
        {
            //Console.WriteLine(Thread.CurrentThread.ManagedThreadId); // use this only to debug threadpooling...

            List <RoomActor> ActorsToUpdate = new List <RoomActor>();
            List <RoomActor> ActorsToRemove = new List <RoomActor>();

            // Copy collection
            Dictionary <uint, RoomActor> ActorsCopy = new Dictionary <uint, RoomActor>();

            List <RoomActor>[,] NewUserGrid = new List <RoomActor> [mCachedModel.Heightmap.SizeX, mCachedModel.Heightmap.SizeY];

            lock (mActorSyncRoot)
            {
                foreach (KeyValuePair <uint, RoomActor> CopyItem in mActors)
                {
                    ActorsCopy.Add(CopyItem.Key, CopyItem.Value);
                }
            }

            foreach (RoomActor Actor in ActorsCopy.Values)
            {
                // If the room is unloaded, allow no actors
                if (mUnloaded)
                {
                    ActorsToRemove.Add(Actor);
                    continue;
                }

                // The idle time is increased in every step.
                if (Actor.Type == RoomActorType.UserCharacter)
                {
                    Actor.IncreaseIdleTime(Actor.ReferenceId == Info.OwnerId);
                }

                // If this is a bot, allow the brain to process this update tick.
                if (Actor.Type == RoomActorType.AiBot)
                {
                    ((Bot)Actor.ReferenceObject).Brain.PerformUpdate(this);
                }

                // Remove any walking statusses (they will be re-applied below if neccessary)
                if (Actor.UserStatusses.ContainsKey("mv"))
                {
                    Actor.RemoveStatus("mv");
                    Actor.UpdateNeeded = true;
                }

                // Update actor position if neccessary
                if (Actor.PositionToSet != null)
                {
                    // Check if the new position is in the door
                    if (Actor.Type == RoomActorType.UserCharacter && Actor.PositionToSet.X == mCachedModel.DoorPosition.X && Actor.PositionToSet.Y == mCachedModel.DoorPosition.Y)
                    {
                        ActorsToRemove.Add(Actor);
                        continue;
                    }

                    // Update the actual position
                    Actor.Position      = new Vector3(Actor.PositionToSet.X, Actor.PositionToSet.Y, (Math.Round(GetUserStepHeight(Actor.PositionToSet), 1)));
                    Actor.PositionToSet = null;

                    // Handle any "MoveToAndInteract" events if this was the last step
                    if (!Actor.IsMoving && Actor.MoveToAndInteract > 0 && Actor.Type == RoomActorType.UserCharacter)
                    {
                        Item Item = GetItem(Actor.MoveToAndInteract);

                        if (Item != null)
                        {
                            ItemEventDispatcher.InvokeItemEventHandler(SessionManager.GetSessionByCharacterId(
                                                                           Actor.ReferenceId), Item, this, ItemEventType.Interact, Actor.MoveToAndInteractData);
                        }

                        Actor.MoveToAndInteract     = 0;
                        Actor.MoveToAndInteractData = 0;
                    }
                }

                // If there are more steps to be made, handle it.
                if (Actor.IsMoving)
                {
                    // Check if moving to door
                    if (!Actor.IsLeavingRoom && Actor.Pathfinder.Target.X == mCachedModel.DoorPosition.X &&
                        Actor.Pathfinder.Target.Y == mCachedModel.DoorPosition.Y)
                    {
                        Actor.IsLeavingRoom = true;
                    }

                    // Get the next step from the pathfinder
                    Vector2 NextStep = Actor.GetNextStep();

                    // If the user is leaving and has exceeded 11 steps, help him out by instantly
                    // removing them.
                    if (Actor.LeaveStepsTaken >= 11)
                    {
                        ActorsToRemove.Add(Actor);
                        continue;
                    }

                    // If the pathfinder reports no more steps to be made, this is the last step.
                    bool LastStep = !Actor.IsMoving;

                    // Check that the next step is valid and allowed
                    if (NextStep != null && ((!Actor.ClippingEnabled && IsValidPosition(NextStep)) ||
                                             IsValidStep(Actor.Position.GetVector2(), NextStep, LastStep, NewUserGrid)))
                    {
                        // Update "mv" status
                        Actor.SetStatus("mv", NextStep.X + "," + NextStep.Y + "," + (Math.Round(GetUserStepHeight(NextStep), 1)).ToString().Replace(',', '.'));
                        Actor.PositionToSet = NextStep;

                        // Update new/temporary grid with our new move to position
                        if (NewUserGrid[NextStep.X, NextStep.Y] == null)
                        {
                            NewUserGrid[NextStep.X, NextStep.Y] = new List <RoomActor>();
                        }

                        NewUserGrid[NextStep.X, NextStep.Y].Add(Actor);

                        // Remove any "sit" statusses
                        if (Actor.UserStatusses.ContainsKey("sit"))
                        {
                            Actor.RemoveStatus("sit");
                        }

                        // Remove any "lay" statusses
                        if (Actor.UserStatusses.ContainsKey("lay"))
                        {
                            Actor.RemoveStatus("lay");
                        }

                        // Update rotation
                        Actor.BodyRotation = Rotation.Calculate(Actor.Position.GetVector2(), NextStep);
                        Actor.HeadRotation = Actor.BodyRotation;

                        // Request update for next @B cycle
                        Actor.UpdateNeeded = true;
                    }
                    else
                    {
                        // Invalid step: tell pathfinder to stop and mark current position on temporary grid
                        Actor.StopMoving();

                        if (NewUserGrid[NextStep.X, NextStep.Y] == null)
                        {
                            NewUserGrid[NextStep.X, NextStep.Y] = new List <RoomActor>();
                        }

                        NewUserGrid[NextStep.X, NextStep.Y].Add(Actor);
                    }
                }
                else
                {
                    if (NewUserGrid[Actor.Position.X, Actor.Position.Y] == null)
                    {
                        NewUserGrid[Actor.Position.X, Actor.Position.Y] = new List <RoomActor>();
                    }

                    NewUserGrid[Actor.Position.X, Actor.Position.Y].Add(Actor);
                }

                // If the actor is leaving and has stopped walking, help them out by removing them.
                if (!Actor.IsMoving && Actor.IsLeavingRoom && Actor.Type == RoomActorType.UserCharacter)
                {
                    ActorsToRemove.Add(Actor);
                    continue;
                }

                // Update status (apply any sit/lay/effect)
                UpdateActorStatus(Actor);

                // Add this actor to the update list if this has been requested
                if (Actor.UpdateNeeded)
                {
                    ActorsToUpdate.Add(Actor);
                    Actor.UpdateNeeded = false;
                }
            }

            // Remove all actors that need to be removed
            foreach (RoomActor Actor in ActorsToRemove)
            {
                lock (mActorSyncRoot)
                {
                    if (ActorsToUpdate.Contains(Actor))
                    {
                        ActorsToUpdate.Remove(Actor);
                    }
                }

                switch (Actor.Type)
                {
                default:

                    RemoveActorFromRoom(Actor.Id);
                    break;

                case RoomActorType.UserCharacter:

                    HardKickUser(Actor.ReferenceId);
                    break;
                }
            }

            // Send update list (if there are any updates) to room
            if (ActorsToUpdate.Count > 0)
            {
                BroadcastMessage(RoomUserStatusListComposer.Compose(ActorsToUpdate));
            }

            // Update tick on all items --
            List <Item> ItemCopy = null;

            lock (mItemSyncRoot)
            {
                ItemCopy = mItems.Values.ToList();
            }

            foreach (Item Item in ItemCopy)
            {
                Item.Update(this);
            }

            // Invalidate door position
            NewUserGrid[mCachedModel.DoorPosition.X, mCachedModel.DoorPosition.Y] = null;

            // Update user grid to our new version
            lock (mActorSyncRoot)
            {
                mUserGrid = NewUserGrid;
            }

            if (mMusicController != null && mMusicController.IsPlaying)
            {
                mMusicController.Update(this);
            }
        }
Exemplo n.º 2
0
        public void SendObjects(Session Session)
        {
            Session.SendData(RoomItemHeightmapComposer.Compose(Model.Heightmap.ToString()));
            Session.SendData(RoomRelativeHeightmapComposer.Compose(RelativeHeightmap));

            List <RoomActor> ActorObjects = new List <RoomActor>();

            Dictionary <uint, int> DancingActors  = new Dictionary <uint, int>();
            Dictionary <uint, int> CarryingActors = new Dictionary <uint, int>();
            Dictionary <uint, int> EffectActors   = new Dictionary <uint, int>();
            List <uint>            SleepingActors = new List <uint>();

            lock (mActorSyncRoot)
            {
                foreach (RoomActor Actor in mActors.Values)
                {
                    ActorObjects.Add(Actor);

                    if (Actor.DanceId > 0)
                    {
                        DancingActors.Add(Actor.Id, Actor.DanceId);
                    }

                    if (Actor.CarryItemId > 0)
                    {
                        CarryingActors.Add(Actor.Id, Actor.CarryItemId);
                    }

                    if (Actor.AvatarEffectId > 0)
                    {
                        EffectActors.Add(Actor.Id, Actor.AvatarEffectId);
                    }

                    if (Actor.IsSleeping)
                    {
                        SleepingActors.Add(Actor.Id);
                    }
                }
            }

            Session.SendData(RoomUserObjectListComposer.Compose(ActorObjects));
            Session.SendData(RoomStaticObjectsComposer.Compose(mStaticObjects));
            Session.SendData(RoomFloorObjectsComposer.Compose(GetFloorItems()));
            Session.SendData(RoomWallObjectsComposer.Compose(GetWallItems()));
            Session.SendData(RoomUserStatusListComposer.Compose(ActorObjects));

            foreach (KeyValuePair <uint, int> DancingActor in DancingActors)
            {
                Session.SendData(RoomUserDanceComposer.Compose(DancingActor.Key, DancingActor.Value));
            }

            foreach (KeyValuePair <uint, int> CarryingActor in CarryingActors)
            {
                Session.SendData(RoomUserCarryComposer.Compose(CarryingActor.Key, CarryingActor.Value));
            }

            foreach (KeyValuePair <uint, int> EffectActor in EffectActors)
            {
                Session.SendData(RoomUserEffectComposer.Compose(EffectActor.Key, EffectActor.Value));
            }

            foreach (uint SleepingActor in SleepingActors)
            {
                Session.SendData(RoomUserSleepComposer.Compose(SleepingActor, true));
            }
        }