* Updates BetaGridLikeMoneyModule

* Several people have asked for a way to limit uploads, so I've decided to show people how to do this in the BetaGridLikeMoneyModule.
* Configure it in OpenSim.ini using the [Economy] header.  See the bottom of the OpenSim.ini.example for more information.
* This also fleshes out the Economy API a bit more.
0.6.0-stable
Teravus Ovares 2008-04-10 09:36:55 +00:00
parent b85624db18
commit 06967e230f
9 changed files with 272 additions and 21 deletions

View File

@ -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,11 +540,13 @@ namespace OpenSim.Framework
// Financial packets
event MoneyTransferRequest OnMoneyTransferRequest;
event EconomyDataRequest OnEconomyDataRequest;
event MoneyBalanceRequest OnMoneyBalanceRequest;
event UpdateAvatarProperties OnUpdateAvatarProperties;
LLVector3 StartPos { get; set; }
LLUUID AgentId { get; }
@ -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);

View File

@ -214,6 +214,8 @@ namespace OpenSim.Region.ClientStack
private ViewerEffectEventHandler handlerViewerEffect = null; //OnViewerEffect;
private Action<IClientAPI> 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");

View File

@ -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)
{
if (config == "Startup")
{
IConfig startupConfig = m_gConfig.Configs["Startup"];
gridmode = startupConfig.GetBoolean("gridmode", false);
m_enabled = (startupConfig.GetString("moneymodule", "BetaGridLikeMoneyModule") == "BetaGridLikeMoneyModule");
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;

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;
/// <summary>
/// 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);
}
}
}
}

View File

@ -101,6 +101,8 @@ namespace OpenSim.Region.Environment.Scenes
private int m_activeScripts = 0;
private int m_scriptLinesPerSecond = 0;
private int objectCapacity = 45000;
SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[21];
SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock();
@ -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
}
}

View File

@ -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)
{
}

View File

@ -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