Пример #1
0
 public void Write(params object[] messages)
 {
     if (Client.IsConnected)
     {
         Client.Write(messages);
     }
 }
Пример #2
0
        protected override void OnBeforeTransition(RegulatorState oldState, RegulatorState newState, object data)
        {
            switch (newState.Name)
            {
            case "CreateSim":
                var packet = (RSGZWrapperPDU)data;
                City.Write(packet);
                AsyncTransition("Waiting");
                break;

            case "ProcessResponse":
                var response = (CreateASimResponse)data;
                if (response.Status == CreateASimStatus.SUCCESS)
                {
                    AsyncTransition("Success", data);
                }
                else
                {
                    AsyncTransition("Error", data);
                }
                break;

            case "Error":
                AsyncReset();
                break;

            case "Success":
                AsyncReset();
                break;
            }
        }
Пример #3
0
        //[MethodImpl(MethodImplOptions.Synchronized)]
        private Task <T> Request <T>(DBRequestType type, DBResponseType responseType, uint?parameter, object complexParameter)
        {
            lock (Sync)
            {
                var id         = NextMessageId();
                var taskSource = new TaskCompletionSource <T>();

                var pending = new PendingRequest();
                pending.Callback = x =>
                {
                    taskSource.SetResult((T)x);
                };
                pending.RequestType  = type;
                pending.ResponseType = responseType;
                PendingRequests.Add(id, pending);

                CityClient.Write(new DBRequestWrapperPDU()
                {
                    Sender = new Sender
                    {
                        AriesID         = "0",
                        MasterAccountID = "0",
                    },
                    SendingAvatarID = id,
                    Body            = new cTSONetMessageStandard()
                    {
                        DatabaseType     = type.GetRequestID(),
                        Parameter        = parameter,
                        ComplexParameter = complexParameter
                    }
                });

                return((Task <T>)taskSource.Task);
            }
        }
Пример #4
0
        public Task <object> Request(MaskedStruct mask, uint id)
        {
            var messageId = NextMessageId();
            var request   = new DataServiceWrapperPDU()
            {
                RequestTypeID   = mask.GetID(),
                SendingAvatarID = messageId, //Reusing this field for easier callbacks rather than scoping them
                Body            = new cTSONetMessageStandard()
                {
                    DataServiceType = mask.GetID(),
                    Parameter       = id
                }
            };

            CityClient.Write(request);

            //TODO: Add timeouts
            var result = new PendingDataRequest(messageId, this, Get(mask, id));

            lock (PendingCallbacks) PendingCallbacks.Add(messageId, result);
            return(result.Task);
        }
Пример #5
0
        protected override void OnAfterTransition(RegulatorState oldState, RegulatorState newState, object data)
        {
            switch (newState.Name)
            {
            case "SelectLot":
                IsDisconnecting = false;
                AsyncTransition("FindLot", data);
                break;

            case "FindLot":
                //LotId = ((JoinLotRequest)data).LotId;
                City.Write(new FSO.Server.Protocol.Electron.Packets.FindLotRequest {
                    LotId = ((JoinLotRequest)data).LotId
                });
                break;

            case "FoundLot":
                var result = (FindLotResponse)data;
                if (result.Status == Server.Protocol.Electron.Model.FindLotResponseStatus.FOUND)
                {
                    LotId           = result.LotId;
                    FindLotResponse = result;
                    AsyncTransition("OpenSocket", result.Address);
                }
                else
                {
                    ThrowErrorAndReset(result.Status);
                }
                break;

            case "OpenSocket":
                ReestablishAttempt = 0;
                var address = data as string;
                LastAddress = address;
                if (address == null)
                {
                    this.ThrowErrorAndReset(new Exception("Unknown parameter"));
                }
                else
                {
                    //101 is plain
                    Client.Connect(address + "101");
                }
                break;

            case "SocketOpen":
                break;

            case "RequestClientSession":
                Client.Write(new RequestClientSessionResponse
                {
                    Password = FindLotResponse.LotServerTicket,
                    User     = FindLotResponse.User
                });
                break;

            case "HostOnline":
                Client.Write(
                    new ClientOnlinePDU
                {
                }
                    );

                AsyncTransition("PartiallyConnected");

                //When we join a property, get the lot info to update the thumbnail cache
                DataService.Request(Server.DataService.Model.MaskedStruct.PropertyPage_LotInfo, LotId);
                break;

            case "UnexpectedDisconnect":
                if (ReestablishAttempt > 0)
                {
                    IsDisconnecting = true;
                    AsyncTransition("Disconnected");
                }
                else
                {
                    GameThread.SetTimeout(() =>
                    {
                        if (CurrentState?.Name == "UnexpectedDisconnect")
                        {
                            AsyncTransition("Reestablish");
                        }
                        else if (CurrentState?.Name != "Disconnected")
                        {
                            IsDisconnecting = true;
                            AsyncTransition("Disconnected");
                        }
                    }, 100);
                }
                break;

            case "Reestablish":
                ReestablishAttempt++;
                Client.Connect(LastAddress + "101");
                break;

            case "Reestablishing":
                Client.Write(new RequestClientSessionResponse
                {
                    Password = FindLotResponse.LotServerTicket,
                    User     = FindLotResponse.User,
                    Unknown2 = 1
                });
                break;

            case "Reestablished":
                Client.Write(
                    new ClientOnlinePDU
                {
                }
                    );
                ReestablishAttempt = 0;
                AsyncTransition("LotCommandStream");
                break;

            case "ReestablishFail":
                if (ReestablishAttempt < 10)
                {
                    GameThread.SetTimeout(() =>
                    {
                        if (CurrentState?.Name == "ReestablishFail")
                        {
                            AsyncTransition("Reestablish");
                        }
                    }, 1000);
                }
                else
                {
                    AsyncTransition("UnexpectedDisconnect");
                }
                break;


            case "Disconnect":
                if (Client.IsConnected && !IsDisconnecting)
                {
                    Client.Write(new ClientByePDU());
                    Client.Disconnect();

                    //When we leave a property, get the lot info to update the thumbnail cache
                    DataService.Request(Server.DataService.Model.MaskedStruct.PropertyPage_LotInfo, LotId);
                }
                else
                {
                    AsyncTransition("Disconnected");
                }
                break;

            case "Disconnected":
                ReestablishAttempt = 0;
                break;
            }
        }
        public CityConnectionRegulator(CityClient cityApi, [Named("City")] AriesClient cityClient, IDatabaseService db, IClientDataService ds, IKernel kernel, IShardsDomain shards)
        {
            CityApi = cityApi;
            Client  = cityClient;
            Client.AddSubscriber(this);
            DB          = db;
            DataService = ds;
            Shards      = shards;

            AddState("Disconnected")
            .Default()
            .Transition()
            .OnData(typeof(ShardSelectorServletRequest))
            .TransitionTo("SelectCity");

            AddState("SelectCity")
            .OnlyTransitionFrom("Disconnected", "Reconnecting");

            AddState("ConnectToCitySelector")
            .OnData(typeof(ShardSelectorServletResponse))
            .TransitionTo("CitySelected")
            .OnlyTransitionFrom("SelectCity");

            AddState("CitySelected")
            .OnData(typeof(ShardSelectorServletResponse))
            .TransitionTo("OpenSocket")
            .OnlyTransitionFrom("ConnectToCitySelector");

            AddState("OpenSocket")
            .OnData(typeof(AriesConnected)).TransitionTo("SocketOpen")
            .OnData(typeof(AriesDisconnected)).TransitionTo("UnexpectedDisconnect")
            .OnlyTransitionFrom("CitySelected");

            AddState("SocketOpen")
            .OnData(typeof(RequestClientSession)).TransitionTo("RequestClientSession")
            .OnData(typeof(AriesDisconnected)).TransitionTo("UnexpectedDisconnect")
            .OnlyTransitionFrom("OpenSocket");

            AddState("RequestClientSession")
            .OnData(typeof(HostOnlinePDU)).TransitionTo("HostOnline")
            .OnData(typeof(AriesDisconnected)).TransitionTo("UnexpectedDisconnect")
            .OnlyTransitionFrom("SocketOpen");

            AddState("HostOnline").OnlyTransitionFrom("RequestClientSession");
            AddState("PartiallyConnected")
            .OnData(typeof(AriesDisconnected)).TransitionTo("UnexpectedDisconnect")
            .OnData(typeof(ShardSelectorServletRequest)).TransitionTo("CompletePartialConnection")
            .OnlyTransitionFrom("HostOnline");

            AddState("CompletePartialConnection").OnlyTransitionFrom("PartiallyConnected");
            AddState("AskForAvatarData")
            .OnData(typeof(LoadAvatarByIDResponse)).TransitionTo("ReceivedAvatarData")
            .OnlyTransitionFrom("PartiallyConnected", "CompletePartialConnection");
            AddState("ReceivedAvatarData").OnlyTransitionFrom("AskForAvatarData");
            AddState("AskForCharacterData").OnlyTransitionFrom("ReceivedAvatarData");
            AddState("ReceivedCharacterData").OnlyTransitionFrom("AskForCharacterData");

            AddState("Connected")
            .OnData(typeof(AriesDisconnected)).TransitionTo("UnexpectedDisconnect")
            .OnlyTransitionFrom("ReceivedCharacterData");

            AddState("UnexpectedDisconnect");

            AddState("Disconnect")
            .OnData(typeof(AriesDisconnected))
            .TransitionTo("Disconnected");

            AddState("Reconnect")
            .OnData(typeof(AriesDisconnected))
            .TransitionTo("Reconnecting");

            AddState("Reconnecting")
            .OnData(typeof(ShardSelectorServletRequest))
            .TransitionTo("SelectCity")
            .OnlyTransitionFrom("Reconnect");

            GameThread.SetInterval(() =>
            {
                if (Client.IsConnected)
                {
                    Client.Write(new KeepAlive());
                }
            }, 10000); //keep alive every 10 seconds. prevents disconnection by aggressive NAT.
        }
Пример #7
0
 public void Write(params object[] messages)
 {
     Client.Write(messages);
 }
Пример #8
0
        protected override void OnAfterTransition(RegulatorState oldState, RegulatorState newState, object data)
        {
            switch (newState.Name)
            {
            case "SelectLot":
                IsDisconnecting = false;
                AsyncTransition("FindLot", data);
                break;

            case "FindLot":
                //LotId = ((JoinLotRequest)data).LotId;
                City.Write(new FindLotRequest
                {
                    LotId = ((JoinLotRequest)data).LotId
                });
                break;

            case "FoundLot":
                var result = (FindLotResponse)data;
                if (result.Status == Server.Protocol.Electron.Model.FindLotResponseStatus.FOUND)
                {
                    LotId           = result.LotId;
                    FindLotResponse = result;
                    AsyncTransition("OpenSocket", result.Address);
                }
                else
                {
                    ThrowErrorAndReset(result.Status);
                }
                break;

            case "OpenSocket":
                var address = data as string;
                if (address == null)
                {
                    ThrowErrorAndReset(new Exception("Unknown parameter"));
                }
                else
                {
                    //101 is plain
                    Client.Connect(address + "101");
                }
                break;

            case "SocketOpen":
                break;

            case "RequestClientSession":
                Client.Write(new RequestClientSessionResponse
                {
                    Password = FindLotResponse.LotServerTicket,
                    User     = FindLotResponse.User
                });
                break;

            case "HostOnline":
                Client.Write(
                    new ClientOnlinePDU
                {
                }
                    );

                AsyncTransition("PartiallyConnected");

                //When we join a property, get the lot info to update the thumbnail cache
                DataService.Request(Server.DataService.Model.MaskedStruct.PropertyPage_LotInfo, LotId);
                break;

            case "UnexpectedDisconnect":
                IsDisconnecting = true;
                AsyncTransition("Disconnected");
                break;

            case "Disconnect":
                if (Client.IsConnected && !IsDisconnecting)
                {
                    Client.Write(new ClientByePDU());
                    Client.Disconnect();

                    //When we leave a property, get the lot info to update the thumbnail cache
                    DataService.Request(Server.DataService.Model.MaskedStruct.PropertyPage_LotInfo, LotId);
                }
                else
                {
                    AsyncTransition("Disconnected");
                }
                break;
            }
        }