diff options
Diffstat (limited to 'OpenSim/Region/Environment/Modules/Avatar/Currency')
-rw-r--r-- | OpenSim/Region/Environment/Modules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs | 1491 |
1 files changed, 1491 insertions, 0 deletions
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs new file mode 100644 index 0000000..0e058ec --- /dev/null +++ b/OpenSim/Region/Environment/Modules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs | |||
@@ -0,0 +1,1491 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using System.Collections; | ||
30 | using System.Collections.Generic; | ||
31 | using System.Net; | ||
32 | using System.Net.Sockets; | ||
33 | using System.Reflection; | ||
34 | using System.Xml; | ||
35 | using libsecondlife; | ||
36 | using log4net; | ||
37 | using Nini.Config; | ||
38 | using Nwc.XmlRpc; | ||
39 | using OpenSim.Framework; | ||
40 | using OpenSim.Region.Environment.Interfaces; | ||
41 | using OpenSim.Region.Environment.Scenes; | ||
42 | |||
43 | namespace OpenSim.Region.Environment.Modules.Avatar.Currency.SampleMoney | ||
44 | { | ||
45 | /// <summary> | ||
46 | /// Demo Economy/Money Module. This is not a production quality money/economy module! | ||
47 | /// This is a demo for you to use when making one that works for you. | ||
48 | /// // To use the following you need to add: | ||
49 | /// -helperuri <ADDRESS TO HERE OR grid MONEY SERVER> | ||
50 | /// to the command line parameters you use to start up your client | ||
51 | /// This commonly looks like -helperuri http://127.0.0.1:9000/ | ||
52 | /// | ||
53 | /// Centralized grid structure example using OpenSimWi Redux revision 9+ | ||
54 | /// svn co https://opensimwiredux.svn.sourceforge.net/svnroot/opensimwiredux | ||
55 | /// </summary> | ||
56 | |||
57 | public delegate void ObjectPaid(LLUUID objectID, LLUUID agentID, int amount); | ||
58 | |||
59 | public interface IMoneyModule : IRegionModule | ||
60 | { | ||
61 | bool ObjectGiveMoney(LLUUID objectID, LLUUID fromID, LLUUID toID, int amount); | ||
62 | |||
63 | event ObjectPaid OnObjectPaid; | ||
64 | } | ||
65 | |||
66 | public class SampleMoneyModule : IMoneyModule | ||
67 | { | ||
68 | public event ObjectPaid OnObjectPaid; | ||
69 | |||
70 | private ObjectPaid handerOnObjectPaid; | ||
71 | |||
72 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
73 | |||
74 | /// <summary> | ||
75 | /// Region UUIDS indexed by AgentID | ||
76 | /// </summary> | ||
77 | Dictionary<LLUUID, LLUUID> m_rootAgents = new Dictionary<LLUUID, LLUUID>(); | ||
78 | |||
79 | /// <summary> | ||
80 | /// Scenes by Region Handle | ||
81 | /// </summary> | ||
82 | private Dictionary<ulong,Scene> m_scenel = new Dictionary<ulong,Scene>(); | ||
83 | |||
84 | private IConfigSource m_gConfig; | ||
85 | |||
86 | private bool m_keepMoneyAcrossLogins = true; | ||
87 | |||
88 | private int m_minFundsBeforeRefresh = 100; | ||
89 | |||
90 | private int m_stipend = 1000; | ||
91 | |||
92 | private bool m_enabled = true; | ||
93 | |||
94 | private Dictionary<LLUUID, int> m_KnownClientFunds = new Dictionary<LLUUID, int>(); | ||
95 | |||
96 | private bool gridmode = false; | ||
97 | private Scene XMLRPCHandler; | ||
98 | private float EnergyEfficiency = 0f; | ||
99 | private int ObjectCapacity = 45000; | ||
100 | private int ObjectCount = 0; | ||
101 | private int PriceEnergyUnit = 0; | ||
102 | private int PriceGroupCreate = 0; | ||
103 | private int PriceObjectClaim = 0; | ||
104 | private float PriceObjectRent = 0f; | ||
105 | private float PriceObjectScaleFactor = 0f; | ||
106 | private int PriceParcelClaim = 0; | ||
107 | private float PriceParcelClaimFactor = 0f; | ||
108 | private int PriceParcelRent = 0; | ||
109 | private int PricePublicObjectDecay = 0; | ||
110 | private int PricePublicObjectDelete = 0; | ||
111 | private int PriceRentLight = 0; | ||
112 | private int PriceUpload = 0; | ||
113 | private int TeleportMinPrice = 0; | ||
114 | private int UserLevelPaysFees = 2; | ||
115 | private string m_MoneyAddress = String.Empty; | ||
116 | private string m_LandAddress = String.Empty; | ||
117 | |||
118 | float TeleportPriceExponent = 0f; | ||
119 | |||
120 | /// <summary> | ||
121 | /// Where Stipends come from and Fees go to. | ||
122 | /// </summary> | ||
123 | LLUUID EconomyBaseAccount = LLUUID.Zero; | ||
124 | |||
125 | /// <summary> | ||
126 | /// Startup | ||
127 | /// </summary> | ||
128 | /// <param name="scene"></param> | ||
129 | /// <param name="config"></param> | ||
130 | public void Initialise(Scene scene, IConfigSource config) | ||
131 | { | ||
132 | m_gConfig = config; | ||
133 | |||
134 | IConfig startupConfig = m_gConfig.Configs["Startup"]; | ||
135 | IConfig economyConfig = m_gConfig.Configs["Economy"]; | ||
136 | |||
137 | scene.RegisterModuleInterface<IMoneyModule>(this); | ||
138 | |||
139 | ReadConfigAndPopulate(scene, startupConfig, "Startup"); | ||
140 | ReadConfigAndPopulate(scene, economyConfig, "Economy"); | ||
141 | |||
142 | if (m_enabled) | ||
143 | { | ||
144 | lock (m_scenel) | ||
145 | { | ||
146 | if (m_scenel.Count == 0) | ||
147 | { | ||
148 | XMLRPCHandler = scene; | ||
149 | |||
150 | // To use the following you need to add: | ||
151 | // -helperuri <ADDRESS TO HERE OR grid MONEY SERVER> | ||
152 | // to the command line parameters you use to start up your client | ||
153 | // This commonly looks like -helperuri http://127.0.0.1:9000/ | ||
154 | |||
155 | if (m_MoneyAddress.Length > 0) | ||
156 | { | ||
157 | // Centralized grid structure using OpenSimWi Redux revision 9+ | ||
158 | // https://opensimwiredux.svn.sourceforge.net/svnroot/opensimwiredux | ||
159 | scene.AddXmlRPCHandler("balanceUpdateRequest", GridMoneyUpdate); | ||
160 | scene.AddXmlRPCHandler("userAlert", UserAlert); | ||
161 | } | ||
162 | else | ||
163 | { | ||
164 | // Local Server.. enables functionality only. | ||
165 | scene.AddXmlRPCHandler("getCurrencyQuote", quote_func); | ||
166 | scene.AddXmlRPCHandler("buyCurrency", buy_func); | ||
167 | scene.AddXmlRPCHandler("preflightBuyLandPrep", preflightBuyLandPrep_func); | ||
168 | scene.AddXmlRPCHandler("buyLandPrep", landBuy_func); | ||
169 | } | ||
170 | |||
171 | |||
172 | } | ||
173 | |||
174 | if (m_scenel.ContainsKey(scene.RegionInfo.RegionHandle)) | ||
175 | { | ||
176 | m_scenel[scene.RegionInfo.RegionHandle] = scene; | ||
177 | } | ||
178 | else | ||
179 | { | ||
180 | m_scenel.Add(scene.RegionInfo.RegionHandle, scene); | ||
181 | } | ||
182 | } | ||
183 | |||
184 | scene.EventManager.OnNewClient += OnNewClient; | ||
185 | scene.EventManager.OnMoneyTransfer += MoneyTransferAction; | ||
186 | scene.EventManager.OnClientClosed += ClientClosed; | ||
187 | scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; | ||
188 | scene.EventManager.OnMakeChildAgent += MakeChildAgent; | ||
189 | scene.EventManager.OnClientClosed += ClientLoggedOut; | ||
190 | scene.EventManager.OnValidateLandBuy += ValidateLandBuy; | ||
191 | scene.EventManager.OnLandBuy += processLandBuy; | ||
192 | |||
193 | } | ||
194 | } | ||
195 | /// <summary> | ||
196 | /// Parse Configuration | ||
197 | /// </summary> | ||
198 | /// <param name="scene"></param> | ||
199 | /// <param name="startupConfig"></param> | ||
200 | /// <param name="config"></param> | ||
201 | private void ReadConfigAndPopulate(Scene scene, IConfig startupConfig, string config) | ||
202 | { | ||
203 | if (config == "Startup" && startupConfig != null) | ||
204 | { | ||
205 | gridmode = startupConfig.GetBoolean("gridmode", false); | ||
206 | m_enabled = (startupConfig.GetString("economymodule", "BetaGridLikeMoneyModule") == "BetaGridLikeMoneyModule"); | ||
207 | } | ||
208 | |||
209 | if (config == "Economy" && startupConfig != null) | ||
210 | { | ||
211 | ObjectCapacity = startupConfig.GetInt("ObjectCapacity", 45000); | ||
212 | PriceEnergyUnit = startupConfig.GetInt("PriceEnergyUnit", 100); | ||
213 | PriceObjectClaim = startupConfig.GetInt("PriceObjectClaim", 10); | ||
214 | PricePublicObjectDecay = startupConfig.GetInt("PricePublicObjectDecay", 4); | ||
215 | PricePublicObjectDelete = startupConfig.GetInt("PricePublicObjectDelete", 4); | ||
216 | PriceParcelClaim = startupConfig.GetInt("PriceParcelClaim", 1); | ||
217 | PriceParcelClaimFactor = startupConfig.GetFloat("PriceParcelClaimFactor", 1f); | ||
218 | PriceUpload = startupConfig.GetInt("PriceUpload", 0); | ||
219 | PriceRentLight = startupConfig.GetInt("PriceRentLight", 5); | ||
220 | TeleportMinPrice = startupConfig.GetInt("TeleportMinPrice", 2); | ||
221 | TeleportPriceExponent = startupConfig.GetFloat("TeleportPriceExponent", 2f); | ||
222 | EnergyEfficiency = startupConfig.GetFloat("EnergyEfficiency", 1); | ||
223 | PriceObjectRent = startupConfig.GetFloat("PriceObjectRent", 1); | ||
224 | PriceObjectScaleFactor = startupConfig.GetFloat("PriceObjectScaleFactor", 10); | ||
225 | PriceParcelRent = startupConfig.GetInt("PriceParcelRent", 1); | ||
226 | PriceGroupCreate = startupConfig.GetInt("PriceGroupCreate", -1); | ||
227 | string EBA = startupConfig.GetString("EconomyBaseAccount", LLUUID.Zero.ToString()); | ||
228 | Helpers.TryParse(EBA,out EconomyBaseAccount); | ||
229 | |||
230 | UserLevelPaysFees = startupConfig.GetInt("UserLevelPaysFees", -1); | ||
231 | m_stipend = startupConfig.GetInt("UserStipend", 500); | ||
232 | m_minFundsBeforeRefresh = startupConfig.GetInt("IssueStipendWhenClientIsBelowAmount", 10); | ||
233 | m_keepMoneyAcrossLogins = startupConfig.GetBoolean("KeepMoneyAcrossLogins", true); | ||
234 | m_MoneyAddress = startupConfig.GetString("CurrencyServer", String.Empty); | ||
235 | m_LandAddress = startupConfig.GetString("LandServer", String.Empty); | ||
236 | } | ||
237 | |||
238 | // Send ObjectCapacity to Scene.. Which sends it to the SimStatsReporter. | ||
239 | scene.SetObjectCapacity(ObjectCapacity); | ||
240 | } | ||
241 | |||
242 | /// <summary> | ||
243 | /// New Client Event Handler | ||
244 | /// </summary> | ||
245 | /// <param name="client"></param> | ||
246 | private void OnNewClient(IClientAPI client) | ||
247 | { | ||
248 | // Here we check if we're in grid mode | ||
249 | // I imagine that the 'check balance' | ||
250 | // function for the client should be here or shortly after | ||
251 | |||
252 | if (gridmode) | ||
253 | { | ||
254 | if (m_MoneyAddress.Length == 0) | ||
255 | { | ||
256 | |||
257 | CheckExistAndRefreshFunds(client.AgentId); | ||
258 | } | ||
259 | else | ||
260 | { | ||
261 | bool childYN = true; | ||
262 | ScenePresence agent = null; | ||
263 | //client.SecureSessionId; | ||
264 | Scene s = LocateSceneClientIn(client.AgentId); | ||
265 | if (s != null) | ||
266 | { | ||
267 | agent = s.GetScenePresence(client.AgentId); | ||
268 | if (agent != null) | ||
269 | childYN = agent.IsChildAgent; | ||
270 | } | ||
271 | if (s != null && agent != null && childYN == false) | ||
272 | { | ||
273 | //s.RegionInfo.RegionHandle; | ||
274 | LLUUID agentID = LLUUID.Zero; | ||
275 | int funds = 0; | ||
276 | |||
277 | Hashtable hbinfo = GetBalanceForUserFromMoneyServer(client.AgentId, client.SecureSessionId, s.RegionInfo.originRegionID.ToString(), s.RegionInfo.regionSecret); | ||
278 | if ((bool)hbinfo["success"] == true) | ||
279 | { | ||
280 | |||
281 | Helpers.TryParse((string)hbinfo["agentId"], out agentID); | ||
282 | try | ||
283 | { | ||
284 | funds = (Int32)hbinfo["funds"]; | ||
285 | } | ||
286 | catch (ArgumentException) | ||
287 | { | ||
288 | } | ||
289 | catch (FormatException) | ||
290 | { | ||
291 | } | ||
292 | catch (OverflowException) | ||
293 | { | ||
294 | m_log.ErrorFormat("[MONEY]: While getting the Currency for user {0}, the return funds overflowed.", agentID); | ||
295 | client.SendAlertMessage("Unable to get your money balance, money operations will be unavailable"); | ||
296 | } | ||
297 | catch (InvalidCastException) | ||
298 | { | ||
299 | funds = 0; | ||
300 | } | ||
301 | |||
302 | m_KnownClientFunds[agentID] = funds; | ||
303 | } | ||
304 | else | ||
305 | { | ||
306 | m_log.WarnFormat("[MONEY]: Getting Money for user {0} failed with the following message:{1}", agentID, (string)hbinfo["errorMessage"]); | ||
307 | client.SendAlertMessage((string)hbinfo["errorMessage"]); | ||
308 | } | ||
309 | SendMoneyBalance(client, agentID, client.SessionId, LLUUID.Zero); | ||
310 | |||
311 | } | ||
312 | } | ||
313 | |||
314 | } | ||
315 | else | ||
316 | { | ||
317 | CheckExistAndRefreshFunds(client.AgentId); | ||
318 | } | ||
319 | |||
320 | // Subscribe to Money messages | ||
321 | client.OnEconomyDataRequest += EconomyDataRequestHandler; | ||
322 | client.OnMoneyBalanceRequest += SendMoneyBalance; | ||
323 | client.OnRequestPayPrice += requestPayPrice; | ||
324 | client.OnLogout += ClientClosed; | ||
325 | |||
326 | |||
327 | } | ||
328 | |||
329 | #region event Handlers | ||
330 | |||
331 | public void requestPayPrice(IClientAPI client, LLUUID objectID) | ||
332 | { | ||
333 | Scene scene=LocateSceneClientIn(client.AgentId); | ||
334 | if(scene == null) | ||
335 | return; | ||
336 | |||
337 | SceneObjectPart task=scene.GetSceneObjectPart(objectID); | ||
338 | if(task == null) | ||
339 | return; | ||
340 | SceneObjectGroup group=task.ParentGroup; | ||
341 | SceneObjectPart root=group.RootPart; | ||
342 | |||
343 | client.SendPayPrice(objectID, root.PayPrice); | ||
344 | } | ||
345 | |||
346 | /// <summary> | ||
347 | /// When the client closes the connection we remove their accounting info from memory to free up resources. | ||
348 | /// </summary> | ||
349 | /// <param name="AgentID"></param> | ||
350 | public void ClientClosed(LLUUID AgentID) | ||
351 | { | ||
352 | lock (m_KnownClientFunds) | ||
353 | { | ||
354 | if (m_keepMoneyAcrossLogins && m_MoneyAddress.Length == 0) | ||
355 | { | ||
356 | } | ||
357 | else | ||
358 | { | ||
359 | m_KnownClientFunds.Remove(AgentID); | ||
360 | } | ||
361 | } | ||
362 | } | ||
363 | |||
364 | /// <summary> | ||
365 | /// Event called Economy Data Request handler. | ||
366 | /// </summary> | ||
367 | /// <param name="agentId"></param> | ||
368 | public void EconomyDataRequestHandler(LLUUID agentId) | ||
369 | { | ||
370 | IClientAPI user = LocateClientObject(agentId); | ||
371 | |||
372 | if (user != null) | ||
373 | { | ||
374 | user.SendEconomyData(EnergyEfficiency, ObjectCapacity, ObjectCount, PriceEnergyUnit, PriceGroupCreate, | ||
375 | PriceObjectClaim, PriceObjectRent, PriceObjectScaleFactor, PriceParcelClaim, PriceParcelClaimFactor, | ||
376 | PriceParcelRent, PricePublicObjectDecay, PricePublicObjectDelete, PriceRentLight, PriceUpload, | ||
377 | TeleportMinPrice, TeleportPriceExponent); | ||
378 | } | ||
379 | } | ||
380 | |||
381 | private void ValidateLandBuy (Object osender, EventManager.LandBuyArgs e) | ||
382 | { | ||
383 | if (m_MoneyAddress.Length == 0) | ||
384 | { | ||
385 | lock (m_KnownClientFunds) | ||
386 | { | ||
387 | if (m_KnownClientFunds.ContainsKey(e.agentId)) | ||
388 | { | ||
389 | // Does the sender have enough funds to give? | ||
390 | if (m_KnownClientFunds[e.agentId] >= e.parcelPrice) | ||
391 | { | ||
392 | lock(e) | ||
393 | { | ||
394 | e.economyValidated=true; | ||
395 | } | ||
396 | } | ||
397 | } | ||
398 | } | ||
399 | } | ||
400 | else | ||
401 | { | ||
402 | if(GetRemoteBalance(e.agentId) >= e.parcelPrice) | ||
403 | { | ||
404 | lock(e) | ||
405 | { | ||
406 | e.economyValidated=true; | ||
407 | } | ||
408 | } | ||
409 | } | ||
410 | } | ||
411 | |||
412 | private void processLandBuy(Object osender, EventManager.LandBuyArgs e) | ||
413 | { | ||
414 | lock(e) | ||
415 | { | ||
416 | if(e.economyValidated == true && e.transactionID == 0) | ||
417 | { | ||
418 | e.transactionID=Util.UnixTimeSinceEpoch(); | ||
419 | |||
420 | if(doMoneyTransfer(e.agentId, e.parcelOwnerID, e.parcelPrice, 0, "Land purchase")) | ||
421 | { | ||
422 | lock (e) | ||
423 | { | ||
424 | e.amountDebited = e.parcelPrice; | ||
425 | } | ||
426 | } | ||
427 | } | ||
428 | } | ||
429 | } | ||
430 | |||
431 | /// <summary> | ||
432 | /// THis method gets called when someone pays someone else as a gift. | ||
433 | /// </summary> | ||
434 | /// <param name="osender"></param> | ||
435 | /// <param name="e"></param> | ||
436 | private void MoneyTransferAction (Object osender, EventManager.MoneyTransferArgs e) | ||
437 | { | ||
438 | IClientAPI sender = null; | ||
439 | IClientAPI receiver = null; | ||
440 | |||
441 | if(m_MoneyAddress.Length > 0) // Handled on server | ||
442 | e.description=String.Empty; | ||
443 | |||
444 | if(e.transactiontype == 5008) // Object gets paid | ||
445 | { | ||
446 | sender = LocateClientObject(e.sender); | ||
447 | if (sender != null) | ||
448 | { | ||
449 | SceneObjectPart part=findPrim(e.receiver); | ||
450 | if(part == null) | ||
451 | return; | ||
452 | |||
453 | string name=resolveAgentName(part.OwnerID); | ||
454 | if(name == String.Empty) | ||
455 | name="(hippos)"; | ||
456 | |||
457 | receiver = LocateClientObject(part.OwnerID); | ||
458 | |||
459 | string description=String.Format("Paid {0} via object {1}", name, e.description); | ||
460 | bool transactionresult = doMoneyTransfer(e.sender, part.OwnerID, e.amount, e.transactiontype, description); | ||
461 | |||
462 | if(transactionresult) | ||
463 | { | ||
464 | ObjectPaid handlerOnObjectPaid = OnObjectPaid; | ||
465 | if(handlerOnObjectPaid != null) | ||
466 | { | ||
467 | handlerOnObjectPaid(e.receiver, e.sender, e.amount); | ||
468 | } | ||
469 | } | ||
470 | |||
471 | if (e.sender != e.receiver) | ||
472 | { | ||
473 | sender.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(e.sender)); | ||
474 | } | ||
475 | if(receiver != null) | ||
476 | { | ||
477 | receiver.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(part.OwnerID)); | ||
478 | } | ||
479 | } | ||
480 | return; | ||
481 | } | ||
482 | |||
483 | sender = LocateClientObject(e.sender); | ||
484 | if (sender != null) | ||
485 | { | ||
486 | receiver = LocateClientObject(e.receiver); | ||
487 | |||
488 | bool transactionresult = doMoneyTransfer(e.sender, e.receiver, e.amount, e.transactiontype, e.description); | ||
489 | |||
490 | if (e.sender != e.receiver) | ||
491 | { | ||
492 | if (sender != null) | ||
493 | { | ||
494 | sender.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(e.sender)); | ||
495 | } | ||
496 | } | ||
497 | |||
498 | if (receiver != null) | ||
499 | { | ||
500 | receiver.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(e.receiver)); | ||
501 | } | ||
502 | } | ||
503 | else | ||
504 | { | ||
505 | m_log.Warn("[MONEY]: Potential Fraud Warning, got money transfer request for avatar that isn't in this simulator - Details; Sender:" + e.sender.ToString() + " Receiver: " + e.receiver.ToString() + " Amount: " + e.amount.ToString()); | ||
506 | } | ||
507 | } | ||
508 | |||
509 | /// <summary> | ||
510 | /// Event Handler for when a root agent becomes a child agent | ||
511 | /// </summary> | ||
512 | /// <param name="avatar"></param> | ||
513 | private void MakeChildAgent(ScenePresence avatar) | ||
514 | { | ||
515 | lock (m_rootAgents) | ||
516 | { | ||
517 | if (m_rootAgents.ContainsKey(avatar.UUID)) | ||
518 | { | ||
519 | if (m_rootAgents[avatar.UUID] == avatar.Scene.RegionInfo.originRegionID) | ||
520 | { | ||
521 | m_rootAgents.Remove(avatar.UUID); | ||
522 | m_log.Info("[MONEY]: Removing " + avatar.Firstname + " " + avatar.Lastname + " as a root agent"); | ||
523 | } | ||
524 | |||
525 | } | ||
526 | } | ||
527 | |||
528 | } | ||
529 | |||
530 | /// <summary> | ||
531 | /// Event Handler for when the client logs out. | ||
532 | /// </summary> | ||
533 | /// <param name="AgentId"></param> | ||
534 | private void ClientLoggedOut(LLUUID AgentId) | ||
535 | { | ||
536 | lock (m_rootAgents) | ||
537 | { | ||
538 | if (m_rootAgents.ContainsKey(AgentId)) | ||
539 | { | ||
540 | m_rootAgents.Remove(AgentId); | ||
541 | //m_log.Info("[MONEY]: Removing " + AgentId + ". Agent logged out."); | ||
542 | } | ||
543 | } | ||
544 | } | ||
545 | |||
546 | /// <summary> | ||
547 | /// Call this when the client disconnects. | ||
548 | /// </summary> | ||
549 | /// <param name="client"></param> | ||
550 | public void ClientClosed(IClientAPI client) | ||
551 | { | ||
552 | ClientClosed(client.AgentId); | ||
553 | } | ||
554 | |||
555 | /// <summary> | ||
556 | /// Event Handler for when an Avatar enters one of the parcels in the simulator. | ||
557 | /// </summary> | ||
558 | /// <param name="avatar"></param> | ||
559 | /// <param name="localLandID"></param> | ||
560 | /// <param name="regionID"></param> | ||
561 | private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, LLUUID regionID) | ||
562 | { | ||
563 | lock (m_rootAgents) | ||
564 | { | ||
565 | if (m_rootAgents.ContainsKey(avatar.UUID)) | ||
566 | { | ||
567 | if (avatar.Scene.RegionInfo.originRegionID != m_rootAgents[avatar.UUID]) | ||
568 | { | ||
569 | m_rootAgents[avatar.UUID] = avatar.Scene.RegionInfo.originRegionID; | ||
570 | //m_log.Info("[MONEY]: Claiming " + avatar.Firstname + " " + avatar.Lastname + " in region:" + avatar.RegionHandle + "."); | ||
571 | // Claim User! my user! Mine mine mine! | ||
572 | if (m_MoneyAddress.Length > 0) | ||
573 | { | ||
574 | Scene RegionItem = GetSceneByUUID(regionID); | ||
575 | if (RegionItem != null) | ||
576 | { | ||
577 | Hashtable hresult = claim_user(avatar.UUID, avatar.ControllingClient.SecureSessionId, regionID, RegionItem.RegionInfo.regionSecret); | ||
578 | if ((bool)hresult["success"] == true) | ||
579 | { | ||
580 | int funds = 0; | ||
581 | try | ||
582 | { | ||
583 | funds = (Int32)hresult["funds"]; | ||
584 | } | ||
585 | catch (InvalidCastException) | ||
586 | { | ||
587 | |||
588 | } | ||
589 | SetLocalFundsForAgentID(avatar.UUID, funds); | ||
590 | } | ||
591 | else | ||
592 | { | ||
593 | avatar.ControllingClient.SendAgentAlertMessage((string)hresult["errorMessage"], true); | ||
594 | } | ||
595 | } | ||
596 | } | ||
597 | } | ||
598 | } | ||
599 | else | ||
600 | { | ||
601 | lock (m_rootAgents) | ||
602 | { | ||
603 | m_rootAgents.Add(avatar.UUID, avatar.Scene.RegionInfo.originRegionID); | ||
604 | } | ||
605 | if (m_MoneyAddress.Length > 0) | ||
606 | { | ||
607 | Scene RegionItem = GetSceneByUUID(regionID); | ||
608 | if (RegionItem != null) | ||
609 | { | ||
610 | Hashtable hresult = claim_user(avatar.UUID, avatar.ControllingClient.SecureSessionId, regionID, RegionItem.RegionInfo.regionSecret); | ||
611 | if ((bool)hresult["success"] == true) | ||
612 | { | ||
613 | int funds = 0; | ||
614 | try | ||
615 | { | ||
616 | funds = (Int32)hresult["funds"]; | ||
617 | } | ||
618 | catch (InvalidCastException) | ||
619 | { | ||
620 | |||
621 | } | ||
622 | SetLocalFundsForAgentID(avatar.UUID, funds); | ||
623 | } | ||
624 | else | ||
625 | { | ||
626 | avatar.ControllingClient.SendAgentAlertMessage((string)hresult["errorMessage"], true); | ||
627 | } | ||
628 | } | ||
629 | } | ||
630 | |||
631 | //m_log.Info("[MONEY]: Claiming " + avatar.Firstname + " " + avatar.Lastname + " in region:" + avatar.RegionHandle + "."); | ||
632 | } | ||
633 | } | ||
634 | //m_log.Info("[FRIEND]: " + avatar.Name + " status:" + (!avatar.IsChildAgent).ToString()); | ||
635 | } | ||
636 | |||
637 | #endregion | ||
638 | |||
639 | /// <summary> | ||
640 | /// Transfer money | ||
641 | /// </summary> | ||
642 | /// <param name="Sender"></param> | ||
643 | /// <param name="Receiver"></param> | ||
644 | /// <param name="amount"></param> | ||
645 | /// <returns></returns> | ||
646 | private bool doMoneyTransfer(LLUUID Sender, LLUUID Receiver, int amount, int transactiontype, string description) | ||
647 | { | ||
648 | bool result = false; | ||
649 | if (amount >= 0) | ||
650 | { | ||
651 | lock (m_KnownClientFunds) | ||
652 | { | ||
653 | // If we don't know about the sender, then the sender can't | ||
654 | // actually be here and therefore this is likely fraud or outdated. | ||
655 | if (m_MoneyAddress.Length == 0) | ||
656 | { | ||
657 | if (m_KnownClientFunds.ContainsKey(Sender)) | ||
658 | { | ||
659 | // Does the sender have enough funds to give? | ||
660 | if (m_KnownClientFunds[Sender] >= amount) | ||
661 | { | ||
662 | // Subtract the funds from the senders account | ||
663 | m_KnownClientFunds[Sender] -= amount; | ||
664 | |||
665 | // do we know about the receiver? | ||
666 | if (!m_KnownClientFunds.ContainsKey(Receiver)) | ||
667 | { | ||
668 | // Make a record for them so they get the updated balance when they login | ||
669 | CheckExistAndRefreshFunds(Receiver); | ||
670 | } | ||
671 | if (m_enabled) | ||
672 | { | ||
673 | //Add the amount to the Receiver's funds | ||
674 | m_KnownClientFunds[Receiver] += amount; | ||
675 | result = true; | ||
676 | } | ||
677 | } | ||
678 | else | ||
679 | { | ||
680 | // These below are redundant to make this clearer to read | ||
681 | result = false; | ||
682 | } | ||
683 | } | ||
684 | else | ||
685 | { | ||
686 | result = false; | ||
687 | } | ||
688 | } | ||
689 | else | ||
690 | { | ||
691 | result = TransferMoneyonMoneyServer(Sender, Receiver, amount, transactiontype, description); | ||
692 | } | ||
693 | } | ||
694 | } | ||
695 | return result; | ||
696 | } | ||
697 | |||
698 | #region Utility Helpers | ||
699 | /// <summary> | ||
700 | /// Locates a IClientAPI for the client specified | ||
701 | /// </summary> | ||
702 | /// <param name="AgentID"></param> | ||
703 | /// <returns></returns> | ||
704 | private IClientAPI LocateClientObject(LLUUID AgentID) | ||
705 | { | ||
706 | ScenePresence tPresence = null; | ||
707 | IClientAPI rclient = null; | ||
708 | |||
709 | lock (m_scenel) | ||
710 | { | ||
711 | foreach (Scene _scene in m_scenel.Values) | ||
712 | { | ||
713 | tPresence = _scene.GetScenePresence(AgentID); | ||
714 | if (tPresence != null) | ||
715 | { | ||
716 | if (!tPresence.IsChildAgent) | ||
717 | { | ||
718 | rclient = tPresence.ControllingClient; | ||
719 | } | ||
720 | } | ||
721 | if (rclient != null) | ||
722 | { | ||
723 | return rclient; | ||
724 | } | ||
725 | } | ||
726 | |||
727 | } | ||
728 | return null; | ||
729 | } | ||
730 | |||
731 | private Scene LocateSceneClientIn(LLUUID AgentId) | ||
732 | { | ||
733 | lock (m_scenel) | ||
734 | { | ||
735 | foreach (Scene _scene in m_scenel.Values) | ||
736 | { | ||
737 | ScenePresence tPresence = _scene.GetScenePresence(AgentId); | ||
738 | if (tPresence != null) | ||
739 | { | ||
740 | if (!tPresence.IsChildAgent) | ||
741 | { | ||
742 | return _scene; | ||
743 | } | ||
744 | } | ||
745 | |||
746 | } | ||
747 | |||
748 | } | ||
749 | return null; | ||
750 | } | ||
751 | |||
752 | /// <summary> | ||
753 | /// Utility function Gets a Random scene in the instance. For when which scene exactly you're doing something with doesn't matter | ||
754 | /// </summary> | ||
755 | /// <returns></returns> | ||
756 | public Scene GetRandomScene() | ||
757 | { | ||
758 | lock (m_scenel) | ||
759 | { | ||
760 | foreach (Scene rs in m_scenel.Values) | ||
761 | return rs; | ||
762 | } | ||
763 | return null; | ||
764 | |||
765 | } | ||
766 | /// <summary> | ||
767 | /// Utility function to get a Scene by RegionID in a module | ||
768 | /// </summary> | ||
769 | /// <param name="RegionID"></param> | ||
770 | /// <returns></returns> | ||
771 | public Scene GetSceneByUUID(LLUUID RegionID) | ||
772 | { | ||
773 | lock (m_scenel) | ||
774 | { | ||
775 | foreach (Scene rs in m_scenel.Values) | ||
776 | { | ||
777 | if (rs.RegionInfo.originRegionID == RegionID) | ||
778 | { | ||
779 | return rs; | ||
780 | } | ||
781 | } | ||
782 | } | ||
783 | return null; | ||
784 | } | ||
785 | #endregion | ||
786 | |||
787 | |||
788 | |||
789 | /// <summary> | ||
790 | /// Sends the the stored money balance to the client | ||
791 | /// </summary> | ||
792 | /// <param name="client"></param> | ||
793 | /// <param name="agentID"></param> | ||
794 | /// <param name="SessionID"></param> | ||
795 | /// <param name="TransactionID"></param> | ||
796 | public void SendMoneyBalance(IClientAPI client, LLUUID agentID, LLUUID SessionID, LLUUID TransactionID) | ||
797 | { | ||
798 | if (client.AgentId == agentID && client.SessionId == SessionID) | ||
799 | { | ||
800 | int returnfunds = 0; | ||
801 | |||
802 | try | ||
803 | { | ||
804 | returnfunds = GetFundsForAgentID(agentID); | ||
805 | } | ||
806 | catch (Exception e) | ||
807 | { | ||
808 | client.SendAlertMessage(e.Message + " "); | ||
809 | } | ||
810 | |||
811 | client.SendMoneyBalance(TransactionID, true, new byte[0], returnfunds); | ||
812 | } | ||
813 | else | ||
814 | { | ||
815 | client.SendAlertMessage("Unable to send your money balance to you!"); | ||
816 | } | ||
817 | } | ||
818 | |||
819 | #region local Fund Management | ||
820 | /// <summary> | ||
821 | /// Ensures that the agent accounting data is set up in this instance. | ||
822 | /// </summary> | ||
823 | /// <param name="agentID"></param> | ||
824 | private void CheckExistAndRefreshFunds(LLUUID agentID) | ||
825 | { | ||
826 | lock (m_KnownClientFunds) | ||
827 | { | ||
828 | if (!m_KnownClientFunds.ContainsKey(agentID)) | ||
829 | { | ||
830 | m_KnownClientFunds.Add(agentID, m_stipend); | ||
831 | } | ||
832 | else | ||
833 | { | ||
834 | if (m_KnownClientFunds[agentID] <= m_minFundsBeforeRefresh) | ||
835 | { | ||
836 | m_KnownClientFunds[agentID] = m_stipend; | ||
837 | } | ||
838 | } | ||
839 | } | ||
840 | } | ||
841 | /// <summary> | ||
842 | /// Gets the amount of Funds for an agent | ||
843 | /// </summary> | ||
844 | /// <param name="AgentID"></param> | ||
845 | /// <returns></returns> | ||
846 | private int GetFundsForAgentID(LLUUID AgentID) | ||
847 | { | ||
848 | int returnfunds = 0; | ||
849 | lock (m_KnownClientFunds) | ||
850 | { | ||
851 | if (m_KnownClientFunds.ContainsKey(AgentID)) | ||
852 | { | ||
853 | returnfunds = m_KnownClientFunds[AgentID]; | ||
854 | } | ||
855 | else | ||
856 | { | ||
857 | //throw new Exception("Unable to get funds."); | ||
858 | } | ||
859 | } | ||
860 | return returnfunds; | ||
861 | } | ||
862 | private void SetLocalFundsForAgentID(LLUUID AgentID, int amount) | ||
863 | { | ||
864 | lock (m_KnownClientFunds) | ||
865 | { | ||
866 | if (m_KnownClientFunds.ContainsKey(AgentID)) | ||
867 | { | ||
868 | m_KnownClientFunds[AgentID] = amount; | ||
869 | } | ||
870 | else | ||
871 | { | ||
872 | m_KnownClientFunds.Add(AgentID, amount); | ||
873 | } | ||
874 | } | ||
875 | |||
876 | } | ||
877 | |||
878 | #endregion | ||
879 | |||
880 | /// <summary> | ||
881 | /// Gets the current balance for the user from the Grid Money Server | ||
882 | /// </summary> | ||
883 | /// <param name="agentId"></param> | ||
884 | /// <param name="secureSessionID"></param> | ||
885 | /// <param name="regionId"></param> | ||
886 | /// <param name="regionSecret"></param> | ||
887 | /// <returns></returns> | ||
888 | public Hashtable GetBalanceForUserFromMoneyServer(LLUUID agentId, LLUUID secureSessionID, LLUUID regionId, string regionSecret) | ||
889 | { | ||
890 | |||
891 | Hashtable MoneyBalanceRequestParams = new Hashtable(); | ||
892 | MoneyBalanceRequestParams["agentId"] = agentId.ToString(); | ||
893 | MoneyBalanceRequestParams["secureSessionId"] = secureSessionID.ToString(); | ||
894 | MoneyBalanceRequestParams["regionId"] = regionId.ToString(); | ||
895 | MoneyBalanceRequestParams["secret"] = regionSecret; | ||
896 | MoneyBalanceRequestParams["currencySecret"] = ""; // per - region/user currency secret gotten from the money system | ||
897 | |||
898 | Hashtable MoneyRespData = genericCurrencyXMLRPCRequest(MoneyBalanceRequestParams, "simulatorUserBalanceRequest"); | ||
899 | |||
900 | return MoneyRespData; | ||
901 | } | ||
902 | |||
903 | |||
904 | |||
905 | /// <summary> | ||
906 | /// Generic XMLRPC client abstraction | ||
907 | /// </summary> | ||
908 | /// <param name="ReqParams">Hashtable containing parameters to the method</param> | ||
909 | /// <param name="method">Method to invoke</param> | ||
910 | /// <returns>Hashtable with success=>bool and other values</returns> | ||
911 | public Hashtable genericCurrencyXMLRPCRequest(Hashtable ReqParams, string method) | ||
912 | { | ||
913 | ArrayList SendParams = new ArrayList(); | ||
914 | SendParams.Add(ReqParams); | ||
915 | // Send Request | ||
916 | XmlRpcResponse MoneyResp; | ||
917 | try | ||
918 | { | ||
919 | XmlRpcRequest BalanceRequestReq = new XmlRpcRequest(method, SendParams); | ||
920 | MoneyResp = BalanceRequestReq.Send(m_MoneyAddress, 30000); | ||
921 | } | ||
922 | catch (WebException ex) | ||
923 | { | ||
924 | |||
925 | m_log.ErrorFormat( | ||
926 | "[MONEY]: Unable to connect to Money Server {0}. Exception {1}", | ||
927 | m_MoneyAddress, ex); | ||
928 | |||
929 | Hashtable ErrorHash = new Hashtable(); | ||
930 | ErrorHash["success"] = false; | ||
931 | ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable"; | ||
932 | ErrorHash["errorURI"] = ""; | ||
933 | |||
934 | return ErrorHash; | ||
935 | //throw (ex); | ||
936 | } | ||
937 | catch (SocketException ex) | ||
938 | { | ||
939 | |||
940 | m_log.ErrorFormat( | ||
941 | "[MONEY]: Unable to connect to Money Server {0}. Exception {1}", | ||
942 | m_MoneyAddress, ex); | ||
943 | |||
944 | Hashtable ErrorHash = new Hashtable(); | ||
945 | ErrorHash["success"] = false; | ||
946 | ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable"; | ||
947 | ErrorHash["errorURI"] = ""; | ||
948 | |||
949 | return ErrorHash; | ||
950 | //throw (ex); | ||
951 | } | ||
952 | catch (XmlException ex) | ||
953 | { | ||
954 | m_log.ErrorFormat( | ||
955 | "[MONEY]: Unable to connect to Money Server {0}. Exception {1}", | ||
956 | m_MoneyAddress, ex); | ||
957 | |||
958 | Hashtable ErrorHash = new Hashtable(); | ||
959 | ErrorHash["success"] = false; | ||
960 | ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable"; | ||
961 | ErrorHash["errorURI"] = ""; | ||
962 | |||
963 | return ErrorHash; | ||
964 | |||
965 | } | ||
966 | if (MoneyResp.IsFault) | ||
967 | { | ||
968 | Hashtable ErrorHash = new Hashtable(); | ||
969 | ErrorHash["success"] = false; | ||
970 | ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable"; | ||
971 | ErrorHash["errorURI"] = ""; | ||
972 | |||
973 | return ErrorHash; | ||
974 | |||
975 | } | ||
976 | Hashtable MoneyRespData = (Hashtable)MoneyResp.Value; | ||
977 | |||
978 | return MoneyRespData; | ||
979 | } | ||
980 | /// <summary> | ||
981 | /// This informs the Money Grid Server that the avatar is in this simulator | ||
982 | /// </summary> | ||
983 | /// <param name="agentId"></param> | ||
984 | /// <param name="secureSessionID"></param> | ||
985 | /// <param name="regionId"></param> | ||
986 | /// <param name="regionSecret"></param> | ||
987 | /// <returns></returns> | ||
988 | public Hashtable claim_user(LLUUID agentId, LLUUID secureSessionID, LLUUID regionId, string regionSecret) | ||
989 | { | ||
990 | |||
991 | Hashtable MoneyBalanceRequestParams = new Hashtable(); | ||
992 | MoneyBalanceRequestParams["agentId"] = agentId.ToString(); | ||
993 | MoneyBalanceRequestParams["secureSessionId"] = secureSessionID.ToString(); | ||
994 | MoneyBalanceRequestParams["regionId"] = regionId.ToString(); | ||
995 | MoneyBalanceRequestParams["secret"] = regionSecret; | ||
996 | |||
997 | Hashtable MoneyRespData = genericCurrencyXMLRPCRequest(MoneyBalanceRequestParams, "simulatorClaimUserRequest"); | ||
998 | IClientAPI sendMoneyBal = LocateClientObject(agentId); | ||
999 | if (sendMoneyBal != null) | ||
1000 | { | ||
1001 | SendMoneyBalance(sendMoneyBal, agentId, sendMoneyBal.SessionId, LLUUID.Zero); | ||
1002 | } | ||
1003 | return MoneyRespData; | ||
1004 | } | ||
1005 | |||
1006 | private SceneObjectPart findPrim(LLUUID objectID) | ||
1007 | { | ||
1008 | lock (m_scenel) | ||
1009 | { | ||
1010 | foreach (Scene s in m_scenel.Values) | ||
1011 | { | ||
1012 | SceneObjectPart part=s.GetSceneObjectPart(objectID); | ||
1013 | if(part != null) | ||
1014 | { | ||
1015 | return part; | ||
1016 | } | ||
1017 | } | ||
1018 | } | ||
1019 | return null; | ||
1020 | } | ||
1021 | |||
1022 | private string resolveObjectName(LLUUID objectID) | ||
1023 | { | ||
1024 | SceneObjectPart part=findPrim(objectID); | ||
1025 | if(part != null) | ||
1026 | { | ||
1027 | return part.Name; | ||
1028 | } | ||
1029 | return String.Empty; | ||
1030 | } | ||
1031 | |||
1032 | private string resolveAgentName(LLUUID agentID) | ||
1033 | { | ||
1034 | // try avatar username surname | ||
1035 | Scene scene=GetRandomScene(); | ||
1036 | UserProfileData profile = scene.CommsManager.UserService.GetUserProfile(agentID); | ||
1037 | if (profile != null) | ||
1038 | { | ||
1039 | string avatarname = profile.FirstName + " " + profile.SurName; | ||
1040 | return avatarname; | ||
1041 | } | ||
1042 | return String.Empty; | ||
1043 | } | ||
1044 | |||
1045 | public bool ObjectGiveMoney(LLUUID objectID, LLUUID fromID, LLUUID toID, int amount) | ||
1046 | { | ||
1047 | string description=String.Format("Object {0} pays {1}", resolveObjectName(objectID), resolveAgentName(toID)); | ||
1048 | |||
1049 | bool give_result = doMoneyTransfer(fromID, toID, amount, 2, description); | ||
1050 | |||
1051 | if (m_MoneyAddress.Length == 0) | ||
1052 | BalanceUpdate(fromID, toID, give_result, description); | ||
1053 | |||
1054 | return give_result; | ||
1055 | |||
1056 | |||
1057 | } | ||
1058 | private void BalanceUpdate(LLUUID senderID, LLUUID receiverID, bool transactionresult, string description) | ||
1059 | { | ||
1060 | IClientAPI sender = LocateClientObject(senderID); | ||
1061 | IClientAPI receiver = LocateClientObject(receiverID); | ||
1062 | |||
1063 | if (senderID != receiverID) | ||
1064 | { | ||
1065 | if (sender != null) | ||
1066 | { | ||
1067 | sender.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(description), GetFundsForAgentID(senderID)); | ||
1068 | } | ||
1069 | |||
1070 | if (receiver != null) | ||
1071 | { | ||
1072 | receiver.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(description), GetFundsForAgentID(receiverID)); | ||
1073 | } | ||
1074 | } | ||
1075 | } | ||
1076 | |||
1077 | /// <summary> | ||
1078 | /// Informs the Money Grid Server of a transfer. | ||
1079 | /// </summary> | ||
1080 | /// <param name="sourceId"></param> | ||
1081 | /// <param name="destId"></param> | ||
1082 | /// <param name="amount"></param> | ||
1083 | /// <returns></returns> | ||
1084 | public bool TransferMoneyonMoneyServer(LLUUID sourceId, LLUUID destId, int amount, int transactiontype, string description) | ||
1085 | { | ||
1086 | int aggregatePermInventory = 0; | ||
1087 | int aggregatePermNextOwner = 0; | ||
1088 | int flags = 0; | ||
1089 | bool rvalue = false; | ||
1090 | |||
1091 | IClientAPI cli = LocateClientObject(sourceId); | ||
1092 | if (cli != null) | ||
1093 | { | ||
1094 | |||
1095 | Scene userScene = null; | ||
1096 | lock (m_rootAgents) | ||
1097 | { | ||
1098 | userScene = GetSceneByUUID(m_rootAgents[sourceId]); | ||
1099 | } | ||
1100 | if (userScene != null) | ||
1101 | { | ||
1102 | Hashtable ht = new Hashtable(); | ||
1103 | ht["agentId"] = sourceId.ToString(); | ||
1104 | ht["secureSessionId"] = cli.SecureSessionId.ToString(); | ||
1105 | ht["regionId"] = userScene.RegionInfo.originRegionID.ToString(); | ||
1106 | ht["secret"] = userScene.RegionInfo.regionSecret; | ||
1107 | ht["currencySecret"] = " "; | ||
1108 | ht["destId"] = destId.ToString(); | ||
1109 | ht["cash"] = amount; | ||
1110 | ht["aggregatePermInventory"] = aggregatePermInventory; | ||
1111 | ht["aggregatePermNextOwner"] = aggregatePermNextOwner; | ||
1112 | ht["flags"] = flags; | ||
1113 | ht["transactionType"] = transactiontype; | ||
1114 | ht["description"] = description; | ||
1115 | |||
1116 | Hashtable hresult = genericCurrencyXMLRPCRequest(ht, "regionMoveMoney"); | ||
1117 | |||
1118 | if ((bool)hresult["success"] == true) | ||
1119 | { | ||
1120 | int funds1 = 0; | ||
1121 | int funds2 = 0; | ||
1122 | try | ||
1123 | { | ||
1124 | funds1 = (Int32)hresult["funds"]; | ||
1125 | } | ||
1126 | catch(InvalidCastException) | ||
1127 | { | ||
1128 | funds1 = 0; | ||
1129 | } | ||
1130 | SetLocalFundsForAgentID(sourceId, funds1); | ||
1131 | if (m_KnownClientFunds.ContainsKey(destId)) | ||
1132 | { | ||
1133 | try | ||
1134 | { | ||
1135 | funds2 = (Int32)hresult["funds2"]; | ||
1136 | } | ||
1137 | catch (InvalidCastException) | ||
1138 | { | ||
1139 | funds2 = 0; | ||
1140 | } | ||
1141 | SetLocalFundsForAgentID(destId, funds2); | ||
1142 | } | ||
1143 | |||
1144 | |||
1145 | rvalue = true; | ||
1146 | } | ||
1147 | else | ||
1148 | { | ||
1149 | cli.SendAgentAlertMessage((string)hresult["errorMessage"], true); | ||
1150 | } | ||
1151 | |||
1152 | } | ||
1153 | } | ||
1154 | else | ||
1155 | { | ||
1156 | m_log.ErrorFormat("[MONEY]: Client {0} not found", sourceId.ToString()); | ||
1157 | } | ||
1158 | |||
1159 | return rvalue; | ||
1160 | |||
1161 | } | ||
1162 | |||
1163 | public int GetRemoteBalance(LLUUID agentId) | ||
1164 | { | ||
1165 | int funds = 0; | ||
1166 | |||
1167 | IClientAPI aClient = LocateClientObject(agentId); | ||
1168 | if (aClient != null) | ||
1169 | { | ||
1170 | Scene s = LocateSceneClientIn(agentId); | ||
1171 | if (s != null) | ||
1172 | { | ||
1173 | if (m_MoneyAddress.Length > 0) | ||
1174 | { | ||
1175 | Hashtable hbinfo = GetBalanceForUserFromMoneyServer(aClient.AgentId, aClient.SecureSessionId, s.RegionInfo.originRegionID.ToString(), s.RegionInfo.regionSecret); | ||
1176 | if ((bool)hbinfo["success"] == true) | ||
1177 | { | ||
1178 | try | ||
1179 | { | ||
1180 | funds = (Int32)hbinfo["funds"]; | ||
1181 | } | ||
1182 | catch (ArgumentException) | ||
1183 | { | ||
1184 | } | ||
1185 | catch (FormatException) | ||
1186 | { | ||
1187 | } | ||
1188 | catch (OverflowException) | ||
1189 | { | ||
1190 | m_log.ErrorFormat("[MONEY]: While getting the Currency for user {0}, the return funds overflowed.", agentId); | ||
1191 | aClient.SendAlertMessage("Unable to get your money balance, money operations will be unavailable"); | ||
1192 | } | ||
1193 | catch (InvalidCastException) | ||
1194 | { | ||
1195 | funds = 0; | ||
1196 | } | ||
1197 | |||
1198 | } | ||
1199 | else | ||
1200 | { | ||
1201 | m_log.WarnFormat("[MONEY]: Getting Money for user {0} failed with the following message:{1}", agentId, (string)hbinfo["errorMessage"]); | ||
1202 | aClient.SendAlertMessage((string)hbinfo["errorMessage"]); | ||
1203 | } | ||
1204 | } | ||
1205 | |||
1206 | SetLocalFundsForAgentID(agentId, funds); | ||
1207 | SendMoneyBalance(aClient, agentId, aClient.SessionId, LLUUID.Zero); | ||
1208 | } | ||
1209 | else | ||
1210 | { | ||
1211 | m_log.Debug("[MONEY]: Got balance request update for agent that is here, but couldn't find which scene."); | ||
1212 | } | ||
1213 | } | ||
1214 | else | ||
1215 | { | ||
1216 | m_log.Debug("[MONEY]: Got balance request update for agent that isn't here."); | ||
1217 | } | ||
1218 | return funds; | ||
1219 | } | ||
1220 | |||
1221 | public XmlRpcResponse GridMoneyUpdate(XmlRpcRequest request) | ||
1222 | { | ||
1223 | m_log.Debug("[MONEY]: Dynamic balance update called."); | ||
1224 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
1225 | |||
1226 | if (requestData.ContainsKey("agentId")) | ||
1227 | { | ||
1228 | LLUUID agentId = LLUUID.Zero; | ||
1229 | |||
1230 | Helpers.TryParse((string)requestData["agentId"], out agentId); | ||
1231 | if (agentId != LLUUID.Zero) | ||
1232 | { | ||
1233 | GetRemoteBalance(agentId); | ||
1234 | |||
1235 | } | ||
1236 | else | ||
1237 | { | ||
1238 | m_log.Debug("[MONEY]: invalid agentId specified, dropping."); | ||
1239 | } | ||
1240 | } | ||
1241 | else | ||
1242 | { | ||
1243 | m_log.Debug("[MONEY]: no agentId specified, dropping."); | ||
1244 | } | ||
1245 | XmlRpcResponse r = new XmlRpcResponse(); | ||
1246 | Hashtable rparms = new Hashtable(); | ||
1247 | rparms["success"] = true; | ||
1248 | |||
1249 | r.Value = rparms; | ||
1250 | return r; | ||
1251 | } | ||
1252 | |||
1253 | /// <summary> | ||
1254 | /// XMLRPC handler to send alert message and sound to client | ||
1255 | /// </summary> | ||
1256 | public XmlRpcResponse UserAlert(XmlRpcRequest request) | ||
1257 | { | ||
1258 | XmlRpcResponse ret = new XmlRpcResponse(); | ||
1259 | Hashtable retparam = new Hashtable(); | ||
1260 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
1261 | |||
1262 | LLUUID agentId = LLUUID.Zero; | ||
1263 | LLUUID soundId = LLUUID.Zero; | ||
1264 | |||
1265 | Helpers.TryParse((string)requestData["agentId"], out agentId); | ||
1266 | Helpers.TryParse((string)requestData["soundId"], out soundId); | ||
1267 | string text=(string)requestData["text"]; | ||
1268 | string secret=(string)requestData["secret"]; | ||
1269 | |||
1270 | Scene userScene = GetRandomScene(); | ||
1271 | if(userScene.RegionInfo.regionSecret.ToString() == secret) | ||
1272 | { | ||
1273 | IClientAPI client = LocateClientObject(agentId); | ||
1274 | |||
1275 | if (client != null) | ||
1276 | { | ||
1277 | if(soundId != LLUUID.Zero) | ||
1278 | client.SendPlayAttachedSound(soundId, LLUUID.Zero, LLUUID.Zero, 1.0f, 0); | ||
1279 | client.SendBlueBoxMessage(LLUUID.Zero, LLUUID.Zero, "", text); | ||
1280 | retparam.Add("success", true); | ||
1281 | } | ||
1282 | else | ||
1283 | { | ||
1284 | retparam.Add("success", false); | ||
1285 | } | ||
1286 | } | ||
1287 | else | ||
1288 | { | ||
1289 | retparam.Add("success", false); | ||
1290 | } | ||
1291 | ret.Value = retparam; | ||
1292 | |||
1293 | return ret; | ||
1294 | } | ||
1295 | |||
1296 | |||
1297 | # region Standalone box enablers only | ||
1298 | |||
1299 | public XmlRpcResponse quote_func(XmlRpcRequest request) | ||
1300 | { | ||
1301 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
1302 | LLUUID agentId = LLUUID.Zero; | ||
1303 | int amount = 0; | ||
1304 | Hashtable quoteResponse = new Hashtable(); | ||
1305 | XmlRpcResponse returnval = new XmlRpcResponse(); | ||
1306 | |||
1307 | if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy")) | ||
1308 | { | ||
1309 | Helpers.TryParse((string)requestData["agentId"], out agentId); | ||
1310 | try | ||
1311 | { | ||
1312 | amount = (Int32)requestData["currencyBuy"]; | ||
1313 | } | ||
1314 | catch (InvalidCastException) | ||
1315 | { | ||
1316 | |||
1317 | } | ||
1318 | Hashtable currencyResponse = new Hashtable(); | ||
1319 | currencyResponse.Add("estimatedCost", 0); | ||
1320 | currencyResponse.Add("currencyBuy", amount); | ||
1321 | |||
1322 | quoteResponse.Add("success", true); | ||
1323 | quoteResponse.Add("currency", currencyResponse); | ||
1324 | quoteResponse.Add("confirm", "asdfad9fj39ma9fj"); | ||
1325 | |||
1326 | returnval.Value = quoteResponse; | ||
1327 | return returnval; | ||
1328 | } | ||
1329 | |||
1330 | |||
1331 | |||
1332 | quoteResponse.Add("success", false); | ||
1333 | quoteResponse.Add("errorMessage", "Invalid parameters passed to the quote box"); | ||
1334 | quoteResponse.Add("errorURI", "http://www.opensimulator.org/wiki"); | ||
1335 | returnval.Value = quoteResponse; | ||
1336 | return returnval; | ||
1337 | } | ||
1338 | public XmlRpcResponse buy_func(XmlRpcRequest request) | ||
1339 | { | ||
1340 | |||
1341 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
1342 | LLUUID agentId = LLUUID.Zero; | ||
1343 | int amount = 0; | ||
1344 | if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy")) | ||
1345 | { | ||
1346 | Helpers.TryParse((string)requestData["agentId"], out agentId); | ||
1347 | try | ||
1348 | { | ||
1349 | amount = (Int32)requestData["currencyBuy"]; | ||
1350 | } | ||
1351 | catch (InvalidCastException) | ||
1352 | { | ||
1353 | |||
1354 | } | ||
1355 | if (agentId != LLUUID.Zero) | ||
1356 | { | ||
1357 | lock (m_KnownClientFunds) | ||
1358 | { | ||
1359 | if (m_KnownClientFunds.ContainsKey(agentId)) | ||
1360 | { | ||
1361 | m_KnownClientFunds[agentId] += amount; | ||
1362 | } | ||
1363 | else | ||
1364 | { | ||
1365 | m_KnownClientFunds.Add(agentId, amount); | ||
1366 | } | ||
1367 | } | ||
1368 | IClientAPI client = LocateClientObject(agentId); | ||
1369 | if (client != null) | ||
1370 | { | ||
1371 | SendMoneyBalance(client, agentId, client.SessionId, LLUUID.Zero); | ||
1372 | } | ||
1373 | } | ||
1374 | } | ||
1375 | XmlRpcResponse returnval = new XmlRpcResponse(); | ||
1376 | Hashtable returnresp = new Hashtable(); | ||
1377 | returnresp.Add("success", true); | ||
1378 | returnval.Value = returnresp; | ||
1379 | return returnval; | ||
1380 | } | ||
1381 | |||
1382 | public XmlRpcResponse preflightBuyLandPrep_func(XmlRpcRequest request) | ||
1383 | { | ||
1384 | XmlRpcResponse ret = new XmlRpcResponse(); | ||
1385 | Hashtable retparam = new Hashtable(); | ||
1386 | Hashtable membershiplevels = new Hashtable(); | ||
1387 | ArrayList levels = new ArrayList(); | ||
1388 | Hashtable level = new Hashtable(); | ||
1389 | level.Add("id", "00000000-0000-0000-0000-000000000000"); | ||
1390 | level.Add("description", "some level"); | ||
1391 | levels.Add(level); | ||
1392 | //membershiplevels.Add("levels",levels); | ||
1393 | |||
1394 | Hashtable landuse = new Hashtable(); | ||
1395 | landuse.Add("upgrade", false); | ||
1396 | landuse.Add("action", "http://invaliddomaininvalid.com/"); | ||
1397 | |||
1398 | Hashtable currency = new Hashtable(); | ||
1399 | currency.Add("estimatedCost", 0); | ||
1400 | |||
1401 | Hashtable membership = new Hashtable(); | ||
1402 | membershiplevels.Add("upgrade", false); | ||
1403 | membershiplevels.Add("action", "http://invaliddomaininvalid.com/"); | ||
1404 | membershiplevels.Add("levels", membershiplevels); | ||
1405 | |||
1406 | retparam.Add("success", true); | ||
1407 | retparam.Add("currency", currency); | ||
1408 | retparam.Add("membership", membership); | ||
1409 | retparam.Add("landuse", landuse); | ||
1410 | retparam.Add("confirm", "asdfajsdkfjasdkfjalsdfjasdf"); | ||
1411 | |||
1412 | ret.Value = retparam; | ||
1413 | |||
1414 | return ret; | ||
1415 | |||
1416 | } | ||
1417 | public XmlRpcResponse landBuy_func(XmlRpcRequest request) | ||
1418 | { | ||
1419 | XmlRpcResponse ret = new XmlRpcResponse(); | ||
1420 | Hashtable retparam = new Hashtable(); | ||
1421 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
1422 | |||
1423 | LLUUID agentId = LLUUID.Zero; | ||
1424 | int amount = 0; | ||
1425 | if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy")) | ||
1426 | { | ||
1427 | Helpers.TryParse((string)requestData["agentId"], out agentId); | ||
1428 | try | ||
1429 | { | ||
1430 | amount = (Int32)requestData["currencyBuy"]; | ||
1431 | } | ||
1432 | catch (InvalidCastException) | ||
1433 | { | ||
1434 | |||
1435 | } | ||
1436 | if (agentId != LLUUID.Zero) | ||
1437 | { | ||
1438 | lock (m_KnownClientFunds) | ||
1439 | { | ||
1440 | if (m_KnownClientFunds.ContainsKey(agentId)) | ||
1441 | { | ||
1442 | m_KnownClientFunds[agentId] += amount; | ||
1443 | } | ||
1444 | else | ||
1445 | { | ||
1446 | m_KnownClientFunds.Add(agentId, amount); | ||
1447 | } | ||
1448 | } | ||
1449 | IClientAPI client = LocateClientObject(agentId); | ||
1450 | if (client != null) | ||
1451 | { | ||
1452 | SendMoneyBalance(client, agentId, client.SessionId, LLUUID.Zero); | ||
1453 | } | ||
1454 | } | ||
1455 | } | ||
1456 | retparam.Add("success", true); | ||
1457 | ret.Value = retparam; | ||
1458 | |||
1459 | return ret; | ||
1460 | |||
1461 | } | ||
1462 | #endregion | ||
1463 | |||
1464 | public void PostInitialise() | ||
1465 | { | ||
1466 | } | ||
1467 | |||
1468 | public void Close() | ||
1469 | { | ||
1470 | } | ||
1471 | |||
1472 | public string Name | ||
1473 | { | ||
1474 | get { return "BetaGridLikeMoneyModule"; } | ||
1475 | } | ||
1476 | |||
1477 | public bool IsSharedModule | ||
1478 | { | ||
1479 | get { return true; } | ||
1480 | } | ||
1481 | } | ||
1482 | |||
1483 | public enum TransactionType : int | ||
1484 | { | ||
1485 | SystemGenerated=0, | ||
1486 | RegionMoneyRequest=1, | ||
1487 | Gift=2, | ||
1488 | Purchase=3 | ||
1489 | |||
1490 | } | ||
1491 | } \ No newline at end of file | ||