Exemplo n.º 1
0
        /// <inheritdoc />
        public override async Task HandleMessage(IPeerMessageContext <GameClientPacketPayload> context, NetworkObjectVisibilityChangeEventPayload payload)
        {
            foreach (var entity in payload.EntitiesToCreate)
            {
                if (Logger.IsDebugEnabled)
                {
                    Logger.Debug($"Encountered new entity: {entity.EntityGuid}");
                }
            }

            foreach (var entity in payload.OutOfRangeEntities)
            {
                if (Logger.IsErrorEnabled)
                {
                    Logger.Debug($"Leaving entity: {entity}");
                }
            }

            //Assume it's a player for now
            foreach (var creationData in payload.EntitiesToCreate)
            {
                //TODO: Right now we're creating a temporary entity data collection.
                EntityFieldDataCollection <EntityDataFieldType> testData = new EntityFieldDataCollection <EntityDataFieldType>();

                //We set the initial values off the main thread, it is much better that way.
                //However, that means initial values won't dispatch OnChange stuff.
                SetInitialFieldValues(creationData, testData);

                OnNetworkEntityNowVisible?.Invoke(this, new NetworkEntityNowVisibleEventArgs(creationData.EntityGuid, creationData, testData));
            }

            foreach (var destroyData in payload.OutOfRangeEntities)
            {
                OnNetworkEntityVisibilityLost?.Invoke(this, new NetworkEntityVisibilityLostEventArgs(destroyData));
            }

            //TODO: We should not waste 2, maybe even more, frames to prevent the race condition for spawn/despawn and other packets.
            //We SHOULD actually only call these awaits in other handlers where we realize we MAY not have spawned the entity yet.
            //This should yield better-case throughput because MANY packets could be handled unrelated inbetween these awaits.
            //Two tickable frames is long enough for all spawn/despawn logic to have run.
            await UnityExtended.AwaitNextTickableFrameAsync()
            .ConfigureAwait(false);

            await UnityExtended.AwaitNextTickableFrameAsync()
            .ConfigureAwait(false);
        }
        /// <inheritdoc />
        protected override void Load(ContainerBuilder builder)
        {
            //https://stackoverflow.com/questions/4926676/mono-https-webrequest-fails-with-the-authentication-or-decryption-has-failed
            ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            ServicePointManager.CheckCertificateRevocationList = false;

            Unity3DProtobufPayloadRegister payloadRegister = new Unity3DProtobufPayloadRegister();

            payloadRegister.RegisterDefaults();
            payloadRegister.Register(ZoneServerMetadataMarker.ClientPayloadTypesByOpcode, ZoneServerMetadataMarker.ServerPayloadTypesByOpcode);

            //Set the sync context
            UnityExtended.InitializeSyncContext();

            //TODO: We need to not have such a high rate of Update and need to add prediction.
            Application.targetFrameRate = 60;

            builder.RegisterInstance(new ProtobufNetGladNetSerializerAdapter(PrefixStyle.Fixed32))
            .As <INetworkSerializationService>();

            builder.RegisterType <ZoneServerDefaultRequestHandler>()
            .AsImplementedInterfaces()
            .SingleInstance();

            builder.RegisterInstance(new UnityLogger(LogLevel.All))
            .As <ILog>();

            builder.RegisterType <MessageHandlerService <GameClientPacketPayload, GameServerPacketPayload, IPeerSessionMessageContext <GameServerPacketPayload> > >()
            .As <MessageHandlerService <GameClientPacketPayload, GameServerPacketPayload, IPeerSessionMessageContext <GameServerPacketPayload> > >()
            .SingleInstance();

            builder.RegisterInstance(new DefaultSessionCollection())
            .As <IRegisterable <int, ZoneClientSession> >()
            .As <ISessionCollection>()
            .SingleInstance();

            builder.RegisterInstance(new NetworkAddressInfo(IPAddress.Parse("192.168.0.3"), 5006))
            .As <NetworkAddressInfo>()
            .SingleInstance()
            .ExternallyOwned();

            builder.RegisterType <ZoneServerApplicationBase>()
            .SingleInstance()
            .AsSelf();

            RegisterEntityMappableCollections(builder);

            //TODO: We should automate the registeration of message senders
            builder.RegisterType <VisibilityChangeMessageSender>()
            .AsImplementedInterfaces()
            .AsSelf();

            builder.RegisterType <DefaultGameObjectToEntityMappable>()
            .As <IReadonlyGameObjectToEntityMappable>()
            .As <IGameObjectToEntityMappable>()
            .SingleInstance();

            RegisterPlayerFactoryServices(builder);

            builder.RegisterType <DefaultEntityFactory <DefaultEntityCreationContext> >()
            .AsImplementedInterfaces()
            .AsSelf()
            .SingleInstance();

            builder.RegisterType <GenericMessageSender <PlayerSelfSpawnEventPayload> >()
            .AsSelf()
            .AsImplementedInterfaces();

            builder.RegisterType <DefaultManagedSessionFactory>()
            .AsImplementedInterfaces();

            //TODO: Extract this into a handlers registrar

            //This is for mapping connection IDs to the main controlled EntityGuid.
            builder.RegisterInstance(new ConnectionEntityMap())
            .AsImplementedInterfaces()
            .SingleInstance();

            builder.RegisterType <PlayerEntityGuidEnumerable>()
            .As <IPlayerEntityGuidEnumerable>()
            .AsSelf();

            builder.RegisterType <MovementUpdateMessageSender>()
            .As <INetworkMessageSender <EntityMovementMessageContext> >()
            .AsSelf();

            //Keep this one here, zoneserver needs it.
            builder.Register <IServiceDiscoveryService>(context => RestService.For <IServiceDiscoveryService>(@"http://192.168.0.3:5000"));
            builder.Register(context =>
            {
                IServiceDiscoveryService serviceDiscovery = context.Resolve <IServiceDiscoveryService>();

                return(new AsyncEndpointZoneServerToGameServerService(QueryForRemoteServiceEndpoint(serviceDiscovery, "GameServer")));
            })
            .As <IZoneServerToGameServerClient>()
            .SingleInstance();

            builder.RegisterType <DefaultMovementHandlerService>()
            .As <IMovementDataHandlerService>()
            .AsSelf();

            builder.RegisterType <PathMovementBlockHandler>()
            .AsImplementedInterfaces()
            .AsSelf();

            builder.RegisterType <PositionChangeMovementBlockHandler>()
            .AsImplementedInterfaces()
            .AsSelf();

            builder.RegisterType <UtcNowNetworkTimeService>()
            .AsSelf()
            .AsImplementedInterfaces()
            .SingleInstance();

            builder.RegisterType <FieldValueUpdateFactory>()
            .AsSelf()
            .AsImplementedInterfaces();

            RegisterEntityDestructionServices(builder);

            //Honestly, before running this I think it'll be a MIRACLE if this actually works
            //Registering the generic networkmessage sender
            builder.RegisterGeneric(typeof(GenericMessageSender <>))
            .As(typeof(INetworkMessageSender <>).MakeGenericType(typeof(GenericSingleTargetMessageContext <>)))
            .SingleInstance();

            RegisterLockingPolicies(builder);

            //IPhysicsTriggerEventSubscribable TriggerEventSubscribable
            builder.RegisterInstance(GlobalPhysicsEventSystem.Instance)
            .AsImplementedInterfaces()
            .SingleInstance();
        }