diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 17d951043e..e081e059ce 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -430,6 +430,8 @@ namespace OpenSim.Framework public delegate void ObjectPermissions(IClientAPI controller, LLUUID agentID, LLUUID sessionID, byte field, uint localId, uint mask, byte set); + public delegate void EconomyDataRequest(LLUUID agentID); + public interface IClientAPI { event ImprovedInstantMessage OnInstantMessage; @@ -538,10 +540,12 @@ namespace OpenSim.Framework // Financial packets event MoneyTransferRequest OnMoneyTransferRequest; + event EconomyDataRequest OnEconomyDataRequest; event MoneyBalanceRequest OnMoneyBalanceRequest; event UpdateAvatarProperties OnUpdateAvatarProperties; + LLVector3 StartPos { get; set; } @@ -647,6 +651,12 @@ namespace OpenSim.Framework void SendBulkUpdateInventory(InventoryItemBase item); void SendXferPacket(ulong xferID, uint packet, byte[] data); + + void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit, + int PriceGroupCreate, int PriceObjectClaim, float PriceObjectRent, float PriceObjectScaleFactor, + int PriceParcelClaim, float PriceParcelClaimFactor, int PriceParcelRent, int PricePublicObjectDecay, + int PricePublicObjectDelete, int PriceRentLight, int PriceUpload, int TeleportMinPrice, float TeleportPriceExponent); + void SendAvatarPickerReply(AvatarPickerReplyPacket Pack); void SendAgentDataUpdate(LLUUID agentid, LLUUID activegroupid, string firstname, string lastname, ulong grouppowers, string groupname, string grouptitle); diff --git a/OpenSim/Region/ClientStack/ClientView.cs b/OpenSim/Region/ClientStack/ClientView.cs index 25ea3c68db..a91987f264 100644 --- a/OpenSim/Region/ClientStack/ClientView.cs +++ b/OpenSim/Region/ClientStack/ClientView.cs @@ -214,6 +214,8 @@ namespace OpenSim.Region.ClientStack private ViewerEffectEventHandler handlerViewerEffect = null; //OnViewerEffect; private Action handlerLogout = null; //OnLogout; private MoneyTransferRequest handlerMoneyTransferRequest = null; //OnMoneyTransferRequest; + private EconomyDataRequest handlerEconomoyDataRequest = null; + private UpdateVector handlerUpdatePrimSinglePosition = null; //OnUpdatePrimSinglePosition; private UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = null; //OnUpdatePrimSingleRotation; private UpdateVector handlerUpdatePrimScale = null; //OnUpdatePrimScale; @@ -223,6 +225,7 @@ namespace OpenSim.Region.ClientStack private PacketStats handlerPacketStats = null; // OnPacketStats;# private RequestAsset handlerRequestAsset = null; // OnRequestAsset; + /* Properties */ public LLUUID SecureSessionId @@ -763,6 +766,7 @@ namespace OpenSim.Region.ClientStack public event PacketStats OnPacketStats; public event MoneyTransferRequest OnMoneyTransferRequest; + public event EconomyDataRequest OnEconomyDataRequest; public event MoneyBalanceRequest OnMoneyBalanceRequest; @@ -1523,6 +1527,34 @@ namespace OpenSim.Region.ClientStack OutPacket(sendXfer, ThrottleOutPacketType.Task); } + public void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit, + int PriceGroupCreate, int PriceObjectClaim, float PriceObjectRent, float PriceObjectScaleFactor, + int PriceParcelClaim, float PriceParcelClaimFactor, int PriceParcelRent, int PricePublicObjectDecay, + int PricePublicObjectDelete, int PriceRentLight, int PriceUpload, int TeleportMinPrice, float TeleportPriceExponent) + { + EconomyDataPacket economyData = (EconomyDataPacket)PacketPool.Instance.GetPacket(PacketType.EconomyData); + economyData.Info.EnergyEfficiency = EnergyEfficiency; + economyData.Info.ObjectCapacity = ObjectCapacity; + economyData.Info.ObjectCount = ObjectCount; + economyData.Info.PriceEnergyUnit = PriceEnergyUnit; + economyData.Info.PriceGroupCreate = PriceGroupCreate; + economyData.Info.PriceObjectClaim = PriceObjectClaim; + economyData.Info.PriceObjectRent = PriceObjectRent; + economyData.Info.PriceObjectScaleFactor = PriceObjectScaleFactor; + economyData.Info.PriceParcelClaim = PriceParcelClaim; + economyData.Info.PriceParcelClaimFactor = PriceParcelClaimFactor; + economyData.Info.PriceParcelRent = PriceParcelRent; + economyData.Info.PricePublicObjectDecay = PricePublicObjectDecay; + economyData.Info.PricePublicObjectDelete = PricePublicObjectDelete; + economyData.Info.PriceRentLight = PriceRentLight; + economyData.Info.PriceUpload = PriceUpload; + economyData.Info.TeleportMinPrice = TeleportMinPrice; + economyData.Info.TeleportPriceExponent = TeleportPriceExponent; + economyData.Header.Reliable = true; + OutPacket(economyData, ThrottleOutPacketType.Unknown); + + } + public void SendAvatarPickerReply(AvatarPickerReplyPacket replyPacket) { OutPacket(replyPacket, ThrottleOutPacketType.Task); @@ -4155,17 +4187,7 @@ namespace OpenSim.Region.ClientStack #endregion - case PacketType.MoneyBalanceRequest: - MoneyBalanceRequestPacket moneybalancerequestpacket = (MoneyBalanceRequestPacket)Pack; - - handlerMoneyBalanceRequest = OnMoneyBalanceRequest; - - if (handlerMoneyBalanceRequest != null) - { - handlerMoneyBalanceRequest(this, moneybalancerequestpacket.AgentData.AgentID, moneybalancerequestpacket.AgentData.SessionID, moneybalancerequestpacket.MoneyData.TransactionID); - } - - break; + case PacketType.UUIDNameRequest: UUIDNameRequestPacket incoming = (UUIDNameRequestPacket)Pack; foreach (UUIDNameRequestPacket.UUIDNameBlockBlock UUIDBlock in incoming.UUIDNameBlock) @@ -4373,6 +4395,32 @@ namespace OpenSim.Region.ClientStack #endregion + #region Economy/Transaction Packets + + case PacketType.MoneyBalanceRequest: + MoneyBalanceRequestPacket moneybalancerequestpacket = (MoneyBalanceRequestPacket)Pack; + + handlerMoneyBalanceRequest = OnMoneyBalanceRequest; + + if (handlerMoneyBalanceRequest != null) + { + handlerMoneyBalanceRequest(this, moneybalancerequestpacket.AgentData.AgentID, moneybalancerequestpacket.AgentData.SessionID, moneybalancerequestpacket.MoneyData.TransactionID); + } + + break; + case PacketType.EconomyDataRequest: + + handlerEconomoyDataRequest = OnEconomyDataRequest; + if (handlerEconomoyDataRequest != null) + { + handlerEconomoyDataRequest(AgentId); + } + // TODO: handle this packet + //m_log.Warn("[CLIENT]: unhandled EconomyDataRequest packet"); + break; + + #endregion + #region unimplemented handlers case PacketType.StartPingCheck: @@ -4422,10 +4470,7 @@ namespace OpenSim.Region.ClientStack // TODO: Don't display this one, we handle it at a lower level //m_log.Warn("[CLIENT]: unhandled UseCircuitCode packet"); break; - case PacketType.EconomyDataRequest: - // TODO: handle this packet - m_log.Warn("[CLIENT]: unhandled EconomyDataRequest packet"); - break; + case PacketType.AgentHeightWidth: // TODO: handle this packet m_log.Warn("[CLIENT]: unhandled AgentHeightWidth packet"); diff --git a/OpenSim/Region/Environment/Modules/BetaGridLikeMoneyModule.cs b/OpenSim/Region/Environment/Modules/BetaGridLikeMoneyModule.cs index 6e16eb3ebe..74ae0dc9d1 100644 --- a/OpenSim/Region/Environment/Modules/BetaGridLikeMoneyModule.cs +++ b/OpenSim/Region/Environment/Modules/BetaGridLikeMoneyModule.cs @@ -56,10 +56,39 @@ namespace OpenSim.Region.Environment.Modules private bool gridmode = false; + private float EnergyEfficiency = 0f; + private int ObjectCapacity = 45000; + private int ObjectCount = 0; + private int PriceEnergyUnit = 0; + private int PriceGroupCreate = 0; + private int PriceObjectClaim = 0; + private float PriceObjectRent = 0f; + private float PriceObjectScaleFactor = 0f; + private int PriceParcelClaim = 0; + private float PriceParcelClaimFactor = 0f; + private int PriceParcelRent = 0; + private int PricePublicObjectDecay = 0; + private int PricePublicObjectDelete = 0; + private int PriceRentLight = 0; + private int PriceUpload = 0; + private int TeleportMinPrice = 0; + private int UserLevelPaysFees = 2; + + float TeleportPriceExponent = 0f; + + LLUUID EconomyBaseAccount = LLUUID.Zero; + public void Initialise(Scene scene, IConfigSource config) { m_gConfig = config; - ReadConfigAndPopulate(); + + IConfig startupConfig = m_gConfig.Configs["Startup"]; + IConfig economyConfig = m_gConfig.Configs["Economy"]; + + + + ReadConfigAndPopulate(scene, startupConfig, "Startup"); + ReadConfigAndPopulate(scene, economyConfig, "Economy"); if (m_enabled) { @@ -79,14 +108,47 @@ namespace OpenSim.Region.Environment.Modules scene.EventManager.OnNewClient += OnNewClient; scene.EventManager.OnMoneyTransfer += MoneyTransferAction; scene.EventManager.OnClientClosed += ClientClosed; + scene.EventManager.OnNewInventoryItemUploadComplete += NewInventoryItemEconomyHandler; + } } - private void ReadConfigAndPopulate() + private void ReadConfigAndPopulate(Scene scene, IConfig startupConfig, string config) { - IConfig startupConfig = m_gConfig.Configs["Startup"]; - gridmode = startupConfig.GetBoolean("gridmode", false); - m_enabled = (startupConfig.GetString("moneymodule", "BetaGridLikeMoneyModule") == "BetaGridLikeMoneyModule"); + if (config == "Startup") + { + gridmode = startupConfig.GetBoolean("gridmode", false); + m_enabled = (startupConfig.GetString("economymodule", "BetaGridLikeMoneyModule") == "BetaGridLikeMoneyModule"); + } + + if (config == "Economy") + { + ObjectCapacity = startupConfig.GetInt("ObjectCapacity", 45000); + PriceEnergyUnit = startupConfig.GetInt("PriceEnergyUnit", 100); + PriceObjectClaim = startupConfig.GetInt("PriceObjectClaim", 10); + PricePublicObjectDecay = startupConfig.GetInt("PricePublicObjectDecay", 4); + PricePublicObjectDelete = startupConfig.GetInt("PricePublicObjectDelete", 4); + PriceParcelClaim = startupConfig.GetInt("PriceParcelClaim", 1); + PriceParcelClaimFactor = startupConfig.GetFloat("PriceParcelClaimFactor", 1f); + PriceUpload = startupConfig.GetInt("PriceUpload", 0); + PriceRentLight = startupConfig.GetInt("PriceRentLight", 5); + TeleportMinPrice = startupConfig.GetInt("TeleportMinPrice", 2); + TeleportPriceExponent = startupConfig.GetFloat("TeleportPriceExponent", 2f); + EnergyEfficiency = startupConfig.GetFloat("EnergyEfficiency", 1); + PriceObjectRent = startupConfig.GetFloat("PriceObjectRent", 1); + PriceObjectScaleFactor = startupConfig.GetFloat("PriceObjectScaleFactor", 10); + PriceParcelRent = startupConfig.GetInt("PriceParcelRent", 1); + PriceGroupCreate = startupConfig.GetInt("PriceGroupCreate", -1); + string EBA = startupConfig.GetString("EconomyBaseAccount", LLUUID.Zero.ToString()); + Helpers.TryParse(EBA,out EconomyBaseAccount); + UserLevelPaysFees = startupConfig.GetInt("UserLevelPaysFees", -1); + m_stipend = startupConfig.GetInt("UserStipend", 500); + m_minFundsBeforeRefresh = startupConfig.GetInt("IssueStipendWhenClientIsBelowAmount", 10); + m_keepMoneyAcrossLogins = startupConfig.GetBoolean("KeepMoneyAcrossLogins", true); + } + + // Send ObjectCapacity to Scene.. Which sends it to the SimStatsReporter. + scene.SetObjectCapacity(ObjectCapacity); } private void OnNewClient(IClientAPI client) @@ -105,8 +167,11 @@ namespace OpenSim.Region.Environment.Modules } // Subscribe to Money messages + client.OnEconomyDataRequest += EconomyDataRequestHandler; client.OnMoneyBalanceRequest += SendMoneyBalance; client.OnLogout += ClientClosed; + + } public void ClientClosed(LLUUID AgentID) @@ -118,6 +183,16 @@ namespace OpenSim.Region.Environment.Modules } } + public void EconomyDataRequestHandler(LLUUID agentId) + { + IClientAPI user = LocateClientObject(agentId); + + user.SendEconomyData(EnergyEfficiency, ObjectCapacity, ObjectCount, PriceEnergyUnit, PriceGroupCreate, + PriceObjectClaim, PriceObjectRent, PriceObjectScaleFactor, PriceParcelClaim, PriceParcelClaimFactor, + PriceParcelRent, PricePublicObjectDecay, PricePublicObjectDelete, PriceRentLight, PriceUpload, + TeleportMinPrice, TeleportPriceExponent); + } + private void MoneyTransferAction (Object osender, MoneyTransferArgs e) { IClientAPI sender = null; @@ -150,6 +225,22 @@ namespace OpenSim.Region.Environment.Modules } } + private void NewInventoryItemEconomyHandler(LLUUID Uploader, LLUUID AssetID, String AssetName, int userlevel) + { + // Presumably a normal grid would actually send this information to a server somewhere. + // We're going to apply the UploadCost here. + if (m_enabled) + { + // Only make users that are below the UserLevelPaysFees value pay. + // Use this to exclude Region Owners (2), Estate Managers(1), Users (0), Disabled(-1) + if (PriceUpload > 0 && userlevel <= UserLevelPaysFees) + { + doMoneyTranfer(Uploader, EconomyBaseAccount, PriceUpload); + } + } + + } + private bool doMoneyTranfer(LLUUID Sender, LLUUID Receiver, int amount) { bool result = false; diff --git a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs index bc8fb5936a..97d09aa1cd 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs @@ -73,6 +73,17 @@ namespace OpenSim.Region.Environment.Scenes { userInfo.AddItem(remoteClient.AgentId, item); remoteClient.SendInventoryItemCreateUpdate(item); + + int userlevel = 0; + if (PermissionsMngr.IsEstateManager(remoteClient.AgentId)) + { + userlevel = 1; + } + if (m_regInfo.MasterAvatarAssignedUUID == remoteClient.AgentId) + { + userlevel = 2; + } + EventManager.TriggerOnNewInventoryItemUploadComplete(remoteClient.AgentId, item.AssetID, item.Name, userlevel); } } diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs index 8f4c332043..4a57c5d0f1 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.cs @@ -219,6 +219,8 @@ namespace OpenSim.Region.Environment.Scenes set { m_innerScene.RestorePresences = value; } } + public int objectCapacity = 45000; + #endregion #region Constructors @@ -299,6 +301,9 @@ namespace OpenSim.Region.Environment.Scenes m_statsReporter = new SimStatsReporter(regInfo); m_statsReporter.OnSendStatsResult += SendSimStatsPackets; + + m_statsReporter.SetObjectCapacity(objectCapacity); + string OSString = ""; if (System.Environment.OSVersion.Platform != PlatformID.Unix) @@ -2016,6 +2021,15 @@ namespace OpenSim.Region.Environment.Scenes } } + public void SetObjectCapacity(int objects) + { + if (m_statsReporter != null) + { + m_statsReporter.SetObjectCapacity(objects); + } + objectCapacity = objects; + } + #endregion #region Other Methods diff --git a/OpenSim/Region/Environment/Scenes/SceneEvents.cs b/OpenSim/Region/Environment/Scenes/SceneEvents.cs index c9160096d5..02c9f3f165 100644 --- a/OpenSim/Region/Environment/Scenes/SceneEvents.cs +++ b/OpenSim/Region/Environment/Scenes/SceneEvents.cs @@ -137,6 +137,10 @@ namespace OpenSim.Region.Environment.Scenes public event OnNewPresenceDelegate OnMakeChildAgent; + public delegate void NewInventoryItemUploadComplete(LLUUID avatarID, LLUUID assetID, string name, int userlevel); + + public event NewInventoryItemUploadComplete OnNewInventoryItemUploadComplete; + /// /// RegisterCapsEvent is called by Scene after the Caps object /// has been instantiated and before it is return to the @@ -207,6 +211,7 @@ namespace OpenSim.Region.Environment.Scenes private OnTerrainTickDelegate handlerTerrainTick = null; // OnTerainTick; private RegisterCapsEvent handlerRegisterCaps = null; // OnRegisterCaps; private DeregisterCapsEvent handlerDeregisterCaps = null; // OnDeregisterCaps; + private NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = null; public void TriggerOnScriptChangedEvent(uint localID, uint change) { @@ -462,5 +467,14 @@ namespace OpenSim.Region.Environment.Scenes handlerDeregisterCaps(agentID, caps); } } + + public void TriggerOnNewInventoryItemUploadComplete(LLUUID agentID, LLUUID AssetID, String AssetName, int userlevel) + { + handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete; + if (handlerNewInventoryItemUpdateComplete != null) + { + handlerNewInventoryItemUpdateComplete(agentID, AssetID, AssetName, userlevel); + } + } } } diff --git a/OpenSim/Region/Environment/Scenes/SimStatsReporter.cs b/OpenSim/Region/Environment/Scenes/SimStatsReporter.cs index ef741d4418..d72bee048f 100644 --- a/OpenSim/Region/Environment/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Environment/Scenes/SimStatsReporter.cs @@ -100,6 +100,8 @@ namespace OpenSim.Region.Environment.Scenes private int m_pendingUploads = 0; private int m_activeScripts = 0; private int m_scriptLinesPerSecond = 0; + + private int objectCapacity = 45000; SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[21]; @@ -152,7 +154,7 @@ namespace OpenSim.Region.Environment.Scenes { statpack.Region.RegionFlags = (uint) 0; } - statpack.Region.ObjectCapacity = (uint) 45000; + statpack.Region.ObjectCapacity = (uint) objectCapacity; #region various statistic googly moogly @@ -389,6 +391,11 @@ namespace OpenSim.Region.Environment.Scenes m_activeScripts = count; } + public void SetObjectCapacity(int objects) + { + objectCapacity = objects; + } + #endregion } } diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index 9901a50884..9e9b52bd3c 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -155,6 +155,8 @@ namespace OpenSim.Region.Examples.SimpleModule public event FriendActionDelegate OnDenyFriendRequest; public event FriendshipTermination OnTerminateFriendship; public event PacketStats OnPacketStats; + + public event EconomyDataRequest OnEconomyDataRequest; public event MoneyBalanceRequest OnMoneyBalanceRequest; public event UpdateAvatarProperties OnUpdateAvatarProperties; @@ -408,6 +410,13 @@ namespace OpenSim.Region.Examples.SimpleModule { } + public virtual void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit, + int PriceGroupCreate, int PriceObjectClaim, float PriceObjectRent, float PriceObjectScaleFactor, + int PriceParcelClaim, float PriceParcelClaimFactor, int PriceParcelRent, int PricePublicObjectDecay, + int PricePublicObjectDelete, int PriceRentLight, int PriceUpload, int TeleportMinPrice, float TeleportPriceExponent) + { + + } public virtual void SendNameReply(LLUUID profileId, string firstname, string lastname) { } diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 42f0d303ef..cbf559160c 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -301,3 +301,53 @@ snapshot_cache_directory = "DataSnapshot" ; This semicolon-separated string serves to notify specific data services ; about the existence of this sim. data_services="http://metaverseink.com/cgi-bin/register.py" + +[Economy] +; These economy values get used in the BetaGridLikeMoneyModule + +; 45000 is the highest value that the sim could possibly report because of protocol constraints +ObjectCapacity = 45000 + +; Money Unit fee to upload textures, animations etc +PriceUpload = 0 + +; Money Unit fee to create groups +PriceGroupCreate = 0 + +; This is the account Money goes to for fees. Remember, economy requires that money circulates somewhere... even if it's an upload fee +EconomyBaseAccount = 00000000-0000-0000-0000-000000000000 + +; This is the type of user that will pay fees. +; Set this to 2 for users, estate managers and Estate Owners +; Set this to 1 for Users and Estate Managers +; Set this to 0 for Users only. +; -1 disables +UserLevelPaysFees = -1 + +; Amount to give to user as a stipend +UserStipend = 1000 + +; When a user gets low on money units and logs off, then logs back on, issue a new stipend if they have less money units then this +; amount. Be aware that the account money isn't stored anywhere so users will get a stipend if you restart the simulator +IssueStipendWhenClientIsBelowAmount = 10 + +; If this is true, the simulator will remember account balances until the simulator is shutdown or restarted. +KeepMoneyAcrossLogins = true + +; We don't really know what the rest of these values do. These get sent to the client +; These taken from Agni at a Public Telehub. Change at your own risk. +ObjectCount = 0 +PriceEnergyUnit = 100 +PriceObjectClaim = 10 +PricePublicObjectDecay = 4 +PricePublicObjectDelete = 4 +PriceParcelClaim = 1 +PriceParcelClaimFactor = 1 + +PriceRentLight = 5 +TeleportMinPrice = 2 +TeleportPriceExponent = 2 +EnergyEfficiency = 1 +PriceObjectRent = 1 +PriceObjectScaleFactor = 10 +PriceParcelRent = 1 \ No newline at end of file