From 1909d74d5fa8e6cea151bb5ff6b8e40b197b9f90 Mon Sep 17 00:00:00 2001 From: Teravus Ovares Date: Wed, 23 Apr 2008 22:44:59 +0000 Subject: * Patch from Melanie. Mantis 0001037: Add various internal plumbing to the example economy module, implements llSetPayPrice(), money() and llGiveMoney() in scripts. Thanks Melanie! * Moves module loading before the script engine so the script engine can pick up events from modules registering interfaces with scene. --- OpenSim/Region/Application/OpenSimMain.cs | 5 +- OpenSim/Region/ClientStack/ClientView.cs | 36 ++++++ .../Environment/Modules/BetaGridLikeMoneyModule.cs | 121 ++++++++++++++++++++- .../Region/Environment/Scenes/SceneObjectPart.cs | 3 + .../Region/Examples/SimpleModule/MyNpcCharacter.cs | 5 + .../ScriptEngine/Common/LSL_BuiltIn_Commands.cs | 49 ++++++++- .../Common/ScriptEngineBase/EventManager.cs | 28 ++++- .../ScriptEngine/Common/ScriptServerInterfaces.cs | 2 +- 8 files changed, 238 insertions(+), 11 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Application/OpenSimMain.cs b/OpenSim/Region/Application/OpenSimMain.cs index e3e0b4a..b0ca496 100644 --- a/OpenSim/Region/Application/OpenSimMain.cs +++ b/OpenSim/Region/Application/OpenSimMain.cs @@ -522,6 +522,10 @@ namespace OpenSim m_log.Info("[MODULES]: Loading Region's modules"); List modules = m_moduleLoader.PickupModules(scene, "."); + // This needs to be ahead of the script engine load, so the + // script module can pick up events exposed by a module + m_moduleLoader.InitialiseSharedModules(scene); + //m_moduleLoader.PickupModules(scene, "ScriptEngines"); //m_moduleLoader.LoadRegionModules(Path.Combine("ScriptEngines", m_scriptEngine), scene); @@ -547,7 +551,6 @@ namespace OpenSim } } - m_moduleLoader.InitialiseSharedModules(scene); scene.SetModuleInterfaces(); //moved these here as the terrain texture has to be created after the modules are initialized diff --git a/OpenSim/Region/ClientStack/ClientView.cs b/OpenSim/Region/ClientStack/ClientView.cs index 9e8830f..216633f 100644 --- a/OpenSim/Region/ClientStack/ClientView.cs +++ b/OpenSim/Region/ClientStack/ClientView.cs @@ -234,6 +234,7 @@ namespace OpenSim.Region.ClientStack private UUIDNameRequest handlerTeleportHomeRequest = null; private ScriptAnswer handlerScriptAnswer = null; + private RequestPayPrice handlerRequestPayPrice = null; /* Properties */ @@ -791,6 +792,7 @@ namespace OpenSim.Region.ClientStack public event UUIDNameRequest OnTeleportHomeRequest; public event ScriptAnswer OnScriptAnswer; + public event RequestPayPrice OnRequestPayPrice; #region Scene/Avatar to Client @@ -1167,6 +1169,32 @@ namespace OpenSim.Region.ClientStack OutPacket(money, ThrottleOutPacketType.Task); } + public void SendPayPrice(LLUUID objectID, int[] payPrice) + { + if(payPrice[0] == 0 && + payPrice[1] == 0 && + payPrice[2] == 0 && + payPrice[3] == 0 && + payPrice[4] == 0) + return; + + PayPriceReplyPacket payPriceReply = (PayPriceReplyPacket)PacketPool.Instance.GetPacket(PacketType.PayPriceReply); + payPriceReply.ObjectData.ObjectID = objectID; + payPriceReply.ObjectData.DefaultPayPrice = payPrice[0]; + + payPriceReply.ButtonData=new PayPriceReplyPacket.ButtonDataBlock[4]; + payPriceReply.ButtonData[0]=new PayPriceReplyPacket.ButtonDataBlock(); + payPriceReply.ButtonData[0].PayButton = payPrice[1]; + payPriceReply.ButtonData[1]=new PayPriceReplyPacket.ButtonDataBlock(); + payPriceReply.ButtonData[1].PayButton = payPrice[2]; + payPriceReply.ButtonData[2]=new PayPriceReplyPacket.ButtonDataBlock(); + payPriceReply.ButtonData[2].PayButton = payPrice[3]; + payPriceReply.ButtonData[3]=new PayPriceReplyPacket.ButtonDataBlock(); + payPriceReply.ButtonData[3].PayButton = payPrice[4]; + + OutPacket(payPriceReply, ThrottleOutPacketType.Task); + } + public void SendStartPingCheck(byte seq) { StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck); @@ -4555,6 +4583,14 @@ namespace OpenSim.Region.ClientStack // TODO: handle this packet //m_log.Warn("[CLIENT]: unhandled EconomyDataRequest packet"); break; + case PacketType.RequestPayPrice: + RequestPayPricePacket requestPayPricePacket = (RequestPayPricePacket)Pack; + handlerRequestPayPrice = OnRequestPayPrice; + if (handlerRequestPayPrice != null) + { + handlerRequestPayPrice(this, requestPayPricePacket.ObjectData.ObjectID); + } + break; #endregion diff --git a/OpenSim/Region/Environment/Modules/BetaGridLikeMoneyModule.cs b/OpenSim/Region/Environment/Modules/BetaGridLikeMoneyModule.cs index d5b2ea2..8e14ec5 100644 --- a/OpenSim/Region/Environment/Modules/BetaGridLikeMoneyModule.cs +++ b/OpenSim/Region/Environment/Modules/BetaGridLikeMoneyModule.cs @@ -53,8 +53,22 @@ namespace OpenSim.Region.Environment.Modules /// Centralized grid structure example using OpenSimWi Redux revision 9+ /// svn co https://opensimwiredux.svn.sourceforge.net/svnroot/opensimwiredux /// - public class BetaGridLikeMoneyModule: IRegionModule + + public delegate void ObjectPaid(LLUUID objectID, LLUUID agentID, int amount); + + public interface IMoneyModule : IRegionModule + { + bool ObjectGiveMoney(LLUUID objectID, LLUUID fromID, LLUUID toID, int amount); + + event ObjectPaid OnObjectPaid; + } + + public class BetaGridLikeMoneyModule: IMoneyModule { + public event ObjectPaid OnObjectPaid; + + private ObjectPaid handerOnObjectPaid; + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); /// @@ -120,7 +134,7 @@ namespace OpenSim.Region.Environment.Modules IConfig startupConfig = m_gConfig.Configs["Startup"]; IConfig economyConfig = m_gConfig.Configs["Economy"]; - + scene.RegisterModuleInterface(this); ReadConfigAndPopulate(scene, startupConfig, "Startup"); ReadConfigAndPopulate(scene, economyConfig, "Economy"); @@ -298,6 +312,7 @@ namespace OpenSim.Region.Environment.Modules // Subscribe to Money messages client.OnEconomyDataRequest += EconomyDataRequestHandler; client.OnMoneyBalanceRequest += SendMoneyBalance; + client.OnRequestPayPrice += requestPayPrice; client.OnLogout += ClientClosed; @@ -305,6 +320,21 @@ namespace OpenSim.Region.Environment.Modules #region event Handlers + public void requestPayPrice(IClientAPI client, LLUUID objectID) + { + Scene scene=LocateSceneClientIn(client.AgentId); + if(scene == null) + return; + + SceneObjectPart task=scene.GetSceneObjectPart(objectID); + if(task == null) + return; + SceneObjectGroup group=task.ParentGroup; + SceneObjectPart root=group.RootPart; + + client.SendPayPrice(objectID, root.PayPrice); + } + /// /// When the client closes the connection we remove their accounting info from memory to free up resources. /// @@ -400,6 +430,48 @@ namespace OpenSim.Region.Environment.Modules IClientAPI sender = null; IClientAPI receiver = null; + if(m_MoneyAddress.Length > 0) // Handled on server + e.description=String.Empty; + + if(e.transactiontype == 5008) // Object gets paid + { + sender = LocateClientObject(e.sender); + if (sender != null) + { + SceneObjectPart part=findPrim(e.receiver); + if(part == null) + return; + + string name=resolveAgentName(part.OwnerID); + if(name == String.Empty) + name="(hippos)"; + + receiver = LocateClientObject(part.OwnerID); + + string description=String.Format("Paid {0} via object {1}", name, e.description); + bool transactionresult = doMoneyTransfer(e.sender, part.OwnerID, e.amount, e.transactiontype, description); + + if(transactionresult) + { + ObjectPaid handlerOnObjectPaid = OnObjectPaid; + if(handlerOnObjectPaid != null) + { + handlerOnObjectPaid(e.receiver, e.sender, e.amount); + } + } + + if (e.sender != e.receiver) + { + sender.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(e.sender)); + } + if(receiver != null) + { + receiver.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(part.OwnerID)); + } + } + return; + } + sender = LocateClientObject(e.sender); if (sender != null) { @@ -923,6 +995,51 @@ namespace OpenSim.Region.Environment.Modules return MoneyRespData; } + private SceneObjectPart findPrim(LLUUID objectID) + { + lock (m_scenel) + { + foreach (Scene s in m_scenel.Values) + { + SceneObjectPart part=s.GetSceneObjectPart(objectID); + if(part != null) + { + return part; + } + } + } + return null; + } + + private string resolveObjectName(LLUUID objectID) + { + SceneObjectPart part=findPrim(objectID); + if(part != null) + { + return part.Name; + } + return String.Empty; + } + + private string resolveAgentName(LLUUID agentID) + { + // try avatar username surname + Scene scene=GetRandomScene(); + UserProfileData profile = scene.CommsManager.UserService.GetUserProfile(agentID); + if (profile != null) + { + string avatarname = profile.FirstName + " " + profile.SurName; + return avatarname; + } + return String.Empty; + } + + public bool ObjectGiveMoney(LLUUID objectID, LLUUID fromID, LLUUID toID, int amount) + { + string description=String.Format("Object {0} pays {1}", resolveObjectName(objectID), resolveAgentName(toID)); + return doMoneyTransfer(fromID, toID, amount, 2, description); + } + /// /// Informs the Money Grid Server of a transfer. /// diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs index 9277954..ba851fc 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs @@ -96,6 +96,8 @@ namespace OpenSim.Region.Environment.Scenes public int SalePrice; public uint Category; + // TODO: This needs to be persisted in next XML version update! + [XmlIgnore] public int[] PayPrice = {0,0,0,0,0}; public Int32 CreationDate; public uint ParentID = 0; @@ -2456,6 +2458,7 @@ namespace OpenSim.Region.Environment.Scenes info.AddValue("m_clickAction", m_clickAction); info.AddValue("m_shape", m_shape); info.AddValue("m_parentGroup", m_parentGroup); + info.AddValue("PayPrice", PayPrice); } } diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index 4f9024c..c4409bc 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -167,6 +167,7 @@ namespace OpenSim.Region.Examples.SimpleModule public event UUIDNameRequest OnTeleportHomeRequest; public event ScriptAnswer OnScriptAnswer; + public event RequestPayPrice OnRequestPayPrice; #pragma warning restore 67 @@ -342,6 +343,10 @@ namespace OpenSim.Region.Examples.SimpleModule { } + public virtual void SendPayPrice(LLUUID objectID, int[] payPrice) + { + } + public virtual void SendAvatarData(ulong regionHandle, string firstName, string lastName, LLUUID avatarID, uint avatarLocalID, LLVector3 Pos, byte[] textureEntry, uint parentID) { diff --git a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs index 09cd4af..2d1b02d 100644 --- a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs +++ b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs @@ -36,6 +36,7 @@ using libsecondlife; using OpenSim.Framework; using OpenSim.Region.Environment; using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Modules; using OpenSim.Region.Environment.Modules.LandManagement; using OpenSim.Region.Environment.Scenes; using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; @@ -1609,8 +1610,42 @@ namespace OpenSim.Region.ScriptEngine.Common public int llGiveMoney(string destination, int amount) { + LLUUID invItemID=InventorySelf(); + if(invItemID == LLUUID.Zero) + return 0; + m_host.AddScriptLPS(1); - NotImplemented("llGiveMoney"); + + if(m_host.TaskInventory[invItemID].PermsGranter == LLUUID.Zero) + return 0; + + if((m_host.TaskInventory[invItemID].PermsMask & BuiltIn_Commands_BaseClass.PERMISSION_DEBIT) == 0) + { + LSLError("No permissions to give money"); + return 0; + } + + LLUUID toID=new LLUUID(); + + if(!LLUUID.TryParse(destination, out toID)) + { + LSLError("Bad key in llGiveMoney"); + return 0; + } + + IMoneyModule money=World.RequestModuleInterface(); + + if(money == null) + { + NotImplemented("llGiveMoney"); + return 0; + } + + bool result=money.ObjectGiveMoney(m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); + + if(result) + return 1; + return 0; } @@ -5101,7 +5136,17 @@ namespace OpenSim.Region.ScriptEngine.Common public void llSetPayPrice(int price, LSL_Types.list quick_pay_buttons) { m_host.AddScriptLPS(1); - NotImplemented("llSetPayPrice"); + + if(quick_pay_buttons.Data.Length != 4) + { + LSLError("List must have 4 elements"); + return; + } + m_host.ParentGroup.RootPart.PayPrice[0]=price; + m_host.ParentGroup.RootPart.PayPrice[1]=(int)quick_pay_buttons.Data[0]; + m_host.ParentGroup.RootPart.PayPrice[2]=(int)quick_pay_buttons.Data[1]; + m_host.ParentGroup.RootPart.PayPrice[3]=(int)quick_pay_buttons.Data[2]; + m_host.ParentGroup.RootPart.PayPrice[4]=(int)quick_pay_buttons.Data[3]; } public LSL_Types.Vector3 llGetCameraPos() diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs index b4789a9..c2e3209 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs @@ -28,6 +28,9 @@ using System; using libsecondlife; using OpenSim.Framework; +using OpenSim.Region.Environment; +using OpenSim.Region.Environment.Modules; +using OpenSim.Region.Environment.Scenes; namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase { @@ -68,6 +71,12 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase myScriptEngine.World.EventManager.OnRemoveScript += OnRemoveScript; myScriptEngine.World.EventManager.OnScriptChangedEvent += changed; // TODO: HOOK ALL EVENTS UP TO SERVER! + IMoneyModule money=myScriptEngine.World.RequestModuleInterface(); + if(money != null) + { + money.OnObjectPaid+=HandleObjectPaid; + } + } } @@ -75,6 +84,15 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase { } + private void HandleObjectPaid(LLUUID objectID, LLUUID agentID, int amount) + { + SceneObjectPart part=myScriptEngine.World.GetSceneObjectPart(objectID); + if(part != null) + { + money(part.LocalId, agentID, amount); + } + } + public void changed(uint localID, uint change) { // Add to queue for all scripts in localID, Object pass change. @@ -112,6 +130,11 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase ); } + public void money(uint localID, LLUUID agentID, int amount) + { + myScriptEngine.m_EventQueueManager.AddToObjectQueue(localID, "money", EventQueueManager.llDetectNull, new object[] { agentID.ToString(), (int)amount }); + } + // TODO: Replace placeholders below // NOTE! THE PARAMETERS FOR THESE FUNCTIONS ARE NOT CORRECT! // These needs to be hooked up to OpenSim during init of this class @@ -194,11 +217,6 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "control", EventQueueManager.llDetectNull); } - public void money(uint localID, LLUUID itemID) - { - myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "money", EventQueueManager.llDetectNull); - } - public void email(uint localID, LLUUID itemID) { myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "email", EventQueueManager.llDetectNull); diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptServerInterfaces.cs b/OpenSim/Region/ScriptEngine/Common/ScriptServerInterfaces.cs index 1119fe8..ea17e20 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptServerInterfaces.cs +++ b/OpenSim/Region/ScriptEngine/Common/ScriptServerInterfaces.cs @@ -55,7 +55,7 @@ namespace OpenSim.Region.ScriptEngine.Common void sensor(uint localID, LLUUID itemID); void no_sensor(uint localID, LLUUID itemID); void control(uint localID, LLUUID itemID); - void money(uint localID, LLUUID itemID); + void money(uint LocalID, LLUUID agentID, int amount); void email(uint localID, LLUUID itemID); void at_target(uint localID, LLUUID itemID); void not_at_target(uint localID, LLUUID itemID); -- cgit v1.1