/// <summary> /// Sends a request to server, retrieves all profile values, and applies them to a provided /// profile /// </summary> public void FillProfileValues(ObservableServerProfile profile, SuccessCallback successCallback, ErrorCallback errorCallback) { if (!Client.IsConnected) { errorCallback.Invoke("Not connected"); return; } Client.SendMessage((ushort)OpCodes.ServerProfileRequest, profile.Username, (status, response) => { if (status != ResponseStatus.Success) { errorCallback.Invoke(response.AsString("Unknown error")); return; } // Use the bytes received, to replicate the profile profile.FromBytes(response.AsBytes()); profile.ClearUpdates(); _profiles[profile.Username] = profile; profile.ModifiedInServer += serverProfile => { OnProfileModified(profile); }; profile.Disposed += OnProfileDisposed; successCallback.Invoke(); }); }
/// <summary> /// Collets changes in the profile, and sends them to client after delay /// </summary> /// <param name="profile"></param> /// <param name="delay"></param> /// <returns></returns> private async void SendUpdatesToClient(ObservableServerProfile profile, float delay) { // Wait for the delay if (delay > 0.01f) { await Task.Delay(TimeSpan.FromSeconds(delay)); } // Remove value from debounced updates debouncedClientUpdates.Remove(profile.Username); if (profile.ClientPeer == null || !profile.ClientPeer.IsConnected) { // If client is not connected, and we don't need to send him profile updates profile.ClearUpdates(); return; } using (var ms = new MemoryStream()) { using (var writer = new EndianBinaryWriter(EndianBitConverter.Big, ms)) { profile.GetUpdates(writer); profile.ClearUpdates(); } profile.ClientPeer.SendMessage(MessageHelper.Create((short)OpCodes.UpdateClientProfile, ms.ToArray()), DeliveryMethod.ReliableOrdered); } }
private IEnumerator ImitateGameServer() { var connection = Msf.Advanced.ClientSocketFactory(); connection.Connect("127.0.0.1", 5000); // Wait until connected to master while (!connection.IsConnected) { yield return(null); } // Construct the profile var profile = new ObservableServerProfile(_username) { new ObservableInt(MyProfileKeys.Coins, 5), new ObservableString(MyProfileKeys.Title, "DefaultTitle"), }; // Fill profile values Msf.Server.Profiles.FillProfileValues(profile, (successful, error) => { if (!successful) { Logs.Error(error); return; } // Modify the profile (changes will automatically be sent to the master server) profile.GetProperty <ObservableInt>(MyProfileKeys.Coins).Add(4); profile.GetProperty <ObservableString>(MyProfileKeys.Title).Set("DifferentTitle"); }, connection); }
/// <summary> /// Update profile info in database /// </summary> /// <param name="profile"></param> public void UpdateProfile(ObservableServerProfile profile) { var data = FindOrCreateData(profile); data.Data = profile.ToBytes(); profiles.Update(data); }
private IEnumerator ImitateGameServer() { var connection = Msf.Advanced.ClientSocketFactory(); connection.Connect("127.0.0.1", 5000); // Wait until connected to master while (!connection.IsConnected) { yield return(null); } var profile = new ObservableServerProfile(_username) { new ObservableInt(0, 5), new ObservableString(1, "TEE") }; Msf.Server.Profiles.FillProfileValues(profile, (successful, error) => { if (!successful) { Logs.Error(error); return; } profile.GetProperty <ObservableInt>(0).Add(4); profile.GetProperty <ObservableString>(1).Set("Medis"); }, connection); }
public MirrorRoomPlayer(int msfPeerId, NetworkConnection mirrorPeer, string username, MstProperties customOptions) { MasterPeerId = msfPeerId; MirrorPeer = mirrorPeer ?? throw new ArgumentNullException(nameof(mirrorPeer)); Username = username ?? throw new ArgumentNullException(nameof(username)); CustomOptions = customOptions ?? throw new ArgumentNullException(nameof(customOptions)); Profile = new ObservableServerProfile(username); }
/// <summary> /// Update profile info in database /// </summary> /// <param name="profile"></param> public async Task UpdateProfileAsync(ObservableServerProfile profile) { var data = await FindOrCreateData(profile); data.Data = profile.ToBytes(); await Task.Run(() => { profiles.Update(data); }); }
private void OnProfileModified(ObservableServerProfile profile) { _modifiedProfiles.Add(profile); if (_sendUpdatesCoroutine != null) { return; } _sendUpdatesCoroutine = Task.Factory.StartNew(() => KeepSendingUpdates(), TaskCreationOptions.LongRunning); }
private void OnProfileModified(ObservableServerProfile profile) { _modifiedProfiles.Add(profile); if (_updateTask != null) { return; } _updateTask = KeepSendingUpdates(); }
/// <summary> /// Saves a profile into database after delay /// </summary> /// <param name="profile"></param> /// <param name="delay"></param> /// <returns></returns> private IEnumerator SaveProfile(ObservableServerProfile profile, float delay) { // Wait for the delay yield return(new WaitForSecondsRealtime(delay)); // Remove value from debounced updates debouncedSaves.Remove(profile.Username); profileDatabaseAccessor.UpdateProfile(profile); profile.UnsavedProperties.Clear(); }
/// <summary> /// Saves a profile into database after delay /// </summary> /// <param name="profile"></param> /// <param name="delay"></param> /// <returns></returns> private async void SaveProfile(ObservableServerProfile profile, float delay) { // Wait for the delay await Task.Delay(TimeSpan.FromSeconds(delay)); // Remove value from debounced updates _debouncedSaves.Remove(profile.Username); database.ProfilesDatabase.UpdateProfile(profile); profile.UnsavedProperties.Clear(); }
public void UpdateProfile(ObservableServerProfile profile) { if (!profile.ShouldBeSavedToDatabase) { return; } using (var con = new NpgsqlConnection(_connectionString)) using (var cmd = new NpgsqlCommand()) { con.Open(); cmd.Connection = con; cmd.CommandText = "SELECT account_id FROM accounts " + "WHERE username = @username"; cmd.Parameters.AddWithValue("@username", profile.Username); var reader = cmd.ExecuteReader(); if (!reader.HasRows) { Logs.Error("Tried to save a profile of a user who has no account: " + profile.Username); return; } reader.Read(); //var accountId = reader.GetInt32("account_id"); var accountId = int.Parse(reader["account_id"].ToString()); reader.Close(); cmd.Parameters.Clear(); cmd.Connection = con; foreach (var unsavedProp in profile.UnsavedProperties) { cmd.CommandText = "INSERT INTO profile_values (account_id, value_key, value_value) " + "VALUES (@account_id, @value_key, @value_value)" + "ON CONFLICT (account_id, value_key) DO UPDATE SET value_value = @value_value"; cmd.Parameters.AddWithValue("@account_id", accountId); cmd.Parameters.AddWithValue("@value_key", unsavedProp.Key); cmd.Parameters.AddWithValue("@value_value", unsavedProp.SerializeToString()); cmd.ExecuteNonQuery(); cmd.Parameters.Clear(); } } profile.UnsavedProperties.Clear(); }
/// <summary> /// Get profile info from database /// </summary> /// <param name="profile"></param> public async Task RestoreProfileAsync(ObservableServerProfile profile) { try { var data = await FindOrCreateData(profile); profile.FromBytes(data.Data); } catch (Exception e) { UnityEngine.Debug.LogError(e); } }
/// <summary> /// Update profile info in database /// </summary> /// <param name="profile"></param> /// <param name="callback"></param> public async void UpdateProfileAsync(ObservableServerProfile profile, SuccessCallback callback) { try { await Task.Run(() => UpdateProfile(profile)); callback?.Invoke(true, string.Empty); } catch (Exception e) { callback?.Invoke(false, e.Message); } }
public async Task UpdateProfileAsync(ObservableServerProfile profile) { var data = await FindOrCreateData(profile); data.Data = profile.ToBytes(); var filter = Builders <ProfileInfoDataMongoDB> .Filter.Eq(e => e.UserId, profile.UserId); await Task.Run(() => { _profiles.ReplaceOne(filter, data); }); }
//Find profile in database or create new data and insert into database private ProfileInfoData FindOrCreateData(ObservableServerProfile profile) { var data = profiles.FindOne(a => a.Username == profile.Username); if (data == null) { data = new ProfileInfoData() { Username = profile.Username, Data = profile.ToBytes() }; profiles.Insert(data); } return(data); }
/// <summary> /// Invoked, when profile is changed /// </summary> /// <param name="profile"></param> private void OnProfileChangedEventHandler(ObservableServerProfile profile) { // Debouncing is used to reduce a number of updates per interval to one // TODO make debounce lookup more efficient than using string hashet if (!debouncedSaves.Contains(profile.Username) && profile.ShouldBeSavedToDatabase) { // If profile is not already waiting to be saved debouncedSaves.Add(profile.Username); StartCoroutine(SaveProfile(profile, saveProfileInterval)); } if (!debouncedClientUpdates.Contains(profile.Username)) { // If it's a master server debouncedClientUpdates.Add(profile.Username); StartCoroutine(SendUpdatesToClient(profile, clientUpdateInterval)); } }
/// <summary> /// Find profile data in database or create new data and insert them to database /// </summary> /// <param name="profile"></param> /// <returns></returns> private async Task <ProfileInfoData> FindOrCreateData(ObservableServerProfile profile) { string username = profile.Username; var data = await Task.Run(() => { return(profiles.FindOne(a => a.Username == username)); }); if (data == null) { data = new ProfileInfoData() { Username = profile.Username, Data = profile.ToBytes() }; await Task.Run(() => { profiles.Insert(data); }); } return(data); }
private async Task <ProfileInfoDataMongoDB> FindOrCreateData(ObservableServerProfile profile) { string userId = profile.UserId; var data = await Task.Run(() => { return(_profiles.Find(a => a.UserId == userId).FirstOrDefault()); }); if (data == null) { data = new ProfileInfoDataMongoDB() { UserId = profile.UserId, Data = profile.ToBytes() }; await Task.Run(() => { _profiles.InsertOne(data); }); } return(data); }
public void RestoreProfile(ObservableServerProfile profile) { using (var con = new NpgsqlConnection(_connectionString)) using (var cmd = new NpgsqlCommand()) { con.Open(); cmd.Connection = con; cmd.CommandText = "SELECT profile_values.* " + "FROM profile_values " + "INNER JOIN accounts " + "ON accounts.account_id = profile_values.account_id " + "WHERE username = @username;"; cmd.Parameters.AddWithValue("@username", profile.Username); var reader = cmd.ExecuteReader(); // There's no such data if (!reader.HasRows) { return; } var data = new Dictionary <short, string>(); while (reader.Read()) { //var key = reader.GetInt16("value_key"); var key = short.Parse(reader["value_key"].ToString()); var value = reader["value_value"] as string ?? ""; data.Add(key, value); } profile.FromStrings(data); } }
/// <summary> /// Collets changes in the profile, and sends them to client after delay /// </summary> /// <param name="profile"></param> /// <param name="delay"></param> /// <returns></returns> private IEnumerator SendUpdatesToClient(ObservableServerProfile profile, float delay) { // Wait for the delay if (delay > 0.01f) { yield return(new WaitForSecondsRealtime(delay)); } else { // Wait one frame, so that we don't send multiple packets // in case we update multiple values yield return(null); } // Remove value from debounced updates debouncedClientUpdates.Remove(profile.Username); if (profile.ClientPeer == null || !profile.ClientPeer.IsConnected) { // If client is not connected, and we don't need to send him profile updates profile.ClearUpdates(); yield break; } using (var ms = new MemoryStream()) { using (var writer = new EndianBinaryWriter(EndianBitConverter.Big, ms)) { profile.GetUpdates(writer); profile.ClearUpdates(); } profile.ClientPeer.SendMessage(MessageHelper.Create((short)MsfMessageCodes.UpdateClientProfile, ms.ToArray()), DeliveryMethod.ReliableSequenced); } }
/// <summary> /// Get profile info from database /// </summary> /// <param name="profile"></param> public void RestoreProfile(ObservableServerProfile profile) { var data = FindOrCreateData(profile); profile.FromBytes(data.Data); }
private void OnProfileDisposed(ObservableServerProfile profile) { profile.Disposed -= OnProfileDisposed; _profiles.Remove(profile.Username); }
public void RestoreProfile(ObservableServerProfile profile) { _concreteDbAccess.RestoreProfile(profile); }
public void UpdateProfile(ObservableServerProfile profile) { _concreteDbAccess.UpdateProfile(profile); }
public ProfileExtension(ObservableServerProfile profile, IPeer peer) { Username = profile.Username; Profile = profile; Peer = peer; }