Exemple #1
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, DefaultEntityActorStateContainer state, PendingSpellCastFinishedWaitingMessage message)
        {
            //This indicates that the spell cast has finished.
            state.EntityData.SetFieldValue(EntityObjectField.UNIT_FIELD_CASTING_SPELLID, 0);

            messageContext.Entity.TellSelf(new ImmediateCastSpellMessage(message.Pending));
        }
Exemple #2
0
		protected override void HandleMessage(EntityActorMessageContext messageContext, DefaultEntityActorStateContainer state, InteractWithEntityActorMessage message)
		{
			if(Logger.IsDebugEnabled)
				Logger.Debug($"Entity: {message.EntityInteracting} Interacted with Creature: {state.EntityGuid}");

			messageContext.Sender.Tell(new AddPlayerExperienceActorMessage(50));

			//Let's create the path data.
			IMovementGenerator<GameObject> movementGenerator = MovementGeneratorMappable.RetrieveEntity(state.EntityGuid);
			var playerMovementGenerator = MovementGeneratorMappable.RetrieveEntity(message.EntityInteracting);

			//WARNING: NEVER DO THIS, NOT SAFE TO ACCESS PLAYER DATA.
			Vector3 creatureCurrentPosition = movementGenerator.CurrentPosition;
			Vector3 playerCurrentPosition = playerMovementGenerator.CurrentPosition;

			UnityAsyncHelper.UnityMainThreadContext.Post(o =>
			{
				var path = new NavMeshPath();
				NavMesh.CalculatePath(creatureCurrentPosition, playerCurrentPosition, NavMesh.AllAreas, path);

				if(path.status != NavMeshPathStatus.PathComplete)
					if(Logger.IsWarnEnabled)
						Logger.Warn($"Produced invalid PathResult: {path.status} for Entity: {state.EntityGuid} Start: {creatureCurrentPosition} End: {playerCurrentPosition}");

				//Don't broadcast if not invalid
				if(path.status == NavMeshPathStatus.PathComplete)
					messageContext.Entity.Tell(new CreatureSetPathMovementMessage(creatureCurrentPosition, path.corners));
			}, null);
		}
Exemple #3
0
        private bool TrySendMessage(object message)
        {
            EntityActorMessage        castedMessage = (EntityActorMessage)message;
            EntityActorMessageContext context       = new EntityActorMessageContext(Sender, Self, Context.System.Scheduler);

            return(MessageRouter.RouteMessage(context, ActorState, castedMessage));
        }
Exemple #4
0
 public void HandleMessage(EntityActorMessageContext messageContext, TEntityStateType state, EntityActorMessage message)
 {
     //Assume caller has verified this will work
     //We downcast so the API consumed is simplier/easier.
     //We need the interface to not be specific so it can be discovered, registered and handled.
     HandleMessage(messageContext, state, (TEntityMessageType)message);
 }
Exemple #5
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, DefaultEntityActorStateContainer state, WorldTeleportPlayerEntityActorMessage message)
        {
            //Something just told player we are teleporting to another world

            //TODO: Kind of a potential exploit here. Since the process to transfer sessions
            //is async they could potentially log off and log back in quickly and avoid a trasnfer
            //So if this is a FORCED transfer, like for death or something or a kick, they could potentially avoid it??
            ProjectVersionStage.AssertBeta();

            //TODO: Find a way to make it so actors state is always valid.
            //If this throws then the entity dies. So no reason to check it.
            EntitySaveableConfiguration entity = PersistenceConfigurationMappable.RetrieveEntity(state.EntityGuid);

            entity.isWorldTeleporting = true;

            ZoneToSeverClient.TryWorldTeleportCharacter(new ZoneServerWorldTeleportCharacterRequest(state.EntityGuid, message.WorldTeleportGameObjectId))
            .ContinueWith((task, o) =>
            {
                //Whether this succeeds or not this continuation will occur
                //either way we should just disconnect the player because we
                //either have uncoverable issues or they are going to be transfered after
                //disconnection.


                //ConnectionServiceMappable.RetrieveEntity(args.TeleportingPlayer).Disconnect();
                //Since this is async the entity might actually be gone, so we used the actor messaging system
                //To indicate that it should disconnect
                messageContext.Entity.Tell(new DisconnectNetworkPlayerEntityActorMessage());
            }, TaskContinuationOptions.ExecuteSynchronously);
        }
Exemple #6
0
        public bool RouteMessage(EntityActorMessageContext messageContext, TEntityActorStateType state, EntityActorMessage message)
        {
            if (messageContext == null)
            {
                throw new ArgumentNullException(nameof(messageContext));
            }
            if (state == null)
            {
                throw new ArgumentNullException(nameof(state));
            }
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            if (EntityHandlerMap.ContainsKey(message.GetType()))
            {
                foreach (var handler in EntityHandlerMap[message.GetType()])
                {
                    handler.HandleMessage(messageContext, state, message);
                }

                return(true);
            }
            else
            {
                return(false);
            }
        }
Exemple #7
0
 protected override void HandleMessage(EntityActorMessageContext messageContext, DefaultEntityActorStateContainer state, HealEntityActorCurrentHealthMessage message)
 {
     //Increases health clamped by current max health.
     if (state.EntityData.DataSetIndicationArray.Get((int)EntityObjectField.UNIT_FIELD_HEALTH))
     {
         state.EntityData.SetFieldValue(EntityObjectField.UNIT_FIELD_HEALTH, Math.Min(state.EntityData.GetFieldValue <int>(EntityObjectField.UNIT_FIELD_MAXHEALTH), state.EntityData.GetFieldValue <int>(EntityObjectField.UNIT_FIELD_HEALTH) + message.HealAmount));
     }
 }
Exemple #8
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, DefaultEntityActorStateContainer state, ReinitializeEntityActorStatsMessage message)
        {
            EntityBaseStatsModel baseStats = GenerateEntityBaseStats(state.EntityGuid, state.EntityData);

            //TODO: Do base eventually. Right now we're only doing regular health fields since that's all we deal with clientside atm.
            state.EntityData.SetFieldValue(EntityObjectField.UNIT_FIELD_HEALTH, baseStats.BaseHealth);
            state.EntityData.SetFieldValue(EntityObjectField.UNIT_FIELD_MAXHEALTH, baseStats.BaseHealth);
        }
Exemple #9
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, DefaultCreatureActorState state, EntityActorInitializationSuccessMessage message)
        {
            //We need to initialize our replicateable state here.
            int creatureLevel = CreatureInitializationRandomGenerator.Value.Next(state.TemplateModel.MinimumLevel, state.TemplateModel.MaximumLevel + 1);             //uppbound is exclusive

            //We should send ourselves the level initialization message because it takes care of stats
            messageContext.Entity.Tell(new SetEntityActorLevelMessage(creatureLevel));
        }
Exemple #10
0
 protected override void HandleMessage(EntityActorMessageContext messageContext, DefaultEntityActorStateContainer state, DamageEntityActorCurrentHealthMessage message)
 {
     //Simple, if the entity has health we just try to subtract from it.
     if (state.EntityData.DataSetIndicationArray.Get((int)EntityObjectField.UNIT_FIELD_HEALTH))
     {
         state.EntityData.SetFieldValue(EntityObjectField.UNIT_FIELD_HEALTH, Math.Max(0, state.EntityData.GetFieldValue <int>(EntityObjectField.UNIT_FIELD_HEALTH) - message.Damage));
     }
 }
Exemple #11
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, DefaultEntityActorStateContainer state, CreatureSetPathMovementMessage message)
        {
            PathBasedMovementData           data      = new PathBasedMovementData(message.PathPoints, TimeService.CurrentLocalTime);
            IMovementGenerator <GameObject> generator = MovementGeneratorFactory.Create(new EntityAssociatedData <IMovementData>(state.EntityGuid, data));

            MovementDataMappable.ReplaceObject(state.EntityGuid, data);
            MovementGeneratorMappable.ReplaceObject(state.EntityGuid, generator);
        }
Exemple #12
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, DefaultEntityActorStateContainer state, DisconnectNetworkPlayerEntityActorMessage message)
        {
            if (Logger.IsInfoEnabled)
            {
                Logger.Info($"Entity: {state.EntityGuid} actor handling disconnection message.");
            }

            //TODO: This can throw, but the entity will die. We should make it so that entity data always exists if the actor is alive.
            ConnectionServiceMappable.RetrieveEntity(state.EntityGuid).Disconnect();
        }
Exemple #13
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, DefaultEntityActorStateContainer state, ChangeEntityActorDisplayModelMessage message)
        {
            //Basically we
            if (Logger.IsDebugEnabled)
            {
                Logger.Debug($"Entity: {state.EntityGuid} changing to ModelId: {message.NewModelId}");
            }

            //We just set the model id, it's fine as simple as this.
            state.EntityData.SetFieldValue(BaseObjectField.UNIT_FIELD_DISPLAYID, message.NewModelId);
        }
Exemple #14
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, DefaultEntityActorStateContainer state, EntityActorInitializationSuccessMessage message)
        {
            //We should send ourselves the level initialization message because it takes care of stats
            CharacterDataInstance     entity = InitialCharacterDataMappable.RetrieveEntity(state.EntityGuid);
            IEntityDataFieldContainer entityDataFieldContainer = state.EntityData;

            entityDataFieldContainer.SetFieldValue((int)PlayerObjectField.PLAYER_TOTAL_EXPERIENCE, entity.Experience);

            //Set the level from the initial experience data.
            messageContext.Entity.Tell(new SetEntityActorLevelMessage(LevelStrategy.ComputeLevelFromExperience(entity.Experience)));
        }
Exemple #15
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, DefaultEntityActorStateContainer state, CancelSpellCastMessage message)
        {
            //If we have a pending cast then cancel it.
            if (PendingSpellCastMappable.ContainsKey(state.EntityGuid))
            {
                PendingSpellCastMappable.RetrieveEntity(state.EntityGuid).PendingCancel.Cancel();
            }

            //Just set the casting state to 0.
            state.EntityData.SetFieldValue(EntityObjectField.UNIT_FIELD_CASTING_SPELLID, 0);
        }
Exemple #16
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, BehaviourGameObjectState <AvatarPedestalInstanceModel> state, EntityActorInitializationSuccessMessage message)
        {
            //We need to initialize our replicateable state here.

            //TODO: Better handling of enum names for specialized gameobjects
            //Basically this is how clients see the avatar id.
            state.EntityData.SetFieldValue(GameObjectField.RESERVED_DATA_1, state.BehaviourData.AvatarModelId);

            //avatar pedestal can be interacted with.
            state.EntityData.AddBaseObjectFieldFlag(BaseObjectFieldFlags.UNIT_FLAG_INTERACTABLE);
        }
Exemple #17
0
 private static void DispatchPendingSpellCast(EntityActorMessageContext messageContext, PendingSpellCastData castData)
 {
     //Instant casts can just directly send.
     if (castData.isInstantCast)
     {
         messageContext.Entity.TellSelf(new PendingSpellCastFinishedWaitingMessage(castData));
     }
     else
     {
         messageContext.ContinuationScheduler.ScheduleTellOnce(castData.CastTime, messageContext.Entity, new PendingSpellCastFinishedWaitingMessage(castData), messageContext.Entity, castData.PendingCancel);
     }
 }
Exemple #18
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, DefaultEntityActorStateContainer state, EntityActorSelectedMessage message)
        {
            if (Logger.IsDebugEnabled)
            {
                Logger.Debug($"Entity: {message.SelectorGuid} Interacted with Player: {state.EntityGuid}");
            }

            //Just tell whatever selected us that they should now target us.
            messageContext.Sender.Tell(new SetEntityActorTargetMessage(state.EntityGuid));

            //TODO: This is just for testing
            messageContext.Entity.TellSelf(new DamageEntityActorCurrentHealthMessage(1));
        }
Exemple #19
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, BehaviourGameObjectState <WorldTeleporterInstanceModel> state, InteractWithEntityActorMessage message)
        {
            if (Logger.IsDebugEnabled)
            {
                Logger.Debug($"Entity: {message.EntityInteracting} Interacted with World Teleporter: {state.EntityGuid}");
            }

            //Only players should be able to interact with this.
            if (message.EntityInteracting.EntityType != EntityType.Player)
            {
                return;
            }

            //Right now there is no validation, just teleport them.
            messageContext.Sender.Tell(new WorldTeleportPlayerEntityActorMessage(state.BehaviourData.RemoteSpawnPointId, state.BehaviourData.LinkedGameObjectId));
        }
Exemple #20
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, DefaultEntityActorStateContainer state, AddPlayerExperienceActorMessage message)
        {
            int newExperienceAmount = state.EntityData.GetFieldValue <int>(PlayerObjectField.PLAYER_TOTAL_EXPERIENCE) + message.ExperienceAmount;

            //Just set the experience.
            state.EntityData.SetFieldValue(PlayerObjectField.PLAYER_TOTAL_EXPERIENCE, newExperienceAmount);

            int currentLevel = state.EntityData.GetFieldValue <int>(BaseObjectField.UNIT_FIELD_LEVEL);

            //We dinged! But don't assume it was only 1 level. Could be multiple
            if (currentLevel < LevelStrategy.ComputeLevelFromExperience(newExperienceAmount))
            {
                int newLevel = LevelStrategy.ComputeLevelFromExperience(newExperienceAmount);

                messageContext.Entity.Tell(new SetEntityActorLevelMessage(newLevel));
            }
        }
Exemple #21
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, DefaultEntityActorStateContainer state, PlayerMovementStateChangedMessage message)
        {
            //If we started moving then we should check the current spell cast.
            if (message.isMoving)
            {
                if (PendingSpellCastMappable.ContainsKey(state.EntityGuid))
                {
                    PendingSpellCastData castData = PendingSpellCastMappable.RetrieveEntity(state.EntityGuid);

                    if (castData.isInstantCast || castData.isCastCanceled || castData.IsSpellcastFinished(TimeService.CurrentLocalTime))
                    {
                        return;
                    }

                    //Ok, so we're casting and moving. Let's cancel the cast.
                    messageContext.Entity.TellSelf(new CancelSpellCastMessage());
                }
            }
        }
Exemple #22
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, NetworkedObjectActorState state, BroadcastToInterestSetMessage message)
        {
            IPeerPayloadSendService <GameServerPacketPayload> sender = null;

            foreach (NetworkEntityGuid guid in state.Interest.ContainedEntities)
            {
                //If it's not a player or the message specified that we shouldn't send to self and it's ourselves
                if (guid.EntityType != EntityType.Player || !message.SendToSelf && guid == state.EntityGuid)
                {
                    continue;
                }

                //Try to get the sender and then just forward the message.
                if (SendServiceMappable.TryGetValue(guid, out sender))
                {
                    sender.SendMessage(message.Message);
                }
            }
        }
Exemple #23
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, WorldActorState state, CreateCreatureEntityActorMessage message)
        {
            if (message.EntityGuid.EntityType != EntityType.Creature)
            {
                throw new InvalidOperationException($"Tried to create Creature Actor for non-Creature Entity: {message.EntityGuid}");
            }

            try
            {
                CreateActor(state, message);
            }
            catch (Exception e)
            {
                if (Logger.IsErrorEnabled)
                {
                    Logger.Error($"Failed to create Actor: {e.Message}\n\nStack: {e.StackTrace}");
                }
                throw;
            }
        }
Exemple #24
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, DefaultEntityActorStateContainer state, EntityActorSelectedMessage message)
        {
            if (Logger.IsDebugEnabled)
            {
                Logger.Debug($"Entity: {message.SelectorGuid} selected Creature: {state.EntityGuid}");
            }

            //Make sure the creature can be selected.
            if (state.EntityData.HasBaseObjectFieldFlag(BaseObjectFieldFlags.UNIT_FLAG_NOT_SELECTABLE))
            {
                if (Logger.IsWarnEnabled)
                {
                    Logger.Warn($"Entity: {message.SelectorGuid} tried to select unselectable Creature: {state.EntityGuid}");
                }
                return;
            }

            //Just tell whatever interacted with us that they should now target us.
            messageContext.Sender.Tell(new SetEntityActorTargetMessage(state.EntityGuid));
        }
Exemple #25
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, WorldActorState state, CreateEntityActorMessage message)
        {
            //Below we just forward to the appropriate handler.
            switch (message.EntityGuid.EntityType)
            {
            case EntityType.Player:
                messageContext.Entity.Tell(new CreatePlayerEntityActorMessage(message.EntityGuid));
                break;

            case EntityType.GameObject:
                messageContext.Entity.Tell(new CreateGameObjectEntityActorMessage(message.EntityGuid));
                break;

            case EntityType.Creature:
                messageContext.Entity.Tell(new CreateCreatureEntityActorMessage(message.EntityGuid));
                break;

            default:
                throw new ArgumentOutOfRangeException($"Cannot handle EntityType: {message.EntityGuid.EntityType}");
            }
        }
Exemple #26
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, BehaviourGameObjectState <AvatarPedestalInstanceModel> state, InteractWithEntityActorMessage message)
        {
            if (Logger.IsDebugEnabled)
            {
                Logger.Debug($"Entity: {message.EntityInteracting} Interacted with Avatar Pedestal: {state.EntityGuid}");
            }

            //Only players should be able to interact with this.
            if (message.EntityInteracting.EntityType != EntityType.Player)
            {
                return;
            }

            //Initially, we should make the assumption that they CAN change their avatr with this pedestal
            //so we will send the change packet BEFORE checking.
            messageContext.Sender.Tell(new ChangeEntityActorDisplayModelMessage(state.BehaviourData.AvatarModelId));

            //Now we REALLY need to be sure.
            ZoneServerDataClient.UpdatePlayerAvatar(new ZoneServerAvatarPedestalInteractionCharacterRequest(message.EntityInteracting, state.BehaviourData.LinkedGameObjectId))
            .ContinueWith((task, o) =>
            {
                if (task.IsFaulted)
                {
                    if (Logger.IsErrorEnabled)
                    {
                        Logger.Error($"TODO: Log");                                 //lazy
                    }
                    return;
                }

                //Now, we should verify the response. If the model id differ then it failed
                //or some race condition externally, the desired result is the player gets changed back.
                //To prevent exploits
                if (state.BehaviourData.AvatarModelId != task.Result.PersistedModelId)
                {
                    messageContext.Sender.Tell(new ChangeEntityActorDisplayModelMessage(task.Result.PersistedModelId));
                }
            }, TaskContinuationOptions.ExecuteSynchronously);
        }
Exemple #27
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, WorldActorState state, CreateGameObjectEntityActorMessage message)
        {
            if (message.EntityGuid.EntityType != EntityType.GameObject)
            {
                throw new InvalidOperationException($"Tried to create GameObject Actor for non-GameObject Entity: {message.EntityGuid}");
            }

            try
            {
                CreateActor(state, message);
            }
            catch (Exception e)
            {
                if (Logger.IsErrorEnabled)
                {
                    Logger.Error($"Failed to create Actor: {e.Message}\n\nStack: {e.StackTrace}");
                }

                //Rather than throw and kill the world let's just despawn this failed object
                DestructionEventPublisher.PublishEvent(this, new EntityDeconstructionRequestedEventArgs(message.EntityGuid));
            }
        }
Exemple #28
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, WorldActorState state, CreatePlayerEntityActorMessage message)
        {
            if (message.EntityGuid.EntityType != EntityType.Player)
            {
                throw new InvalidOperationException($"Tried to create Player Actor for non-Player Entity: {message.EntityGuid}");
            }

            try
            {
                IActorRef actor = CreateActor(state, message);

                //If it succeeded, add the death watch message
                state.DeathWatchService.WatchWith(actor, new KillPlayerActorMessage(message.EntityGuid));
            }
            catch (Exception e)
            {
                if (Logger.IsErrorEnabled)
                {
                    Logger.Error($"Failed to create Actor: {e.Message}\n\nStack: {e.StackTrace}");
                }
                throw;
            }
        }
Exemple #29
0
        protected override void HandleMessage(EntityActorMessageContext messageContext, DefaultEntityActorStateContainer state, TryCastSpellMessage message)
        {
            //Validate the cast before we starer it at all.
            SpellCastResult spellCastAttemptValidationResult = SpellCastValidator.ValidateSpellCast(state, message.SpellId);

            if (spellCastAttemptValidationResult != SpellCastResult.SPELL_FAILED_SUCCESS)
            {
                messageContext.Entity.TellSelf(new SpellCastFailedMessage(spellCastAttemptValidationResult, message.SpellId));
                return;
            }

            //We also need to check if we're moving. If the generator isn't finished then that means we're actually moving.
            if (state.EntityGuid.EntityType == EntityType.Player)            //only players should get successful callbacks
            {
                messageContext.Entity.TellSelf(new SpellCastFailedMessage(SpellCastResult.SPELL_FAILED_SUCCESS, message.SpellId));
            }

            PendingSpellCastData castData = CreatePendingSpellData(state, message);

            SetCastingEntityState(state, message);

            DispatchPendingSpellCast(messageContext, castData);
        }
Exemple #30
0
 protected abstract void HandleMessage(EntityActorMessageContext messageContext, TEntityStateType state, TEntityMessageType message);