From 5eb3707804d5a510d3fcf458fac5de37be3ef405 Mon Sep 17 00:00:00 2001 From: Date: Thu, 21 Aug 2008 08:36:37 +0000 Subject: [PATCH] Fixed terrain affecting Simian movement speed while flying, merged Chat extension into new Messaging extension, fixed resend timer not cleaning up when avatars are removed, fixed some xml comments git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@2136 52acb1d6-8a22-11de-b505-999d5b087335 --- OpenMetaverse/Types/Color4.cs | 3 + OpenMetaverse/Types/Quaternion.cs | 2 +- Programs/Simian/Agent.cs | 8 ++ .../Simian/Extensions/ConnectionManagement.cs | 1 + Programs/Simian/Extensions/Messaging.cs | 90 +++++++++++++++++++ Programs/Simian/Extensions/Movement.cs | 89 +++++++++++++++--- 6 files changed, 178 insertions(+), 15 deletions(-) create mode 100644 Programs/Simian/Extensions/Messaging.cs diff --git a/OpenMetaverse/Types/Color4.cs b/OpenMetaverse/Types/Color4.cs index ce4b97ce..5ecc2d8b 100644 --- a/OpenMetaverse/Types/Color4.cs +++ b/OpenMetaverse/Types/Color4.cs @@ -85,6 +85,9 @@ namespace OpenMetaverse /// /// Byte array containing a 16 byte color /// Beginning position in the byte array + /// True if the byte array stores inverted values, + /// otherwise false. For example the color black (fully opaque) inverted + /// would be 0xFF 0xFF 0xFF 0x00 public Color4(byte[] byteArray, int pos, bool inverted) { R = G = B = A = 0f; diff --git a/OpenMetaverse/Types/Quaternion.cs b/OpenMetaverse/Types/Quaternion.cs index a6808de4..a52a2869 100644 --- a/OpenMetaverse/Types/Quaternion.cs +++ b/OpenMetaverse/Types/Quaternion.cs @@ -373,7 +373,7 @@ namespace OpenMetaverse /// Creates a quaternion from a vector containing roll, pitch, and yaw /// in radians /// - /// Vector representation of the euler angles in + /// Vector representation of the euler angles in /// radians /// Quaternion representation of the euler angles public static Quaternion CreateFromEulers(Vector3 eulers) diff --git a/Programs/Simian/Agent.cs b/Programs/Simian/Agent.cs index 4c1227b3..a8aa24d7 100644 --- a/Programs/Simian/Agent.cs +++ b/Programs/Simian/Agent.cs @@ -19,6 +19,7 @@ namespace Simian public int Balance; public bool Running; public AgentManager.ControlFlags ControlFlags = AgentManager.ControlFlags.NONE; + public List Animations = new List(); public Dictionary Inventory = new Dictionary(); public Dictionary Library = new Dictionary(); public Dictionary Wearables = new Dictionary(); @@ -59,6 +60,13 @@ namespace Simian Settings.NETWORK_TICK_INTERVAL); } + public void Dispose() + { + ackTimer.Dispose(); + packetArchive.Clear(); + needAcks.Clear(); + } + public void SendPacket(Packet packet) { SendPacket(packet, true); diff --git a/Programs/Simian/Extensions/ConnectionManagement.cs b/Programs/Simian/Extensions/ConnectionManagement.cs index 32621611..3c8bc4dc 100644 --- a/Programs/Simian/Extensions/ConnectionManagement.cs +++ b/Programs/Simian/Extensions/ConnectionManagement.cs @@ -88,6 +88,7 @@ namespace Simian.Extensions kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); kill.ObjectData[0].ID = agent.Avatar.LocalID; + agent.Dispose(); server.Agents.Remove(agent.Address); foreach (Agent recipient in server.Agents.Values) diff --git a/Programs/Simian/Extensions/Messaging.cs b/Programs/Simian/Extensions/Messaging.cs new file mode 100644 index 00000000..d03f09cd --- /dev/null +++ b/Programs/Simian/Extensions/Messaging.cs @@ -0,0 +1,90 @@ +using OpenMetaverse; +using OpenMetaverse.Packets; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; + +namespace Simian.Extensions +{ + public class Messaging : ISimianExtension + { + Simian Server; + + public Messaging(Simian server) + { + Server = server; + } + + public void Start() + { + Server.UDPServer.RegisterPacketCallback(PacketType.ChatFromViewer, new UDPServer.PacketCallback(ChatFromViewerHandler)); + Server.UDPServer.RegisterPacketCallback(PacketType.ImprovedInstantMessage, new UDPServer.PacketCallback(ImprovedInstantMessageHandler)); + } + + public void Stop() + { + } + + void ChatFromViewerHandler(Packet packet, Agent agent) + { + ChatFromViewerPacket viewerChat = (ChatFromViewerPacket)packet; + + if (viewerChat.ChatData.Channel != 0) return; //not public chat + + //TODO: add distance constraints to AudibleLevel and Message + + ChatFromSimulatorPacket chat = new ChatFromSimulatorPacket(); + chat.ChatData.Audible = (byte)ChatAudibleLevel.Fully; + chat.ChatData.ChatType = viewerChat.ChatData.Type; + chat.ChatData.OwnerID = agent.AgentID; + chat.ChatData.SourceID = agent.AgentID; + chat.ChatData.SourceType = (byte)ChatSourceType.Agent; + chat.ChatData.Position = agent.Avatar.Position; + chat.ChatData.FromName = Utils.StringToBytes(agent.Avatar.Name); + chat.ChatData.Message = viewerChat.ChatData.Message; + + lock (Server.Agents) + { + foreach(Agent recipient in Server.Agents.Values) + recipient.SendPacket(chat); + } + } + + void ImprovedInstantMessageHandler(Packet packet, Agent agent) + { + ImprovedInstantMessagePacket im = (ImprovedInstantMessagePacket)packet; + InstantMessageDialog dialog = (InstantMessageDialog)im.MessageBlock.Dialog; + + if (dialog == InstantMessageDialog.MessageFromAgent) + { + lock (Server.Agents) + { + foreach (Agent recipient in Server.Agents.Values) + { + if (recipient.AgentID == im.MessageBlock.ToAgentID) + { + ImprovedInstantMessagePacket sendIM = new ImprovedInstantMessagePacket(); + sendIM.MessageBlock.RegionID = UUID.Random(); //FIXME + sendIM.MessageBlock.ParentEstateID = 1; + sendIM.MessageBlock.FromGroup = false; + sendIM.MessageBlock.FromAgentName = Utils.StringToBytes(agent.Avatar.Name); + sendIM.MessageBlock.ToAgentID = im.MessageBlock.ToAgentID; + sendIM.MessageBlock.Dialog = (byte)InstantMessageDialog.MessageFromAgent; + sendIM.MessageBlock.Offline = (byte)InstantMessageOnline.Online; + sendIM.MessageBlock.ID = agent.AgentID; + sendIM.MessageBlock.Message = im.MessageBlock.Message; + sendIM.MessageBlock.BinaryBucket = new byte[0]; + sendIM.MessageBlock.Timestamp = 0; + sendIM.MessageBlock.Position = agent.Avatar.Position; + recipient.SendPacket(sendIM); + + break; + } + } + } + } + } + + } +} diff --git a/Programs/Simian/Extensions/Movement.cs b/Programs/Simian/Extensions/Movement.cs index 0c80099e..d3d90e4d 100644 --- a/Programs/Simian/Extensions/Movement.cs +++ b/Programs/Simian/Extensions/Movement.cs @@ -11,10 +11,21 @@ namespace Simian.Extensions { Simian Server; Timer UpdateTimer; + long _LastTick; + + const int UPDATE_ITERATION = 100; + + const float WALK_SPEED = 3f; + const float RUN_SPEED = 6f; + const float FLY_SPEED = 12f; + const float SQRT_TWO = 1.41421356f; - const float WALK_SPEED = 0.5f; - const float RUN_SPEED = 1.0f; - const float FLY_SPEED = 1.5f; + + public int LastTick + { + get { return (int) Interlocked.Read(ref _LastTick); } + set { Interlocked.Exchange(ref _LastTick, value); } + } public Movement(Simian server) { @@ -23,13 +34,15 @@ namespace Simian.Extensions public void Start() { + Server.UDPServer.RegisterPacketCallback(PacketType.AgentAnimation, new UDPServer.PacketCallback(AgentAnimationHandler)); Server.UDPServer.RegisterPacketCallback(PacketType.AgentUpdate, new UDPServer.PacketCallback(AgentUpdateHandler)); Server.UDPServer.RegisterPacketCallback(PacketType.AgentHeightWidth, new UDPServer.PacketCallback(AgentHeightWidthHandler)); Server.UDPServer.RegisterPacketCallback(PacketType.SetAlwaysRun, new UDPServer.PacketCallback(SetAlwaysRunHandler)); Server.UDPServer.RegisterPacketCallback(PacketType.ViewerEffect, new UDPServer.PacketCallback(ViewerEffectHandler)); UpdateTimer = new Timer(new TimerCallback(UpdateTimer_Elapsed)); - UpdateTimer.Change(100, 100); + LastTick = Environment.TickCount; + UpdateTimer.Change(UPDATE_ITERATION, UPDATE_ITERATION); } public void Stop() @@ -39,6 +52,10 @@ namespace Simian.Extensions void UpdateTimer_Elapsed(object sender) { + int tick = Environment.TickCount; + float seconds = (float)((tick - LastTick) / 1000f); + LastTick = tick; + lock (Server.Agents) { foreach (Agent agent in Server.Agents.Values) @@ -53,10 +70,15 @@ namespace Simian.Extensions bool heldBack = (agent.ControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG; bool heldLeft = (agent.ControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS; bool heldRight = (agent.ControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG; + bool heldTurnLeft = (agent.ControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT; + bool heldTurnRight = (agent.ControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT; bool heldUp = (agent.ControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS; bool heldDown = (agent.ControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG; bool flying = (agent.ControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) == AgentManager.ControlFlags.AGENT_CONTROL_FLY; - + bool mouselook = (agent.ControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) == AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK; + + float speed = seconds * (flying ? FLY_SPEED : agent.Running ? RUN_SPEED : WALK_SPEED); + Vector3 move = Vector3.Zero; if (heldForward) { move.X += fwd.X; move.Y += fwd.Y; } @@ -68,10 +90,11 @@ namespace Simian.Extensions float newFloor = GetLandHeightAt(agent.Avatar.Position + move); float lowerLimit = newFloor + agent.Avatar.Scale.Z / 2; - float speed = flying ? FLY_SPEED : agent.Running ? RUN_SPEED : WALK_SPEED; if ((heldForward || heldBack) && (heldLeft || heldRight)) speed /= SQRT_TWO; + if (!flying && newFloor != oldFloor) speed /= (1 + (SQRT_TWO * Math.Abs(newFloor - oldFloor))); + if (flying) { if (heldUp) @@ -102,20 +125,34 @@ namespace Simian.Extensions { AgentUpdatePacket update = (AgentUpdatePacket)packet; + agent.Avatar.Rotation = update.AgentData.BodyRotation; + agent.ControlFlags = (AgentManager.ControlFlags)update.AgentData.ControlFlags; + agent.State = update.AgentData.State; + agent.Flags = (LLObject.ObjectFlags)update.AgentData.Flags; + lock (Server.Agents) { - agent.Avatar.Rotation = update.AgentData.BodyRotation; - agent.ControlFlags = (AgentManager.ControlFlags)update.AgentData.ControlFlags; - agent.State = update.AgentData.State; - //agent.Flags = (LLObject.ObjectFlags)update.AgentData.Flags; - ObjectUpdatePacket fullUpdate = BuildFullUpdate(agent, agent.Avatar, Server.RegionHandle, agent.State, agent.Flags); - lock (Server.Agents) + foreach (Agent recipient in Server.Agents.Values) { - foreach (Agent recipient in Server.Agents.Values) - recipient.SendPacket(fullUpdate); + recipient.SendPacket(fullUpdate); + + if (agent.Animations.Count == 0) //TODO: need to start default standing animation + { + agent.Animations.Add(ANIM_STAND); + + AgentAnimationPacket startAnim = new AgentAnimationPacket(); + startAnim.AgentData.AgentID = agent.AgentID; + startAnim.AnimationList = new AgentAnimationPacket.AnimationListBlock[1]; + startAnim.AnimationList[0] = new AgentAnimationPacket.AnimationListBlock(); + startAnim.AnimationList[0].AnimID = ANIM_STAND; + startAnim.AnimationList[0].StartAnim = true; + startAnim.PhysicalAvatarEventList = new AgentAnimationPacket.PhysicalAvatarEventListBlock[0]; + + recipient.SendPacket(startAnim); + } } } } @@ -156,6 +193,30 @@ namespace Simian.Extensions return ((lerpX + lerpY) / 2); } + void AgentAnimationHandler(Packet packet, Agent agent) + { + AgentAnimationPacket anim = (AgentAnimationPacket)packet; + anim.AgentData.SessionID = UUID.Zero; + + lock (agent.Animations) + { + foreach (AgentAnimationPacket.AnimationListBlock block in anim.AnimationList) + { + if (agent.Animations.Contains(block.AnimID)) + { + if (!block.StartAnim) agent.Animations.Remove(block.AnimID); + } + else if (block.StartAnim) agent.Animations.Add(block.AnimID); + } + } + + lock (Server.Agents) + { + foreach (Agent recipient in Server.Agents.Values) + recipient.SendPacket(anim); + } + } + void AgentHeightWidthHandler(Packet packet, Agent agent) { AgentHeightWidthPacket heightWidth = (AgentHeightWidthPacket)packet;