internal Realm(Realm parent, long id) { Parent = parent; ID = id; }
private void ChangeRealm(User user, long targetRealmID, bool createChildRealm) { // Don't do anything if the user is staying in the same realm if ((user.Realm == null && targetRealmID == -1) || (user.Realm != null && user.Realm.ID == targetRealmID)) { return; } // Child realms can only be created if user is currently in a realm var oldRealm = user.Realm; if (oldRealm == null && createChildRealm) { createChildRealm = false; } // Remove user from the old realm, informing everyone that the user has left it if (oldRealm != null) { oldRealm.Users.Remove(user); user.Realm = null; foreach (var realmUser in oldRealm.Users) { Send(realmUser.EndPoint, "-" + user.ID); } } // Get the target realm, creating it if necessary var newRealm = (Realm)null; if (targetRealmID != -1) { if (!realmsByID.TryGetValue(targetRealmID, out newRealm)) { var parentRealm = createChildRealm ? oldRealm : null; newRealm = new Realm(parentRealm, targetRealmID); realmsByID.Add(targetRealmID, newRealm); if (parentRealm != null) { parentRealm.ChildRealms.Add(newRealm); } } // Add the user to the new realm newRealm.Users.Add(user); user.Realm = newRealm; // Advise user that the new realm has been joined successfully Send(user.EndPoint, (createChildRealm ? "&" : "^") + targetRealmID); // Advise user of all child realms already existing in the new realm foreach (var realm in newRealm.ChildRealms) { Send(user.EndPoint, "{" + realm.ID); } // Advise user of all other users already connected to that realm var otherRealmUsers = newRealm.Users.Where(u => u != user).ToArray(); Send(user.EndPoint, "=" + string.Join(",", otherRealmUsers.Select(u => u.ID))); // Advise everyone in the target realm that user has joined foreach (var realmUser in otherRealmUsers) { Send(realmUser.EndPoint, "+" + user.ID); } } // Advise everyone in the old realm that there is a new child realm if (createChildRealm) { foreach (var realmUser in oldRealm.Users) { Send(realmUser.EndPoint, "{" + newRealm.ID); } } // If there aren't any more users or child realms in the old realm then recursively destroy the old realm(s) var currentRealm = oldRealm; while (!createChildRealm && currentRealm != null && currentRealm.Users.Count == 0 && currentRealm.ChildRealms.Count == 0) { // Remove the realm from the parent's child list if (currentRealm.Parent != null) { currentRealm.Parent.ChildRealms.Remove(currentRealm); // Advise users of the parent realm that the child realm has been destroyed foreach (var realmUser in currentRealm.Parent.Users) { Send(realmUser.EndPoint, "}" + currentRealm.ID); } } // Remove realm data if (currentRealm.ID >= Settings.Default.PublicRealmCount) { foreach (var fileName in Directory.GetFiles(".", "realm." + currentRealm.ID + ".*.entity")) { File.Delete(fileName); } } // Remove the realm from the list if (currentRealm.ID >= Settings.Default.PublicRealmCount) { reclaimableRealmIDs.Enqueue(currentRealm.ID); } realmsByID.Remove(currentRealm.ID); // Move on to checking parent realm currentRealm = currentRealm.Parent; } }