2008-08-24 05:21:42 +00:00
using System ;
using System.Collections.Generic ;
using System.Threading ;
using OpenMetaverse ;
using OpenMetaverse.Rendering ;
using OpenMetaverse.Packets ;
namespace Simian.Extensions
{
public class ObjectManager : ISimianExtension
{
Simian Server ;
2008-09-04 21:09:44 +00:00
2008-08-24 05:21:42 +00:00
public ObjectManager ( Simian server )
{
Server = server ;
}
public void Start ( )
{
2008-08-28 22:11:47 +00:00
Server . UDP . RegisterPacketCallback ( PacketType . ObjectAdd , new PacketCallback ( ObjectAddHandler ) ) ;
Server . UDP . RegisterPacketCallback ( PacketType . ObjectSelect , new PacketCallback ( ObjectSelectHandler ) ) ;
Server . UDP . RegisterPacketCallback ( PacketType . ObjectDeselect , new PacketCallback ( ObjectDeselectHandler ) ) ;
2008-08-30 22:48:37 +00:00
Server . UDP . RegisterPacketCallback ( PacketType . ObjectLink , new PacketCallback ( ObjectLinkHandler ) ) ;
Server . UDP . RegisterPacketCallback ( PacketType . ObjectDelink , new PacketCallback ( ObjectDelinkHandler ) ) ;
2008-08-28 22:11:47 +00:00
Server . UDP . RegisterPacketCallback ( PacketType . ObjectShape , new PacketCallback ( ObjectShapeHandler ) ) ;
2008-09-06 18:02:38 +00:00
Server . UDP . RegisterPacketCallback ( PacketType . ObjectFlagUpdate , new PacketCallback ( ObjectFlagUpdateHandler ) ) ;
2008-08-28 22:11:47 +00:00
Server . UDP . RegisterPacketCallback ( PacketType . DeRezObject , new PacketCallback ( DeRezObjectHandler ) ) ;
Server . UDP . RegisterPacketCallback ( PacketType . MultipleObjectUpdate , new PacketCallback ( MultipleObjectUpdateHandler ) ) ;
Server . UDP . RegisterPacketCallback ( PacketType . RequestObjectPropertiesFamily , new PacketCallback ( RequestObjectPropertiesFamilyHandler ) ) ;
2008-08-24 05:21:42 +00:00
}
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 ;
2008-09-04 21:09:44 +00:00
if ( Server . Scene . TryGetObject ( add . ObjectData . RayTargetID , out obj ) )
2008-08-24 05:21:42 +00:00
{
// Test for a collision with the specified object
position = 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 ) ;
}
}
2008-08-28 02:38:32 +00:00
// 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 ;
2008-08-27 23:41:25 +00:00
2008-09-06 18:02:38 +00:00
// HACK: Push the prim up a little to keep it from falling through the world
position . Z + = 3.0f ;
2008-08-24 05:21:42 +00:00
#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 ( ) ;
prim . Flags =
PrimFlags . ObjectModify |
PrimFlags . ObjectCopy |
PrimFlags . ObjectAnyOwner |
PrimFlags . ObjectMove |
PrimFlags . ObjectTransfer |
PrimFlags . ObjectOwnerModify ;
// TODO: Security check
prim . GroupID = add . AgentData . GroupID ;
prim . ID = UUID . Random ( ) ;
prim . MediaURL = String . Empty ;
prim . OwnerID = agent . AgentID ;
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 . CreationDate = DateTime . Now ;
prim . Properties . CreatorID = agent . AgentID ;
prim . Properties . Description = String . Empty ;
prim . Properties . GroupID = add . AgentData . GroupID ;
prim . Properties . LastOwnerID = agent . AgentID ;
prim . Properties . Name = "New Object" ;
prim . Properties . ObjectID = prim . ID ;
prim . Properties . OwnerID = prim . OwnerID ;
prim . Properties . Permissions = Permissions . FullPermissions ;
prim . Properties . SalePrice = 10 ;
prim . RegionHandle = Server . RegionHandle ;
prim . Rotation = add . ObjectData . Rotation ;
prim . Scale = scale ;
prim . Textures = new Primitive . TextureEntry ( Primitive . TextureEntry . WHITE_TEXTURE ) ;
prim . TextColor = Color4 . Black ;
// Add this prim to the object database
SimulationObject simObj = new SimulationObject ( prim , Server ) ;
2008-09-08 18:23:16 +00:00
Server . Scene . ObjectAdd ( this , agent , simObj ) ;
2008-08-24 05:21:42 +00:00
}
void ObjectSelectHandler ( Packet packet , Agent agent )
{
ObjectSelectPacket select = ( ObjectSelectPacket ) packet ;
ObjectPropertiesPacket properties = new ObjectPropertiesPacket ( ) ;
properties . ObjectData = new ObjectPropertiesPacket . ObjectDataBlock [ select . ObjectData . Length ] ;
for ( int i = 0 ; i < select . ObjectData . Length ; i + + )
{
properties . ObjectData [ i ] = new ObjectPropertiesPacket . ObjectDataBlock ( ) ;
SimulationObject obj ;
2008-09-04 21:09:44 +00:00
if ( Server . Scene . TryGetObject ( select . ObjectData [ i ] . ObjectLocalID , out obj ) )
2008-08-24 05:21:42 +00:00
{
2008-08-27 23:27:48 +00:00
properties . ObjectData [ i ] . BaseMask = ( uint ) obj . Prim . Properties . Permissions . BaseMask ;
properties . ObjectData [ i ] . CreationDate = Utils . DateTimeToUnixTime ( obj . Prim . Properties . CreationDate ) ;
properties . ObjectData [ i ] . CreatorID = obj . Prim . Properties . CreatorID ;
properties . ObjectData [ i ] . Description = Utils . StringToBytes ( obj . Prim . Properties . Description ) ;
properties . ObjectData [ i ] . EveryoneMask = ( uint ) obj . Prim . Properties . Permissions . EveryoneMask ;
properties . ObjectData [ i ] . GroupID = obj . Prim . Properties . GroupID ;
properties . ObjectData [ i ] . GroupMask = ( uint ) obj . Prim . Properties . Permissions . GroupMask ;
properties . ObjectData [ i ] . LastOwnerID = obj . Prim . Properties . LastOwnerID ;
properties . ObjectData [ i ] . Name = Utils . StringToBytes ( obj . Prim . Properties . Name ) ;
properties . ObjectData [ i ] . NextOwnerMask = ( uint ) obj . Prim . Properties . Permissions . NextOwnerMask ;
properties . ObjectData [ i ] . ObjectID = obj . Prim . ID ;
properties . ObjectData [ i ] . OwnerID = obj . Prim . Properties . OwnerID ;
properties . ObjectData [ i ] . OwnerMask = ( uint ) obj . Prim . Properties . Permissions . OwnerMask ;
properties . ObjectData [ i ] . OwnershipCost = obj . Prim . Properties . OwnershipCost ;
properties . ObjectData [ i ] . SalePrice = obj . Prim . Properties . SalePrice ;
properties . ObjectData [ i ] . SaleType = ( byte ) obj . Prim . Properties . SaleType ;
2008-08-24 05:21:42 +00:00
properties . ObjectData [ i ] . SitName = new byte [ 0 ] ;
properties . ObjectData [ i ] . TextureID = new byte [ 0 ] ;
properties . ObjectData [ i ] . TouchName = new byte [ 0 ] ;
}
2008-09-04 21:09:44 +00:00
else
{
Logger . Log ( "ObjectSelect sent for missing object " + select . ObjectData [ i ] . ObjectLocalID ,
Helpers . LogLevel . Warning ) ;
properties . ObjectData [ i ] . Description = new byte [ 0 ] ;
properties . ObjectData [ i ] . Name = new byte [ 0 ] ;
properties . ObjectData [ i ] . SitName = new byte [ 0 ] ;
properties . ObjectData [ i ] . TextureID = new byte [ 0 ] ;
properties . ObjectData [ i ] . TouchName = new byte [ 0 ] ;
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 . AgentID , kill , PacketCategory . State ) ;
}
2008-08-24 05:21:42 +00:00
}
2008-08-28 22:11:47 +00:00
Server . UDP . SendPacket ( agent . AgentID , properties , PacketCategory . Transaction ) ;
2008-08-24 05:21:42 +00:00
}
2008-08-28 02:38:32 +00:00
void ObjectDeselectHandler ( Packet packet , Agent agent )
{
ObjectDeselectPacket deselect = ( ObjectDeselectPacket ) packet ;
// TODO: Do we need this at all?
}
2008-08-30 22:48:37 +00:00
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 ;
2008-09-04 21:09:44 +00:00
if ( ! Server . Scene . TryGetObject ( link . ObjectData [ i ] . ObjectLocalID , out obj ) )
2008-08-30 22:48:37 +00:00
{
//TODO: send an error message
return ;
}
else if ( obj . Prim . OwnerID ! = agent . AgentID )
{
//TODO: send an error message
return ;
}
else
{
linkSet . Add ( obj ) ;
}
}
ObjectUpdatePacket update = new ObjectUpdatePacket ( ) ;
2008-08-31 00:44:11 +00:00
update . RegionData . RegionHandle = Server . RegionHandle ;
update . RegionData . TimeDilation = UInt16 . MaxValue ;
2008-08-30 22:48:37 +00:00
update . ObjectData = new ObjectUpdatePacket . ObjectDataBlock [ linkSet . Count ] ;
2008-08-31 00:44:11 +00:00
2008-08-30 22:48:37 +00:00
for ( int i = 0 ; i < linkSet . Count ; i + + )
{
linkSet [ i ] . LinkNumber = i + 1 ;
2008-08-31 00:44:11 +00:00
2008-09-04 21:09:44 +00:00
update . ObjectData [ i ] = SimulationObject . BuildUpdateBlock ( linkSet [ i ] . Prim , Server . RegionHandle ,
2008-08-30 22:48:37 +00:00
linkSet [ i ] . Prim . PrimData . State , linkSet [ i ] . Prim . Flags ) ;
2008-08-31 02:03:13 +00:00
if ( linkSet [ i ] . Prim . ParentID > 0 )
{
SimulationObject parent ;
2008-09-04 21:09:44 +00:00
if ( Server . Scene . TryGetObject ( linkSet [ i ] . Prim . ParentID , out parent ) )
2008-08-31 02:03:13 +00:00
{
//re-add old root orientation
linkSet [ i ] . Prim . Position + = parent . Prim . Position ;
linkSet [ i ] . Prim . Rotation * = parent . Prim . Rotation ;
}
}
2008-08-31 00:44:11 +00:00
if ( i > 0 )
2008-08-30 22:48:37 +00:00
{
2008-08-31 00:44:11 +00:00
//subtract root prim orientation
linkSet [ i ] . Prim . Position - = linkSet [ 0 ] . Prim . Position ;
linkSet [ i ] . Prim . Rotation / = linkSet [ 0 ] . Prim . Rotation ;
//set parent ID
2008-08-30 22:48:37 +00:00
update . ObjectData [ i ] . ParentID = linkSet [ 0 ] . Prim . LocalID ;
}
2008-08-31 00:44:11 +00:00
else update . ObjectData [ i ] . ParentID = 0 ;
update . ObjectData [ i ] . ObjectData = SimulationObject . BuildObjectData (
linkSet [ i ] . Prim . Position , linkSet [ i ] . Prim . Rotation ,
Vector3 . Zero , Vector3 . Zero , Vector3 . Zero ) ;
2008-08-30 22:48:37 +00:00
}
Server . UDP . BroadcastPacket ( update , PacketCategory . State ) ;
}
void ObjectDelinkHandler ( Packet packet , Agent agent )
{
2008-08-31 00:44:11 +00:00
ObjectDelinkPacket delink = ( ObjectDelinkPacket ) packet ;
List < SimulationObject > linkSet = new List < SimulationObject > ( ) ;
for ( int i = 0 ; i < delink . ObjectData . Length ; i + + )
{
SimulationObject obj ;
2008-09-04 21:09:44 +00:00
if ( ! Server . Scene . TryGetObject ( delink . ObjectData [ i ] . ObjectLocalID , out obj ) )
2008-08-31 00:44:11 +00:00
{
//TODO: send an error message
return ;
}
else if ( obj . Prim . OwnerID ! = agent . AgentID )
{
//TODO: send an error message
return ;
}
else
{
linkSet . Add ( obj ) ;
}
}
ObjectUpdatePacket update = new ObjectUpdatePacket ( ) ;
update . RegionData . RegionHandle = Server . RegionHandle ;
update . RegionData . TimeDilation = UInt16 . MaxValue ;
update . ObjectData = new ObjectUpdatePacket . ObjectDataBlock [ linkSet . Count ] ;
for ( int i = 0 ; i < linkSet . Count ; i + + )
{
2008-09-04 21:09:44 +00:00
update . ObjectData [ i ] = SimulationObject . BuildUpdateBlock ( linkSet [ i ] . Prim ,
2008-08-31 00:44:11 +00:00
Server . RegionHandle , 0 , linkSet [ i ] . Prim . Flags ) ;
update . ObjectData [ i ] . ParentID = 0 ;
linkSet [ i ] . LinkNumber = 0 ;
//add root prim orientation to child prims
if ( i > 0 )
{
linkSet [ i ] . Prim . Position + = linkSet [ 0 ] . Prim . Position ;
linkSet [ i ] . Prim . Rotation * = linkSet [ 0 ] . Prim . Rotation ;
}
update . ObjectData [ i ] . ObjectData = SimulationObject . BuildObjectData (
linkSet [ i ] . Prim . Position , linkSet [ i ] . Prim . Rotation ,
Vector3 . Zero , Vector3 . Zero , Vector3 . Zero ) ;
}
Server . UDP . BroadcastPacket ( update , PacketCategory . State ) ;
2008-08-30 22:48:37 +00:00
}
2008-08-28 02:55:37 +00:00
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 ;
2008-09-04 21:09:44 +00:00
if ( Server . Scene . TryGetObject ( block . ObjectLocalID , out obj ) )
2008-08-28 02:55:37 +00:00
{
2008-09-08 18:23:16 +00:00
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 ) ;
Server . Scene . ObjectModify ( this , obj , data ) ;
2008-08-28 02:55:37 +00:00
}
else
{
Logger . Log ( "Got an ObjectShape packet for unknown object " + block . ObjectLocalID ,
Helpers . LogLevel . Warning ) ;
}
}
}
2008-09-06 18:02:38 +00:00
void ObjectFlagUpdateHandler ( Packet packet , Agent agent )
{
ObjectFlagUpdatePacket update = ( ObjectFlagUpdatePacket ) packet ;
SimulationObject obj ;
if ( Server . Scene . TryGetObject ( update . AgentData . ObjectLocalID , out obj ) )
{
2008-09-08 18:23:16 +00:00
PrimFlags flags = obj . Prim . Flags ;
2008-09-06 18:02:38 +00:00
if ( update . AgentData . CastsShadows )
2008-09-08 18:23:16 +00:00
flags | = PrimFlags . CastShadows ;
2008-09-06 18:02:38 +00:00
else
2008-09-08 18:23:16 +00:00
flags & = ~ PrimFlags . CastShadows ;
2008-09-06 18:02:38 +00:00
if ( update . AgentData . IsPhantom )
2008-09-08 18:23:16 +00:00
flags | = PrimFlags . Phantom ;
2008-09-06 18:02:38 +00:00
else
2008-09-08 18:23:16 +00:00
flags & = ~ PrimFlags . Phantom ;
2008-09-06 18:02:38 +00:00
if ( update . AgentData . IsTemporary )
2008-09-08 18:23:16 +00:00
flags | = PrimFlags . Temporary ;
2008-09-06 18:02:38 +00:00
else
2008-09-08 18:23:16 +00:00
flags & = ~ PrimFlags . Temporary ;
2008-09-06 18:02:38 +00:00
if ( update . AgentData . UsePhysics )
2008-09-08 18:23:16 +00:00
flags | = PrimFlags . Physics ;
2008-09-06 18:02:38 +00:00
else
2008-09-08 18:23:16 +00:00
flags & = ~ PrimFlags . Physics ;
2008-09-06 18:02:38 +00:00
2008-09-08 18:23:16 +00:00
Server . Scene . ObjectFlags ( this , obj , flags ) ;
2008-09-06 18:02:38 +00:00
}
else
{
Logger . Log ( "Got an ObjectFlagUpdate packet for unknown object " + update . AgentData . ObjectLocalID ,
Helpers . LogLevel . Warning ) ;
}
}
2008-08-27 23:27:48 +00:00
void DeRezObjectHandler ( Packet packet , Agent agent )
{
DeRezObjectPacket derez = ( DeRezObjectPacket ) packet ;
DeRezDestination destination = ( DeRezDestination ) derez . AgentBlock . Destination ;
// TODO: Check permissions
2008-08-28 22:35:19 +00:00
for ( int i = 0 ; i < derez . ObjectData . Length ; i + + )
2008-08-27 23:27:48 +00:00
{
2008-08-28 22:35:19 +00:00
uint localID = derez . ObjectData [ i ] . ObjectLocalID ;
2008-08-27 23:27:48 +00:00
2008-08-28 22:35:19 +00:00
SimulationObject obj ;
2008-09-04 21:09:44 +00:00
if ( Server . Scene . TryGetObject ( localID , out obj ) )
2008-08-28 22:35:19 +00:00
{
switch ( destination )
2008-08-27 23:27:48 +00:00
{
2008-08-28 22:35:19 +00:00
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 ( agent . Inventory . TryGetValue ( derez . AgentBlock . DestinationID , out invObj ) & & invObj is InventoryFolder )
{
// FIXME: Handle children
InventoryFolder trash = ( InventoryFolder ) invObj ;
Server . Inventory . CreateItem ( agent , 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 ) ;
2008-09-08 18:23:16 +00:00
Server . Scene . ObjectRemove ( this , obj ) ;
2008-08-28 22:35:19 +00:00
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: " +
2008-08-27 23:27:48 +00:00
derez . AgentBlock . DestinationID . ToString ( ) , Helpers . LogLevel . Warning ) ;
2008-08-28 22:35:19 +00:00
}
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 ;
2008-08-27 23:27:48 +00:00
}
}
}
}
2008-08-28 02:38:32 +00:00
void MultipleObjectUpdateHandler ( Packet packet , Agent agent )
{
MultipleObjectUpdatePacket update = ( MultipleObjectUpdatePacket ) packet ;
for ( int i = 0 ; i < update . ObjectData . Length ; i + + )
{
MultipleObjectUpdatePacket . ObjectDataBlock block = update . ObjectData [ i ] ;
SimulationObject obj ;
2008-09-04 21:09:44 +00:00
if ( Server . Scene . TryGetObject ( block . ObjectLocalID , out obj ) )
2008-08-28 02:38:32 +00:00
{
UpdateType type = ( UpdateType ) block . Type ;
bool linked = ( ( type & UpdateType . Linked ) ! = 0 ) ;
int pos = 0 ;
2008-09-08 18:23:16 +00:00
Vector3 position = obj . Prim . Position ;
Quaternion rotation = obj . Prim . Rotation ;
Vector3 scale = obj . Prim . Scale ;
2008-08-28 02:38:32 +00:00
if ( ( type & UpdateType . Position ) ! = 0 )
{
2008-09-08 18:23:16 +00:00
position = new Vector3 ( block . Data , pos ) ;
2008-08-28 02:38:32 +00:00
pos + = 12 ;
}
if ( ( type & UpdateType . Rotation ) ! = 0 )
{
2008-09-08 18:23:16 +00:00
rotation = new Quaternion ( block . Data , pos , true ) ;
2008-08-28 02:38:32 +00:00
pos + = 12 ;
}
if ( ( type & UpdateType . Scale ) ! = 0 )
{
2008-09-08 18:23:16 +00:00
scale = new Vector3 ( block . Data , pos ) ;
2008-08-28 02:38:32 +00:00
pos + = 12 ;
2008-09-06 18:02:38 +00:00
// FIXME: Use this in linksets
2008-08-28 02:38:32 +00:00
bool uniform = ( ( type & UpdateType . Uniform ) ! = 0 ) ;
}
2008-09-06 18:02:38 +00:00
// Although the object has already been modified, we need
// to inform the scene manager of the changes so they are
// sent to clients and propagated to other extensions
2008-09-08 18:23:16 +00:00
Server . Scene . ObjectTransform ( this , obj , position , rotation ,
obj . Prim . Velocity , obj . Prim . Acceleration , obj . Prim . AngularVelocity ,
scale ) ;
2008-08-28 02:38:32 +00:00
}
else
{
// Ghosted prim, send a kill message to this agent
// FIXME: Handle children
KillObjectPacket kill = new KillObjectPacket ( ) ;
kill . ObjectData = new KillObjectPacket . ObjectDataBlock [ 1 ] ;
kill . ObjectData [ 0 ] = new KillObjectPacket . ObjectDataBlock ( ) ;
kill . ObjectData [ 0 ] . ID = block . ObjectLocalID ;
2008-08-28 22:11:47 +00:00
Server . UDP . SendPacket ( agent . AgentID , kill , PacketCategory . State ) ;
2008-08-28 02:38:32 +00:00
}
}
}
void RequestObjectPropertiesFamilyHandler ( Packet packet , Agent agent )
{
RequestObjectPropertiesFamilyPacket request = ( RequestObjectPropertiesFamilyPacket ) packet ;
ReportType type = ( ReportType ) request . ObjectData . RequestFlags ;
SimulationObject obj ;
2008-09-04 21:09:44 +00:00
if ( Server . Scene . TryGetObject ( request . ObjectData . ObjectID , out obj ) )
2008-08-28 02:38:32 +00:00
{
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 ;
2008-08-28 22:11:47 +00:00
Server . UDP . SendPacket ( agent . AgentID , props , PacketCategory . Transaction ) ;
2008-08-28 02:38:32 +00:00
}
else
{
Logger . Log ( "RequestObjectPropertiesFamily sent for unknown object " +
request . ObjectData . ObjectID . ToString ( ) , Helpers . LogLevel . Warning ) ;
}
}
2008-08-24 05:21:42 +00:00
Vector3 FullSceneCollisionTest ( Vector3 rayStart , Vector3 rayEnd )
{
// HACK: For now
Logger . DebugLog ( "Full scene collision test was requested, ignoring" ) ;
return rayEnd ;
}
Vector3 ObjectCollisionTest ( Vector3 rayStart , Vector3 rayEnd , SimulationObject obj )
{
const float OO_THREE = 1f / 3f ;
Vector3 closestPoint = rayEnd ;
if ( rayStart = = rayEnd )
{
2008-08-28 02:38:32 +00:00
Logger . DebugLog ( "RayStart is equal to RayEnd, returning given location" ) ;
2008-08-24 05:21:42 +00:00
return closestPoint ;
}
Vector3 direction = Vector3 . Normalize ( rayEnd - rayStart ) ;
Ray ray = new Ray ( rayStart , direction ) ;
// Get the mesh that has been transformed into world-space
SimpleMesh mesh = null ;
2008-08-28 02:38:32 +00:00
if ( obj . Prim . ParentID ! = 0 )
2008-08-24 05:21:42 +00:00
{
SimulationObject parent ;
2008-09-04 21:09:44 +00:00
if ( Server . Scene . TryGetObject ( obj . Prim . ParentID , out parent ) )
2008-08-24 05:21:42 +00:00
mesh = obj . GetWorldMesh ( DetailLevel . Low , parent ) ;
}
else
{
mesh = obj . GetWorldMesh ( DetailLevel . Low , null ) ;
}
if ( mesh ! = null )
{
// Iterate through all of the triangles in the mesh, doing a ray-triangle intersection
float closestDistance = Single . MaxValue ;
for ( int i = 0 ; i < mesh . Indices . Count ; i + = 3 )
{
2008-08-28 02:38:32 +00:00
Vector3 point0 = mesh . Vertices [ mesh . Indices [ i + 0 ] ] . Position ;
Vector3 point1 = mesh . Vertices [ mesh . Indices [ i + 1 ] ] . Position ;
Vector3 point2 = mesh . Vertices [ mesh . Indices [ i + 2 ] ] . Position ;
if ( RayTriangleIntersection ( rayStart , direction , point0 , point1 , point2 ) )
2008-08-24 05:21:42 +00:00
{
2008-08-28 02:38:32 +00:00
// HACK: Find the barycenter of this triangle. Would be better to have
// RayTriangleIntersection return the exact collision point
Vector3 center = ( point0 + point1 + point2 ) * OO_THREE ;
2008-08-24 05:21:42 +00:00
Logger . DebugLog ( "Collision hit with triangle at " + center ) ;
if ( ( center - rayStart ) . Length ( ) < closestDistance )
closestPoint = center ;
}
}
}
return closestPoint ;
}
2008-08-24 22:42:14 +00:00
/// <summary>
/// Adapted from http://www.cs.virginia.edu/~gfx/Courses/2003/ImageSynthesis/papers/Acceleration/Fast%20MinimumStorage%20RayTriangle%20Intersection.pdf
/// </summary>
2008-08-27 23:27:48 +00:00
/// <param name="origin">Origin point of the ray</param>
/// <param name="direction">Unit vector representing the direction of the ray</param>
/// <param name="vert0">Position of the first triangle corner</param>
/// <param name="vert1">Position of the second triangle corner</param>
/// <param name="vert2">Position of the third triangle corner</param>
/// <returns>True if the ray passes through the triangle, otherwise false</returns>
2008-08-24 05:21:42 +00:00
bool RayTriangleIntersection ( Vector3 origin , Vector3 direction , Vector3 vert0 , Vector3 vert1 , Vector3 vert2 )
{
2008-08-24 22:42:14 +00:00
const float EPSILON = 0.00001f ;
Vector3 edge1 , edge2 , pvec ;
float determinant , invDeterminant ;
// Find vectors for two edges sharing vert0
edge1 = vert1 - vert0 ;
edge2 = vert2 - vert0 ;
// Begin calculating the determinant
pvec = Vector3 . Cross ( direction , edge2 ) ;
// If the determinant is near zero, ray lies in plane of triangle
determinant = Vector3 . Dot ( edge1 , pvec ) ;
if ( determinant > - EPSILON & & determinant < EPSILON )
return false ;
invDeterminant = 1f / determinant ;
2008-08-24 05:21:42 +00:00
2008-08-24 22:42:14 +00:00
// Calculate distance from vert0 to ray origin
Vector3 tvec = origin - vert0 ;
// Calculate U parameter and test bounds
float u = Vector3 . Dot ( tvec , pvec ) * invDeterminant ;
if ( u < 0.0f | | u > 1.0f )
return false ;
// Prepare to test V parameter
Vector3 qvec = Vector3 . Cross ( tvec , edge1 ) ;
// Calculate V parameter and test bounds
float v = Vector3 . Dot ( direction , qvec ) * invDeterminant ;
if ( v < 0.0f | | u + v > 1.0f )
return false ;
//t = Vector3.Dot(edge2, qvec) * invDeterminant;
return true ;
}
2008-08-30 22:48:37 +00:00
2008-08-24 05:21:42 +00:00
}
}