public void Write(params object[] messages) { if (Client.IsConnected) { Client.Write(messages); } }
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; } }
//[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); } }
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); }
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. }
public void Write(params object[] messages) { Client.Write(messages); }
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; } }