* Implemented asset and appearance persistence in Simian

git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@2283 52acb1d6-8a22-11de-b505-999d5b087335
This commit is contained in:
John Hurliman
2008-10-09 04:50:03 +00:00
parent 003eb8a220
commit 29026f68f0
10 changed files with 251 additions and 230 deletions

View File

@@ -10,9 +10,12 @@ namespace Simian.Extensions
{
public class AssetManager : IExtension, IAssetProvider
{
public const string UPLOAD_DIR = "uploadedAssets";
Simian Server;
Dictionary<UUID, Asset> AssetStore = new Dictionary<UUID, Asset>();
Dictionary<ulong, Asset> CurrentUploads = new Dictionary<ulong, Asset>();
string UploadDir;
public AssetManager(Simian server)
{
@@ -21,7 +24,22 @@ namespace Simian.Extensions
public void Start()
{
LoadDefaultAssets(Server.DataDir);
UploadDir = Path.Combine(Server.DataDir, UPLOAD_DIR);
// Try to create the data directories if they don't already exist
if (!Directory.Exists(Server.DataDir))
{
try { Directory.CreateDirectory(Server.DataDir); }
catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Warning, ex); }
}
if (!Directory.Exists(UploadDir))
{
try { Directory.CreateDirectory(UploadDir); }
catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Warning, ex); }
}
LoadAssets(Server.DataDir);
LoadAssets(UploadDir);
Server.UDP.RegisterPacketCallback(PacketType.AssetUploadRequest, new PacketCallback(AssetUploadRequestHandler));
Server.UDP.RegisterPacketCallback(PacketType.SendXferPacket, new PacketCallback(SendXferPacketHandler));
@@ -43,6 +61,8 @@ namespace Simian.Extensions
{
lock (AssetStore)
AssetStore[asset.AssetID] = texture;
if (!asset.Temporary)
SaveAsset(texture);
}
else
{
@@ -56,6 +76,8 @@ namespace Simian.Extensions
{
lock (AssetStore)
AssetStore[asset.AssetID] = asset;
if (!asset.Temporary)
SaveAsset(asset);
}
else
{
@@ -77,9 +99,10 @@ namespace Simian.Extensions
AssetUploadRequestPacket request = (AssetUploadRequestPacket)packet;
UUID assetID = UUID.Combine(request.AssetBlock.TransactionID, agent.SecureSessionID);
// Check if the asset is small enough to fit in a single packet
if (request.AssetBlock.AssetData.Length != 0)
{
// Create a new asset from the upload
// Create a new asset from the completed upload
Asset asset = CreateAsset((AssetType)request.AssetBlock.Type, assetID, request.AssetBlock.AssetData);
if (asset == null)
{
@@ -89,6 +112,8 @@ namespace Simian.Extensions
Logger.DebugLog(String.Format("Storing uploaded asset {0} ({1})", assetID, asset.AssetType));
asset.Temporary = (request.AssetBlock.Tempfile | request.AssetBlock.StoreLocal);
// Store the asset
StoreAsset(asset);
@@ -101,15 +126,18 @@ namespace Simian.Extensions
}
else
{
// Create a new asset for the upload
// Create a new (empty) asset for the upload
Asset asset = CreateAsset((AssetType)request.AssetBlock.Type, assetID, null);
if (asset == null)
{
Logger.Log("Failed to create asset from uploaded data", Helpers.LogLevel.Warning);
return;
}
Logger.DebugLog(String.Format("Starting upload for {0} ({1})", assetID, asset.AssetType));
asset.Temporary = (request.AssetBlock.Tempfile | request.AssetBlock.StoreLocal);
RequestXferPacket xfer = new RequestXferPacket();
xfer.XferID.DeleteOnCompletion = request.AssetBlock.Tempfile;
xfer.XferID.FilePath = 0;
@@ -168,7 +196,7 @@ namespace Simian.Extensions
if ((xfer.XferID.Packet & (uint)0x80000000) != 0)
{
// Asset upload finished
Logger.DebugLog("Completed asset upload");
Logger.DebugLog(String.Format("Completed Xfer upload of asset {0} ({1}", asset.AssetID, asset.AssetType));
lock (CurrentUploads)
CurrentUploads.Remove(xfer.XferID.ID);
@@ -348,6 +376,19 @@ namespace Simian.Extensions
#endregion Transfer System
void SaveAsset(Asset asset)
{
try
{
File.WriteAllBytes(Path.Combine(UploadDir, String.Format("{0}.{1}", asset.AssetID,
asset.AssetType.ToString().ToLower())), asset.AssetData);
}
catch (Exception ex)
{
Logger.Log(ex.Message, Helpers.LogLevel.Warning, ex);
}
}
Asset CreateAsset(AssetType type, UUID assetID, byte[] data)
{
switch (type)
@@ -389,38 +430,51 @@ namespace Simian.Extensions
}
}
void LoadDefaultAssets(string path)
void LoadAssets(string path)
{
string[] textures = Directory.GetFiles(path, "*.jp2", SearchOption.TopDirectoryOnly);
string[] clothing = Directory.GetFiles(path, "*.clothing", SearchOption.TopDirectoryOnly);
string[] bodyparts = Directory.GetFiles(path, "*.bodypart", SearchOption.TopDirectoryOnly);
string[] sounds = Directory.GetFiles(path, "*.ogg", SearchOption.TopDirectoryOnly);
for (int i = 0; i < textures.Length; i++)
try
{
UUID assetID = ParseUUIDFromFilename(textures[i]);
StoreAsset(new AssetTexture(assetID, File.ReadAllBytes(textures[i])));
}
string[] textures = Directory.GetFiles(path, "*.jp2", SearchOption.TopDirectoryOnly);
string[] clothing = Directory.GetFiles(path, "*.clothing", SearchOption.TopDirectoryOnly);
string[] bodyparts = Directory.GetFiles(path, "*.bodypart", SearchOption.TopDirectoryOnly);
string[] sounds = Directory.GetFiles(path, "*.ogg", SearchOption.TopDirectoryOnly);
for (int i = 0; i < clothing.Length; i++)
for (int i = 0; i < textures.Length; i++)
{
UUID assetID = ParseUUIDFromFilename(textures[i]);
Asset asset = new AssetTexture(assetID, File.ReadAllBytes(textures[i]));
asset.Temporary = true;
StoreAsset(asset);
}
for (int i = 0; i < clothing.Length; i++)
{
UUID assetID = ParseUUIDFromFilename(clothing[i]);
Asset asset = new AssetClothing(assetID, File.ReadAllBytes(clothing[i]));
asset.Temporary = true;
StoreAsset(asset);
}
for (int i = 0; i < bodyparts.Length; i++)
{
UUID assetID = ParseUUIDFromFilename(bodyparts[i]);
Asset asset = new AssetBodypart(assetID, File.ReadAllBytes(bodyparts[i]));
asset.Temporary = true;
StoreAsset(asset);
}
for (int i = 0; i < sounds.Length; i++)
{
UUID assetID = ParseUUIDFromFilename(sounds[i]);
Asset asset = new AssetSound(assetID, File.ReadAllBytes(sounds[i]));
asset.Temporary = true;
StoreAsset(asset);
}
}
catch (Exception ex)
{
UUID assetID = ParseUUIDFromFilename(clothing[i]);
StoreAsset(new AssetClothing(assetID, File.ReadAllBytes(clothing[i])));
Logger.Log(ex.Message, Helpers.LogLevel.Warning, ex);
}
for (int i = 0; i < bodyparts.Length; i++)
{
UUID assetID = ParseUUIDFromFilename(bodyparts[i]);
StoreAsset(new AssetBodypart(assetID, File.ReadAllBytes(bodyparts[i])));
}
for (int i = 0; i < sounds.Length; i++)
{
UUID assetID = ParseUUIDFromFilename(sounds[i]);
StoreAsset(new AssetSound(assetID, File.ReadAllBytes(sounds[i])));
}
Logger.DebugLog(String.Format("Loaded {0} assets", AssetStore.Count));
}
static UUID ParseUUIDFromFilename(string filename)

View File

@@ -66,39 +66,33 @@ namespace Simian.Extensions
UUID hairAsset = new UUID("dc675529-7ba5-4976-b91d-dcb9e5e36188");
UUID hairItem = server.Inventory.CreateItem(agent.AgentID, "Default Hair", "Default Hair",
InventoryType.Wearable, AssetType.Bodypart, hairAsset, defaultOutfitFolder,
PermissionMask.All, PermissionMask.All, agent.AgentID, agent.AgentID, UUID.Random(), 0);
PermissionMask.All, PermissionMask.All, agent.AgentID, agent.AgentID, UUID.Random(), 0, false);
UUID pantsAsset = new UUID("3e8ee2d6-4f21-4a55-832d-77daa505edff");
UUID pantsItem = server.Inventory.CreateItem(agent.AgentID, "Default Pants", "Default Pants",
InventoryType.Wearable, AssetType.Clothing, pantsAsset, defaultOutfitFolder,
PermissionMask.All, PermissionMask.All, agent.AgentID, agent.AgentID, UUID.Random(), 0);
PermissionMask.All, PermissionMask.All, agent.AgentID, agent.AgentID, UUID.Random(), 0, false);
UUID shapeAsset = new UUID("530a2614-052e-49a2-af0e-534bb3c05af0");
UUID shapeItem = server.Inventory.CreateItem(agent.AgentID, "Default Shape", "Default Shape",
InventoryType.Wearable, AssetType.Clothing, shapeAsset, defaultOutfitFolder,
PermissionMask.All, PermissionMask.All, agent.AgentID, agent.AgentID, UUID.Random(), 0);
PermissionMask.All, PermissionMask.All, agent.AgentID, agent.AgentID, UUID.Random(), 0, false);
UUID shirtAsset = new UUID("6a714f37-fe53-4230-b46f-8db384465981");
UUID shirtItem = server.Inventory.CreateItem(agent.AgentID, "Default Shirt", "Default Shirt",
InventoryType.Wearable, AssetType.Clothing, shirtAsset, defaultOutfitFolder,
PermissionMask.All, PermissionMask.All, agent.AgentID, agent.AgentID, UUID.Random(), 0);
PermissionMask.All, PermissionMask.All, agent.AgentID, agent.AgentID, UUID.Random(), 0, false);
UUID skinAsset = new UUID("5f787f25-f761-4a35-9764-6418ee4774c4");
UUID skinItem = server.Inventory.CreateItem(agent.AgentID, "Default Skin", "Default Skin",
InventoryType.Wearable, AssetType.Clothing, skinAsset, defaultOutfitFolder,
PermissionMask.All, PermissionMask.All, agent.AgentID, agent.AgentID, UUID.Random(), 0);
PermissionMask.All, PermissionMask.All, agent.AgentID, agent.AgentID, UUID.Random(), 0, false);
UUID eyesAsset = new UUID("78d20332-9b07-44a2-bf74-3b368605f4b5");
UUID eyesItem = server.Inventory.CreateItem(agent.AgentID, "Default Eyes", "Default Eyes",
InventoryType.Wearable, AssetType.Bodypart, eyesAsset, defaultOutfitFolder,
PermissionMask.All, PermissionMask.All, agent.AgentID, agent.AgentID, UUID.Random(), 0);
PermissionMask.All, PermissionMask.All, agent.AgentID, agent.AgentID, UUID.Random(), 0, false);
agent.HairAsset = hairAsset;
agent.HairItem = hairItem;
agent.PantsAsset = pantsAsset;
agent.PantsItem = pantsItem;
agent.ShapeAsset = shapeAsset;
agent.ShapeItem = shapeItem;
agent.ShirtAsset = shirtAsset;
agent.ShirtItem = shirtItem;
agent.SkinAsset = skinAsset;
agent.SkinItem = skinItem;
agent.EyesAsset = eyesAsset;
agent.EyesItem = eyesItem;
server.Accounts.AddAccount(agent);

View File

@@ -152,23 +152,38 @@ namespace Simian.Extensions
}
}
int CountWearables(Agent agent)
bool TryAddWearable(UUID agentID, Dictionary<WearableType, InventoryItem> wearables, WearableType type, UUID itemID)
{
int wearables = 0;
InventoryObject obj;
if (itemID != UUID.Zero && Server.Inventory.TryGetInventory(agentID, itemID, out obj) &&
obj is InventoryItem)
{
wearables.Add(type, (InventoryItem)obj);
return true;
}
else
{
return false;
}
}
if (agent.ShapeAsset != UUID.Zero) ++wearables;
if (agent.SkinAsset != UUID.Zero) ++wearables;
if (agent.HairAsset != UUID.Zero) ++wearables;
if (agent.EyesAsset != UUID.Zero) ++wearables;
if (agent.ShirtAsset != UUID.Zero) ++wearables;
if (agent.PantsAsset != UUID.Zero) ++wearables;
if (agent.ShoesAsset != UUID.Zero) ++wearables;
if (agent.SocksAsset != UUID.Zero) ++wearables;
if (agent.JacketAsset != UUID.Zero) ++wearables;
if (agent.GlovesAsset != UUID.Zero) ++wearables;
if (agent.UndershirtAsset != UUID.Zero) ++wearables;
if (agent.UnderpantsAsset != UUID.Zero) ++wearables;
if (agent.SkirtAsset != UUID.Zero) ++wearables;
Dictionary<WearableType, InventoryItem> GetCurrentWearables(Agent agent)
{
Dictionary<WearableType, InventoryItem> wearables = new Dictionary<WearableType, InventoryItem>();
TryAddWearable(agent.AgentID, wearables, WearableType.Shape, agent.ShapeItem);
TryAddWearable(agent.AgentID, wearables, WearableType.Skin, agent.SkinItem);
TryAddWearable(agent.AgentID, wearables, WearableType.Hair, agent.HairItem);
TryAddWearable(agent.AgentID, wearables, WearableType.Eyes, agent.EyesItem);
TryAddWearable(agent.AgentID, wearables, WearableType.Shirt, agent.ShirtItem);
TryAddWearable(agent.AgentID, wearables, WearableType.Pants, agent.PantsItem);
TryAddWearable(agent.AgentID, wearables, WearableType.Shoes, agent.ShoesItem);
TryAddWearable(agent.AgentID, wearables, WearableType.Socks, agent.SocksItem);
TryAddWearable(agent.AgentID, wearables, WearableType.Jacket, agent.JacketItem);
TryAddWearable(agent.AgentID, wearables, WearableType.Gloves, agent.GlovesItem);
TryAddWearable(agent.AgentID, wearables, WearableType.Undershirt, agent.UndershirtItem);
TryAddWearable(agent.AgentID, wearables, WearableType.Underpants, agent.UnderpantsItem);
TryAddWearable(agent.AgentID, wearables, WearableType.Skirt, agent.SkirtItem);
return wearables;
}
@@ -178,126 +193,24 @@ namespace Simian.Extensions
AgentWearablesUpdatePacket update = new AgentWearablesUpdatePacket();
update.AgentData.AgentID = agent.AgentID;
// Count the number of WearableData blocks needed
int wearableCount = CountWearables(agent);
Dictionary<WearableType, InventoryItem> wearables = GetCurrentWearables(agent);
update.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[wearables.Count];
int i = 0;
update.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[wearableCount];
#region WearableData Blocks
if (agent.ShapeAsset != UUID.Zero)
foreach (KeyValuePair<WearableType, InventoryItem> kvp in wearables)
{
update.WearableData[i] = new AgentWearablesUpdatePacket.WearableDataBlock();
update.WearableData[i].AssetID = agent.ShapeAsset;
update.WearableData[i].ItemID = agent.ShapeItem;
update.WearableData[i].WearableType = (byte)WearableType.Shape;
update.WearableData[i].AssetID = kvp.Value.AssetID;
update.WearableData[i].ItemID = kvp.Value.ID;
update.WearableData[i].WearableType = (byte)kvp.Key;
++i;
}
if (agent.SkinAsset != UUID.Zero)
{
update.WearableData[i] = new AgentWearablesUpdatePacket.WearableDataBlock();
update.WearableData[i].AssetID = agent.SkinAsset;
update.WearableData[i].ItemID = agent.SkinItem;
update.WearableData[i].WearableType = (byte)WearableType.Skin;
++i;
}
if (agent.HairAsset != UUID.Zero)
{
update.WearableData[i] = new AgentWearablesUpdatePacket.WearableDataBlock();
update.WearableData[i].AssetID = agent.HairAsset;
update.WearableData[i].ItemID = agent.HairItem;
update.WearableData[i].WearableType = (byte)WearableType.Hair;
++i;
}
if (agent.EyesAsset != UUID.Zero)
{
update.WearableData[i] = new AgentWearablesUpdatePacket.WearableDataBlock();
update.WearableData[i].AssetID = agent.EyesAsset;
update.WearableData[i].ItemID = agent.EyesItem;
update.WearableData[i].WearableType = (byte)WearableType.Eyes;
++i;
}
if (agent.ShirtAsset != UUID.Zero)
{
update.WearableData[i] = new AgentWearablesUpdatePacket.WearableDataBlock();
update.WearableData[i].AssetID = agent.ShirtAsset;
update.WearableData[i].ItemID = agent.ShirtItem;
update.WearableData[i].WearableType = (byte)WearableType.Shirt;
++i;
}
if (agent.PantsAsset != UUID.Zero)
{
update.WearableData[i] = new AgentWearablesUpdatePacket.WearableDataBlock();
update.WearableData[i].AssetID = agent.PantsAsset;
update.WearableData[i].ItemID = agent.PantsItem;
update.WearableData[i].WearableType = (byte)WearableType.Pants;
++i;
}
if (agent.ShoesAsset != UUID.Zero)
{
update.WearableData[i] = new AgentWearablesUpdatePacket.WearableDataBlock();
update.WearableData[i].AssetID = agent.ShoesAsset;
update.WearableData[i].ItemID = agent.ShoesItem;
update.WearableData[i].WearableType = (byte)WearableType.Shoes;
++i;
}
if (agent.SocksAsset != UUID.Zero)
{
update.WearableData[i] = new AgentWearablesUpdatePacket.WearableDataBlock();
update.WearableData[i].AssetID = agent.SocksAsset;
update.WearableData[i].ItemID = agent.SocksItem;
update.WearableData[i].WearableType = (byte)WearableType.Socks;
++i;
}
if (agent.JacketAsset != UUID.Zero)
{
update.WearableData[i] = new AgentWearablesUpdatePacket.WearableDataBlock();
update.WearableData[i].AssetID = agent.JacketAsset;
update.WearableData[i].ItemID = agent.JacketItem;
update.WearableData[i].WearableType = (byte)WearableType.Jacket;
++i;
}
if (agent.GlovesAsset != UUID.Zero)
{
update.WearableData[i] = new AgentWearablesUpdatePacket.WearableDataBlock();
update.WearableData[i].AssetID = agent.GlovesAsset;
update.WearableData[i].ItemID = agent.GlovesItem;
update.WearableData[i].WearableType = (byte)WearableType.Gloves;
++i;
}
if (agent.UndershirtAsset != UUID.Zero)
{
update.WearableData[i] = new AgentWearablesUpdatePacket.WearableDataBlock();
update.WearableData[i].AssetID = agent.UndershirtAsset;
update.WearableData[i].ItemID = agent.UndershirtItem;
update.WearableData[i].WearableType = (byte)WearableType.Undershirt;
++i;
}
if (agent.UnderpantsAsset != UUID.Zero)
{
update.WearableData[i] = new AgentWearablesUpdatePacket.WearableDataBlock();
update.WearableData[i].AssetID = agent.UnderpantsAsset;
update.WearableData[i].ItemID = agent.UnderpantsItem;
update.WearableData[i].WearableType = (byte)WearableType.Underpants;
++i;
}
if (agent.SkirtAsset != UUID.Zero)
{
update.WearableData[i] = new AgentWearablesUpdatePacket.WearableDataBlock();
update.WearableData[i].AssetID = agent.SkirtAsset;
update.WearableData[i].ItemID = agent.SkirtItem;
update.WearableData[i].WearableType = (byte)WearableType.Skirt;
++i;
}
#endregion WearableData Blocks
// Technically this should be per-agent, but if the only requirement is that it
// increments this is easier
update.AgentData.SerialNum = (uint)Interlocked.Increment(ref currentWearablesSerialNum);
Logger.DebugLog(String.Format("Sending info about {0} wearables", wearableCount));
Logger.DebugLog(String.Format("Sending info about {0} wearables", wearables.Count));
Server.UDP.SendPacket(agent.AgentID, update, PacketCategory.Asset);
}
@@ -313,67 +226,49 @@ namespace Simian.Extensions
for (int i = 0; i < wearing.WearableData.Length; i++)
{
UUID assetID = UUID.Zero;
UUID itemID = wearing.WearableData[i].ItemID;
InventoryObject invObj;
if (Server.Inventory.TryGetInventory(agent.AgentID, itemID, out invObj) && invObj is InventoryItem)
assetID = ((InventoryItem)invObj).AssetID;
#region Update Wearables
switch ((WearableType)wearing.WearableData[i].WearableType)
{
case WearableType.Shape:
agent.ShapeAsset = assetID;
agent.ShapeItem = itemID;
break;
case WearableType.Skin:
agent.SkinAsset = assetID;
agent.SkinItem = itemID;
break;
case WearableType.Hair:
agent.HairAsset = assetID;
agent.HairItem = itemID;
break;
case WearableType.Eyes:
agent.EyesAsset = assetID;
agent.EyesItem = itemID;
break;
case WearableType.Shirt:
agent.ShirtAsset = assetID;
agent.ShirtItem = itemID;
break;
case WearableType.Pants:
agent.PantsAsset = assetID;
agent.PantsItem = itemID;
break;
case WearableType.Shoes:
agent.ShoesAsset = assetID;
agent.ShoesItem = itemID;
break;
case WearableType.Socks:
agent.SocksAsset = assetID;
agent.SocksItem = itemID;
break;
case WearableType.Jacket:
agent.JacketAsset = assetID;
agent.JacketItem = itemID;
break;
case WearableType.Gloves:
agent.GlovesAsset = assetID;
agent.GlovesItem = itemID;
break;
case WearableType.Undershirt:
agent.UndershirtAsset = assetID;
agent.UndershirtItem = itemID;
break;
case WearableType.Underpants:
agent.UnderpantsAsset = assetID;
agent.UnderpantsItem = itemID;
break;
case WearableType.Skirt:
agent.SkirtAsset = assetID;
agent.SkirtItem = itemID;
break;
}
@@ -381,7 +276,8 @@ namespace Simian.Extensions
#endregion Update Wearables
}
Logger.DebugLog("Updated agent wearables, new count: " + CountWearables(agent));
// FIXME: GetCurrentWearables() is a very expensive call, remove it from this debug line
Logger.DebugLog("Updated agent wearables, new count: " + GetCurrentWearables(agent).Count);
}
void AgentSetAppearanceHandler(Packet packet, Agent agent)

View File

@@ -81,7 +81,7 @@ namespace Simian.Extensions
CreateItem(agent.AgentID, Utils.BytesToString(create.InventoryBlock.Name), "Created in Simian",
(InventoryType)create.InventoryBlock.InvType, assetType, assetID, parentID,
PermissionMask.All, (PermissionMask)create.InventoryBlock.NextOwnerMask, agent.AgentID,
agent.AgentID, create.InventoryBlock.TransactionID, create.InventoryBlock.CallbackID);
agent.AgentID, create.InventoryBlock.TransactionID, create.InventoryBlock.CallbackID, true);
}
void CreateInventoryFolderHandler(Packet packet, Agent agent)
@@ -137,6 +137,7 @@ namespace Simian.Extensions
item.SalePrice = block.SalePrice;
item.SaleType = (SaleType)block.SaleType;
item.AssetType = (AssetType)block.Type;
item.AssetID = UUID.Combine(block.TransactionID, agent.SecureSessionID);
Logger.DebugLog(String.Format(
"UpdateInventoryItem: CallbackID: {0}, TransactionID: {1}",
@@ -228,14 +229,7 @@ namespace Simian.Extensions
itemBlocks[i] = new InventoryDescendentsPacket.ItemDataBlock();
itemBlocks[i].AssetID = currentItem.AssetID;
itemBlocks[i].BaseMask = (uint)currentItem.Permissions.BaseMask;
itemBlocks[i].CRC = Helpers.InventoryCRC(
(int)Utils.DateTimeToUnixTime(currentItem.CreationDate),
(byte)currentItem.SaleType, (sbyte)currentItem.InventoryType,
(sbyte)currentItem.AssetType, currentItem.AssetID, currentItem.GroupID,
currentItem.SalePrice, currentItem.OwnerID, currentItem.CreatorID, currentItem.ID,
currentItem.ParentID, (uint)currentItem.Permissions.EveryoneMask, currentItem.Flags,
(uint)currentItem.Permissions.NextOwnerMask, (uint)currentItem.Permissions.GroupMask,
(uint)currentItem.Permissions.OwnerMask);
itemBlocks[i].CRC = currentItem.CRC;
itemBlocks[i].CreationDate = (int)Utils.DateTimeToUnixTime(currentItem.CreationDate);
itemBlocks[i].CreatorID = currentItem.CreatorID;
itemBlocks[i].Description = Utils.StringToBytes(currentItem.Description);
@@ -366,11 +360,7 @@ namespace Simian.Extensions
blocks[i].AssetID = item.AssetID;
blocks[i].BaseMask = (uint)item.Permissions.BaseMask;
blocks[i].CRC = Helpers.InventoryCRC((int)Utils.DateTimeToUnixTime(item.CreationDate),
(byte)item.SaleType, (sbyte)item.InventoryType, (sbyte)item.AssetType, item.AssetID, item.GroupID,
item.SalePrice, item.OwnerID, item.CreatorID, item.ID, item.ParentID,
(uint)item.Permissions.EveryoneMask, item.Flags, (uint)item.Permissions.NextOwnerMask,
(uint)item.Permissions.GroupMask, (uint)item.Permissions.OwnerMask);
blocks[i].CRC = item.CRC;
blocks[i].CreationDate = (int)Utils.DateTimeToUnixTime(item.CreationDate);
blocks[i].CreatorID = item.CreatorID;
blocks[i].Description = Utils.StringToBytes(item.Description);
@@ -447,7 +437,7 @@ namespace Simian.Extensions
// Create the copy
CreateItem(agent.AgentID, newName, item.Description, item.InventoryType, item.AssetType,
item.AssetID, folderObj.ID, item.Permissions.OwnerMask, item.Permissions.NextOwnerMask,
agent.AgentID, item.CreatorID, UUID.Zero, block.CallbackID);
agent.AgentID, item.CreatorID, UUID.Zero, block.CallbackID, true);
}
else
{
@@ -477,7 +467,8 @@ namespace Simian.Extensions
UUID newFolderID = block.FolderID;
if (newFolderID == UUID.Zero)
newFolderID = agent.InventoryRoot;
MoveInventory(agentInventory, block.ItemID, newFolderID, Utils.BytesToString(block.NewName));
MoveInventory(agent, agentInventory, block.ItemID, newFolderID, Utils.BytesToString(block.NewName),
UUID.Zero, 0);
}
}
@@ -494,11 +485,64 @@ namespace Simian.Extensions
UUID newFolderID = block.ParentID;
if (newFolderID == UUID.Zero)
newFolderID = agent.InventoryRoot;
MoveInventory(agentInventory, block.FolderID, newFolderID, null);
MoveInventory(agent, agentInventory, block.FolderID, newFolderID, null, UUID.Zero, 0);
}
}
void MoveInventory(Dictionary<UUID, InventoryObject> agentInventory, UUID objectID, UUID newFolderID, string newName)
void SendBulkUpdate(Agent agent, InventoryObject obj, UUID transactionID, uint callbackID)
{
BulkUpdateInventoryPacket update = new BulkUpdateInventoryPacket();
update.AgentData.AgentID = agent.AgentID;
update.AgentData.TransactionID = transactionID;
if (obj is InventoryItem)
{
InventoryItem item = (InventoryItem)obj;
update.FolderData = new BulkUpdateInventoryPacket.FolderDataBlock[0];
update.ItemData = new BulkUpdateInventoryPacket.ItemDataBlock[1];
update.ItemData[0] = new BulkUpdateInventoryPacket.ItemDataBlock();
update.ItemData[0].AssetID = item.AssetID;
update.ItemData[0].BaseMask = (uint)item.Permissions.BaseMask;
update.ItemData[0].CallbackID = callbackID;
update.ItemData[0].CRC = item.CRC;
update.ItemData[0].CreationDate = (int)Utils.DateTimeToUnixTime(item.CreationDate);
update.ItemData[0].CreatorID = item.CreatorID;
update.ItemData[0].Description = Utils.StringToBytes(item.Description);
update.ItemData[0].EveryoneMask = (uint)item.Permissions.EveryoneMask;
update.ItemData[0].Flags = item.Flags;
update.ItemData[0].FolderID = item.ParentID;
update.ItemData[0].GroupID = item.GroupID;
update.ItemData[0].GroupMask = (uint)item.Permissions.GroupMask;
update.ItemData[0].GroupOwned = item.GroupOwned;
update.ItemData[0].InvType = (sbyte)item.InventoryType;
update.ItemData[0].ItemID = item.ID;
update.ItemData[0].Name = Utils.StringToBytes(item.Name);
update.ItemData[0].NextOwnerMask = (uint)item.Permissions.NextOwnerMask;
update.ItemData[0].OwnerID = item.OwnerID;
update.ItemData[0].OwnerMask = (uint)item.Permissions.OwnerMask;
update.ItemData[0].SalePrice = item.SalePrice;
update.ItemData[0].SaleType = (byte)item.SaleType;
update.ItemData[0].Type = (sbyte)item.InventoryType;
}
else
{
InventoryFolder folder = (InventoryFolder)obj;
update.ItemData = new BulkUpdateInventoryPacket.ItemDataBlock[0];
update.FolderData = new BulkUpdateInventoryPacket.FolderDataBlock[1];
update.FolderData[0] = new BulkUpdateInventoryPacket.FolderDataBlock();
update.FolderData[0].FolderID = folder.ID;
update.FolderData[0].Name = Utils.StringToBytes(folder.Name);
update.FolderData[0].ParentID = folder.ParentID;
update.FolderData[0].Type = (sbyte)folder.PreferredType;
}
Server.UDP.SendPacket(agent.AgentID, update, PacketCategory.Inventory);
}
void MoveInventory(Agent agent, Dictionary<UUID, InventoryObject> agentInventory, UUID objectID,
UUID newFolderID, string newName, UUID transactionID, uint callbackID)
{
InventoryObject obj;
if (agentInventory.TryGetValue(objectID, out obj))
@@ -531,6 +575,8 @@ namespace Simian.Extensions
Logger.Log("MoveInventory called with an unknown destination folder " + newFolderID,
Helpers.LogLevel.Warning);
}
SendBulkUpdate(agent, obj, transactionID, callbackID);
}
}
else
@@ -662,7 +708,7 @@ namespace Simian.Extensions
public UUID CreateItem(UUID agentID, string name, string description, InventoryType invType, AssetType type,
UUID assetID, UUID parentID, PermissionMask ownerMask, PermissionMask nextOwnerMask, UUID ownerID,
UUID creatorID, UUID transactionID, uint callbackID)
UUID creatorID, UUID transactionID, uint callbackID, bool sendPacket)
{
Dictionary<UUID, InventoryObject> agentInventory = GetAgentInventory(agentID);
@@ -716,12 +762,7 @@ namespace Simian.Extensions
update.InventoryData[0].BaseMask = (uint)PermissionMask.All;
update.InventoryData[0].CallbackID = callbackID;
update.InventoryData[0].CreationDate = (int)Utils.DateTimeToUnixTime(item.CreationDate);
update.InventoryData[0].CRC =
Helpers.InventoryCRC((int)Utils.DateTimeToUnixTime(item.CreationDate), (byte)item.SaleType,
(sbyte)item.InventoryType, (sbyte)item.AssetType, item.AssetID, item.GroupID, item.SalePrice,
item.OwnerID, item.CreatorID, item.ID, item.ParentID, (uint)item.Permissions.EveryoneMask,
item.Flags, (uint)item.Permissions.NextOwnerMask, (uint)item.Permissions.GroupMask,
(uint)item.Permissions.OwnerMask);
update.InventoryData[0].CRC = item.CRC;
update.InventoryData[0].CreatorID = item.CreatorID;
update.InventoryData[0].Description = Utils.StringToBytes(item.Description);
update.InventoryData[0].EveryoneMask = (uint)item.Permissions.EveryoneMask;
@@ -740,7 +781,9 @@ namespace Simian.Extensions
update.InventoryData[0].SaleType = (byte)item.SaleType;
update.InventoryData[0].Type = (sbyte)item.AssetType;
Server.UDP.SendPacket(agentID, update, PacketCategory.Inventory);
if (sendPacket)
Server.UDP.SendPacket(agentID, update, PacketCategory.Inventory);
return item.ID;
}
else

View File

@@ -565,7 +565,7 @@ namespace Simian.Extensions
InventoryFolder trash = (InventoryFolder)invObj;
Server.Inventory.CreateItem(agent.AgentID, obj.Prim.Properties.Name, obj.Prim.Properties.Description, InventoryType.Object,
AssetType.Object, obj.Prim.ID, trash.ID, PermissionMask.All, PermissionMask.All, agent.AgentID,
obj.Prim.Properties.CreatorID, derez.AgentBlock.TransactionID, 0);
obj.Prim.Properties.CreatorID, derez.AgentBlock.TransactionID, 0, true);
Server.Scene.ObjectRemove(this, obj);
Logger.DebugLog(String.Format("Derezzed prim {0} to agent inventory trash", obj.Prim.LocalID));