Files
libremetaverse/Programs/Simian/Extensions/ObjectManager.cs
John Hurliman 8106fccdd2 * Changed Primitive.TextureEntry.ToBytes() to GetBytes() to follow naming conventions
* Added Primitive.TreeSpecies and Primitive.ScratchPad
* Converted Primitive.SoundFlags to the new SoundFlags enum
* Added a Utils.BytesToString() overload that accepts index and count parameters
* Added Utils.FloatToUInt16()
[Simian]
* Lots of changes in Simian to use the new unified ISceneProvider.ObjectAddOrUpdate() function
* Update flags are checked to determine the minimum sized packet that needs to be sent out for an update. ImprovedTerseObjectUpdate is working, and started work on ObjectUpdateCached (updates using this will currently not send)
* Adding three new variables to SimulationObject to store attachment-related state

git-svn-id: http://libopenmetaverse.googlecode.com/svn/libopenmetaverse/trunk@2478 52acb1d6-8a22-11de-b505-999d5b087335
2009-03-10 01:54:45 +00:00

766 lines
37 KiB
C#

using System;
using System.Collections.Generic;
using System.Threading;
using ExtensionLoader;
using OpenMetaverse;
using OpenMetaverse.Rendering;
using OpenMetaverse.Packets;
namespace Simian.Extensions
{
public class ObjectManager : IExtension<Simian>
{
Simian server;
public ObjectManager()
{
}
public void Start(Simian server)
{
this.server = server;
server.UDP.RegisterPacketCallback(PacketType.ObjectAdd, new PacketCallback(ObjectAddHandler));
server.UDP.RegisterPacketCallback(PacketType.ObjectAttach, new PacketCallback(ObjectAttachHandler));
server.UDP.RegisterPacketCallback(PacketType.ObjectDuplicate, new PacketCallback(ObjectDuplicateHandler));
server.UDP.RegisterPacketCallback(PacketType.ObjectSelect, new PacketCallback(ObjectSelectHandler));
server.UDP.RegisterPacketCallback(PacketType.ObjectDeselect, new PacketCallback(ObjectDeselectHandler));
server.UDP.RegisterPacketCallback(PacketType.ObjectLink, new PacketCallback(ObjectLinkHandler));
server.UDP.RegisterPacketCallback(PacketType.ObjectDelink, new PacketCallback(ObjectDelinkHandler));
server.UDP.RegisterPacketCallback(PacketType.ObjectShape, new PacketCallback(ObjectShapeHandler));
server.UDP.RegisterPacketCallback(PacketType.ObjectFlagUpdate, new PacketCallback(ObjectFlagUpdateHandler));
server.UDP.RegisterPacketCallback(PacketType.ObjectExtraParams, new PacketCallback(ObjectExtraParamsHandler));
server.UDP.RegisterPacketCallback(PacketType.ObjectImage, new PacketCallback(ObjectImageHandler));
server.UDP.RegisterPacketCallback(PacketType.Undo, new PacketCallback(UndoHandler));
server.UDP.RegisterPacketCallback(PacketType.Redo, new PacketCallback(RedoHandler));
server.UDP.RegisterPacketCallback(PacketType.DeRezObject, new PacketCallback(DeRezObjectHandler));
server.UDP.RegisterPacketCallback(PacketType.MultipleObjectUpdate, new PacketCallback(MultipleObjectUpdateHandler));
server.UDP.RegisterPacketCallback(PacketType.RequestObjectPropertiesFamily, new PacketCallback(RequestObjectPropertiesFamilyHandler));
}
public void Stop()
{
}
void ObjectAddHandler(Packet packet, Agent agent)
{
ObjectAddPacket add = (ObjectAddPacket)packet;
Vector3 position = Vector3.Zero;
Vector3 scale = add.ObjectData.Scale;
PCode pcode = (PCode)add.ObjectData.PCode;
PrimFlags flags = (PrimFlags)add.ObjectData.AddFlags;
//bool bypassRaycast = (add.ObjectData.BypassRaycast == 1);
bool rayEndIsIntersection = (add.ObjectData.RayEndIsIntersection == 1);
#region Position Calculation
if (rayEndIsIntersection)
{
// HACK: Blindly trust where the client tells us to place
position = add.ObjectData.RayEnd;
}
else
{
if (add.ObjectData.RayTargetID != UUID.Zero)
{
SimulationObject obj;
if (server.Scene.TryGetObject(add.ObjectData.RayTargetID, out obj))
{
// Test for a collision with the specified object
position = server.Physics.ObjectCollisionTest(add.ObjectData.RayStart, add.ObjectData.RayEnd, obj);
}
}
if (position == Vector3.Zero)
{
// Test for a collision with the entire scene
position = FullSceneCollisionTest(add.ObjectData.RayStart, add.ObjectData.RayEnd);
}
}
// Position lies on the face of another surface, either terrain of an object.
// Back up along the ray so we are not colliding with the mesh.
// HACK: This is really cheesy and should be done by a collision system
Vector3 rayDir = Vector3.Normalize(add.ObjectData.RayEnd - add.ObjectData.RayStart);
position -= rayDir * scale;
#endregion Position Calculation
#region Foliage Handling
// Set all foliage to phantom
if (pcode == PCode.Grass || pcode == PCode.Tree || pcode == PCode.NewTree)
{
flags |= PrimFlags.Phantom;
if (pcode != PCode.Grass)
{
// Resize based on the foliage type
Tree tree = (Tree)add.ObjectData.State;
switch (tree)
{
case Tree.Cypress1:
case Tree.Cypress2:
scale = new Vector3(4f, 4f, 10f);
break;
default:
scale = new Vector3(4f, 4f, 4f);
break;
}
}
}
#endregion Foliage Handling
// Create an object
Primitive prim = new Primitive();
// TODO: Security check
prim.GroupID = add.AgentData.GroupID;
prim.ID = UUID.Random();
prim.MediaURL = String.Empty;
prim.OwnerID = agent.ID;
prim.Position = position;
prim.PrimData.Material = (Material)add.ObjectData.Material;
prim.PrimData.PathCurve = (PathCurve)add.ObjectData.PathCurve;
prim.PrimData.ProfileCurve = (ProfileCurve)add.ObjectData.ProfileCurve;
prim.PrimData.PathBegin = Primitive.UnpackBeginCut(add.ObjectData.PathBegin);
prim.PrimData.PathEnd = Primitive.UnpackEndCut(add.ObjectData.PathEnd);
prim.PrimData.PathScaleX = Primitive.UnpackPathScale(add.ObjectData.PathScaleX);
prim.PrimData.PathScaleY = Primitive.UnpackPathScale(add.ObjectData.PathScaleY);
prim.PrimData.PathShearX = Primitive.UnpackPathShear((sbyte)add.ObjectData.PathShearX);
prim.PrimData.PathShearY = Primitive.UnpackPathShear((sbyte)add.ObjectData.PathShearY);
prim.PrimData.PathTwist = Primitive.UnpackPathTwist(add.ObjectData.PathTwist);
prim.PrimData.PathTwistBegin = Primitive.UnpackPathTwist(add.ObjectData.PathTwistBegin);
prim.PrimData.PathRadiusOffset = Primitive.UnpackPathTwist(add.ObjectData.PathRadiusOffset);
prim.PrimData.PathTaperX = Primitive.UnpackPathTaper(add.ObjectData.PathTaperX);
prim.PrimData.PathTaperY = Primitive.UnpackPathTaper(add.ObjectData.PathTaperY);
prim.PrimData.PathRevolutions = Primitive.UnpackPathRevolutions(add.ObjectData.PathRevolutions);
prim.PrimData.PathSkew = Primitive.UnpackPathTwist(add.ObjectData.PathSkew);
prim.PrimData.ProfileBegin = Primitive.UnpackBeginCut(add.ObjectData.ProfileBegin);
prim.PrimData.ProfileEnd = Primitive.UnpackEndCut(add.ObjectData.ProfileEnd);
prim.PrimData.ProfileHollow = Primitive.UnpackProfileHollow(add.ObjectData.ProfileHollow);
prim.PrimData.PCode = pcode;
prim.Properties = new Primitive.ObjectProperties();
prim.Properties.CreationDate = DateTime.Now;
prim.Properties.CreatorID = agent.ID;
prim.Properties.Description = String.Empty;
prim.Properties.GroupID = add.AgentData.GroupID;
prim.Properties.LastOwnerID = agent.ID;
prim.Properties.Name = "New Object";
prim.Properties.ObjectID = prim.ID;
prim.Properties.OwnerID = prim.OwnerID;
prim.Properties.Permissions = server.Permissions.GetDefaultPermissions();
prim.Properties.SalePrice = 10;
prim.RegionHandle = server.Scene.RegionHandle;
prim.Rotation = add.ObjectData.Rotation;
prim.Scale = scale;
prim.TextColor = Color4.Black;
// Add this prim to the object database
SimulationObject simObj = new SimulationObject(prim, server);
server.Scene.ObjectAddOrUpdate(this, simObj, agent.ID, 0, flags, UpdateFlags.FullUpdate);
}
void ObjectAttachHandler(Packet packet, Agent agent)
{
ObjectAttachPacket attach = (ObjectAttachPacket)packet;
for (int i = 0; i < attach.ObjectData.Length; i++)
{
SimulationObject obj;
if (server.Scene.TryGetObject(attach.ObjectData[i].ObjectLocalID, out obj))
{
obj.BeforeAttachmentRotation = attach.ObjectData[i].Rotation;
obj.Prim.ParentID = agent.Avatar.Prim.LocalID;
obj.Prim.Position = obj.AttachmentPosition;
obj.Prim.Rotation = obj.AttachmentRotation;
AttachmentPoint point = (AttachmentPoint)attach.AgentData.AttachmentPoint;
obj.Prim.PrimData.AttachmentPoint = (point == AttachmentPoint.Default ? obj.LastAttachmentPoint : point);
// Send an update out to everyone
server.Scene.ObjectAddOrUpdate(this, obj, agent.ID, 0, obj.Prim.Flags,
UpdateFlags.ParentID | UpdateFlags.Position | UpdateFlags.Rotation | UpdateFlags.AttachmentPoint);
}
}
}
void ObjectDuplicateHandler(Packet packet, Agent agent)
{
ObjectDuplicatePacket duplicate = (ObjectDuplicatePacket)packet;
PrimFlags flags = (PrimFlags)duplicate.SharedData.DuplicateFlags;
Vector3 offset = duplicate.SharedData.Offset;
for (int i = 0; i < duplicate.ObjectData.Length; i++)
{
uint dupeID = duplicate.ObjectData[i].ObjectLocalID;
SimulationObject obj;
if (server.Scene.TryGetObject(dupeID, out obj))
{
SimulationObject newObj = new SimulationObject(obj);
newObj.Prim.Position += offset;
newObj.Prim.ID = UUID.Zero;
newObj.Prim.LocalID = 0;
newObj.Prim.Properties.CreationDate = DateTime.Now;
server.Scene.ObjectAddOrUpdate(this, newObj, agent.ID, 0, flags, UpdateFlags.FullUpdate);
}
else
{
Logger.Log("ObjectDuplicate sent for missing object " + dupeID,
Helpers.LogLevel.Warning);
KillObjectPacket kill = new KillObjectPacket();
kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1];
kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock();
kill.ObjectData[0].ID = dupeID;
server.UDP.SendPacket(agent.ID, kill, PacketCategory.State);
}
}
}
void ObjectSelectHandler(Packet packet, Agent agent)
{
ObjectSelectPacket select = (ObjectSelectPacket)packet;
for (int i = 0; i < select.ObjectData.Length; i++)
{
ObjectPropertiesPacket properties = new ObjectPropertiesPacket();
properties.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[1];
properties.ObjectData[0] = new ObjectPropertiesPacket.ObjectDataBlock();
SimulationObject obj;
if (server.Scene.TryGetObject(select.ObjectData[i].ObjectLocalID, out obj))
{
//Logger.DebugLog("Selecting object " + obj.Prim.LocalID);
properties.ObjectData[0].BaseMask = (uint)obj.Prim.Properties.Permissions.BaseMask;
properties.ObjectData[0].CreationDate = Utils.DateTimeToUnixTime(obj.Prim.Properties.CreationDate);
properties.ObjectData[0].CreatorID = obj.Prim.Properties.CreatorID;
properties.ObjectData[0].Description = Utils.StringToBytes(obj.Prim.Properties.Description);
properties.ObjectData[0].EveryoneMask = (uint)obj.Prim.Properties.Permissions.EveryoneMask;
properties.ObjectData[0].GroupID = obj.Prim.Properties.GroupID;
properties.ObjectData[0].GroupMask = (uint)obj.Prim.Properties.Permissions.GroupMask;
properties.ObjectData[0].LastOwnerID = obj.Prim.Properties.LastOwnerID;
properties.ObjectData[0].Name = Utils.StringToBytes(obj.Prim.Properties.Name);
properties.ObjectData[0].NextOwnerMask = (uint)obj.Prim.Properties.Permissions.NextOwnerMask;
properties.ObjectData[0].ObjectID = obj.Prim.ID;
properties.ObjectData[0].OwnerID = obj.Prim.Properties.OwnerID;
properties.ObjectData[0].OwnerMask = (uint)obj.Prim.Properties.Permissions.OwnerMask;
properties.ObjectData[0].OwnershipCost = obj.Prim.Properties.OwnershipCost;
properties.ObjectData[0].SalePrice = obj.Prim.Properties.SalePrice;
properties.ObjectData[0].SaleType = (byte)obj.Prim.Properties.SaleType;
properties.ObjectData[0].SitName = Utils.StringToBytes(obj.Prim.Properties.SitName);
properties.ObjectData[0].TextureID = Utils.EmptyBytes; // FIXME: What is this?
properties.ObjectData[0].TouchName = Utils.StringToBytes(obj.Prim.Properties.TouchName);
server.UDP.SendPacket(agent.ID, properties, PacketCategory.Transaction);
}
else
{
Logger.Log("ObjectSelect sent for missing object " + select.ObjectData[i].ObjectLocalID,
Helpers.LogLevel.Warning);
properties.ObjectData[0].Description = Utils.EmptyBytes;
properties.ObjectData[0].Name = Utils.EmptyBytes;
properties.ObjectData[0].SitName = Utils.EmptyBytes;
properties.ObjectData[0].TextureID = Utils.EmptyBytes;
properties.ObjectData[0].TouchName = Utils.EmptyBytes;
KillObjectPacket kill = new KillObjectPacket();
kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1];
kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock();
kill.ObjectData[0].ID = select.ObjectData[i].ObjectLocalID;
server.UDP.SendPacket(agent.ID, kill, PacketCategory.State);
}
}
}
void ObjectDeselectHandler(Packet packet, Agent agent)
{
ObjectDeselectPacket deselect = (ObjectDeselectPacket)packet;
for (int i = 0; i < deselect.ObjectData.Length; i++)
{
uint localID = deselect.ObjectData[i].ObjectLocalID;
SimulationObject obj;
if (server.Scene.TryGetObject(localID, out obj))
{
//Logger.DebugLog("Deselecting object " + obj.Prim.LocalID);
}
}
// TODO: Do we need this at all?
}
void ObjectLinkHandler(Packet packet, Agent agent)
{
ObjectLinkPacket link = (ObjectLinkPacket)packet;
List<SimulationObject> linkSet = new List<SimulationObject>();
for (int i = 0; i < link.ObjectData.Length; i++)
{
SimulationObject obj;
if (!server.Scene.TryGetObject(link.ObjectData[i].ObjectLocalID, out obj))
{
//TODO: Send an error message
return;
}
else if (obj.Prim.OwnerID != agent.ID)
{
//TODO: Do a full permissions check
return;
}
else
{
linkSet.Add(obj);
}
}
for (int i = 0; i < linkSet.Count; i++)
{
linkSet[i].LinkNumber = i + 1;
if (linkSet[i].Prim.ParentID > 0)
{
// Previously linked children
SimulationObject parent;
if (server.Scene.TryGetObject(linkSet[i].Prim.ParentID, out parent))
{
// Re-add old root orientation
linkSet[i].Prim.Position = parent.Prim.Position + Vector3.Transform(linkSet[i].Prim.Position,
Matrix4.CreateFromQuaternion(parent.Prim.Rotation));
linkSet[i].Prim.Rotation *= parent.Prim.Rotation;
}
}
if (i > 0)
{
// Subtract root prim orientation
linkSet[i].Prim.Position = Vector3.Transform(linkSet[i].Prim.Position - linkSet[0].Prim.Position,
Matrix4.CreateFromQuaternion(Quaternion.Identity / linkSet[0].Prim.Rotation));
linkSet[i].Prim.Rotation /= linkSet[0].Prim.Rotation;
// Set parent ID
linkSet[i].Prim.ParentID = linkSet[0].Prim.LocalID;
}
else
{
// Root prim
linkSet[i].Prim.ParentID = 0;
}
server.Scene.ObjectAddOrUpdate(this, linkSet[i], agent.ID, 0, linkSet[i].Prim.Flags,
UpdateFlags.Position | UpdateFlags.Rotation | UpdateFlags.ParentID);
}
}
void ObjectDelinkHandler(Packet packet, Agent agent)
{
ObjectDelinkPacket delink = (ObjectDelinkPacket)packet;
List<SimulationObject> linkSet = new List<SimulationObject>();
for (int i = 0; i < delink.ObjectData.Length; i++)
{
SimulationObject obj;
if (!server.Scene.TryGetObject(delink.ObjectData[i].ObjectLocalID, out obj))
{
//TODO: Send an error message
return;
}
else if (obj.Prim.OwnerID != agent.ID)
{
//TODO: Do a full permissions check
return;
}
else
{
linkSet.Add(obj);
}
}
for (int i = 0; i < linkSet.Count; i++)
{
linkSet[i].Prim.ParentID = 0;
linkSet[i].LinkNumber = 0;
// Add root prim orientation to child prims
if (i > 0)
{
linkSet[i].Prim.Position = linkSet[0].Prim.Position + Vector3.Transform(linkSet[i].Prim.Position,
Matrix4.CreateFromQuaternion(linkSet[0].Prim.Rotation));
linkSet[i].Prim.Rotation *= linkSet[0].Prim.Rotation;
}
server.Scene.ObjectAddOrUpdate(this, linkSet[i], agent.ID, 0, linkSet[i].Prim.Flags,
UpdateFlags.Position | UpdateFlags.Rotation | UpdateFlags.ParentID);
}
}
void ObjectShapeHandler(Packet packet, Agent agent)
{
ObjectShapePacket shape = (ObjectShapePacket)packet;
for (int i = 0; i < shape.ObjectData.Length; i++)
{
ObjectShapePacket.ObjectDataBlock block = shape.ObjectData[i];
SimulationObject obj;
if (server.Scene.TryGetObject(block.ObjectLocalID, out obj))
{
Primitive.ConstructionData data = obj.Prim.PrimData;
data.PathBegin = Primitive.UnpackBeginCut(block.PathBegin);
data.PathCurve = (PathCurve)block.PathCurve;
data.PathEnd = Primitive.UnpackEndCut(block.PathEnd);
data.PathRadiusOffset = Primitive.UnpackPathTwist(block.PathRadiusOffset);
data.PathRevolutions = Primitive.UnpackPathRevolutions(block.PathRevolutions);
data.PathScaleX = Primitive.UnpackPathScale(block.PathScaleX);
data.PathScaleY = Primitive.UnpackPathScale(block.PathScaleY);
data.PathShearX = Primitive.UnpackPathShear((sbyte)block.PathShearX);
data.PathShearY = Primitive.UnpackPathShear((sbyte)block.PathShearY);
data.PathSkew = Primitive.UnpackPathTwist(block.PathSkew);
data.PathTaperX = Primitive.UnpackPathTaper(block.PathTaperX);
data.PathTaperY = Primitive.UnpackPathTaper(block.PathTaperY);
data.PathTwist = Primitive.UnpackPathTwist(block.PathTwist);
data.PathTwistBegin = Primitive.UnpackPathTwist(block.PathTwistBegin);
data.ProfileBegin = Primitive.UnpackBeginCut(block.ProfileBegin);
data.profileCurve = block.ProfileCurve;
data.ProfileEnd = Primitive.UnpackEndCut(block.ProfileEnd);
data.ProfileHollow = Primitive.UnpackProfileHollow(block.ProfileHollow);
obj.Prim.PrimData = data;
server.Scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.PrimData);
}
else
{
Logger.Log("Got an ObjectShape packet for unknown object " + block.ObjectLocalID,
Helpers.LogLevel.Warning);
}
}
}
void ObjectFlagUpdateHandler(Packet packet, Agent agent)
{
ObjectFlagUpdatePacket update = (ObjectFlagUpdatePacket)packet;
SimulationObject obj;
if (server.Scene.TryGetObject(update.AgentData.ObjectLocalID, out obj))
{
PrimFlags flags = obj.Prim.Flags;
if (update.AgentData.CastsShadows)
flags |= PrimFlags.CastShadows;
else
flags &= ~PrimFlags.CastShadows;
if (update.AgentData.IsPhantom)
flags |= PrimFlags.Phantom;
else
flags &= ~PrimFlags.Phantom;
if (update.AgentData.IsTemporary)
flags |= PrimFlags.Temporary;
else
flags &= ~PrimFlags.Temporary;
if (update.AgentData.UsePhysics)
flags |= PrimFlags.Physics;
else
flags &= ~PrimFlags.Physics;
obj.Prim.Flags = flags;
server.Scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.PrimFlags);
}
else
{
Logger.Log("Got an ObjectFlagUpdate packet for unknown object " + update.AgentData.ObjectLocalID,
Helpers.LogLevel.Warning);
}
}
void ObjectExtraParamsHandler(Packet packet, Agent agent)
{
ObjectExtraParamsPacket extra = (ObjectExtraParamsPacket)packet;
for (int i = 0; i < extra.ObjectData.Length; i++)
{
ObjectExtraParamsPacket.ObjectDataBlock block = extra.ObjectData[i];
SimulationObject obj;
if (server.Scene.TryGetObject(block.ObjectLocalID, out obj))
{
ExtraParamType type = (ExtraParamType)block.ParamType;
if (block.ParamInUse)
{
switch (type)
{
case ExtraParamType.Flexible:
obj.Prim.Flexible = new Primitive.FlexibleData(block.ParamData, 0);
break;
case ExtraParamType.Light:
obj.Prim.Light = new Primitive.LightData(block.ParamData, 0);
break;
case ExtraParamType.Sculpt:
obj.Prim.Sculpt = new Primitive.SculptData(block.ParamData, 0);
break;
}
}
else
{
switch (type)
{
case ExtraParamType.Flexible:
obj.Prim.Flexible = null;
break;
case ExtraParamType.Light:
obj.Prim.Light = null;
break;
case ExtraParamType.Sculpt:
obj.Prim.Sculpt = null;
break;
}
}
server.Scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.ExtraData);
}
}
}
void ObjectImageHandler(Packet packet, Agent agent)
{
ObjectImagePacket image = (ObjectImagePacket)packet;
for (int i = 0; i < image.ObjectData.Length; i++)
{
SimulationObject obj;
if (server.Scene.TryGetObject(image.ObjectData[i].ObjectLocalID, out obj))
{
obj.Prim.MediaURL = Utils.BytesToString(image.ObjectData[i].MediaURL);
obj.Prim.Textures = new Primitive.TextureEntry(image.ObjectData[i].TextureEntry, 0, image.ObjectData[i].TextureEntry.Length);
server.Scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.MediaURL | UpdateFlags.Textures);
}
}
}
void UndoHandler(Packet packet, Agent agent)
{
UndoPacket undo = (UndoPacket)packet;
for (int i = 0; i < undo.ObjectData.Length; i++)
{
SimulationObject obj;
if (server.Scene.TryGetObject(undo.ObjectData[i].ObjectID, out obj))
server.Scene.ObjectUndo(this, obj);
}
}
void RedoHandler(Packet packet, Agent agent)
{
RedoPacket redo = (RedoPacket)packet;
for (int i = 0; i < redo.ObjectData.Length; i++)
{
SimulationObject obj;
if (server.Scene.TryGetObject(redo.ObjectData[i].ObjectID, out obj))
server.Scene.ObjectRedo(this, obj);
}
}
void DeRezObjectHandler(Packet packet, Agent agent)
{
DeRezObjectPacket derez = (DeRezObjectPacket)packet;
DeRezDestination destination = (DeRezDestination)derez.AgentBlock.Destination;
// TODO: Check permissions
for (int i = 0; i < derez.ObjectData.Length; i++)
{
uint localID = derez.ObjectData[i].ObjectLocalID;
SimulationObject obj;
if (server.Scene.TryGetObject(localID, out obj))
{
switch (destination)
{
case DeRezDestination.AgentInventorySave:
Logger.Log("DeRezObject: Got an AgentInventorySave, DestID: " +
derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning);
break;
case DeRezDestination.AgentInventoryCopy:
Logger.Log("DeRezObject: Got an AgentInventorySave, DestID: " +
derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning);
break;
case DeRezDestination.TaskInventory:
Logger.Log("DeRezObject: Got a TaskInventory, DestID: " +
derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning);
break;
case DeRezDestination.Attachment:
Logger.Log("DeRezObject: Got an Attachment, DestID: " +
derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning);
break;
case DeRezDestination.AgentInventoryTake:
Logger.Log("DeRezObject: Got an AgentInventoryTake, DestID: " +
derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning);
break;
case DeRezDestination.ForceToGodInventory:
Logger.Log("DeRezObject: Got a ForceToGodInventory, DestID: " +
derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning);
break;
case DeRezDestination.TrashFolder:
InventoryObject invObj;
if (server.Inventory.TryGetInventory(agent.ID, derez.AgentBlock.DestinationID, out invObj) &&
invObj is InventoryFolder)
{
// FIXME: Handle children
InventoryFolder trash = (InventoryFolder)invObj;
server.Inventory.CreateItem(agent.ID, obj.Prim.Properties.Name, obj.Prim.Properties.Description, InventoryType.Object,
AssetType.Object, obj.Prim.ID, trash.ID, PermissionMask.All, PermissionMask.All, agent.ID,
obj.Prim.Properties.CreatorID, derez.AgentBlock.TransactionID, 0, true);
server.Scene.ObjectRemove(this, obj.Prim.LocalID);
Logger.DebugLog(String.Format("Derezzed prim {0} to agent inventory trash", obj.Prim.LocalID));
}
else
{
Logger.Log("DeRezObject: Got a TrashFolder with an invalid trash folder: " +
derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning);
}
break;
case DeRezDestination.AttachmentToInventory:
Logger.Log("DeRezObject: Got an AttachmentToInventory, DestID: " +
derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning);
break;
case DeRezDestination.AttachmentExists:
Logger.Log("DeRezObject: Got an AttachmentExists, DestID: " +
derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning);
break;
case DeRezDestination.ReturnToOwner:
Logger.Log("DeRezObject: Got a ReturnToOwner, DestID: " +
derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning);
break;
case DeRezDestination.ReturnToLastOwner:
Logger.Log("DeRezObject: Got a ReturnToLastOwner, DestID: " +
derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning);
break;
}
}
}
}
void MultipleObjectUpdateHandler(Packet packet, Agent agent)
{
MultipleObjectUpdatePacket update = (MultipleObjectUpdatePacket)packet;
for (int i = 0; i < update.ObjectData.Length; i++)
{
bool scaled = false;
MultipleObjectUpdatePacket.ObjectDataBlock block = update.ObjectData[i];
SimulationObject obj;
if (server.Scene.TryGetObject(block.ObjectLocalID, out obj))
{
UpdateType type = (UpdateType)block.Type;
//bool linked = ((type & UpdateType.Linked) != 0);
int pos = 0;
Vector3 position = obj.Prim.Position;
Quaternion rotation = obj.Prim.Rotation;
Vector3 scale = obj.Prim.Scale;
UpdateFlags updateFlags = UpdateFlags.None;
if ((type & UpdateType.Position) != 0)
{
updateFlags |= UpdateFlags.Position;
position = new Vector3(block.Data, pos);
pos += 12;
}
if ((type & UpdateType.Rotation) != 0)
{
updateFlags |= UpdateFlags.Rotation;
rotation = new Quaternion(block.Data, pos, true);
pos += 12;
}
if ((type & UpdateType.Scale) != 0)
{
updateFlags |= UpdateFlags.Scale;
scaled = true;
scale = new Vector3(block.Data, pos);
pos += 12;
// FIXME: Use this in linksets
//bool uniform = ((type & UpdateType.Uniform) != 0);
}
obj.Prim.Position = position;
obj.Prim.Rotation = rotation;
if (scaled) obj.Prim.Scale = scale;
server.Scene.ObjectAddOrUpdate(this, obj, agent.ID, 0, PrimFlags.None, updateFlags);
}
else
{
// Ghosted prim, send a kill message to this agent
KillObjectPacket kill = new KillObjectPacket();
kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1];
kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock();
kill.ObjectData[0].ID = block.ObjectLocalID;
server.UDP.SendPacket(agent.ID, kill, PacketCategory.State);
}
}
}
void RequestObjectPropertiesFamilyHandler(Packet packet, Agent agent)
{
RequestObjectPropertiesFamilyPacket request = (RequestObjectPropertiesFamilyPacket)packet;
ReportType type = (ReportType)request.ObjectData.RequestFlags;
SimulationObject obj;
if (server.Scene.TryGetObject(request.ObjectData.ObjectID, out obj))
{
ObjectPropertiesFamilyPacket props = new ObjectPropertiesFamilyPacket();
props.ObjectData.BaseMask = (uint)obj.Prim.Properties.Permissions.BaseMask;
props.ObjectData.Category = (uint)obj.Prim.Properties.Category;
props.ObjectData.Description = Utils.StringToBytes(obj.Prim.Properties.Description);
props.ObjectData.EveryoneMask = (uint)obj.Prim.Properties.Permissions.EveryoneMask;
props.ObjectData.GroupID = obj.Prim.Properties.GroupID;
props.ObjectData.GroupMask = (uint)obj.Prim.Properties.Permissions.GroupMask;
props.ObjectData.LastOwnerID = obj.Prim.Properties.LastOwnerID;
props.ObjectData.Name = Utils.StringToBytes(obj.Prim.Properties.Name);
props.ObjectData.NextOwnerMask = (uint)obj.Prim.Properties.Permissions.NextOwnerMask;
props.ObjectData.ObjectID = obj.Prim.ID;
props.ObjectData.OwnerID = obj.Prim.Properties.OwnerID;
props.ObjectData.OwnerMask = (uint)obj.Prim.Properties.Permissions.OwnerMask;
props.ObjectData.OwnershipCost = obj.Prim.Properties.OwnershipCost;
props.ObjectData.RequestFlags = (uint)type;
props.ObjectData.SalePrice = obj.Prim.Properties.SalePrice;
props.ObjectData.SaleType = (byte)obj.Prim.Properties.SaleType;
server.UDP.SendPacket(agent.ID, props, PacketCategory.Transaction);
}
else
{
Logger.Log("RequestObjectPropertiesFamily sent for unknown object " +
request.ObjectData.ObjectID.ToString(), Helpers.LogLevel.Warning);
}
}
Vector3 FullSceneCollisionTest(Vector3 rayStart, Vector3 rayEnd)
{
// HACK: For now
Logger.DebugLog("Full scene collision test was requested, ignoring");
return rayEnd;
}
}
}