* Renaming ObjectPropertiesRequestType to ReportType, filling out the enum Simian: * Added UUIDNameRequest, MultipleObjectUpdate, ObjectDeselect, and RequestObjectPropertiesFamily handlers * Fixed some bugs in object-object collision * Slightly improved prim spawn location (will always be hacky until we have a collision system) git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@2177 52acb1d6-8a22-11de-b505-999d5b087335
293 lines
13 KiB
C#
293 lines
13 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading;
|
|
using OpenMetaverse;
|
|
using OpenMetaverse.Packets;
|
|
|
|
namespace Simian.Extensions
|
|
{
|
|
class AvatarManager : ISimianExtension, IAvatarProvider
|
|
{
|
|
Simian Server;
|
|
int currentWearablesSerialNum = -1;
|
|
int currentAnimSequenceNum = 0;
|
|
|
|
public AvatarManager(Simian server)
|
|
{
|
|
Server = server;
|
|
}
|
|
|
|
public void Start()
|
|
{
|
|
Server.UDPServer.RegisterPacketCallback(PacketType.AvatarPropertiesRequest, new UDPServer.PacketCallback(AvatarPropertiesRequestHandler));
|
|
Server.UDPServer.RegisterPacketCallback(PacketType.AgentWearablesRequest, new UDPServer.PacketCallback(AgentWearablesRequestHandler));
|
|
Server.UDPServer.RegisterPacketCallback(PacketType.AgentIsNowWearing, new UDPServer.PacketCallback(AgentIsNowWearingHandler));
|
|
Server.UDPServer.RegisterPacketCallback(PacketType.AgentSetAppearance, new UDPServer.PacketCallback(AgentSetAppearanceHandler));
|
|
Server.UDPServer.RegisterPacketCallback(PacketType.AgentAnimation, new UDPServer.PacketCallback(AgentAnimationHandler));
|
|
Server.UDPServer.RegisterPacketCallback(PacketType.ViewerEffect, new UDPServer.PacketCallback(ViewerEffectHandler));
|
|
Server.UDPServer.RegisterPacketCallback(PacketType.UUIDNameRequest, new UDPServer.PacketCallback(UUIDNameRequestHandler));
|
|
}
|
|
|
|
public void Stop()
|
|
{
|
|
}
|
|
|
|
public bool SetDefaultAnimation(Agent agent, UUID animID)
|
|
{
|
|
return agent.Animations.SetDefaultAnimation(animID, ref currentAnimSequenceNum);
|
|
}
|
|
|
|
public bool AddAnimation(Agent agent, UUID animID)
|
|
{
|
|
return agent.Animations.Add(animID, ref currentAnimSequenceNum);
|
|
}
|
|
|
|
public bool RemoveAnimation(Agent agent, UUID animID)
|
|
{
|
|
return agent.Animations.Remove(animID);
|
|
}
|
|
|
|
public void SendAnimations(Agent agent)
|
|
{
|
|
AvatarAnimationPacket sendAnim = new AvatarAnimationPacket();
|
|
sendAnim.Sender.ID = agent.AgentID;
|
|
sendAnim.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[1];
|
|
sendAnim.AnimationSourceList[0] = new AvatarAnimationPacket.AnimationSourceListBlock();
|
|
sendAnim.AnimationSourceList[0].ObjectID = agent.AgentID;
|
|
|
|
UUID[] animIDS;
|
|
int[] sequenceNums;
|
|
agent.Animations.GetArrays(out animIDS, out sequenceNums);
|
|
|
|
sendAnim.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animIDS.Length];
|
|
for (int i = 0; i < animIDS.Length; i++)
|
|
{
|
|
sendAnim.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock();
|
|
sendAnim.AnimationList[i].AnimID = animIDS[i];
|
|
sendAnim.AnimationList[i].AnimSequenceID = sequenceNums[i];
|
|
}
|
|
|
|
lock (Server.Agents)
|
|
{
|
|
foreach (Agent recipient in Server.Agents.Values)
|
|
recipient.SendPacket(sendAnim);
|
|
}
|
|
}
|
|
|
|
void AgentAnimationHandler(Packet packet, Agent agent)
|
|
{
|
|
AgentAnimationPacket animPacket = (AgentAnimationPacket)packet;
|
|
bool changed = false;
|
|
|
|
for (int i = 0; i < animPacket.AnimationList.Length; i++)
|
|
{
|
|
AgentAnimationPacket.AnimationListBlock block = animPacket.AnimationList[i];
|
|
|
|
if (block.StartAnim)
|
|
{
|
|
if (agent.Animations.Add(block.AnimID, ref currentAnimSequenceNum))
|
|
changed = true;
|
|
}
|
|
else
|
|
{
|
|
if (agent.Animations.Remove(block.AnimID))
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
if (changed)
|
|
SendAnimations(agent);
|
|
}
|
|
|
|
void ViewerEffectHandler(Packet packet, Agent agent)
|
|
{
|
|
ViewerEffectPacket effect = (ViewerEffectPacket)packet;
|
|
|
|
effect.AgentData.AgentID = UUID.Zero;
|
|
effect.AgentData.SessionID = UUID.Zero;
|
|
|
|
// Broadcast this to everyone
|
|
lock (Server.Agents)
|
|
{
|
|
foreach (Agent recipient in Server.Agents.Values)
|
|
recipient.SendPacket(effect);
|
|
}
|
|
}
|
|
|
|
void AvatarPropertiesRequestHandler(Packet packet, Agent agent)
|
|
{
|
|
AvatarPropertiesRequestPacket request = (AvatarPropertiesRequestPacket)packet;
|
|
|
|
lock (Server.Agents)
|
|
{
|
|
foreach (Agent agt in Server.Agents.Values)
|
|
{
|
|
if (agent.AgentID == request.AgentData.AvatarID)
|
|
{
|
|
AvatarPropertiesReplyPacket reply = new AvatarPropertiesReplyPacket();
|
|
reply.AgentData.AgentID = agt.AgentID;
|
|
reply.AgentData.AvatarID = request.AgentData.AvatarID;
|
|
reply.PropertiesData.AboutText = Utils.StringToBytes("Profile info unavailable");
|
|
reply.PropertiesData.BornOn = Utils.StringToBytes("Unknown");
|
|
reply.PropertiesData.CharterMember = Utils.StringToBytes("Test User");
|
|
reply.PropertiesData.FLAboutText = Utils.StringToBytes("First life info unavailable");
|
|
reply.PropertiesData.Flags = 0;
|
|
//TODO: at least generate static image uuids based on name.
|
|
//this will prevent re-caching the default image for the same av name.
|
|
reply.PropertiesData.FLImageID = agent.AgentID; //temporary hack
|
|
reply.PropertiesData.ImageID = agent.AgentID; //temporary hack
|
|
reply.PropertiesData.PartnerID = UUID.Zero;
|
|
reply.PropertiesData.ProfileURL = Utils.StringToBytes(String.Empty);
|
|
|
|
agent.SendPacket(reply);
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void AgentWearablesRequestHandler(Packet packet, Agent agent)
|
|
{
|
|
AgentWearablesUpdatePacket update = new AgentWearablesUpdatePacket();
|
|
update.AgentData.AgentID = agent.AgentID;
|
|
// 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);
|
|
update.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[5];
|
|
|
|
// TODO: These are hardcoded in for now, should change that
|
|
update.WearableData[0] = new AgentWearablesUpdatePacket.WearableDataBlock();
|
|
update.WearableData[0].AssetID = new UUID("dc675529-7ba5-4976-b91d-dcb9e5e36188");
|
|
update.WearableData[0].ItemID = UUID.Random();
|
|
update.WearableData[0].WearableType = (byte)WearableType.Hair;
|
|
|
|
update.WearableData[1] = new AgentWearablesUpdatePacket.WearableDataBlock();
|
|
update.WearableData[1].AssetID = new UUID("3e8ee2d6-4f21-4a55-832d-77daa505edff");
|
|
update.WearableData[1].ItemID = UUID.Random();
|
|
update.WearableData[1].WearableType = (byte)WearableType.Pants;
|
|
|
|
update.WearableData[2] = new AgentWearablesUpdatePacket.WearableDataBlock();
|
|
update.WearableData[2].AssetID = new UUID("530a2614-052e-49a2-af0e-534bb3c05af0");
|
|
update.WearableData[2].ItemID = UUID.Random();
|
|
update.WearableData[2].WearableType = (byte)WearableType.Shape;
|
|
|
|
update.WearableData[3] = new AgentWearablesUpdatePacket.WearableDataBlock();
|
|
update.WearableData[3].AssetID = new UUID("6a714f37-fe53-4230-b46f-8db384465981");
|
|
update.WearableData[3].ItemID = UUID.Random();
|
|
update.WearableData[3].WearableType = (byte)WearableType.Shirt;
|
|
|
|
update.WearableData[4] = new AgentWearablesUpdatePacket.WearableDataBlock();
|
|
update.WearableData[4].AssetID = new UUID("5f787f25-f761-4a35-9764-6418ee4774c4");
|
|
update.WearableData[4].ItemID = UUID.Random();
|
|
update.WearableData[4].WearableType = (byte)WearableType.Skin;
|
|
|
|
agent.SendPacket(update);
|
|
}
|
|
|
|
void AgentIsNowWearingHandler(Packet packet, Agent agent)
|
|
{
|
|
AgentIsNowWearingPacket wearing = (AgentIsNowWearingPacket)packet;
|
|
|
|
Logger.DebugLog("Updating agent wearables");
|
|
|
|
lock (agent.Wearables)
|
|
{
|
|
agent.Wearables.Clear();
|
|
|
|
for (int i = 0; i < wearing.WearableData.Length; i++)
|
|
agent.Wearables[(WearableType)wearing.WearableData[i].WearableType] = wearing.WearableData[i].ItemID;
|
|
}
|
|
}
|
|
|
|
void AgentSetAppearanceHandler(Packet packet, Agent agent)
|
|
{
|
|
AgentSetAppearancePacket set = (AgentSetAppearancePacket)packet;
|
|
|
|
Logger.DebugLog("Updating avatar appearance");
|
|
|
|
agent.Avatar.Textures = new Primitive.TextureEntry(set.ObjectData.TextureEntry, 0,
|
|
set.ObjectData.TextureEntry.Length);
|
|
|
|
// Update agent visual params
|
|
for (int i = 0; i < set.VisualParam.Length; i++)
|
|
agent.VisualParams[i] = set.VisualParam[i].ParamValue;
|
|
|
|
//TODO: What is WearableData used for?
|
|
|
|
ObjectUpdatePacket update = Movement.BuildFullUpdate(agent.Avatar,
|
|
NameValue.NameValuesToString(agent.Avatar.NameValues), Server.RegionHandle,
|
|
agent.State, agent.Flags | PrimFlags.ObjectYouOwner);
|
|
agent.SendPacket(update);
|
|
|
|
// Send out this appearance to all other connected avatars
|
|
AvatarAppearancePacket appearance = BuildAppearancePacket(agent);
|
|
|
|
lock (Server.Agents)
|
|
{
|
|
foreach (Agent recipient in Server.Agents.Values)
|
|
{
|
|
if (recipient != agent)
|
|
recipient.SendPacket(appearance);
|
|
}
|
|
}
|
|
}
|
|
|
|
void UUIDNameRequestHandler(Packet packet, Agent agent)
|
|
{
|
|
UUIDNameRequestPacket request = (UUIDNameRequestPacket)packet;
|
|
Dictionary<UUID, Agent> replies = new Dictionary<UUID, Agent>(request.UUIDNameBlock.Length);
|
|
|
|
// FIXME: This is messy/slow until we get a proper ISceneProvider
|
|
for (int i = 0; i < request.UUIDNameBlock.Length; i++)
|
|
{
|
|
lock (Server.Agents)
|
|
{
|
|
foreach (Agent curAgent in Server.Agents.Values)
|
|
{
|
|
if (curAgent.AgentID == request.UUIDNameBlock[i].ID)
|
|
{
|
|
replies[curAgent.AgentID] = curAgent;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (replies.Count > 0)
|
|
{
|
|
UUIDNameReplyPacket reply = new UUIDNameReplyPacket();
|
|
reply.UUIDNameBlock = new UUIDNameReplyPacket.UUIDNameBlockBlock[replies.Count];
|
|
|
|
int i = 0;
|
|
foreach (KeyValuePair<UUID, Agent> kvp in replies)
|
|
{
|
|
reply.UUIDNameBlock[i] = new UUIDNameReplyPacket.UUIDNameBlockBlock();
|
|
reply.UUIDNameBlock[i].ID = kvp.Key;
|
|
reply.UUIDNameBlock[i].FirstName = Utils.StringToBytes(kvp.Value.FirstName);
|
|
reply.UUIDNameBlock[i].LastName = Utils.StringToBytes(kvp.Value.LastName);
|
|
}
|
|
|
|
agent.SendPacket(reply);
|
|
}
|
|
}
|
|
|
|
public static AvatarAppearancePacket BuildAppearancePacket(Agent agent)
|
|
{
|
|
AvatarAppearancePacket appearance = new AvatarAppearancePacket();
|
|
appearance.ObjectData.TextureEntry = agent.Avatar.Textures.ToBytes();
|
|
appearance.Sender.ID = agent.AgentID;
|
|
appearance.Sender.IsTrial = false;
|
|
|
|
appearance.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218];
|
|
for (int i = 0; i < 218; i++)
|
|
{
|
|
appearance.VisualParam[i] = new AvatarAppearancePacket.VisualParamBlock();
|
|
appearance.VisualParam[i].ParamValue = agent.VisualParams[i];
|
|
}
|
|
|
|
return appearance;
|
|
}
|
|
}
|
|
}
|