opensim-development – Blame information for rev 1

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