diff --git a/OpenMetaverse.Http/CapsServer.cs b/OpenMetaverse.Http/CapsServer.cs
index 67d2e9fc..1df5446d 100644
--- a/OpenMetaverse.Http/CapsServer.cs
+++ b/OpenMetaverse.Http/CapsServer.cs
@@ -75,16 +75,14 @@ namespace OpenMetaverse.Http
{
serverOwned = true;
capsHandler = BuildCapsHandler(@"^/caps/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$");
- server = HttpListener.Create(address, port);
- server.LogWriter = new log4netLogWriter(Logger.Log);
+ server = HttpListener.Create(log4netLogWriter.Instance, address, port);
}
public CapsServer(IPAddress address, int port, X509Certificate sslCertificate, X509Certificate rootCA, bool requireClientCertificate)
{
serverOwned = true;
capsHandler = BuildCapsHandler(@"^/caps/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$");
- server = HttpListener.Create(address, port, sslCertificate, rootCA, SslProtocols.Default, requireClientCertificate);
- server.LogWriter = new log4netLogWriter(Logger.Log);
+ server = HttpListener.Create(log4netLogWriter.Instance, address, port, sslCertificate, rootCA, SslProtocols.Default, requireClientCertificate);
}
public CapsServer(HttpListener httpServer, string handlerPath)
diff --git a/OpenMetaverse.Http/log4netLogWriter.cs b/OpenMetaverse.Http/log4netLogWriter.cs
index 5abed1a1..b3361ab3 100644
--- a/OpenMetaverse.Http/log4netLogWriter.cs
+++ b/OpenMetaverse.Http/log4netLogWriter.cs
@@ -6,9 +6,14 @@ namespace OpenMetaverse.Http
{
public class log4netLogWriter : ILogWriter
{
+ ///
+ /// Singleton instance of this class
+ ///
+ public static log4netLogWriter Instance = new log4netLogWriter(Logger.Log);
+
ILog Log;
- public log4netLogWriter(ILog log)
+ log4netLogWriter(ILog log)
{
Log = log;
}
@@ -18,6 +23,7 @@ namespace OpenMetaverse.Http
switch (prio)
{
case LogPrio.Trace:
+ return; // This logging is very noisy
case LogPrio.Debug:
Log.DebugFormat("{0}: {1}", source, message);
break;
diff --git a/Programs/Simian/AnimationSet.cs b/Programs/Simian/AnimationSet.cs
index 3528c538..9f624da9 100644
--- a/Programs/Simian/AnimationSet.cs
+++ b/Programs/Simian/AnimationSet.cs
@@ -131,21 +131,18 @@ namespace Simian
}
}
- public void GetArrays(out UUID[] animIDs, out int[] sequenceNums)
+ public AnimationTrigger[] GetAnimations()
{
lock (animations)
{
- animIDs = new UUID[animations.Count + 1];
- sequenceNums = new int[animations.Count + 1];
+ AnimationTrigger[] triggers = new AnimationTrigger[animations.Count + 1];
- animIDs[0] = defaultAnimation.ID;
- sequenceNums[0] = defaultAnimation.SequenceNum;
+ triggers[0] = new AnimationTrigger(defaultAnimation.ID, defaultAnimation.SequenceNum);
- for (int i = 0; i < animations.Count; ++i)
- {
- animIDs[i + 1] = animations[i].ID;
- sequenceNums[i + 1] = animations[i].SequenceNum;
- }
+ for (int i = 0; i < animations.Count; i++)
+ triggers[i + 1] = new AnimationTrigger(animations[i].ID, animations[i].SequenceNum);
+
+ return triggers;
}
}
diff --git a/Programs/Simian/Extensions/AvatarManager.cs b/Programs/Simian/Extensions/AvatarManager.cs
index edcad733..232860c7 100644
--- a/Programs/Simian/Extensions/AvatarManager.cs
+++ b/Programs/Simian/Extensions/AvatarManager.cs
@@ -71,39 +71,12 @@ namespace Simian.Extensions
public void SendAnimations(Agent agent)
{
- AvatarAnimationPacket sendAnim = new AvatarAnimationPacket();
- sendAnim.Sender.ID = agent.Avatar.ID;
- sendAnim.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[1];
- sendAnim.AnimationSourceList[0] = new AvatarAnimationPacket.AnimationSourceListBlock();
- sendAnim.AnimationSourceList[0].ObjectID = agent.Avatar.ID;
-
- 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];
- }
-
- server.UDP.BroadcastPacket(sendAnim, PacketCategory.State);
+ server.Scene.ObjectAnimate(this, agent.Avatar.ID, agent.Avatar.ID, agent.Animations.GetAnimations());
}
public void TriggerSound(Agent agent, UUID soundID, float gain)
{
- SoundTriggerPacket sound = new SoundTriggerPacket();
- sound.SoundData.Handle = server.Scene.RegionHandle;
- sound.SoundData.ObjectID = agent.Avatar.ID;
- sound.SoundData.ParentID = agent.Avatar.ID;
- sound.SoundData.OwnerID = agent.Avatar.ID;
- sound.SoundData.Position = agent.Avatar.Position;
- sound.SoundData.SoundID = soundID;
- sound.SoundData.Gain = gain;
-
- server.UDP.BroadcastPacket(sound, PacketCategory.State);
+ server.Scene.TriggerSound(this, agent.Avatar.ID, agent.Avatar.ID, agent.Avatar.ID, soundID, agent.Avatar.Position, gain);
}
public void SendAlert(Agent agent, string message)
@@ -142,10 +115,15 @@ namespace Simian.Extensions
{
ViewerEffectPacket effect = (ViewerEffectPacket)packet;
- effect.AgentData.AgentID = UUID.Zero;
- effect.AgentData.SessionID = UUID.Zero;
+ ViewerEffect[] effects = new ViewerEffect[effect.Effect.Length];
- server.UDP.BroadcastPacket(effect, PacketCategory.State);
+ for (int i = 0; i < effects.Length; i++)
+ {
+ ViewerEffectPacket.EffectBlock block = effect.Effect[i];
+ effects[i] = new ViewerEffect(block.ID, (EffectType)block.Type, block.AgentID, new Color4(block.Color, 0, true), block.Duration);
+ }
+
+ server.Scene.TriggerEffects(this, effects);
}
void AvatarPropertiesRequestHandler(Packet packet, Agent agent)
diff --git a/Programs/Simian/Extensions/ImageDelivery.cs b/Programs/Simian/Extensions/ImageDelivery.cs
index 8cba68cb..d4dba396 100644
--- a/Programs/Simian/Extensions/ImageDelivery.cs
+++ b/Programs/Simian/Extensions/ImageDelivery.cs
@@ -46,8 +46,9 @@ namespace Simian.Extensions
}
else
{
+ // No layers, send the full image
DiscardLevel = 0;
- StopPacket = GetPacketForBytePosition(Texture.AssetData.Length);
+ StopPacket = GetPacketForBytePosition(Texture.AssetData.Length - 1);
}
CurrentPacket = Utils.Clamp(packet, 1, TexturePacketCount());
diff --git a/Programs/Simian/Extensions/ObjectManager.cs b/Programs/Simian/Extensions/ObjectManager.cs
index 6bdc09ff..4b274be8 100644
--- a/Programs/Simian/Extensions/ObjectManager.cs
+++ b/Programs/Simian/Extensions/ObjectManager.cs
@@ -538,7 +538,7 @@ namespace Simian.Extensions
{
SimulationObject obj;
if (server.Scene.TryGetObject(image.ObjectData[i].ObjectLocalID, out obj))
- server.Scene.ObjectImage(this, obj,
+ server.Scene.ObjectModifyTextures(this, obj,
Utils.BytesToString(image.ObjectData[i].MediaURL),
new Primitive.TextureEntry(image.ObjectData[i].TextureEntry, 0, image.ObjectData[i].TextureEntry.Length));
}
diff --git a/Programs/Simian/Extensions/SceneManager.cs b/Programs/Simian/Extensions/SceneManager.cs
index c6009685..881aae52 100644
--- a/Programs/Simian/Extensions/SceneManager.cs
+++ b/Programs/Simian/Extensions/SceneManager.cs
@@ -43,11 +43,14 @@ namespace Simian.Extensions
public event ObjectRemoveCallback OnObjectRemove;
public event ObjectTransformCallback OnObjectTransform;
public event ObjectFlagsCallback OnObjectFlags;
- public event ObjectImageCallback OnObjectImage;
public event ObjectModifyCallback OnObjectModify;
+ public event ObjectModifyTexturesCallback OnObjectModifyTextures;
+ public event ObjectAnimateCallback OnObjectAnimate;
public event AgentAddCallback OnAgentAdd;
public event AgentRemoveCallback OnAgentRemove;
public event AgentAppearanceCallback OnAgentAppearance;
+ public event TriggerSoundCallback OnTriggerSound;
+ public event TriggerEffectsCallback OnTriggerEffects;
public event TerrainUpdateCallback OnTerrainUpdate;
public uint RegionX { get { return 7777; } }
@@ -150,6 +153,8 @@ namespace Simian.Extensions
public bool ObjectRemove(object sender, uint localID)
{
SimulationObject obj;
+ Agent agent;
+
if (sceneObjects.TryGetValue(localID, out obj))
{
if (OnObjectRemove != null)
@@ -165,27 +170,22 @@ namespace Simian.Extensions
server.UDP.BroadcastPacket(kill, PacketCategory.State);
return true;
}
+ else if (sceneAgents.TryGetValue(localID, out agent))
+ {
+ AgentRemove(sender, agent);
+ return true;
+ }
else
{
- Agent agent;
- if (sceneAgents.TryGetValue(localID, out agent))
- {
- if (OnAgentRemove != null)
- OnAgentRemove(sender, agent);
-
- AgentRemove(agent);
- return true;
- }
- else
- {
- return false;
- }
+ return false;
}
}
public bool ObjectRemove(object sender, UUID id)
{
SimulationObject obj;
+ Agent agent;
+
if (sceneObjects.TryGetValue(id, out obj))
{
if (OnObjectRemove != null)
@@ -201,26 +201,22 @@ namespace Simian.Extensions
server.UDP.BroadcastPacket(kill, PacketCategory.State);
return true;
}
+ else if (sceneAgents.TryGetValue(id, out agent))
+ {
+ AgentRemove(sender, agent);
+ return true;
+ }
else
{
- Agent agent;
- if (sceneAgents.TryGetValue(id, out agent))
- {
- if (OnAgentRemove != null)
- OnAgentRemove(sender, agent);
-
- AgentRemove(agent);
- return true;
- }
- else
- {
- return false;
- }
+ return false;
}
}
- void AgentRemove(Agent agent)
+ void AgentRemove(object sender, Agent agent)
{
+ if (OnAgentRemove != null)
+ OnAgentRemove(sender, agent);
+
Logger.Log("Removing agent " + agent.FullName + " from the scene", Helpers.LogLevel.Info);
sceneAgents.Remove(agent.Avatar.LocalID, agent.Avatar.ID);
@@ -304,21 +300,6 @@ namespace Simian.Extensions
BroadcastObjectUpdate(obj.Prim);
}
- public void ObjectImage(object sender, SimulationObject obj, string mediaURL, Primitive.TextureEntry textureEntry)
- {
- if (OnObjectImage != null)
- {
- OnObjectImage(sender, obj, mediaURL, textureEntry);
- }
-
- // Update the object
- obj.Prim.Textures = textureEntry;
- obj.Prim.MediaURL = mediaURL;
-
- // Inform clients
- BroadcastObjectUpdate(obj.Prim);
- }
-
public void ObjectModify(object sender, uint localID, Primitive.ConstructionData data)
{
SimulationObject obj;
@@ -337,6 +318,92 @@ namespace Simian.Extensions
}
}
+ public void ObjectModifyTextures(object sender, SimulationObject obj, string mediaURL, Primitive.TextureEntry textureEntry)
+ {
+ if (OnObjectModifyTextures != null)
+ {
+ OnObjectModifyTextures(sender, obj, mediaURL, textureEntry);
+ }
+
+ // Update the object
+ obj.Prim.Textures = textureEntry;
+ obj.Prim.MediaURL = mediaURL;
+
+ // Inform clients
+ BroadcastObjectUpdate(obj.Prim);
+ }
+
+ public void ObjectAnimate(object sender, UUID senderID, UUID objectID, AnimationTrigger[] animations)
+ {
+ if (OnObjectAnimate != null)
+ {
+ OnObjectAnimate(sender, senderID, objectID, animations);
+ }
+
+ AvatarAnimationPacket sendAnim = new AvatarAnimationPacket();
+ sendAnim.Sender.ID = senderID;
+ sendAnim.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[1];
+ sendAnim.AnimationSourceList[0] = new AvatarAnimationPacket.AnimationSourceListBlock();
+ sendAnim.AnimationSourceList[0].ObjectID = objectID;
+
+ sendAnim.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length];
+ for (int i = 0; i < animations.Length; i++)
+ {
+ sendAnim.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock();
+ sendAnim.AnimationList[i].AnimID = animations[i].AnimationID;
+ sendAnim.AnimationList[i].AnimSequenceID = animations[i].SequenceID;
+ }
+
+ server.UDP.BroadcastPacket(sendAnim, PacketCategory.State);
+ }
+
+ public void TriggerSound(object sender, UUID objectID, UUID parentID, UUID ownerID, UUID soundID, Vector3 position, float gain)
+ {
+ if (OnTriggerSound != null)
+ {
+ OnTriggerSound(sender, objectID, parentID, ownerID, soundID, position, gain);
+ }
+
+ SoundTriggerPacket sound = new SoundTriggerPacket();
+ sound.SoundData.Handle = server.Scene.RegionHandle;
+ sound.SoundData.ObjectID = objectID;
+ sound.SoundData.ParentID = parentID;
+ sound.SoundData.OwnerID = ownerID;
+ sound.SoundData.Position = position;
+ sound.SoundData.SoundID = soundID;
+ sound.SoundData.Gain = gain;
+
+ server.UDP.BroadcastPacket(sound, PacketCategory.State);
+ }
+
+ public void TriggerEffects(object sender, ViewerEffect[] effects)
+ {
+ if (OnTriggerEffects != null)
+ {
+ OnTriggerEffects(sender, effects);
+ }
+
+ ViewerEffectPacket effect = new ViewerEffectPacket();
+ effect.AgentData.AgentID = UUID.Zero;
+ effect.AgentData.SessionID = UUID.Zero;
+
+ effect.Effect = new ViewerEffectPacket.EffectBlock[effects.Length];
+
+ for (int i = 0; i < effects.Length; i++)
+ {
+ ViewerEffect currentEffect = effects[i];
+ ViewerEffectPacket.EffectBlock block = new ViewerEffectPacket.EffectBlock();
+
+ block.AgentID = currentEffect.AgentID;
+ block.Color = currentEffect.Color.GetBytes(true);
+ block.Duration = currentEffect.Duration;
+ block.ID = currentEffect.EffectID;
+ block.Type = (byte)currentEffect.Type;
+ }
+
+ server.UDP.BroadcastPacket(effect, PacketCategory.State);
+ }
+
public bool ContainsObject(uint localID)
{
return sceneObjects.ContainsKey(localID) || sceneAgents.ContainsKey(localID);
diff --git a/Programs/Simian/Interfaces/ISceneProvider.cs b/Programs/Simian/Interfaces/ISceneProvider.cs
index d937acaf..4de9cafc 100644
--- a/Programs/Simian/Interfaces/ISceneProvider.cs
+++ b/Programs/Simian/Interfaces/ISceneProvider.cs
@@ -16,18 +16,67 @@ namespace Simian
}
}
+ public struct AnimationTrigger
+ {
+ public UUID AnimationID;
+ public int SequenceID;
+
+ public AnimationTrigger(UUID animationID, int sequenceID)
+ {
+ AnimationID = animationID;
+ SequenceID = sequenceID;
+ }
+ }
+
+ public struct ViewerEffect
+ {
+ public UUID EffectID;
+ public EffectType Type;
+ public UUID AgentID;
+ public Color4 Color;
+ public float Duration;
+
+ public ViewerEffect(UUID effectID, EffectType type, UUID agentID, Color4 color, float duration)
+ {
+ EffectID = effectID;
+ Type = type;
+ AgentID = agentID;
+ Color = color;
+ Duration = duration;
+ }
+ }
+
+ public enum SceneActionType
+ {
+ None = 0,
+ ObjectAdd,
+ ObjectRemove,
+ ObjectTransform,
+ ObjectFlags,
+ ObjectModify,
+ ObjectModifyTextures,
+ ObjectAnimate,
+ AgentAdd,
+ AgentAppearance,
+ TriggerSound,
+ TriggerEffects,
+ TerrainUpdate,
+ }
+
+ //public delegate void SceneActionCallback(SceneActionType type, OSD actionData);
+
public delegate void ObjectAddCallback(object sender, SimulationObject obj, PrimFlags creatorFlags);
public delegate void ObjectRemoveCallback(object sender, SimulationObject obj);
- public delegate void ObjectTransformCallback(object sender, SimulationObject obj, Vector3 position,
- Quaternion rotation, Vector3 velocity, Vector3 acceleration, Vector3 angularVelocity);
+ public delegate void ObjectTransformCallback(object sender, SimulationObject obj, Vector3 position, Quaternion rotation, Vector3 velocity, Vector3 acceleration, Vector3 angularVelocity);
public delegate void ObjectFlagsCallback(object sender, SimulationObject obj, PrimFlags flags);
- public delegate void ObjectImageCallback(object sender, SimulationObject obj,
- string mediaURL, Primitive.TextureEntry textureEntry);
public delegate void ObjectModifyCallback(object sender, SimulationObject obj, Primitive.ConstructionData data);
+ public delegate void ObjectModifyTexturesCallback(object sender, SimulationObject obj, string mediaURL, Primitive.TextureEntry textureEntry);
+ public delegate void ObjectAnimateCallback(object sender, UUID senderID, UUID objectID, AnimationTrigger[] animations);
public delegate void AgentAddCallback(object sender, Agent agent, PrimFlags creatorFlags);
public delegate void AgentRemoveCallback(object sender, Agent agent);
- public delegate void AgentAppearanceCallback(object sender, Agent agent, Primitive.TextureEntry textures,
- byte[] visualParams);
+ public delegate void AgentAppearanceCallback(object sender, Agent agent, Primitive.TextureEntry textures, byte[] visualParams);
+ public delegate void TriggerSoundCallback(object sender, UUID objectID, UUID parentID, UUID ownerID, UUID soundID, Vector3 position, float gain);
+ public delegate void TriggerEffectsCallback(object sender, ViewerEffect[] effects);
public delegate void TerrainUpdateCallback(object sender, uint x, uint y, float[,] patchData);
public interface ISceneProvider
@@ -37,9 +86,13 @@ namespace Simian
event ObjectTransformCallback OnObjectTransform;
event ObjectFlagsCallback OnObjectFlags;
event ObjectModifyCallback OnObjectModify;
+ event ObjectModifyTexturesCallback OnObjectModifyTextures;
+ event ObjectAnimateCallback OnObjectAnimate;
event AgentAddCallback OnAgentAdd;
event AgentRemoveCallback OnAgentRemove;
event AgentAppearanceCallback OnAgentAppearance;
+ event TriggerSoundCallback OnTriggerSound;
+ event TriggerEffectsCallback OnTriggerEffects;
event TerrainUpdateCallback OnTerrainUpdate;
uint RegionX { get; }
@@ -54,26 +107,28 @@ namespace Simian
uint TerrainPatchWidth { get; }
uint TerrainPatchHeight { get; }
- float[,] GetTerrainPatch(uint x, uint y);
void SetTerrainPatch(object sender, uint x, uint y, float[,] patchData);
-
bool ObjectAdd(object sender, SimulationObject obj, PrimFlags creatorFlags);
bool ObjectRemove(object sender, uint localID);
bool ObjectRemove(object sender, UUID id);
- void ObjectTransform(object sender, uint localID, Vector3 position, Quaternion rotation, Vector3 velocity,
- Vector3 acceleration, Vector3 angularVelocity);
+ void ObjectTransform(object sender, uint localID, Vector3 position, Quaternion rotation, Vector3 velocity, Vector3 acceleration, Vector3 angularVelocity);
void ObjectFlags(object sender, SimulationObject obj, PrimFlags flags);
- void ObjectImage(object sender, SimulationObject obj, string mediaURL, Primitive.TextureEntry textureEntry);
void ObjectModify(object sender, uint localID, Primitive.ConstructionData data);
+ void ObjectModifyTextures(object sender, SimulationObject obj, string mediaURL, Primitive.TextureEntry textureEntry);
+ void ObjectAnimate(object sender, UUID senderID, UUID objectID, AnimationTrigger[] animations);
+ void TriggerSound(object sender, UUID objectID, UUID parentID, UUID ownerID, UUID soundID, Vector3 position, float gain);
+ void TriggerEffects(object sender, ViewerEffect[] effects);
+ bool AgentAdd(object sender, Agent agent, PrimFlags creatorFlags);
+ void AgentAppearance(object sender, Agent agent, Primitive.TextureEntry textures, byte[] visualParams);
+
+ float[,] GetTerrainPatch(uint x, uint y);
bool ContainsObject(uint localID);
bool ContainsObject(UUID id);
int ObjectCount();
bool TryGetObject(uint localID, out SimulationObject obj);
bool TryGetObject(UUID id, out SimulationObject obj);
void ForEachObject(Action obj);
-
- bool AgentAdd(object sender, Agent agent, PrimFlags creatorFlags);
- void AgentAppearance(object sender, Agent agent, Primitive.TextureEntry textures, byte[] visualParams);
+
int AgentCount();
bool TryGetAgent(uint localID, out Agent agent);
bool TryGetAgent(UUID id, out Agent agent);
diff --git a/Programs/Simian/Simian.cs b/Programs/Simian/Simian.cs
index beb6d76e..a9bb12ea 100644
--- a/Programs/Simian/Simian.cs
+++ b/Programs/Simian/Simian.cs
@@ -66,7 +66,7 @@ namespace Simian
}
// TODO: SSL support
- HttpServer = HttpListener.Create(IPAddress.Any, HttpPort);
+ HttpServer = HttpListener.Create(log4netLogWriter.Instance, IPAddress.Any, HttpPort);
HttpServer.Start(10);
try
diff --git a/Programs/Simian/SimulationObject.cs b/Programs/Simian/SimulationObject.cs
index db8076ad..bf873d81 100644
--- a/Programs/Simian/SimulationObject.cs
+++ b/Programs/Simian/SimulationObject.cs
@@ -17,8 +17,8 @@ namespace Simian
public bool Frozen;
protected Simian Server;
- protected SimpleMesh[] Meshes = new SimpleMesh[4];
- protected SimpleMesh[] WorldTransformedMeshes = new SimpleMesh[4];
+ protected SimpleMesh[] Meshes;
+ protected SimpleMesh[] WorldTransformedMeshes;
public SimulationObject(SimulationObject obj)
{
@@ -39,6 +39,8 @@ namespace Simian
{
int i = (int)lod;
+ if (Meshes == null) Meshes = new SimpleMesh[4];
+
if (Meshes[i] != null)
{
return Meshes[i];
@@ -56,6 +58,8 @@ namespace Simian
{
int i = (int)lod;
+ if (WorldTransformedMeshes == null) WorldTransformedMeshes = new SimpleMesh[4];
+
if (WorldTransformedMeshes[i] != null)
{
return WorldTransformedMeshes[i];