aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/Avatar/Currency
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment/Modules/Avatar/Currency')
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs1491
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
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Net;
32using System.Net.Sockets;
33using System.Reflection;
34using System.Xml;
35using libsecondlife;
36using log4net;
37using Nini.Config;
38using Nwc.XmlRpc;
39using OpenSim.Framework;
40using OpenSim.Region.Environment.Interfaces;
41using OpenSim.Region.Environment.Scenes;
42
43namespace 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