clockwerk-opensim – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 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 OpenSimulator 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.Reflection;
33 using log4net;
34 using Nini.Config;
35 using Nwc.XmlRpc;
36 using Mono.Addins;
37 using OpenMetaverse;
38 using OpenSim.Framework;
39 using OpenSim.Framework.Servers;
40 using OpenSim.Framework.Servers.HttpServer;
41 using OpenSim.Region.Framework.Interfaces;
42 using OpenSim.Region.Framework.Scenes;
43 using OpenSim.Services.Interfaces;
44  
45 namespace OpenSim.Region.OptionalModules.World.MoneyModule
46 {
47 /// <summary>
48 /// This is only the functionality required to make the functionality associated with money work
49 /// (such as land transfers). There is no money code here! Use FORGE as an example for money code.
50 /// Demo Economy/Money Module. This is a purposely crippled module!
51 /// // To land transfer you need to add:
52 /// -helperuri http://serveraddress:port/
53 /// to the command line parameters you use to start up your client
54 /// This commonly looks like -helperuri http://127.0.0.1:9000/
55 ///
56 /// </summary>
57  
58 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SampleMoneyModule")]
59 public class SampleMoneyModule : IMoneyModule, ISharedRegionModule
60 {
61 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
62  
63 /// <summary>
64 /// Where Stipends come from and Fees go to.
65 /// </summary>
66 // private UUID EconomyBaseAccount = UUID.Zero;
67  
68 private float EnergyEfficiency = 0f;
69 // private ObjectPaid handerOnObjectPaid;
70 private bool m_enabled = true;
71 private bool m_sellEnabled = false;
72  
73 private IConfigSource m_gConfig;
74  
75 /// <summary>
76 /// Region UUIDS indexed by AgentID
77 /// </summary>
78  
79 /// <summary>
80 /// Scenes by Region Handle
81 /// </summary>
82 private Dictionary<ulong, Scene> m_scenel = new Dictionary<ulong, Scene>();
83  
84 // private int m_stipend = 1000;
85  
86 private int ObjectCount = 0;
87 private int PriceEnergyUnit = 0;
88 private int PriceGroupCreate = 0;
89 private int PriceObjectClaim = 0;
90 private float PriceObjectRent = 0f;
91 private float PriceObjectScaleFactor = 0f;
92 private int PriceParcelClaim = 0;
93 private float PriceParcelClaimFactor = 0f;
94 private int PriceParcelRent = 0;
95 private int PricePublicObjectDecay = 0;
96 private int PricePublicObjectDelete = 0;
97 private int PriceRentLight = 0;
98 private int PriceUpload = 0;
99 private int TeleportMinPrice = 0;
100  
101 private float TeleportPriceExponent = 0f;
102  
103  
104 #region IMoneyModule Members
105  
106 #pragma warning disable 0067
107 public event ObjectPaid OnObjectPaid;
108 #pragma warning restore 0067
109  
110 public int UploadCharge
111 {
112 get { return 0; }
113 }
114  
115 public int GroupCreationCharge
116 {
117 get { return 0; }
118 }
119  
120 /// <summary>
121 /// Called on startup so the module can be configured.
122 /// </summary>
123 /// <param name="config">Configuration source.</param>
124 public void Initialise(IConfigSource config)
125 {
126 m_gConfig = config;
127  
128 IConfig startupConfig = m_gConfig.Configs["Startup"];
129 IConfig economyConfig = m_gConfig.Configs["Economy"];
130  
131  
132 ReadConfigAndPopulate(startupConfig, "Startup");
133 ReadConfigAndPopulate(economyConfig, "Economy");
134 }
135  
136 public void AddRegion(Scene scene)
137 {
138 if (m_enabled)
139 {
140 scene.RegisterModuleInterface<IMoneyModule>(this);
141 IHttpServer httpServer = MainServer.Instance;
142  
143 lock (m_scenel)
144 {
145 if (m_scenel.Count == 0)
146 {
147 // XMLRPCHandler = scene;
148  
149 // To use the following you need to add:
150 // -helperuri <ADDRESS TO HERE OR grid MONEY SERVER>
151 // to the command line parameters you use to start up your client
152 // This commonly looks like -helperuri http://127.0.0.1:9000/
153  
154  
155 // Local Server.. enables functionality only.
156 httpServer.AddXmlRPCHandler("getCurrencyQuote", quote_func);
157 httpServer.AddXmlRPCHandler("buyCurrency", buy_func);
158 httpServer.AddXmlRPCHandler("preflightBuyLandPrep", preflightBuyLandPrep_func);
159 httpServer.AddXmlRPCHandler("buyLandPrep", landBuy_func);
160  
161 }
162  
163 if (m_scenel.ContainsKey(scene.RegionInfo.RegionHandle))
164 {
165 m_scenel[scene.RegionInfo.RegionHandle] = scene;
166 }
167 else
168 {
169 m_scenel.Add(scene.RegionInfo.RegionHandle, scene);
170 }
171 }
172  
173 scene.EventManager.OnNewClient += OnNewClient;
174 scene.EventManager.OnMoneyTransfer += MoneyTransferAction;
175 scene.EventManager.OnClientClosed += ClientClosed;
176 scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel;
177 scene.EventManager.OnMakeChildAgent += MakeChildAgent;
178 scene.EventManager.OnClientClosed += ClientLoggedOut;
179 scene.EventManager.OnValidateLandBuy += ValidateLandBuy;
180 scene.EventManager.OnLandBuy += processLandBuy;
181 }
182 }
183  
184 public void RemoveRegion(Scene scene)
185 {
186 }
187  
188 public void RegionLoaded(Scene scene)
189 {
190 }
191  
192  
193 // Please do not refactor these to be just one method
194 // Existing implementations need the distinction
195 //
196 public void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type, string extraData)
197 {
198 }
199  
200 public void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type)
201 {
202 }
203  
204 public void ApplyUploadCharge(UUID agentID, int amount, string text)
205 {
206 }
207  
208 public bool ObjectGiveMoney(UUID objectID, UUID fromID, UUID toID, int amount)
209 {
210 string description = String.Format("Object {0} pays {1}", resolveObjectName(objectID), resolveAgentName(toID));
211  
212 bool give_result = doMoneyTransfer(fromID, toID, amount, 2, description);
213  
214  
215 BalanceUpdate(fromID, toID, give_result, description);
216  
217 return give_result;
218 }
219  
220 public void PostInitialise()
221 {
222 }
223  
224 public void Close()
225 {
226 }
227  
228 public Type ReplaceableInterface
229 {
230 get { return typeof(IMoneyModule); }
231 }
232  
233 public string Name
234 {
235 get { return "BetaGridLikeMoneyModule"; }
236 }
237  
238 #endregion
239  
240 /// <summary>
241 /// Parse Configuration
242 /// </summary>
243 /// <param name="scene"></param>
244 /// <param name="startupConfig"></param>
245 /// <param name="config"></param>
246 private void ReadConfigAndPopulate(IConfig startupConfig, string config)
247 {
248 if (config == "Startup" && startupConfig != null)
249 {
250 m_enabled = (startupConfig.GetString("economymodule", "BetaGridLikeMoneyModule") == "BetaGridLikeMoneyModule");
251 }
252  
253 if (config == "Economy" && startupConfig != null)
254 {
255 PriceEnergyUnit = startupConfig.GetInt("PriceEnergyUnit", 100);
256 PriceObjectClaim = startupConfig.GetInt("PriceObjectClaim", 10);
257 PricePublicObjectDecay = startupConfig.GetInt("PricePublicObjectDecay", 4);
258 PricePublicObjectDelete = startupConfig.GetInt("PricePublicObjectDelete", 4);
259 PriceParcelClaim = startupConfig.GetInt("PriceParcelClaim", 1);
260 PriceParcelClaimFactor = startupConfig.GetFloat("PriceParcelClaimFactor", 1f);
261 PriceUpload = startupConfig.GetInt("PriceUpload", 0);
262 PriceRentLight = startupConfig.GetInt("PriceRentLight", 5);
263 TeleportMinPrice = startupConfig.GetInt("TeleportMinPrice", 2);
264 TeleportPriceExponent = startupConfig.GetFloat("TeleportPriceExponent", 2f);
265 EnergyEfficiency = startupConfig.GetFloat("EnergyEfficiency", 1);
266 PriceObjectRent = startupConfig.GetFloat("PriceObjectRent", 1);
267 PriceObjectScaleFactor = startupConfig.GetFloat("PriceObjectScaleFactor", 10);
268 PriceParcelRent = startupConfig.GetInt("PriceParcelRent", 1);
269 PriceGroupCreate = startupConfig.GetInt("PriceGroupCreate", -1);
270 m_sellEnabled = startupConfig.GetBoolean("SellEnabled", false);
271 }
272 }
273  
274 private void GetClientFunds(IClientAPI client)
275 {
276 CheckExistAndRefreshFunds(client.AgentId);
277 }
278  
279 /// <summary>
280 /// New Client Event Handler
281 /// </summary>
282 /// <param name="client"></param>
283 private void OnNewClient(IClientAPI client)
284 {
285 GetClientFunds(client);
286  
287 // Subscribe to Money messages
288 client.OnEconomyDataRequest += EconomyDataRequestHandler;
289 client.OnMoneyBalanceRequest += SendMoneyBalance;
290 client.OnRequestPayPrice += requestPayPrice;
291 client.OnObjectBuy += ObjectBuy;
292 client.OnLogout += ClientClosed;
293 }
294  
295 /// <summary>
296 /// Transfer money
297 /// </summary>
298 /// <param name="Sender"></param>
299 /// <param name="Receiver"></param>
300 /// <param name="amount"></param>
301 /// <returns></returns>
302 private bool doMoneyTransfer(UUID Sender, UUID Receiver, int amount, int transactiontype, string description)
303 {
304 bool result = true;
305  
306 return result;
307 }
308  
309  
310 /// <summary>
311 /// Sends the the stored money balance to the client
312 /// </summary>
313 /// <param name="client"></param>
314 /// <param name="agentID"></param>
315 /// <param name="SessionID"></param>
316 /// <param name="TransactionID"></param>
317 public void SendMoneyBalance(IClientAPI client, UUID agentID, UUID SessionID, UUID TransactionID)
318 {
319 if (client.AgentId == agentID && client.SessionId == SessionID)
320 {
321 int returnfunds = 0;
322  
323 try
324 {
325 returnfunds = GetFundsForAgentID(agentID);
326 }
327 catch (Exception e)
328 {
329 client.SendAlertMessage(e.Message + " ");
330 }
331  
332 client.SendMoneyBalance(TransactionID, true, new byte[0], returnfunds, 0, UUID.Zero, false, UUID.Zero, false, 0, String.Empty);
333 }
334 else
335 {
336 client.SendAlertMessage("Unable to send your money balance to you!");
337 }
338 }
339  
340 private SceneObjectPart findPrim(UUID objectID)
341 {
342 lock (m_scenel)
343 {
344 foreach (Scene s in m_scenel.Values)
345 {
346 SceneObjectPart part = s.GetSceneObjectPart(objectID);
347 if (part != null)
348 {
349 return part;
350 }
351 }
352 }
353 return null;
354 }
355  
356 private string resolveObjectName(UUID objectID)
357 {
358 SceneObjectPart part = findPrim(objectID);
359 if (part != null)
360 {
361 return part.Name;
362 }
363 return String.Empty;
364 }
365  
366 private string resolveAgentName(UUID agentID)
367 {
368 // try avatar username surname
369 Scene scene = GetRandomScene();
370 UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, agentID);
371 if (account != null)
372 {
373 string avatarname = account.FirstName + " " + account.LastName;
374 return avatarname;
375 }
376 else
377 {
378 m_log.ErrorFormat(
379 "[MONEY]: Could not resolve user {0}",
380 agentID);
381 }
382  
383 return String.Empty;
384 }
385  
386 private void BalanceUpdate(UUID senderID, UUID receiverID, bool transactionresult, string description)
387 {
388 IClientAPI sender = LocateClientObject(senderID);
389 IClientAPI receiver = LocateClientObject(receiverID);
390  
391 if (senderID != receiverID)
392 {
393 if (sender != null)
394 {
395 sender.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(description), GetFundsForAgentID(senderID), 0, UUID.Zero, false, UUID.Zero, false, 0, String.Empty);
396 }
397  
398 if (receiver != null)
399 {
400 receiver.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(description), GetFundsForAgentID(receiverID), 0, UUID.Zero, false, UUID.Zero, false, 0, String.Empty);
401 }
402 }
403 }
404  
405 /// <summary>
406 /// XMLRPC handler to send alert message and sound to client
407 /// </summary>
408 public XmlRpcResponse UserAlert(XmlRpcRequest request, IPEndPoint remoteClient)
409 {
410 XmlRpcResponse ret = new XmlRpcResponse();
411 Hashtable retparam = new Hashtable();
412 Hashtable requestData = (Hashtable) request.Params[0];
413  
414 UUID agentId;
415 UUID soundId;
416 UUID regionId;
417  
418 UUID.TryParse((string) requestData["agentId"], out agentId);
419 UUID.TryParse((string) requestData["soundId"], out soundId);
420 UUID.TryParse((string) requestData["regionId"], out regionId);
421 string text = (string) requestData["text"];
422 string secret = (string) requestData["secret"];
423  
424 Scene userScene = GetSceneByUUID(regionId);
425 if (userScene != null)
426 {
427 if (userScene.RegionInfo.regionSecret == secret)
428 {
429  
430 IClientAPI client = LocateClientObject(agentId);
431 if (client != null)
432 {
433  
434 if (soundId != UUID.Zero)
435 client.SendPlayAttachedSound(soundId, UUID.Zero, UUID.Zero, 1.0f, 0);
436  
437 client.SendBlueBoxMessage(UUID.Zero, "", text);
438  
439 retparam.Add("success", true);
440 }
441 else
442 {
443 retparam.Add("success", false);
444 }
445 }
446 else
447 {
448 retparam.Add("success", false);
449 }
450 }
451  
452 ret.Value = retparam;
453 return ret;
454 }
455  
456 # region Standalone box enablers only
457  
458 public XmlRpcResponse quote_func(XmlRpcRequest request, IPEndPoint remoteClient)
459 {
460 // Hashtable requestData = (Hashtable) request.Params[0];
461 // UUID agentId = UUID.Zero;
462 int amount = 0;
463 Hashtable quoteResponse = new Hashtable();
464 XmlRpcResponse returnval = new XmlRpcResponse();
465  
466  
467 Hashtable currencyResponse = new Hashtable();
468 currencyResponse.Add("estimatedCost", 0);
469 currencyResponse.Add("currencyBuy", amount);
470  
471 quoteResponse.Add("success", true);
472 quoteResponse.Add("currency", currencyResponse);
473 quoteResponse.Add("confirm", "asdfad9fj39ma9fj");
474  
475 returnval.Value = quoteResponse;
476 return returnval;
477  
478  
479  
480 }
481  
482 public XmlRpcResponse buy_func(XmlRpcRequest request, IPEndPoint remoteClient)
483 {
484 // Hashtable requestData = (Hashtable) request.Params[0];
485 // UUID agentId = UUID.Zero;
486 // int amount = 0;
487  
488 XmlRpcResponse returnval = new XmlRpcResponse();
489 Hashtable returnresp = new Hashtable();
490 returnresp.Add("success", true);
491 returnval.Value = returnresp;
492 return returnval;
493 }
494  
495 public XmlRpcResponse preflightBuyLandPrep_func(XmlRpcRequest request, IPEndPoint remoteClient)
496 {
497 XmlRpcResponse ret = new XmlRpcResponse();
498 Hashtable retparam = new Hashtable();
499 Hashtable membershiplevels = new Hashtable();
500 ArrayList levels = new ArrayList();
501 Hashtable level = new Hashtable();
502 level.Add("id", "00000000-0000-0000-0000-000000000000");
503 level.Add("description", "some level");
504 levels.Add(level);
505 //membershiplevels.Add("levels",levels);
506  
507 Hashtable landuse = new Hashtable();
508 landuse.Add("upgrade", false);
509 landuse.Add("action", "http://invaliddomaininvalid.com/");
510  
511 Hashtable currency = new Hashtable();
512 currency.Add("estimatedCost", 0);
513  
514 Hashtable membership = new Hashtable();
515 membershiplevels.Add("upgrade", false);
516 membershiplevels.Add("action", "http://invaliddomaininvalid.com/");
517 membershiplevels.Add("levels", membershiplevels);
518  
519 retparam.Add("success", true);
520 retparam.Add("currency", currency);
521 retparam.Add("membership", membership);
522 retparam.Add("landuse", landuse);
523 retparam.Add("confirm", "asdfajsdkfjasdkfjalsdfjasdf");
524  
525 ret.Value = retparam;
526  
527 return ret;
528 }
529  
530 public XmlRpcResponse landBuy_func(XmlRpcRequest request, IPEndPoint remoteClient)
531 {
532 XmlRpcResponse ret = new XmlRpcResponse();
533 Hashtable retparam = new Hashtable();
534 // Hashtable requestData = (Hashtable) request.Params[0];
535  
536 // UUID agentId = UUID.Zero;
537 // int amount = 0;
538  
539 retparam.Add("success", true);
540 ret.Value = retparam;
541  
542 return ret;
543 }
544  
545 #endregion
546  
547 #region local Fund Management
548  
549 /// <summary>
550 /// Ensures that the agent accounting data is set up in this instance.
551 /// </summary>
552 /// <param name="agentID"></param>
553 private void CheckExistAndRefreshFunds(UUID agentID)
554 {
555  
556 }
557  
558 /// <summary>
559 /// Gets the amount of Funds for an agent
560 /// </summary>
561 /// <param name="AgentID"></param>
562 /// <returns></returns>
563 private int GetFundsForAgentID(UUID AgentID)
564 {
565 int returnfunds = 0;
566  
567 return returnfunds;
568 }
569  
570 // private void SetLocalFundsForAgentID(UUID AgentID, int amount)
571 // {
572  
573 // }
574  
575 #endregion
576  
577 #region Utility Helpers
578  
579 /// <summary>
580 /// Locates a IClientAPI for the client specified
581 /// </summary>
582 /// <param name="AgentID"></param>
583 /// <returns></returns>
584 private IClientAPI LocateClientObject(UUID AgentID)
585 {
586 ScenePresence tPresence = null;
587 IClientAPI rclient = null;
588  
589 lock (m_scenel)
590 {
591 foreach (Scene _scene in m_scenel.Values)
592 {
593 tPresence = _scene.GetScenePresence(AgentID);
594 if (tPresence != null)
595 {
596 if (!tPresence.IsChildAgent)
597 {
598 rclient = tPresence.ControllingClient;
599 }
600 }
601 if (rclient != null)
602 {
603 return rclient;
604 }
605 }
606 }
607 return null;
608 }
609  
610 private Scene LocateSceneClientIn(UUID AgentId)
611 {
612 lock (m_scenel)
613 {
614 foreach (Scene _scene in m_scenel.Values)
615 {
616 ScenePresence tPresence = _scene.GetScenePresence(AgentId);
617 if (tPresence != null)
618 {
619 if (!tPresence.IsChildAgent)
620 {
621 return _scene;
622 }
623 }
624 }
625 }
626 return null;
627 }
628  
629 /// <summary>
630 /// Utility function Gets a Random scene in the instance. For when which scene exactly you're doing something with doesn't matter
631 /// </summary>
632 /// <returns></returns>
633 public Scene GetRandomScene()
634 {
635 lock (m_scenel)
636 {
637 foreach (Scene rs in m_scenel.Values)
638 return rs;
639 }
640 return null;
641 }
642  
643 /// <summary>
644 /// Utility function to get a Scene by RegionID in a module
645 /// </summary>
646 /// <param name="RegionID"></param>
647 /// <returns></returns>
648 public Scene GetSceneByUUID(UUID RegionID)
649 {
650 lock (m_scenel)
651 {
652 foreach (Scene rs in m_scenel.Values)
653 {
654 if (rs.RegionInfo.originRegionID == RegionID)
655 {
656 return rs;
657 }
658 }
659 }
660 return null;
661 }
662  
663 #endregion
664  
665 #region event Handlers
666  
667 public void requestPayPrice(IClientAPI client, UUID objectID)
668 {
669 Scene scene = LocateSceneClientIn(client.AgentId);
670 if (scene == null)
671 return;
672  
673 SceneObjectPart task = scene.GetSceneObjectPart(objectID);
674 if (task == null)
675 return;
676 SceneObjectGroup group = task.ParentGroup;
677 SceneObjectPart root = group.RootPart;
678  
679 client.SendPayPrice(objectID, root.PayPrice);
680 }
681  
682 /// <summary>
683 /// When the client closes the connection we remove their accounting
684 /// info from memory to free up resources.
685 /// </summary>
686 /// <param name="AgentID">UUID of agent</param>
687 /// <param name="scene">Scene the agent was connected to.</param>
688 /// <see cref="OpenSim.Region.Framework.Scenes.EventManager.ClientClosed"/>
689 public void ClientClosed(UUID AgentID, Scene scene)
690 {
691  
692 }
693  
694 /// <summary>
695 /// Event called Economy Data Request handler.
696 /// </summary>
697 /// <param name="agentId"></param>
698 public void EconomyDataRequestHandler(IClientAPI user)
699 {
700 Scene s = (Scene)user.Scene;
701  
702 user.SendEconomyData(EnergyEfficiency, s.RegionInfo.ObjectCapacity, ObjectCount, PriceEnergyUnit, PriceGroupCreate,
703 PriceObjectClaim, PriceObjectRent, PriceObjectScaleFactor, PriceParcelClaim, PriceParcelClaimFactor,
704 PriceParcelRent, PricePublicObjectDecay, PricePublicObjectDelete, PriceRentLight, PriceUpload,
705 TeleportMinPrice, TeleportPriceExponent);
706 }
707  
708 private void ValidateLandBuy(Object osender, EventManager.LandBuyArgs e)
709 {
710  
711  
712 lock (e)
713 {
714 e.economyValidated = true;
715 }
716  
717  
718 }
719  
720 private void processLandBuy(Object osender, EventManager.LandBuyArgs e)
721 {
722  
723 }
724  
725 /// <summary>
726 /// THis method gets called when someone pays someone else as a gift.
727 /// </summary>
728 /// <param name="osender"></param>
729 /// <param name="e"></param>
730 private void MoneyTransferAction(Object osender, EventManager.MoneyTransferArgs e)
731 {
732  
733 }
734  
735 /// <summary>
736 /// Event Handler for when a root agent becomes a child agent
737 /// </summary>
738 /// <param name="avatar"></param>
739 private void MakeChildAgent(ScenePresence avatar)
740 {
741  
742 }
743  
744 /// <summary>
745 /// Event Handler for when the client logs out.
746 /// </summary>
747 /// <param name="AgentId"></param>
748 private void ClientLoggedOut(UUID AgentId, Scene scene)
749 {
750  
751 }
752  
753 /// <summary>
754 /// Call this when the client disconnects.
755 /// </summary>
756 /// <param name="client"></param>
757 public void ClientClosed(IClientAPI client)
758 {
759 ClientClosed(client.AgentId, null);
760 }
761  
762 /// <summary>
763 /// Event Handler for when an Avatar enters one of the parcels in the simulator.
764 /// </summary>
765 /// <param name="avatar"></param>
766 /// <param name="localLandID"></param>
767 /// <param name="regionID"></param>
768 private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID)
769 {
770  
771 //m_log.Info("[FRIEND]: " + avatar.Name + " status:" + (!avatar.IsChildAgent).ToString());
772 }
773  
774 public int GetBalance(UUID agentID)
775 {
776 return 0;
777 }
778  
779 // Please do not refactor these to be just one method
780 // Existing implementations need the distinction
781 //
782 public bool UploadCovered(UUID agentID, int amount)
783 {
784 return true;
785 }
786 public bool AmountCovered(UUID agentID, int amount)
787 {
788 return true;
789 }
790  
791 #endregion
792  
793 public void ObjectBuy(IClientAPI remoteClient, UUID agentID,
794 UUID sessionID, UUID groupID, UUID categoryID,
795 uint localID, byte saleType, int salePrice)
796 {
797 if (!m_sellEnabled)
798 {
799 remoteClient.SendBlueBoxMessage(UUID.Zero, "", "Buying is not implemented in this version");
800 return;
801 }
802  
803 if (salePrice != 0)
804 {
805 remoteClient.SendBlueBoxMessage(UUID.Zero, "", "Buying anything for a price other than zero is not implemented");
806 return;
807 }
808  
809 Scene s = LocateSceneClientIn(remoteClient.AgentId);
810  
811 // Implmenting base sale data checking here so the default OpenSimulator implementation isn't useless
812 // combined with other implementations. We're actually validating that the client is sending the data
813 // that it should. In theory, the client should already know what to send here because it'll see it when it
814 // gets the object data. If the data sent by the client doesn't match the object, the viewer probably has an
815 // old idea of what the object properties are. Viewer developer Hazim informed us that the base module
816 // didn't check the client sent data against the object do any. Since the base modules are the
817 // 'crowning glory' examples of good practice..
818  
819 // Validate that the object exists in the scene the user is in
820 SceneObjectPart part = s.GetSceneObjectPart(localID);
821 if (part == null)
822 {
823 remoteClient.SendAgentAlertMessage("Unable to buy now. The object was not found.", false);
824 return;
825 }
826  
827 // Validate that the client sent the price that the object is being sold for
828 if (part.SalePrice != salePrice)
829 {
830 remoteClient.SendAgentAlertMessage("Cannot buy at this price. Buy Failed. If you continue to get this relog.", false);
831 return;
832 }
833  
834 // Validate that the client sent the proper sale type the object has set
835 if (part.ObjectSaleType != saleType)
836 {
837 remoteClient.SendAgentAlertMessage("Cannot buy this way. Buy Failed. If you continue to get this relog.", false);
838 return;
839 }
840  
841 IBuySellModule module = s.RequestModuleInterface<IBuySellModule>();
842 if (module != null)
843 module.BuyObject(remoteClient, categoryID, localID, saleType, salePrice);
844 }
845 }
846  
847 public enum TransactionType : int
848 {
849 SystemGenerated = 0,
850 RegionMoneyRequest = 1,
851 Gift = 2,
852 Purchase = 3
853 }
854 }