/// <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(); }