Пример #1
0
        protected override void OnGuildStatusChanged(GuildStatusChangedEventModel changeArgs)
        {
            //Don't need to get the guild list if we're guildless.
            if (changeArgs.IsGuildless)
            {
                return;
            }

            UnityAsyncHelper.UnityMainThreadContext.PostAsync(async() =>
            {
                var rosterResponseModel = await SocialService.GetGuildListAsync();

                if (!rosterResponseModel.isSuccessful)
                {
                    if (Logger.IsWarnEnabled)
                    {
                        Logger.Warn($"Failed to query guild roster. Reason: {rosterResponseModel.ResultCode}");
                    }
                    return;
                }

                //Now we can publish the roster.
                foreach (int rosterCharacterId in rosterResponseModel.Result.GuildedCharacterIds)
                {
                    NetworkEntityGuid characterGuid = NetworkEntityGuidBuilder.New()
                                                      .WithType(EntityType.Player)
                                                      .WithId(rosterCharacterId)
                                                      .Build();

                    //This is a hidden join, or the alerts would be spammed.
                    GuildJoinEventPublisher.PublishEvent(this, new CharacterJoinedGuildEventArgs(characterGuid, true));
                }
            });
        }
Пример #2
0
        private void OnChatMessageRecieved(ChatChannelType channelType, [NotNull] IChannelTextMessage args)
        {
            if (args == null)
            {
                throw new ArgumentNullException(nameof(args));
            }
            if (!Enum.IsDefined(typeof(ChatChannelType), channelType))
            {
                throw new InvalidEnumArgumentException(nameof(channelType), (int)channelType, typeof(ChatChannelType));
            }

            AccountId id          = args.Sender;
            int       characterId = int.Parse(id.Name);

            //TODO: We need to translate the guid to a name.
            NetworkEntityGuid guid = NetworkEntityGuidBuilder.New()
                                     .WithType(EntityType.Player)
                                     .WithId(characterId)
                                     .Build();

            if (NameQueryService.Exists(guid))
            {
                PublishTextData(channelType, args, guid, NameQueryService.Retrieve(guid));
            }
            else
            {
                UnityAsyncHelper.UnityMainThreadContext.PostAsync(async() =>
                {
                    string queryResponse = await NameQueryService.RetrieveAsync(guid)
                                           .ConfigureAwaitFalse();

                    PublishTextData(channelType, args, guid, queryResponse);
                });
            }
        }
Пример #3
0
        private void AddGameObjectInstances <TInstanceModelType>([NotNull] IReadOnlyCollection <TInstanceModelType> resultEntries)
            where TInstanceModelType : IGameObjectLinkable
        {
            if (resultEntries == null)
            {
                throw new ArgumentNullException(nameof(resultEntries));
            }

            BehaviourInstanceDataMappable.Add(typeof(TInstanceModelType), new InstanceStaticEntityDataCollection <object>());

            foreach (var instance in resultEntries)
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Info($"Processing {typeof(TInstanceModelType).Name} Data Instance: {instance.LinkedGameObjectId}");
                }

                NetworkEntityGuid guid = new NetworkEntityGuidBuilder()
                                         .WithEntryId(instance.LinkedGameObjectId)
                                         .WithType(EntityType.GameObject)
                                         .Build();

                BehaviourInstanceDataMappable[typeof(TInstanceModelType)].Add(guid, instance);
            }
        }
Пример #4
0
        public NetworkEntityGuid Create(GameObjectInstanceModel context)
        {
            if (!context.Guid.isTemplateGuid)
            {
                throw new InvalidOperationException($"Cannot create instance {nameof(NetworkEntityGuid)} from non-Template {nameof(NetworkEntityGuid)}.");
            }

            NetworkEntityGuidBuilder builder = new NetworkEntityGuidBuilder();

            return(builder.WithId(Interlocked.Increment(ref GameObjectCount))
                   .WithType(EntityType.GameObject)
                   .WithEntryId(context.Guid.EntryId)
                   .Build());
        }
Пример #5
0
        public CreatureInstanceModel Convert([NotNull] CreatureEntryModel fromObject)
        {
            if (fromObject == null)
            {
                throw new ArgumentNullException(nameof(fromObject));
            }

            NetworkEntityGuid guid = new NetworkEntityGuidBuilder()
                                     .WithId(0) //0 means that it's not an instance.
                                     .WithType(EntityType.Creature)
                                     .WithEntryId(fromObject.CreatureEntryId)
                                     .Build();

            //TODO: better handle position crap
            return(new CreatureInstanceModel(guid, fromObject.CreatureTemplateId, new Vector3(fromObject.SpawnPosition.X, fromObject.SpawnPosition.Y, fromObject.SpawnPosition.Z), fromObject.InitialOrientation));
        }
Пример #6
0
        //We don't currently use this. It was a good idea but may not be supported as usernames for vivox.
        private unsafe string ComputeCharacterString(int contextCharacterId)
        {
            NetworkEntityGuid playerGuid = new NetworkEntityGuidBuilder()
                                           .WithType(EntityType.Player)
                                           .WithId(contextCharacterId)
                                           .Build();

            //Access raw memory of the guid.
            ulong playerRawGuid = playerGuid.RawGuidValue;
            byte *rawValue      = (byte *)&playerRawGuid;

            //The idea here is we use the player's 64bit guid value directly
            //as the string character value. That way it can be moved to and from
            //the player guid efficiently.
            return(Encoding.ASCII.GetString(rawValue, sizeof(ulong)));
        }
Пример #7
0
        /// <inheritdoc />
        public async Task OnGameInitialized()
        {
            try
            {
                CharacterListResponse listResponse = await CharacterServiceQueryable.GetCharacters()
                                                     .ConfigureAwaitFalse();

                //TODO: Handle errors
                foreach (var character in listResponse.CharacterIds)
                {
                    var entityGuid = new NetworkEntityGuidBuilder()
                                     .WithId(character)
                                     .WithType(EntityType.Player)
                                     .Build();

                    //TODO: Optimize below awaits.
                    //Do a namequery so it's in the cache for when anything tries to get entities name.
                    await EntityNameQueryable.RetrieveAsync(entityGuid)
                    .ConfigureAwaitFalse();

                    var appearanceResponse = await CharacterServiceQueryable.GetCharacterAppearance(entityGuid.EntityId)
                                             .ConfigureAwaitFalse();

                    var characterData = await CharacterServiceQueryable.GetCharacterData(entityGuid.EntityId)
                                        .ConfigureAwaitFalse();

                    //Don't throw, because we actually don't want to stop the
                    //character screen from working just because we can't visually display some stuff.
                    if (!appearanceResponse.isSuccessful)
                    {
                        Logger.Error($"Failed to query for Character: {entityGuid.EntityId} appearance. Reason: {appearanceResponse.ResultCode}");
                    }

                    //TODO: Handle errors.
                    CharacterAppearanceMappable.AddObject(entityGuid, appearanceResponse.Result);
                    InitialCharacterDataInstance.AddObject(entityGuid, characterData.Result);

                    OnCharacterSelectionEntryChanged?.Invoke(this, new CharacterSelectionEntryDataChangeEventArgs(entityGuid));
                }
            }
            catch (Exception e)
            {
                Logger.Error($"Encountered Error: {e.Message}");
                throw;
            }
        }
Пример #8
0
        protected override void OnEventFired(object source, EventArgs args)
        {
            UnityAsyncHelper.UnityMainThreadContext.PostAsync(async() =>
            {
                CharacterFriendListResponseModel friendsResponse = await SocialService.GetCharacterListAsync();

                foreach (int characterId in friendsResponse.CharacterFriendsId)
                {
                    NetworkEntityGuid entityGuid = NetworkEntityGuidBuilder.New()
                                                   .WithType(EntityType.Player)
                                                   .WithId(characterId)
                                                   .Build();

                    FriendAddedPublisher.PublishEvent(this, new CharacterFriendAddedEventArgs(entityGuid));
                }
            });
        }
Пример #9
0
        /// <inheritdoc />
        public override async Task OnDisconnectedAsync(Exception exception)
        {
            NetworkEntityGuid guid = new NetworkEntityGuidBuilder()
                                     .WithId(int.Parse(Context.UserIdentifier))
                                     .WithType(EntityType.Player)
                                     .Build();

            if (Logger.IsEnabled(LogLevel.Information))
            {
                Logger.LogInformation($"About to attempt final cleanup for Entity: {guid}");
            }

            foreach (var c in EntityRemovable)
            {
                c.RemoveEntityEntry(guid);
            }

            await base.OnDisconnectedAsync(exception);
        }
Пример #10
0
        public async Task <IActionResult> ReverseNameQuery([FromRoute(Name = "name")][JetBrains.Annotations.NotNull] string characterPlayerName)
        {
            if (string.IsNullOrWhiteSpace(characterPlayerName))
            {
                return(BuildFailedResponseModel(NameQueryResponseCode.UnknownIdError));
            }

            bool knownId = await CharacterRepository.ContainsAsync(characterPlayerName);

            //TODO: JSON Response
            if (!knownId)
            {
                return(BuildFailedResponseModel(NameQueryResponseCode.UnknownIdError));
            }

            //Else if it is a known id we should grab the name of the character
            CharacterEntryModel characterModel = await CharacterRepository.RetrieveAsync(characterPlayerName);

            return(BuildSuccessfulResponseModel(NetworkEntityGuidBuilder.New().WithType(EntityType.Player).WithId(characterModel.CharacterId).Build()));
        }
Пример #11
0
        /// <inheritdoc />
        public async Task <HubOnConnectionState> OnConnected(Hub hubConnectedTo)
        {
            //TODO: Verify that the character they requested is owned by them.
            ProjectVersionStage.AssertAlpha();

            NetworkEntityGuid guid = new NetworkEntityGuidBuilder()
                                     .WithId(int.Parse(hubConnectedTo.Context.UserIdentifier))
                                     .WithType(EntityType.Player)
                                     .Build();

            HubOnConnectionState state = await TryRequestCharacterGuildStatus(guid, hubConnectedTo.Context.UserIdentifier)
                                         .ConfigureAwaitFalse();

            if (state == HubOnConnectionState.Success)
            {
                await RegisterGuildOnExistingResponse(guid, hubConnectedTo.Groups, hubConnectedTo.Context.ConnectionId)
                .ConfigureAwaitFalseVoid();

                return(HubOnConnectionState.Success);
            }

            //Just error, we don't need to abort. Something didn't work right though.
            return(HubOnConnectionState.Error);
        }
Пример #12
0
        /// <inheritdoc />
        public override async Task HandleMessage(IPeerSessionMessageContext <GameServerPacketPayload> context, ClientSessionClaimRequestPayload payload)
        {
            //TODO: We need better validation/authorization for clients trying to claim a session. Right now it's open to malicious attack
            ZoneServerTryClaimSessionResponse zoneServerTryClaimSessionResponse = null;

            try
            {
                ProjectVersionStage.AssertAlpha();
                zoneServerTryClaimSessionResponse = await GameServerClient.TryClaimSession(new ZoneServerTryClaimSessionRequest(await GameServerClient.GetAccountIdFromToken(payload.JWT), payload.CharacterId))
                                                    .ConfigureAwaitFalse();
            }
            catch (Exception e)            //we could get an unauthorized response
            {
                Logger.Error($"Failed to Query for AccountId: {e.Message}. AuthToken provided was: {payload.JWT}");
                throw;
            }

            if (!zoneServerTryClaimSessionResponse.isSuccessful)
            {
                if (Logger.IsWarnEnabled)
                {
                    Logger.Warn($"Client attempted to claim session for Character: {payload.CharacterId} but was denied.");
                }

                //TODO: Better error code
                await context.PayloadSendService.SendMessage(new ClientSessionClaimResponsePayload(ClientSessionClaimResponseCode.SessionUnavailable))
                .ConfigureAwaitFalse();

                return;
            }

            NetworkEntityGuid entityGuid = new NetworkEntityGuidBuilder()
                                           .WithId(payload.CharacterId)
                                           .WithType(EntityType.Player)
                                           .Build();

            //TODO: We assume they are authenticated, we don't check at the moment but we WILL and SHOULD. Just load their location.
            ZoneServerCharacterLocationResponse locationResponse = await GameServerClient.GetCharacterLocation(payload.CharacterId)
                                                                   .ConfigureAwaitFalse();

            Vector3 position = locationResponse.isSuccessful ? locationResponse.Position : SpawnPointProvider.GetSpawnPoint().WorldPosition;

            SpawnPointData pointData = new SpawnPointData(position, Quaternion.identity);

            if (Logger.IsDebugEnabled)
            {
                Logger.Debug($"Recieved player location: {pointData.WorldPosition} from {(locationResponse.isSuccessful ? "Database" : "Spawnpoint")}");
            }

            //TODO: We need a cleaner/better way to load initial player data.
            ResponseModel <CharacterDataInstance, CharacterDataQueryReponseCode> characterData = await CharacterService.GetCharacterData(payload.CharacterId);

            //TODO: Check success.
            InitialCharacterDataMappable.AddObject(entityGuid, characterData.Result);

            //Just broadcast successful claim, let listeners figure out what to do with this information.
            OnSuccessfulSessionClaimed?.Invoke(this, new PlayerSessionClaimedEventArgs(entityGuid, pointData.WorldPosition, new PlayerEntitySessionContext(context.PayloadSendService, context.Details.ConnectionId, context.ConnectionService)));

            await context.PayloadSendService.SendMessage(new ClientSessionClaimResponsePayload(ClientSessionClaimResponseCode.Success))
            .ConfigureAwaitFalse();
        }