protected void SendCloseChildAgent(UUID agentID, IEnumerable <GridRegion> regionsToClose) { IClientCapsService clientCaps = m_registry.RequestModuleInterface <ICapsService>().GetClientCapsService(agentID); //Close all agents that we've been given regions for foreach (GridRegion region in regionsToClose) { m_log.Debug("[AgentProcessing]: Closing child agent in " + region.RegionName); m_registry.RequestModuleInterface <ISimulationService>().CloseAgent(region, agentID); IRegionClientCapsService regionClientCaps = clientCaps.GetCapsService(region.RegionHandle); if (regionClientCaps != null) { regionClientCaps.Close(); clientCaps.RemoveCAPS(region.RegionHandle); } } }
void OnClosingClient(IClientAPI client) { ICapsService service = m_scene.RequestModuleInterface <ICapsService>(); if (service != null) { IClientCapsService clientCaps = service.GetClientCapsService(client.AgentId); if (clientCaps != null) { IRegionClientCapsService regionCaps = clientCaps.GetCapsService(m_scene.RegionInfo.RegionHandle); if (regionCaps != null) { regionCaps.Close(); clientCaps.RemoveCAPS(m_scene.RegionInfo.RegionHandle); } } } }
protected OSDMap OnMessageReceived(OSDMap message) { if (!message.ContainsKey("Method")) { return(null); } UUID AgentID = message["AgentID"].AsUUID(); ulong requestingRegion = message["RequestingRegion"].AsULong(); ICapsService capsService = m_registry.RequestModuleInterface <ICapsService>(); if (capsService == null) { //m_log.Info("[AgentProcessing]: Failed OnMessageReceived ICapsService is null"); return(new OSDMap()); } IClientCapsService clientCaps = capsService.GetClientCapsService(AgentID); IRegionClientCapsService regionCaps = null; if (clientCaps != null) { regionCaps = clientCaps.GetCapsService(requestingRegion); } if (message["Method"] == "LogoutRegionAgents") { LogOutAllAgentsForRegion(requestingRegion); } else if (message["Method"] == "RegionIsOnline") //This gets fired when the scene is fully finished starting up { //Log out all the agents first, then add any child agents that should be in this region LogOutAllAgentsForRegion(requestingRegion); IGridService GridService = m_registry.RequestModuleInterface <IGridService>(); if (GridService != null) { int x, y; Util.UlongToInts(requestingRegion, out x, out y); GridRegion requestingGridRegion = GridService.GetRegionByPosition(UUID.Zero, x, y); if (requestingGridRegion != null) { EnableChildAgentsForRegion(requestingGridRegion); } } } else if (message["Method"] == "DisableSimulator") { //KILL IT! if (regionCaps == null || clientCaps == null) { return(null); } regionCaps.Close(); clientCaps.RemoveCAPS(requestingRegion); } else if (message["Method"] == "ArrivedAtDestination") { if (regionCaps == null || clientCaps == null) { return(null); } //Recieved a callback if (clientCaps.InTeleport) //Only set this if we are in a teleport, // otherwise (such as on login), this won't check after the first tp! { clientCaps.CallbackHasCome = true; } regionCaps.Disabled = false; //The agent is getting here for the first time (eg. login) OSDMap body = ((OSDMap)message["Message"]); //Parse the OSDMap int DrawDistance = body["DrawDistance"].AsInteger(); AgentCircuitData circuitData = new AgentCircuitData(); circuitData.UnpackAgentCircuitData((OSDMap)body["Circuit"]); //Now do the creation EnableChildAgents(AgentID, requestingRegion, DrawDistance, circuitData); } else if (message["Method"] == "CancelTeleport") { if (regionCaps == null || clientCaps == null) { return(null); } //Only the region the client is root in can do this IRegionClientCapsService rootCaps = clientCaps.GetRootCapsService(); if (rootCaps != null && rootCaps.RegionHandle == regionCaps.RegionHandle) { //The user has requested to cancel the teleport, stop them. clientCaps.RequestToCancelTeleport = true; regionCaps.Disabled = false; } } else if (message["Method"] == "AgentLoggedOut") { //ONLY if the agent is root do we even consider it if (regionCaps != null) { if (regionCaps.RootAgent) { LogoutAgent(regionCaps); } } } else if (message["Method"] == "SendChildAgentUpdate") { if (regionCaps == null || clientCaps == null) { return(null); } IRegionClientCapsService rootCaps = clientCaps.GetRootCapsService(); if (rootCaps != null && rootCaps.RegionHandle == regionCaps.RegionHandle) { OSDMap body = ((OSDMap)message["Message"]); AgentPosition pos = new AgentPosition(); pos.Unpack((OSDMap)body["AgentPos"]); SendChildAgentUpdate(pos, regionCaps); regionCaps.Disabled = false; } } else if (message["Method"] == "TeleportAgent") { if (regionCaps == null || clientCaps == null) { return(null); } IRegionClientCapsService rootCaps = clientCaps.GetRootCapsService(); if (rootCaps != null && rootCaps.RegionHandle == regionCaps.RegionHandle) { OSDMap body = ((OSDMap)message["Message"]); GridRegion destination = new GridRegion(); destination.FromOSD((OSDMap)body["Region"]); uint TeleportFlags = body["TeleportFlags"].AsUInteger(); int DrawDistance = body["DrawDistance"].AsInteger(); AgentCircuitData Circuit = new AgentCircuitData(); Circuit.UnpackAgentCircuitData((OSDMap)body["Circuit"]); AgentData AgentData = new AgentData(); AgentData.Unpack((OSDMap)body["AgentData"]); regionCaps.Disabled = false; OSDMap result = new OSDMap(); string reason = ""; result["Success"] = TeleportAgent(destination, TeleportFlags, DrawDistance, Circuit, AgentData, AgentID, requestingRegion, out reason); result["Reason"] = reason; return(result); } } else if (message["Method"] == "CrossAgent") { if (regionCaps == null || clientCaps == null) { return(null); } if (clientCaps.GetRootCapsService().RegionHandle == regionCaps.RegionHandle) { //This is a simulator message that tells us to cross the agent OSDMap body = ((OSDMap)message["Message"]); Vector3 pos = body["Pos"].AsVector3(); Vector3 Vel = body["Vel"].AsVector3(); GridRegion Region = new GridRegion(); Region.FromOSD((OSDMap)body["Region"]); AgentCircuitData Circuit = new AgentCircuitData(); Circuit.UnpackAgentCircuitData((OSDMap)body["Circuit"]); AgentData AgentData = new AgentData(); AgentData.Unpack((OSDMap)body["AgentData"]); regionCaps.Disabled = false; OSDMap result = new OSDMap(); string reason = ""; result["Success"] = CrossAgent(Region, pos, Vel, Circuit, AgentData, AgentID, requestingRegion, out reason); result["Reason"] = reason; return(result); } } return(null); }
public bool TeleportAgent(GridRegion destination, uint TeleportFlags, int DrawDistance, AgentCircuitData circuit, AgentData agentData, UUID AgentID, ulong requestingRegion, out string reason) { IClientCapsService clientCaps = m_registry.RequestModuleInterface <ICapsService>().GetClientCapsService(AgentID); IRegionClientCapsService regionCaps = clientCaps.GetCapsService(requestingRegion); if (regionCaps == null || !regionCaps.RootAgent) { reason = ""; return(false); } bool result = false; try { bool callWasCanceled = false; ISimulationService SimulationService = m_registry.RequestModuleInterface <ISimulationService>(); if (SimulationService != null) { //Set the user in transit so that we block duplicate tps and reset any cancelations if (!SetUserInTransit(AgentID)) { reason = "Already in a teleport"; return(false); } //Note: we have to pull the new grid region info as the one from the region cannot be trusted IGridService GridService = m_registry.RequestModuleInterface <IGridService>(); if (GridService != null) { destination = GridService.GetRegionByUUID(UUID.Zero, destination.RegionID); //Inform the client of the neighbor if needed circuit.child = false; //Force child status to the correct type if (!InformClientOfNeighbor(AgentID, requestingRegion, circuit, destination, TeleportFlags, agentData, out reason)) { ResetFromTransit(AgentID); return(false); } } else { reason = "Could not find the grid service"; ResetFromTransit(AgentID); return(false); } IEventQueueService EQService = m_registry.RequestModuleInterface <IEventQueueService>(); IRegionClientCapsService otherRegion = clientCaps.GetCapsService(destination.RegionHandle); EQService.TeleportFinishEvent(destination.RegionHandle, destination.Access, destination.ExternalEndPoint, otherRegion.CapsUrl, 4, AgentID, TeleportFlags, destination.RegionSizeX, destination.RegionSizeY, requestingRegion); // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation // that the client contacted the destination before we send the attachments and close things here. result = WaitForCallback(AgentID, out callWasCanceled); if (!result) { //It says it failed, lets call the sim and check IAgentData data = null; result = SimulationService.RetrieveAgent(destination, AgentID, out data); } if (!result) { if (!callWasCanceled) { m_log.Warn("[AgentProcessing]: Callback never came for teleporting agent " + AgentID + ". Resetting."); } INeighborService service = m_registry.RequestModuleInterface <INeighborService>(); if (service != null) { //Close the agent at the place we just created if it isn't a neighbor if (service.IsOutsideView(regionCaps.RegionX, destination.RegionLocX, regionCaps.Region.RegionSizeX, destination.RegionSizeX, regionCaps.RegionY, destination.RegionLocY, regionCaps.Region.RegionSizeY, destination.RegionSizeY)) { SimulationService.CloseAgent(destination, AgentID); } } clientCaps.RemoveCAPS(destination.RegionHandle); if (!callWasCanceled) { reason = "The teleport timed out"; } else { reason = "Cancelled"; } } else { //Fix the root agent status otherRegion.RootAgent = true; regionCaps.RootAgent = false; // Next, let's close the child agent connections that are too far away. CloseNeighborAgents(regionCaps.Region, destination, AgentID); reason = ""; } } else { reason = "No SimulationService found!"; } } catch (Exception ex) { m_log.WarnFormat("[AgentProcessing]: Exception occured during agent teleport, {0}", ex.ToString()); reason = "Exception occured."; } //All done ResetFromTransit(AgentID); return(result); }
/// <summary> /// Async component for informing client of which neighbors exist /// </summary> /// <remarks> /// This needs to run asynchronously, as a network timeout may block the thread for a long while /// </remarks> /// <param name="remoteClient"></param> /// <param name="a"></param> /// <param name="regionHandle"></param> /// <param name="endPoint"></param> private bool InformClientOfNeighbor(UUID AgentID, ulong requestingRegion, AgentCircuitData circuitData, GridRegion neighbor, uint TeleportFlags, AgentData agentData, out string reason) { if (neighbor == null) { reason = "Could not find neighbor to inform"; return(false); } m_log.Info("[AgentProcessing]: Starting to inform client about neighbor " + neighbor.RegionName); //Notes on this method // 1) the SimulationService.CreateAgent MUST have a fixed CapsUrl for the region, so we have to create (if needed) // a new Caps handler for it. // 2) Then we can call the methods (EnableSimulator and EstatablishAgentComm) to tell the client the new Urls // 3) This allows us to make the Caps on the grid server without telling any other regions about what the // Urls are. ISimulationService SimulationService = m_registry.RequestModuleInterface <ISimulationService>(); if (SimulationService != null) { ICapsService capsService = m_registry.RequestModuleInterface <ICapsService>(); IClientCapsService clientCaps = capsService.GetClientCapsService(AgentID); IRegionClientCapsService oldRegionService = clientCaps.GetCapsService(neighbor.RegionHandle); //If its disabled, it should be removed, so kill it! if (oldRegionService != null && oldRegionService.Disabled) { clientCaps.RemoveCAPS(neighbor.RegionHandle); oldRegionService = null; } bool newAgent = oldRegionService == null; IRegionClientCapsService otherRegionService = clientCaps.GetOrCreateCapsService(neighbor.RegionHandle, CapsUtil.GetCapsSeedPath(CapsUtil.GetRandomCapsObjectPath()), circuitData); if (!newAgent) { //Note: if the agent is already there, send an agent update then bool result = true; if (agentData != null) { result = SimulationService.UpdateAgent(neighbor, agentData); if (result) { oldRegionService.Disabled = false; } } reason = ""; return(result); } ICommunicationService commsService = m_registry.RequestModuleInterface <ICommunicationService>(); if (commsService != null) { circuitData.OtherInformation["UserUrls"] = commsService.GetUrlsForUser(neighbor, circuitData.AgentID); } #region OpenSim teleport compatibility! if (!m_useCallbacks) { circuitData.CapsPath = CapsUtil.GetRandomCapsObjectPath(); circuitData.startpos.X += (neighbor.RegionLocX - clientCaps.GetRootCapsService().RegionX); circuitData.startpos.Y += (neighbor.RegionLocY - clientCaps.GetRootCapsService().RegionY); } #endregion bool regionAccepted = SimulationService.CreateAgent(neighbor, circuitData, TeleportFlags, agentData, out reason); if (regionAccepted) { string otherRegionsCapsURL; //If the region accepted us, we should get a CAPS url back as the reason, if not, its not updated or not an Aurora region, so don't touch it. if (reason != "") { OSDMap responseMap = (OSDMap)OSDParser.DeserializeJson(reason); OSDMap SimSeedCaps = (OSDMap)responseMap["CapsUrls"]; otherRegionService.AddCAPS(SimSeedCaps); otherRegionsCapsURL = otherRegionService.CapsUrl; } else { //We are assuming an OpenSim region now! #region OpenSim teleport compatibility! otherRegionsCapsURL = "http://" + otherRegionService.Region.ExternalEndPoint.ToString() + CapsUtil.GetCapsSeedPath(circuitData.CapsPath); otherRegionService.CapsUrl = otherRegionsCapsURL; #endregion } IEventQueueService EQService = m_registry.RequestModuleInterface <IEventQueueService>(); EQService.EnableSimulator(neighbor.RegionHandle, neighbor.ExternalEndPoint.Address.GetAddressBytes(), neighbor.ExternalEndPoint.Port, AgentID, neighbor.RegionSizeX, neighbor.RegionSizeY, requestingRegion); // EnableSimulator makes the client send a UseCircuitCode message to the destination, // which triggers a bunch of things there. // So let's wait Thread.Sleep(300); EQService.EstablishAgentCommunication(AgentID, neighbor.RegionHandle, neighbor.ExternalEndPoint.Address.GetAddressBytes(), neighbor.ExternalEndPoint.Port, otherRegionsCapsURL, neighbor.RegionSizeX, neighbor.RegionSizeY, requestingRegion); if (!m_useCallbacks) { Thread.Sleep(3000); //Give it a bit of time } m_log.Info("[AgentProcessing]: Completed inform client about neighbor " + neighbor.RegionName); } else { m_log.Error("[AgentProcessing]: Failed to inform client about neighbor " + neighbor.RegionName + ", reason: " + reason); return(false); } return(true); } reason = "SimulationService does not exist"; m_log.Error("[AgentProcessing]: Failed to inform client about neighbor " + neighbor.RegionName + ", reason: " + reason + "!"); return(false); }
protected object OnGenericEvent(string FunctionName, object parameters) { if (FunctionName == "NewUserConnection") { ICapsService service = m_scene.RequestModuleInterface <ICapsService>(); if (service != null) { object[] obj = (object[])parameters; OSDMap param = (OSDMap)obj[0]; AgentCircuitData circuit = (AgentCircuitData)obj[1]; if (circuit.reallyischild)//If Aurora is sending this, it'll show that it really is a child agent { return(null); } AvatarAppearance appearance = m_scene.AvatarService.GetAppearance(circuit.AgentID); if (appearance != null) { circuit.Appearance = appearance; } else { m_scene.AvatarService.SetAppearance(circuit.AgentID, circuit.Appearance); } //circuit.Appearance.Texture = new Primitive.TextureEntry(UUID.Zero); circuit.child = false;//ONLY USE ROOT AGENTS, SINCE OPENSIM SENDS CHILD == TRUE ALL THE TIME if (circuit.ServiceURLs != null && circuit.ServiceURLs.ContainsKey("IncomingCAPSHandler")) { AddCapsHandler(circuit); } else { IClientCapsService clientService = service.GetOrCreateClientCapsService(circuit.AgentID); clientService.RemoveCAPS(m_scene.RegionInfo.RegionHandle); string caps = service.CreateCAPS(circuit.AgentID, CapsUtil.GetCapsSeedPath(circuit.CapsPath), m_scene.RegionInfo.RegionHandle, true, circuit, MainServer.Instance.Port); //We ONLY use root agents because of OpenSim's inability to send the correct data MainConsole.Instance.Output("setting up on " + clientService.HostUri + CapsUtil.GetCapsSeedPath(circuit.CapsPath)); IClientCapsService clientCaps = service.GetClientCapsService(circuit.AgentID); if (clientCaps != null) { IRegionClientCapsService regionCaps = clientCaps.GetCapsService(m_scene.RegionInfo.RegionHandle); if (regionCaps != null) { regionCaps.AddCAPS((OSDMap)param["CapsUrls"]); } } } } } else if (FunctionName == "UserStatusChange") { object[] info = (object[])parameters; if (!bool.Parse(info[1].ToString())) //Logging out { ICapsService service = m_scene.RequestModuleInterface <ICapsService>(); if (service != null) { service.RemoveCAPS(UUID.Parse(info[0].ToString())); } } } return(null); }
public override bool InformClientOfNeighbor(UUID AgentID, ulong requestingRegion, AgentCircuitData circuitData, ref GridRegion neighbor, uint TeleportFlags, AgentData agentData, out string reason, out bool useCallbacks) { useCallbacks = true; if (neighbor == null) { reason = "Could not find neighbor to inform"; return(false); } MainConsole.Instance.Info("[AgentProcessing]: Starting to inform client about neighbor " + neighbor.RegionName); //Notes on this method // 1) the SimulationService.CreateAgent MUST have a fixed CapsUrl for the region, so we have to create (if needed) // a new Caps handler for it. // 2) Then we can call the methods (EnableSimulator and EstatablishAgentComm) to tell the client the new Urls // 3) This allows us to make the Caps on the grid server without telling any other regions about what the // Urls are. ISimulationService SimulationService = m_registry.RequestModuleInterface <ISimulationService> (); if (SimulationService != null) { ICapsService capsService = m_registry.RequestModuleInterface <ICapsService> (); IClientCapsService clientCaps = capsService.GetClientCapsService(AgentID); GridRegion originalDest = neighbor; if ((neighbor.Flags & (int)Aurora.Framework.RegionFlags.Hyperlink) == (int)Aurora.Framework.RegionFlags.Hyperlink) { neighbor = GetFinalDestination(neighbor); if (neighbor == null || neighbor.RegionHandle == 0) { reason = "Could not find neighbor to inform"; return(false); } //Remove any offenders clientCaps.RemoveCAPS(originalDest.RegionHandle); clientCaps.RemoveCAPS(neighbor.RegionHandle); } IRegionClientCapsService oldRegionService = clientCaps.GetCapsService(neighbor.RegionHandle); //If its disabled, it should be removed, so kill it! if (oldRegionService != null && oldRegionService.Disabled) { clientCaps.RemoveCAPS(neighbor.RegionHandle); oldRegionService = null; } bool newAgent = oldRegionService == null; IRegionClientCapsService otherRegionService = clientCaps.GetOrCreateCapsService(neighbor.RegionHandle, CapsUtil.GetCapsSeedPath(CapsUtil.GetRandomCapsObjectPath()), circuitData, 0); if (!newAgent) { //Note: if the agent is already there, send an agent update then bool result = true; if (agentData != null) { agentData.IsCrossing = false; result = SimulationService.UpdateAgent(neighbor, agentData); } if (result) { oldRegionService.Disabled = false; } reason = ""; return(result); } ICommunicationService commsService = m_registry.RequestModuleInterface <ICommunicationService> (); if (commsService != null) { commsService.GetUrlsForUser(neighbor, circuitData.AgentID); //Make sure that we make userURLs if we need to } circuitData.CapsPath = CapsUtil.GetCapsPathFromCapsSeed(otherRegionService.CapsUrl); if (clientCaps.AccountInfo != null) { circuitData.firstname = clientCaps.AccountInfo.FirstName; circuitData.lastname = clientCaps.AccountInfo.LastName; } bool regionAccepted = false; int requestedUDPPort = 0; if ((originalDest.Flags & (int)Aurora.Framework.RegionFlags.Hyperlink) == (int)Aurora.Framework.RegionFlags.Hyperlink) { if (circuitData.ServiceURLs == null || circuitData.ServiceURLs.Count == 0) { if (clientCaps.AccountInfo != null) { circuitData.ServiceURLs = new Dictionary <string, object> (); circuitData.ServiceURLs[GetHandlers.Helpers_HomeURI] = GetHandlers.GATEKEEPER_URL; circuitData.ServiceURLs[GetHandlers.Helpers_GatekeeperURI] = GetHandlers.GATEKEEPER_URL; circuitData.ServiceURLs[GetHandlers.Helpers_InventoryServerURI] = GetHandlers.GATEKEEPER_URL; circuitData.ServiceURLs[GetHandlers.Helpers_AssetServerURI] = GetHandlers.GATEKEEPER_URL; circuitData.ServiceURLs[GetHandlers.Helpers_ProfileServerURI] = GetHandlers.GATEKEEPER_URL; circuitData.ServiceURLs[GetHandlers.Helpers_FriendsServerURI] = GetHandlers.GATEKEEPER_URL; circuitData.ServiceURLs[GetHandlers.Helpers_IMServerURI] = GetHandlers.IM_URL; clientCaps.AccountInfo.ServiceURLs = circuitData.ServiceURLs; //Store the new urls m_registry.RequestModuleInterface <IUserAccountService> ().StoreUserAccount(clientCaps.AccountInfo); } } string userAgentDriver = circuitData.ServiceURLs[GetHandlers.Helpers_HomeURI].ToString(); IUserAgentService connector = new UserAgentServiceConnector(userAgentDriver); regionAccepted = connector.LoginAgentToGrid(circuitData, originalDest, neighbor, new IPEndPoint(IPAddress.Parse(circuitData.IPAddress), circuitData.RegionUDPPort), out reason); } else { if (circuitData.child) { circuitData.reallyischild = true; } regionAccepted = SimulationService.CreateAgent(neighbor, circuitData, TeleportFlags, agentData, out requestedUDPPort, out reason); } if (regionAccepted) { IPAddress ipAddress = neighbor.ExternalEndPoint.Address; string otherRegionsCapsURL; //If the region accepted us, we should get a CAPS url back as the reason, if not, its not updated or not an Aurora region, so don't touch it. if (reason != "" && reason != "authorized") { OSDMap responseMap = (OSDMap)OSDParser.DeserializeJson(reason); OSDMap SimSeedCaps = (OSDMap)responseMap["CapsUrls"]; if (responseMap.ContainsKey("OurIPForClient")) { string ip = responseMap["OurIPForClient"].AsString(); ipAddress = IPAddress.Parse(ip); } otherRegionService.AddCAPS(SimSeedCaps); otherRegionsCapsURL = otherRegionService.CapsUrl; } else { //We are assuming an OpenSim region now! #region OpenSim teleport compatibility! useCallbacks = false; otherRegionsCapsURL = neighbor.ServerURI + CapsUtil.GetCapsSeedPath(circuitData.CapsPath); otherRegionService.CapsUrl = otherRegionsCapsURL; #endregion } if (requestedUDPPort == 0) { requestedUDPPort = neighbor.ExternalEndPoint.Port; } if (ipAddress == null) { ipAddress = neighbor.ExternalEndPoint.Address; } circuitData.RegionUDPPort = requestedUDPPort; otherRegionService = clientCaps.GetCapsService(neighbor.RegionHandle); otherRegionService.LoopbackRegionIP = ipAddress; otherRegionService.CircuitData.RegionUDPPort = requestedUDPPort; IEventQueueService EQService = m_registry.RequestModuleInterface <IEventQueueService> (); EQService.EnableSimulator(neighbor.RegionHandle, ipAddress.GetAddressBytes(), requestedUDPPort, AgentID, neighbor.RegionSizeX, neighbor.RegionSizeY, requestingRegion); // EnableSimulator makes the client send a UseCircuitCode message to the destination, // which triggers a bunch of things there. // So let's wait Thread.Sleep(300); EQService.EstablishAgentCommunication(AgentID, neighbor.RegionHandle, ipAddress.GetAddressBytes(), requestedUDPPort, otherRegionsCapsURL, neighbor.RegionSizeX, neighbor.RegionSizeY, requestingRegion); if (!useCallbacks) { Thread.Sleep(3000); //Give it a bit of time, only for OpenSim... } MainConsole.Instance.Info("[AgentProcessing]: Completed inform client about neighbor " + neighbor.RegionName); } else { clientCaps.RemoveCAPS(neighbor.RegionHandle); MainConsole.Instance.Error("[AgentProcessing]: Failed to inform client about neighbor " + neighbor.RegionName + ", reason: " + reason); return(false); } return(true); } reason = "SimulationService does not exist"; MainConsole.Instance.Error("[AgentProcessing]: Failed to inform client about neighbor " + neighbor.RegionName + ", reason: " + reason + "!"); return(false); }