diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 2ef05ae820..d2d736528d 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -403,6 +403,8 @@ namespace OpenSim.Framework public delegate void MoneyTransferRequest(LLUUID sourceID, LLUUID destID, int amount, int transactionType, string description); + // We keep all this information for fraud purposes in the future. + public delegate void MoneyBalanceRequest(IClientAPI remoteClient, LLUUID agentID, LLUUID sessionID, LLUUID TransactionID); public delegate void ObjectPermissions( IClientAPI remoteClinet, LLUUID AgentID, LLUUID SessionID, @@ -507,6 +509,8 @@ namespace OpenSim.Framework // Financial packets event MoneyTransferRequest OnMoneyTransferRequest; + event MoneyBalanceRequest OnMoneyBalanceRequest; + LLVector3 StartPos { get; set; } diff --git a/OpenSim/Region/ClientStack/ClientView.cs b/OpenSim/Region/ClientStack/ClientView.cs index e89b722951..5fdb9b3dc5 100644 --- a/OpenSim/Region/ClientStack/ClientView.cs +++ b/OpenSim/Region/ClientStack/ClientView.cs @@ -581,6 +581,8 @@ namespace OpenSim.Region.ClientStack public event MoneyTransferRequest OnMoneyTransferRequest; + public event MoneyBalanceRequest OnMoneyBalanceRequest; + #region Scene/Avatar to Client @@ -2067,15 +2069,23 @@ namespace OpenSim.Region.ClientStack private bool HandleMoneyTransferRequest(IClientAPI sender, Packet Pack) { MoneyTransferRequestPacket money = (MoneyTransferRequestPacket)Pack; - - if (OnMoneyTransferRequest != null) + // validate the agent owns the agentID and sessionID + if (money.MoneyData.SourceID == sender.AgentId && money.AgentData.AgentID == sender.AgentId && money.AgentData.SessionID == sender.SessionId) { - OnMoneyTransferRequest(money.MoneyData.SourceID, money.MoneyData.DestID, - money.MoneyData.Amount, money.MoneyData.TransactionType, - Util.FieldToString(money.MoneyData.Description)); - } - return true; + if (OnMoneyTransferRequest != null) + { + OnMoneyTransferRequest(money.MoneyData.SourceID, money.MoneyData.DestID, + money.MoneyData.Amount, money.MoneyData.TransactionType, + Util.FieldToString(money.MoneyData.Description)); + } + + return true; + } + else + { + return false; + } } private bool HandleViewerEffect(IClientAPI sender, Packet Pack) @@ -3434,7 +3444,13 @@ namespace OpenSim.Region.ClientStack #endregion case PacketType.MoneyBalanceRequest: - SendMoneyBalance(LLUUID.Zero, true, new byte[0], MoneyBalance); + MoneyBalanceRequestPacket moneybalancerequestpacket = (MoneyBalanceRequestPacket)Pack; + if (OnMoneyBalanceRequest != null) + { + OnMoneyBalanceRequest(this, moneybalancerequestpacket.AgentData.AgentID, moneybalancerequestpacket.AgentData.SessionID, moneybalancerequestpacket.MoneyData.TransactionID); + } + + break; case PacketType.UUIDNameRequest: UUIDNameRequestPacket incoming = (UUIDNameRequestPacket)Pack; diff --git a/OpenSim/Region/Environment/Modules/BetaGridLikeMoneyModule.cs b/OpenSim/Region/Environment/Modules/BetaGridLikeMoneyModule.cs new file mode 100644 index 0000000000..81478a1add --- /dev/null +++ b/OpenSim/Region/Environment/Modules/BetaGridLikeMoneyModule.cs @@ -0,0 +1,324 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using Nini.Config; +using System; +using System.Collections; +using System.Collections.Generic; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using libsecondlife; +using MoneyTransferArgs = OpenSim.Region.Environment.Scenes.EventManager.MoneyTransferArgs; + +namespace OpenSim.Region.Environment.Modules +{ + public class BetaGridLikeMoneyModule: IRegionModule + { + + private LogBase m_log; + + private Dictionary m_scenel = new Dictionary(); + + private IConfigSource m_gConfig; + + private bool m_keepMoneyAcrossLogins = true; + + private int m_minFundsBeforeRefresh = 100; + + private int m_stipend = 1000; + + private bool m_enabled = true; + + + + private Dictionary m_KnownClientFunds = new Dictionary(); + + + + private bool gridmode = false; + + public void Initialise(Scene scene, IConfigSource config) + { + m_log = MainLog.Instance; + + m_gConfig = config; + ReadConfigAndPopulate(); + + if (m_enabled) + { + lock (m_scenel) + { + + if (m_scenel.ContainsKey(scene.RegionInfo.RegionHandle)) + { + m_scenel[scene.RegionInfo.RegionHandle] = scene; + } + else + { + m_scenel.Add(scene.RegionInfo.RegionHandle, scene); + } + } + + scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnMoneyTransfer += MoneyTransferAction; + scene.EventManager.OnClientClosed += ClientClosed; + } + } + private void ReadConfigAndPopulate() + { + IConfig startupConfig = m_gConfig.Configs["Startup"]; + gridmode = startupConfig.GetBoolean("gridmode", false); + m_enabled = (startupConfig.GetString("moneymodule", "BetaGridLikeMoneyModule") == "BetaGridLikeMoneyModule"); + + } + + private void OnNewClient(IClientAPI client) + { + // Here we check if we're in grid mode + // I imagine that the 'check balance' + // function for the client should be here or shortly after + + if (gridmode) + { + CheckExistAndRefreshFunds(client.AgentId); + } + else + { + CheckExistAndRefreshFunds(client.AgentId); + } + + // Subscribe to Money messages + client.OnMoneyBalanceRequest += SendMoneyBalance; + client.OnLogout += ClientClosed; + + } + + public void ClientClosed(LLUUID AgentID) + { + lock (m_KnownClientFunds) + { + if (!m_keepMoneyAcrossLogins) + m_KnownClientFunds.Remove(AgentID); + } + + } + + private void MoneyTransferAction (Object osender, MoneyTransferArgs e) + { + IClientAPI sender = null; + IClientAPI receiver = null; + + sender = LocateClientObject(e.sender); + if (sender != null) + { + + + receiver = LocateClientObject(e.reciever); + bool transactionresult = doMoneyTranfer(e.sender, e.reciever, e.amount); + + if (e.sender != e.reciever) + { + if (sender != null) + { + 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(e.reciever)); + } + + + } + else + { + MainLog.Instance.Warn("MONEY", "Potential Fraud Warning, got money transfer request for avatar that isn't in this simulator - Details; Sender:" + e.sender.ToString() + " Reciver: " + e.reciever.ToString() + " Amount: " + e.amount.ToString()); + } + + + + } + + private bool doMoneyTranfer(LLUUID Sender, LLUUID Receiver, int amount) + { + bool result = false; + if (amount >= 0) + { + lock (m_KnownClientFunds) + { + // If we don't know about the sender, then the sender can't + // actually be here and therefore this is likely fraud or outdated. + if (m_KnownClientFunds.ContainsKey(Sender)) + { + // Does the sender have enough funds to give? + if (m_KnownClientFunds[Sender] >= amount) + { + // Subtract the funds from the senders account + m_KnownClientFunds[Sender] -= amount; + + // do we know about the receiver? + if (!m_KnownClientFunds.ContainsKey(Receiver)) + { + // Make a record for them so they get the updated balance when they login + CheckExistAndRefreshFunds(Receiver); + } + + //Add the amount to the Receiver's funds + m_KnownClientFunds[Receiver] += amount; + result = true; + } + else + { + // These below are redundant to make this clearer to read + result = false; + } + } + else + { + result = false; + } + } + } + return result; + } + + private IClientAPI LocateClientObject(LLUUID AgentID) + { + ScenePresence tPresence = null; + IClientAPI rclient = null; + + lock (m_scenel) + { + foreach (Scene _scene in m_scenel.Values) + { + tPresence = _scene.GetScenePresence(AgentID); + if (tPresence != null) + { + if (!tPresence.IsChildAgent) + { + rclient = tPresence.ControllingClient; + } + } + if (rclient != null) + { + return rclient; + } + } + + } + return null; + } + + public void ClientClosed(IClientAPI client) + { + ClientClosed(client.AgentId); + } + + public void SendMoneyBalance(IClientAPI client, LLUUID agentID, LLUUID SessionID, LLUUID TransactionID) + { + if (client.AgentId == agentID && client.SessionId == SessionID) + { + + int returnfunds = 0; + + try + { + returnfunds = GetFundsForAgentID(agentID); + } + catch (System.Exception e) + { + client.SendAlertMessage(e.Message + " "); + } + + client.SendMoneyBalance(TransactionID, true, new byte[0], returnfunds); + } + else + { + client.SendAlertMessage("Unable to send your money balance to you!"); + } + } + + private void CheckExistAndRefreshFunds(LLUUID agentID) + { + lock (m_KnownClientFunds) + { + if (!m_KnownClientFunds.ContainsKey(agentID)) + { + m_KnownClientFunds.Add(agentID, m_stipend); + } + else + { + if (m_KnownClientFunds[agentID] <= m_minFundsBeforeRefresh) + { + m_KnownClientFunds[agentID] = m_stipend; + } + } + } + } + private int GetFundsForAgentID(LLUUID AgentID) + { + int returnfunds = 0; + lock (m_KnownClientFunds) + { + if (m_KnownClientFunds.ContainsKey(AgentID)) + { + returnfunds = m_KnownClientFunds[AgentID]; + } + else + { + throw new Exception("Unable to get funds."); + } + } + return returnfunds; + } + + public void PostInitialise() + { + } + + + + public void Close() + { + } + + public string Name + { + get { return "BetaGridLikeMoneyModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + } + +} diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs index 89fd5ea371..a80426bd17 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.cs @@ -1315,6 +1315,8 @@ namespace OpenSim.Region.Environment.Scenes avatar.AbsolutePosition.Z); m_sceneGridService.SendCloseChildAgentConnections(avatar); } + + m_eventManager.TriggerClientClosed(agentID); } catch (NullReferenceException) { diff --git a/OpenSim/Region/Environment/Scenes/SceneEvents.cs b/OpenSim/Region/Environment/Scenes/SceneEvents.cs index 51d1b32ff0..cada9916b7 100644 --- a/OpenSim/Region/Environment/Scenes/SceneEvents.cs +++ b/OpenSim/Region/Environment/Scenes/SceneEvents.cs @@ -125,6 +125,10 @@ namespace OpenSim.Region.Environment.Scenes public event NewGridInstantMessage OnGridInstantMessageToGroupsModule; + public delegate void ClientClosed(LLUUID clientID); + + public event ClientClosed OnClientClosed; + public delegate void ScriptChangedEvent(uint localID, uint change); public event ScriptChangedEvent OnScriptChangedEvent; @@ -338,6 +342,14 @@ namespace OpenSim.Region.Environment.Scenes } } + + public void TriggerClientClosed(LLUUID ClientID) + { + if (OnClientClosed != null) + { + OnClientClosed(ClientID); + } + } } } \ No newline at end of file diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs index 159eaf1f8c..0ba64f21f3 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs @@ -1457,6 +1457,84 @@ namespace OpenSim.Region.Environment.Scenes #endregion + #region Sound + public void PreloadSound(string sound) + { + LLUUID ownerID = OwnerID; + LLUUID objectID = UUID; + LLUUID soundID = LLUUID.Zero; + + if (!LLUUID.TryParse(sound, out soundID)) + { + //Trys to fetch sound id from prim's inventory. + //Prim's inventory doesn't support non script items yet + SceneObjectPart op = this; + foreach (KeyValuePair item in op.TaskInventory) + { + if (item.Value.Name == sound) + { + soundID = item.Value.ItemID; + break; + } + } + } + + List avatarts = m_parentGroup.Scene.GetAvatars(); + foreach (ScenePresence p in avatarts) + { + // TODO: some filtering by distance of avatar + + p.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); + } + } + + public void SendSound(string sound, double volume, bool triggered) + { + if (volume > 1) + volume = 1; + if (volume < 0) + volume = 0; + + LLUUID ownerID = OwnerID; + LLUUID objectID = UUID; + LLUUID parentID = GetRootPartUUID(); + LLUUID soundID = LLUUID.Zero; + LLVector3 position = AbsolutePosition; // region local + ulong regionHandle = m_parentGroup.Scene.RegionInfo.RegionHandle; + + byte flags = 0; + + if (!LLUUID.TryParse(sound, out soundID)) + { + // search sound file from inventory + SceneObjectPart op = this; + foreach (KeyValuePair item in op.TaskInventory) + { + if (item.Value.Name == sound) + { + soundID = item.Value.ItemID; + break; + } + } + } + + List avatarts = m_parentGroup.Scene.GetAvatars(); + foreach (ScenePresence p in avatarts) + { + // TODO: some filtering by distance of avatar + if (triggered) + { + p.ControllingClient.SendTriggeredSound(soundID, ownerID, objectID, parentID, regionHandle, position, (float)volume); + } + else + { + p.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)volume, flags); + } + } + } + + #endregion + #region Resizing/Scale /// diff --git a/OpenSim/Region/Examples/SimpleApp/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleApp/MyNpcCharacter.cs index 19bd6cdeb2..b15db3117d 100644 --- a/OpenSim/Region/Examples/SimpleApp/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleApp/MyNpcCharacter.cs @@ -145,6 +145,7 @@ namespace SimpleApp public event FriendActionDelegate OnDenyFriendRequest; public event FriendshipTermination OnTerminateFriendship; public event PacketStats OnPacketStats; + public event MoneyBalanceRequest OnMoneyBalanceRequest; #pragma warning restore 67 diff --git a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs index 367a5f74ce..80df86ed04 100644 --- a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs +++ b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs @@ -906,37 +906,8 @@ namespace OpenSim.Region.ScriptEngine.Common public void llPlaySound(string sound, double volume) { - if (volume > 1) - volume = 1; - if (volume < 0) - volume = 0; - - LLUUID ownerID = m_host.OwnerID; - LLUUID objectID = m_host.UUID; - LLUUID soundID = LLUUID.Zero; - byte flags = 0; - - if (!LLUUID.TryParse(sound, out soundID)) - { - //Trys to fetch sound id from prim's inventory. - //Prim's inventory doesn't support non script items yet - SceneObjectPart op = World.GetSceneObjectPart(objectID); - foreach (KeyValuePair item in op.TaskInventory) - { - if (item.Value.Name == sound) - { - soundID = item.Value.ItemID; - break; - } - } - } - - List avatarts = World.GetAvatars(); - foreach (ScenePresence p in avatarts) - { - // TODO: some filtering by distance of avatar - p.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)volume, flags); - } + + m_host.SendSound(sound, volume, false); } public void llLoopSound(string sound, double volume) @@ -961,38 +932,7 @@ namespace OpenSim.Region.ScriptEngine.Common public void llTriggerSound(string sound, double volume) { - if (volume > 1) - volume = 1; - if (volume < 0) - volume = 0; - - LLUUID ownerID = m_host.OwnerID; - LLUUID objectID = m_host.UUID; - LLUUID parentID = this.m_host.GetRootPartUUID(); - LLUUID soundID = LLUUID.Zero; - LLVector3 position = this.m_host.AbsolutePosition; // region local - ulong regionHandle = World.RegionInfo.RegionHandle; - - if (!LLUUID.TryParse(sound, out soundID)) - { - // search sound file from inventory - SceneObjectPart op = World.GetSceneObjectPart(objectID); - foreach (KeyValuePair item in op.TaskInventory) - { - if (item.Value.Name == sound) - { - soundID = item.Value.ItemID; - break; - } - } - } - - List avatarts = World.GetAvatars(); - foreach (ScenePresence p in avatarts) - { - // TODO: some filtering by distance of avatar - p.ControllingClient.SendTriggeredSound(soundID, ownerID, objectID, parentID, regionHandle, position, (float)volume); - } + m_host.SendSound(sound, volume, true); } public void llStopSound() @@ -1002,31 +942,7 @@ namespace OpenSim.Region.ScriptEngine.Common public void llPreloadSound(string sound) { - LLUUID ownerID = m_host.OwnerID; - LLUUID objectID = m_host.UUID; - LLUUID soundID = LLUUID.Zero; - - if (!LLUUID.TryParse(sound, out soundID)) - { - //Trys to fetch sound id from prim's inventory. - //Prim's inventory doesn't support non script items yet - SceneObjectPart op = World.GetSceneObjectPart(objectID); - foreach (KeyValuePair item in op.TaskInventory) - { - if (item.Value.Name == sound) - { - soundID = item.Value.ItemID; - break; - } - } - } - - List avatarts = World.GetAvatars(); - foreach (ScenePresence p in avatarts) - { - // TODO: some filtering by distance of avatar - p.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); - } + m_host.PreloadSound(sound); } public string llGetSubString(string src, int start, int end) @@ -2439,32 +2355,7 @@ namespace OpenSim.Region.ScriptEngine.Common } prules.CRC = 1; - Console.WriteLine("----------ps----------\n"); - Console.WriteLine(" AngularVelocity:" + prules.AngularVelocity.ToString() + "\n" + - " BurstPartCount:" + prules.BurstPartCount.ToString() + "\n" + - " BurstRadius:" + prules.BurstRadius.ToString() + "\n" + - " BurstRate:" + prules.BurstRate.ToString() + "\n" + - " BurstSpeedMax:" + prules.BurstSpeedMax.ToString() + "\n" + - " BurstSpeedMin:" + prules.BurstSpeedMin.ToString() + "\n" + - " CRC:" + prules.CRC.ToString() + "\n" + - " InnerAngle:" + prules.InnerAngle.ToString() + "\n" + - " MaxAge:" + prules.MaxAge.ToString() + "\n" + - " OuterAngle:" + prules.OuterAngle.ToString() + "\n" + - " PartAcceleration:" + prules.PartAcceleration.ToString() + "\n" + - " PartDataFlags:" + prules.PartDataFlags.ToString() + "\n" + - " PartEndColor:" + prules.PartEndColor.ToString() + "\n" + - " PartEndScaleX:" + prules.PartEndScaleX.ToString() + "\n" + - " PartEndScaleY:" + prules.PartEndScaleY.ToString() + "\n" + - " PartFlags:" + prules.PartFlags.ToString() + "\n" + - " PartMaxAge:" + prules.PartMaxAge.ToString() + "\n" + - " PartStartColor:" + prules.PartStartColor.ToString() + "\n" + - " PartStartScaleX:" + prules.PartStartScaleX.ToString() + "\n" + - " PartStartScaleY:" + prules.PartStartScaleY.ToString() + "\n" + - " Pattern:" + prules.Pattern.ToString() + "\n" + - " StartAge:" + prules.StartAge.ToString() + "\n" + - " Target:" + prules.Target.ToString() + "\n" + - " Texture:" + prules.Texture.ToString() + ""); - OpenSim.Framework.Console.MainLog.Instance.Verbose("PARTICLE", "PS: " + prules.ToString()); + m_host.AddNewParticleSystem(prules); m_host.SendFullUpdateToAllClients(); }