diff options
author | Justin Clarke Casey | 2008-09-12 20:12:03 +0000 |
---|---|---|
committer | Justin Clarke Casey | 2008-09-12 20:12:03 +0000 |
commit | 52a4c4d82f9c5b808e6c61fd51c1c70e42865565 (patch) | |
tree | f63a4ea443597b2d79ad6c2b7acff058c4437425 /OpenSim/Region/Communications | |
parent | remove hidden faces inside prim meshes to improve memory use and startup time (diff) | |
download | opensim-SC-52a4c4d82f9c5b808e6c61fd51c1c70e42865565.zip opensim-SC-52a4c4d82f9c5b808e6c61fd51c1c70e42865565.tar.gz opensim-SC-52a4c4d82f9c5b808e6c61fd51c1c70e42865565.tar.bz2 opensim-SC-52a4c4d82f9c5b808e6c61fd51c1c70e42865565.tar.xz |
* Check in first part of http://opensimulator.org/mantis/view.php?id=2073
* This patch aims to introduce look at direction persistence between logins. It won't be active until the second part of the patch is committed in about two weeks time. At
this point, region servers that haven't upgraded past this revision may run into problems
* This checkin upgrades the user database. As always, we recommend you have backups in case something goes wrong.
* Many thanks to tyre for this patch.
Diffstat (limited to 'OpenSim/Region/Communications')
-rw-r--r-- | OpenSim/Region/Communications/Local/LocalLoginService.cs | 257 | ||||
-rw-r--r-- | OpenSim/Region/Communications/OGS1/OGS1UserServices.cs | 35 |
2 files changed, 154 insertions, 138 deletions
diff --git a/OpenSim/Region/Communications/Local/LocalLoginService.cs b/OpenSim/Region/Communications/Local/LocalLoginService.cs index 93a1e46..2f7fdb7 100644 --- a/OpenSim/Region/Communications/Local/LocalLoginService.cs +++ b/OpenSim/Region/Communications/Local/LocalLoginService.cs | |||
@@ -41,8 +41,7 @@ namespace OpenSim.Region.Communications.Local | |||
41 | 41 | ||
42 | public class LocalLoginService : LoginService | 42 | public class LocalLoginService : LoginService |
43 | { | 43 | { |
44 | private static readonly ILog m_log | 44 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
45 | = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
46 | 45 | ||
47 | private CommunicationsLocal m_Parent; | 46 | private CommunicationsLocal m_Parent; |
48 | 47 | ||
@@ -120,167 +119,167 @@ namespace OpenSim.Region.Communications.Local | |||
120 | } | 119 | } |
121 | } | 120 | } |
122 | 121 | ||
123 | private Regex reURI = new Regex(@"^uri:(?<region>[^&]+)&(?<x>\d+)&(?<y>\d+)&(?<z>\d+)$"); | 122 | /// <summary> |
124 | 123 | /// Customises the login response and fills in missing values. | |
124 | /// </summary> | ||
125 | /// <param name="response">The existing response</param> | ||
126 | /// <param name="theUser">The user profile</param> | ||
127 | /// <param name="startLocationRequest">The requested start location</param> | ||
125 | public override bool CustomiseResponse(LoginResponse response, UserProfileData theUser, string startLocationRequest) | 128 | public override bool CustomiseResponse(LoginResponse response, UserProfileData theUser, string startLocationRequest) |
126 | { | 129 | { |
127 | ulong currentRegion = 0; | 130 | // HomeLocation |
128 | 131 | RegionInfo homeInfo = null; | |
129 | uint locX = 0; | 132 | // use the homeRegionID if it is stored already. If not, use the regionHandle as before |
130 | uint locY = 0; | 133 | if (theUser.HomeRegionID != UUID.Zero) |
131 | uint locZ = 0; | 134 | homeInfo = m_Parent.GridService.RequestNeighbourInfo(theUser.HomeRegionID); |
132 | bool specificStartLocation = false; | 135 | else |
136 | homeInfo = m_Parent.GridService.RequestNeighbourInfo(theUser.HomeRegion); | ||
137 | if (homeInfo != null) | ||
138 | { | ||
139 | response.Home = | ||
140 | string.Format( | ||
141 | "{{'region_handle':[r{0},r{1}], 'position':[r{2},r{3},r{4}], 'look_at':[r{5},r{6},r{7}]}}", | ||
142 | (homeInfo.RegionLocX*Constants.RegionSize), | ||
143 | (homeInfo.RegionLocY*Constants.RegionSize), | ||
144 | theUser.HomeLocation.X, theUser.HomeLocation.Y, theUser.HomeLocation.Z, | ||
145 | theUser.HomeLookAt.X, theUser.HomeLookAt.Y, theUser.HomeLookAt.Z); | ||
146 | } | ||
147 | else | ||
148 | { | ||
149 | // Emergency mode: Home-region isn't available, so we can't request the region info. | ||
150 | // Use the stored home regionHandle instead. | ||
151 | // NOTE: If the home-region moves, this will be wrong until the users update their user-profile again | ||
152 | ulong regionX = theUser.HomeRegion >> 32; | ||
153 | ulong regionY = theUser.HomeRegion & 0xffffffff; | ||
154 | response.Home = | ||
155 | string.Format( | ||
156 | "{{'region_handle':[r{0},r{1}], 'position':[r{2},r{3},r{4}], 'look_at':[r{5},r{6},r{7}]}}", | ||
157 | regionX, regionY, | ||
158 | theUser.HomeLocation.X, theUser.HomeLocation.Y, theUser.HomeLocation.Z, | ||
159 | theUser.HomeLookAt.X, theUser.HomeLookAt.Y, theUser.HomeLookAt.Z); | ||
160 | m_log.InfoFormat("[LOGIN] Home region of user {0} {1} is not available; using computed region position {2} {3}", | ||
161 | theUser.FirstName, theUser.SurName, | ||
162 | regionX, regionY); | ||
163 | } | ||
133 | 164 | ||
134 | // get start location | 165 | // StartLocation |
135 | if (startLocationRequest == "last") | 166 | RegionInfo regionInfo = null; |
167 | if (startLocationRequest == "home") | ||
136 | { | 168 | { |
137 | currentRegion = theUser.CurrentAgent.Handle; | 169 | regionInfo = homeInfo; |
138 | locX = (UInt32)theUser.CurrentAgent.Position.X; | 170 | theUser.CurrentAgent.Position = theUser.HomeLocation; |
139 | locY = (UInt32)theUser.CurrentAgent.Position.Y; | 171 | response.LookAt = "[r" + theUser.HomeLookAt.X.ToString() + ",r" + theUser.HomeLookAt.Y.ToString() + ",r" + theUser.HomeLookAt.Z.ToString() + "]"; |
140 | locZ = (UInt32)theUser.CurrentAgent.Position.Z; | ||
141 | response.StartLocation = "last"; | ||
142 | specificStartLocation = true; | ||
143 | } | 172 | } |
144 | else if (startLocationRequest == "home") | 173 | else if (startLocationRequest == "last") |
145 | { | 174 | { |
146 | currentRegion = theUser.HomeRegion; | 175 | regionInfo = m_Parent.GridService.RequestNeighbourInfo(theUser.CurrentAgent.Region); |
147 | response.StartLocation = "home"; | 176 | response.LookAt = "[r" + theUser.CurrentAgent.LookAt.X.ToString() + ",r" + theUser.CurrentAgent.LookAt.Y.ToString() + ",r" + theUser.CurrentAgent.LookAt.Z.ToString() + "]"; |
148 | } | 177 | } |
149 | else | 178 | else |
150 | { | 179 | { |
151 | // use last location as default | 180 | Regex reURI = new Regex(@"^uri:(?<region>[^&]+)&(?<x>\d+)&(?<y>\d+)&(?<z>\d+)$"); |
152 | currentRegion = theUser.CurrentAgent.Handle; | ||
153 | |||
154 | Match uriMatch = reURI.Match(startLocationRequest); | 181 | Match uriMatch = reURI.Match(startLocationRequest); |
155 | if (null == uriMatch) | 182 | if (uriMatch == null) |
156 | { | 183 | { |
157 | m_log.InfoFormat("[LOGIN]: Got Custom Login URL {0}, but can't process it", startLocationRequest); | 184 | m_log.InfoFormat("[LOGIN]: Got Custom Login URL {0}, but can't process it", startLocationRequest); |
158 | } | 185 | } |
159 | else | 186 | else |
160 | { | 187 | { |
161 | string region = uriMatch.Groups["region"].ToString(); | 188 | string region = uriMatch.Groups["region"].ToString(); |
162 | 189 | regionInfo = m_Parent.GridService.RequestClosestRegion(region); | |
163 | RegionInfo r = m_Parent.GridService.RequestClosestRegion(region); | 190 | if (regionInfo == null) |
164 | if (null == r) | ||
165 | { | 191 | { |
166 | m_log.InfoFormat("[LOGIN]: Got Custom Login URL {0}, can't locate region {1}", | 192 | m_log.InfoFormat("[LOGIN]: Got Custom Login URL {0}, can't locate region {1}", startLocationRequest, region); |
167 | startLocationRequest, region); | ||
168 | } | 193 | } |
169 | else | 194 | else |
170 | { | 195 | { |
171 | currentRegion = r.RegionHandle; | 196 | theUser.CurrentAgent.Position = new Vector3(float.Parse(uriMatch.Groups["x"].Value), |
172 | locX = UInt32.Parse(uriMatch.Groups["x"].ToString()); | 197 | float.Parse(uriMatch.Groups["y"].Value), float.Parse(uriMatch.Groups["x"].Value)); |
173 | locY = UInt32.Parse(uriMatch.Groups["y"].ToString()); | ||
174 | locZ = UInt32.Parse(uriMatch.Groups["z"].ToString()); | ||
175 | // can be: last, home, safe, url | ||
176 | response.StartLocation = "url"; | ||
177 | specificStartLocation = true; | ||
178 | } | 198 | } |
179 | } | 199 | } |
200 | response.LookAt = "[r0,r1,r0]"; | ||
201 | // can be: last, home, safe, url | ||
202 | response.StartLocation = "url"; | ||
180 | } | 203 | } |
181 | 204 | ||
182 | RegionInfo homeReg = m_Parent.GridService.RequestNeighbourInfo(theUser.HomeRegion); | 205 | if ((regionInfo != null) && (PrepareLoginToRegion(regionInfo, theUser, response))) |
183 | RegionInfo reg = m_Parent.GridService.RequestNeighbourInfo(currentRegion); | ||
184 | |||
185 | if ((homeReg != null) || (reg != null)) | ||
186 | { | 206 | { |
187 | if (homeReg != null) | 207 | return true; |
188 | { | 208 | } |
189 | response.Home = "{'region_handle':[r" + | ||
190 | (homeReg.RegionLocX * Constants.RegionSize).ToString() + ",r" + | ||
191 | (homeReg.RegionLocY * Constants.RegionSize).ToString() + "], " + | ||
192 | "'position':[r" + | ||
193 | theUser.HomeLocation.X.ToString() + ",r" + | ||
194 | theUser.HomeLocation.Y.ToString() + ",r" + | ||
195 | theUser.HomeLocation.Z.ToString() + "], " + | ||
196 | "'look_at':[r" + | ||
197 | theUser.HomeLocation.X.ToString() + ",r" + | ||
198 | theUser.HomeLocation.Y.ToString() + ",r" + | ||
199 | theUser.HomeLocation.Z.ToString() + "]}"; | ||
200 | } | ||
201 | else | ||
202 | { | ||
203 | m_log.Warn("[LOGIN]: Your home region doesn't exist"); | ||
204 | response.Home = "{'region_handle':[r" + | ||
205 | (reg.RegionLocX * Constants.RegionSize).ToString() + ",r" + | ||
206 | (reg.RegionLocY * Constants.RegionSize).ToString() + "], " + | ||
207 | "'position':[r" + | ||
208 | theUser.HomeLocation.X.ToString() + ",r" + | ||
209 | theUser.HomeLocation.Y.ToString() + ",r" + | ||
210 | theUser.HomeLocation.Z.ToString() + "], " + | ||
211 | "'look_at':[r" + | ||
212 | theUser.HomeLocation.X.ToString() + ",r" + | ||
213 | theUser.HomeLocation.Y.ToString() + ",r" + | ||
214 | theUser.HomeLocation.Z.ToString() + "]}"; | ||
215 | } | ||
216 | string capsPath = Util.GetRandomCapsPath(); | ||
217 | response.SimAddress = reg.ExternalEndPoint.Address.ToString(); | ||
218 | response.SimPort = (uint) reg.ExternalEndPoint.Port; | ||
219 | response.RegionX = reg.RegionLocX; | ||
220 | response.RegionY = reg.RegionLocY; | ||
221 | |||
222 | m_log.DebugFormat( | ||
223 | "[CAPS][LOGIN]: RegionX {0} RegionY {0}", response.RegionX, response.RegionY); | ||
224 | |||
225 | response.SeedCapability = "http://" + reg.ExternalHostName + ":" + | ||
226 | serversInfo.HttpListenerPort.ToString() + "/CAPS/" + capsPath + "0000/"; | ||
227 | |||
228 | m_log.DebugFormat( | ||
229 | "[CAPS]: Sending new CAPS seed url {0} to client {1}", | ||
230 | response.SeedCapability, response.AgentID); | ||
231 | |||
232 | theUser.CurrentAgent.Region = reg.RegionID; | ||
233 | theUser.CurrentAgent.Handle = reg.RegionHandle; | ||
234 | |||
235 | // LoginResponse.BuddyList buddyList = new LoginResponse.BuddyList(); | ||
236 | |||
237 | response.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(theUser.ID)); | ||
238 | |||
239 | Login _login = new Login(); | ||
240 | //copy data to login object | ||
241 | _login.First = response.Firstname; | ||
242 | _login.Last = response.Lastname; | ||
243 | _login.Agent = response.AgentID; | ||
244 | _login.Session = response.SessionID; | ||
245 | _login.SecureSession = response.SecureSessionID; | ||
246 | _login.CircuitCode = (uint) response.CircuitCode; | ||
247 | if (specificStartLocation) | ||
248 | _login.StartPos = new Vector3(locX, locY, locZ); | ||
249 | else | ||
250 | _login.StartPos = new Vector3(128, 128, 128); | ||
251 | _login.CapsPath = capsPath; | ||
252 | 209 | ||
253 | m_log.InfoFormat( | 210 | // StartLocation not available, send him to a nearby region instead |
254 | "[LOGIN]: Telling region {0} @ {1},{2} ({3}:{4}) to expect user connection", | 211 | // regionInfo = m_Parent.GridService.RequestClosestRegion(""); |
255 | reg.RegionName, response.RegionX, response.RegionY, response.SimAddress, response.SimPort); | 212 | //m_log.InfoFormat("[LOGIN]: StartLocation not available sending to region {0}", regionInfo.regionName); |
256 | 213 | ||
257 | handlerLoginToRegion = OnLoginToRegion; | 214 | // Send him to default region instead |
258 | if (handlerLoginToRegion != null) | 215 | ulong defaultHandle = (((ulong)defaultHomeX * Constants.RegionSize) << 32) | |
259 | { | 216 | ((ulong)defaultHomeY * Constants.RegionSize); |
260 | handlerLoginToRegion(currentRegion, _login); | 217 | |
261 | } | 218 | if ((regionInfo != null) && (defaultHandle == regionInfo.RegionHandle)) |
262 | } | ||
263 | else | ||
264 | { | 219 | { |
265 | m_log.Warn("[LOGIN]: Not found region " + currentRegion); | 220 | m_log.ErrorFormat("[LOGIN]: Not trying the default region since this is the same as the selected region"); |
266 | return false; | 221 | return false; |
267 | } | 222 | } |
268 | 223 | ||
269 | return true; | 224 | m_log.Error("[LOGIN]: Sending user to default region " + defaultHandle + " instead"); |
225 | regionInfo = m_Parent.GridService.RequestNeighbourInfo(defaultHandle); | ||
226 | |||
227 | // Customise the response | ||
228 | //response.Home = | ||
229 | // string.Format( | ||
230 | // "{{'region_handle':[r{0},r{1}], 'position':[r{2},r{3},r{4}], 'look_at':[r{5},r{6},r{7}]}}", | ||
231 | // (SimInfo.regionLocX * Constants.RegionSize), | ||
232 | // (SimInfo.regionLocY*Constants.RegionSize), | ||
233 | // theUser.HomeLocation.X, theUser.HomeLocation.Y, theUser.HomeLocation.Z, | ||
234 | // theUser.HomeLookAt.X, theUser.HomeLookAt.Y, theUser.HomeLookAt.Z); | ||
235 | theUser.CurrentAgent.Position = new Vector3(128,128,0); | ||
236 | response.StartLocation = "safe"; | ||
237 | |||
238 | return PrepareLoginToRegion(regionInfo, theUser, response); | ||
270 | } | 239 | } |
271 | 240 | ||
272 | private LoginResponse.BuddyList ConvertFriendListItem(List<FriendListItem> LFL) | 241 | /// <summary> |
242 | /// Prepare a login to the given region. This involves both telling the region to expect a connection | ||
243 | /// and appropriately customising the response to the user. | ||
244 | /// </summary> | ||
245 | /// <param name="sim"></param> | ||
246 | /// <param name="user"></param> | ||
247 | /// <param name="response"></param> | ||
248 | /// <returns>true if the region was successfully contacted, false otherwise</returns> | ||
249 | private bool PrepareLoginToRegion(RegionInfo regionInfo, UserProfileData user, LoginResponse response) | ||
273 | { | 250 | { |
274 | LoginResponse.BuddyList buddylistreturn = new LoginResponse.BuddyList(); | 251 | response.SimAddress = regionInfo.ExternalEndPoint.Address.ToString(); |
275 | foreach (FriendListItem fl in LFL) | 252 | response.SimPort = (uint)regionInfo.ExternalEndPoint.Port; |
276 | { | 253 | response.RegionX = regionInfo.RegionLocX; |
277 | LoginResponse.BuddyList.BuddyInfo buddyitem = new LoginResponse.BuddyList.BuddyInfo(fl.Friend); | 254 | response.RegionY = regionInfo.RegionLocY; |
278 | buddyitem.BuddyID = fl.Friend; | 255 | |
279 | buddyitem.BuddyRightsHave = (int)fl.FriendListOwnerPerms; | 256 | string capsPath = Util.GetRandomCapsPath(); |
280 | buddyitem.BuddyRightsGiven = (int)fl.FriendPerms; | 257 | response.SeedCapability = regionInfo.ServerURI + "/CAPS/" + capsPath + "0000/"; |
281 | buddylistreturn.AddNewBuddy(buddyitem); | 258 | |
282 | } | 259 | // Notify the target of an incoming user |
283 | return buddylistreturn; | 260 | m_log.InfoFormat( |
261 | "[LOGIN]: Telling {0} @ {1},{2} ({3}) to prepare for client connection", | ||
262 | regionInfo.RegionName, response.RegionX, response.RegionY, regionInfo.ServerURI); | ||
263 | // Update agent with target sim | ||
264 | user.CurrentAgent.Region = regionInfo.RegionID; | ||
265 | user.CurrentAgent.Handle = regionInfo.RegionHandle; | ||
266 | // Prepare notification | ||
267 | Login loginParams = new Login(); | ||
268 | loginParams.Session = user.CurrentAgent.SessionID.ToString(); | ||
269 | loginParams.SecureSession = user.CurrentAgent.SecureSessionID.ToString(); | ||
270 | loginParams.First = user.FirstName; | ||
271 | loginParams.Last = user.SurName; | ||
272 | loginParams.Agent = user.ID.ToString(); | ||
273 | loginParams.CircuitCode = Convert.ToUInt32(response.CircuitCode); | ||
274 | loginParams.StartPos = user.CurrentAgent.Position; | ||
275 | loginParams.CapsPath = capsPath; | ||
276 | |||
277 | handlerLoginToRegion = OnLoginToRegion; | ||
278 | if (handlerLoginToRegion == null) | ||
279 | return false; | ||
280 | |||
281 | handlerLoginToRegion(user.CurrentAgent.Handle, loginParams); | ||
282 | return true; | ||
284 | } | 283 | } |
285 | 284 | ||
286 | // See LoginService | 285 | // See LoginService |
diff --git a/OpenSim/Region/Communications/OGS1/OGS1UserServices.cs b/OpenSim/Region/Communications/OGS1/OGS1UserServices.cs index 36a82a8..b8268eb 100644 --- a/OpenSim/Region/Communications/OGS1/OGS1UserServices.cs +++ b/OpenSim/Region/Communications/OGS1/OGS1UserServices.cs | |||
@@ -235,19 +235,22 @@ namespace OpenSim.Region.Communications.OGS1 | |||
235 | /// Logs off a user on the user server | 235 | /// Logs off a user on the user server |
236 | /// </summary> | 236 | /// </summary> |
237 | /// <param name="UserID">UUID of the user</param> | 237 | /// <param name="UserID">UUID of the user</param> |
238 | /// <param name="regionData">UUID of the Region</param> | 238 | /// <param name="regionID">UUID of the Region</param> |
239 | /// <param name="posx">final position x</param> | 239 | /// <param name="regionhandle">regionhandle</param> |
240 | /// <param name="posy">final position y</param> | 240 | /// <param name="position">final position</param> |
241 | /// <param name="posz">final position z</param> | 241 | /// <param name="lookat">final lookat</param> |
242 | public void LogOffUser(UUID userid, UUID regionid, ulong regionhandle, float posx, float posy, float posz) | 242 | public void LogOffUser(UUID userid, UUID regionid, ulong regionhandle, Vector3 position, Vector3 lookat) |
243 | { | 243 | { |
244 | Hashtable param = new Hashtable(); | 244 | Hashtable param = new Hashtable(); |
245 | param["avatar_uuid"] = userid.Guid.ToString(); | 245 | param["avatar_uuid"] = userid.Guid.ToString(); |
246 | param["region_uuid"] = regionid.Guid.ToString(); | 246 | param["region_uuid"] = regionid.Guid.ToString(); |
247 | param["region_handle"] = regionhandle.ToString(); | 247 | param["region_handle"] = regionhandle.ToString(); |
248 | param["region_pos_x"] = posx.ToString(); | 248 | param["region_pos_x"] = position.X.ToString(); |
249 | param["region_pos_y"] = posy.ToString(); | 249 | param["region_pos_y"] = position.Y.ToString(); |
250 | param["region_pos_z"] = posz.ToString(); | 250 | param["region_pos_z"] = position.Z.ToString(); |
251 | param["lookat_x"] = lookat.X.ToString(); | ||
252 | param["lookat_y"] = lookat.Y.ToString(); | ||
253 | param["lookat_z"] = lookat.Z.ToString(); | ||
251 | 254 | ||
252 | IList parameters = new ArrayList(); | 255 | IList parameters = new ArrayList(); |
253 | parameters.Add(param); | 256 | parameters.Add(param); |
@@ -263,6 +266,20 @@ namespace OpenSim.Region.Communications.OGS1 | |||
263 | } | 266 | } |
264 | } | 267 | } |
265 | 268 | ||
269 | /// <summary> | ||
270 | /// Logs off a user on the user server (deprecated as of 2008-08-27) | ||
271 | /// </summary> | ||
272 | /// <param name="UserID">UUID of the user</param> | ||
273 | /// <param name="regionID">UUID of the Region</param> | ||
274 | /// <param name="regionhandle">regionhandle</param> | ||
275 | /// <param name="posx">final position x</param> | ||
276 | /// <param name="posy">final position y</param> | ||
277 | /// <param name="posz">final position z</param> | ||
278 | public void LogOffUser(UUID userid, UUID regionid, ulong regionhandle, float posx, float posy, float posz) | ||
279 | { | ||
280 | LogOffUser(userid, regionid, regionhandle, new Vector3(posx, posy, posz), new Vector3()); | ||
281 | } | ||
282 | |||
266 | public UserProfileData GetUserProfile(string firstName, string lastName) | 283 | public UserProfileData GetUserProfile(string firstName, string lastName) |
267 | { | 284 | { |
268 | return GetUserProfile(firstName + " " + lastName); | 285 | return GetUserProfile(firstName + " " + lastName); |
@@ -672,7 +689,7 @@ namespace OpenSim.Region.Communications.OGS1 | |||
672 | } | 689 | } |
673 | } | 690 | } |
674 | /// <summary> | 691 | /// <summary> |
675 | /// Returns a list of FriendsListItems that describe the friends and permissions in the friend relationship for LLUUID friendslistowner | 692 | /// Returns a list of FriendsListItems that describe the friends and permissions in the friend relationship for UUID friendslistowner |
676 | /// </summary> | 693 | /// </summary> |
677 | /// <param name="friendlistowner">The agent that we're retreiving the friends Data.</param> | 694 | /// <param name="friendlistowner">The agent that we're retreiving the friends Data.</param> |
678 | public List<FriendListItem> GetUserFriendList(UUID friendlistowner) | 695 | public List<FriendListItem> GetUserFriendList(UUID friendlistowner) |