| 14 |
using OpenSim.Region.ClientStack; |
using OpenSim.Region.ClientStack; |
| 15 |
using OpenSim.Region.ClientStack.LindenUDP; |
using OpenSim.Region.ClientStack.LindenUDP; |
| 16 |
using ModularRex.RexNetwork.RexLogin; |
using ModularRex.RexNetwork.RexLogin; |
| 17 |
|
using System.Timers; |
| 18 |
|
|
| 19 |
namespace ModularRex.RexNetwork |
namespace ModularRex.RexNetwork |
| 20 |
{ |
{ |
| 932 |
m_log.DebugFormat("[REXCLIENT]: Sending region teleport to client {0}", newRegionEndPoint); |
m_log.DebugFormat("[REXCLIENT]: Sending region teleport to client {0}", newRegionEndPoint); |
| 933 |
base.SendRegionTeleport(regionHandle, simAccess, new IPEndPoint(newRegionEndPoint.Address, udpport), locationID, flags, capsURL); |
base.SendRegionTeleport(regionHandle, simAccess, new IPEndPoint(newRegionEndPoint.Address, udpport), locationID, flags, capsURL); |
| 934 |
} |
} |
| 935 |
|
|
| 936 |
|
#region Avatar terse update |
| 937 |
|
|
| 938 |
|
protected override void InitNewClient() |
| 939 |
|
{ |
| 940 |
|
m_avatarTerseUpdateTimer = new System.Timers.Timer(m_avatarTerseUpdateRate); |
| 941 |
|
m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates); |
| 942 |
|
m_avatarTerseUpdateTimer.AutoReset = false; |
| 943 |
|
|
| 944 |
|
base.InitNewClient(); |
| 945 |
|
} |
| 946 |
|
|
| 947 |
|
private System.Timers.Timer m_avatarTerseUpdateTimer; |
| 948 |
|
private List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); |
| 949 |
|
|
| 950 |
|
/// <summary> |
| 951 |
|
/// Send a terse positional/rotation/velocity update about an avatar |
| 952 |
|
/// to the client. This avatar can be that of the client itself. |
| 953 |
|
/// </summary> |
| 954 |
|
public override void SendAvatarTerseUpdate(ulong regionHandle, |
| 955 |
|
ushort timeDilation, uint localID, Vector3 position, |
| 956 |
|
Vector3 velocity, Quaternion rotation, UUID agentid) |
| 957 |
|
{ |
| 958 |
|
if (rotation.X == rotation.Y && |
| 959 |
|
rotation.Y == rotation.Z && |
| 960 |
|
rotation.Z == rotation.W && rotation.W == 0) |
| 961 |
|
rotation = Quaternion.Identity; |
| 962 |
|
|
| 963 |
|
position.Z = (float)(position.Z - 0.15); |
| 964 |
|
|
| 965 |
|
ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = |
| 966 |
|
RexCreateAvatarImprovedBlock(localID, position, velocity, rotation); |
| 967 |
|
//CreateAvatarImprovedBlock(localID, position, velocity, rotation); |
| 968 |
|
|
| 969 |
|
lock (m_avatarTerseUpdates) |
| 970 |
|
{ |
| 971 |
|
m_avatarTerseUpdates.Add(terseBlock); |
| 972 |
|
|
| 973 |
|
// If packet is full or own movement packet, send it. |
| 974 |
|
if (m_avatarTerseUpdates.Count >= m_avatarTerseUpdatesPerPacket) |
| 975 |
|
{ |
| 976 |
|
ProcessAvatarTerseUpdates(this, null); |
| 977 |
|
} |
| 978 |
|
else if (m_avatarTerseUpdates.Count == 1) |
| 979 |
|
{ |
| 980 |
|
m_avatarTerseUpdateTimer.Start(); |
| 981 |
|
} |
| 982 |
|
} |
| 983 |
|
} |
| 984 |
|
|
| 985 |
|
private void ProcessAvatarTerseUpdates(object sender, ElapsedEventArgs e) |
| 986 |
|
{ |
| 987 |
|
lock (m_avatarTerseUpdates) |
| 988 |
|
{ |
| 989 |
|
ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); |
| 990 |
|
|
| 991 |
|
terse.RegionData = new ImprovedTerseObjectUpdatePacket.RegionDataBlock(); |
| 992 |
|
|
| 993 |
|
terse.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle; |
| 994 |
|
terse.RegionData.TimeDilation = |
| 995 |
|
(ushort)(Scene.TimeDilation * ushort.MaxValue); |
| 996 |
|
|
| 997 |
|
int max = m_avatarTerseUpdatesPerPacket; |
| 998 |
|
if (max > m_avatarTerseUpdates.Count) |
| 999 |
|
max = m_avatarTerseUpdates.Count; |
| 1000 |
|
|
| 1001 |
|
int count = 0; |
| 1002 |
|
int size = 0; |
| 1003 |
|
|
| 1004 |
|
byte[] zerobuffer = new byte[1024]; |
| 1005 |
|
byte[] blockbuffer = new byte[1024]; |
| 1006 |
|
|
| 1007 |
|
for (count = 0; count < max; count++) |
| 1008 |
|
{ |
| 1009 |
|
int length = 0; |
| 1010 |
|
m_avatarTerseUpdates[count].ToBytes(blockbuffer, ref length); |
| 1011 |
|
length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); |
| 1012 |
|
if (size + length > m_packetMTU) |
| 1013 |
|
break; |
| 1014 |
|
size += length; |
| 1015 |
|
} |
| 1016 |
|
|
| 1017 |
|
terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count]; |
| 1018 |
|
|
| 1019 |
|
for (int i = 0; i < count; i++) |
| 1020 |
|
{ |
| 1021 |
|
terse.ObjectData[i] = m_avatarTerseUpdates[0]; |
| 1022 |
|
m_avatarTerseUpdates.RemoveAt(0); |
| 1023 |
|
} |
| 1024 |
|
|
| 1025 |
|
terse.Header.Reliable = false; |
| 1026 |
|
terse.Header.Zerocoded = true; |
| 1027 |
|
OutPacket(terse, ThrottleOutPacketType.Task); |
| 1028 |
|
|
| 1029 |
|
if (m_avatarTerseUpdates.Count == 0) |
| 1030 |
|
m_avatarTerseUpdateTimer.Stop(); |
| 1031 |
|
} |
| 1032 |
|
} |
| 1033 |
|
|
| 1034 |
|
/// <summary> |
| 1035 |
|
/// Creates compressed avatar terse update block. This is about half smaller than the orginal SL |
| 1036 |
|
/// </summary> |
| 1037 |
|
/// <param name="localID"></param> |
| 1038 |
|
/// <param name="pos"></param> |
| 1039 |
|
/// <param name="velocity"></param> |
| 1040 |
|
/// <param name="rotation"></param> |
| 1041 |
|
/// <returns></returns> |
| 1042 |
|
protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock RexCreateAvatarImprovedBlock(uint localID, Vector3 pos, |
| 1043 |
|
Vector3 velocity, |
| 1044 |
|
Quaternion rotation) |
| 1045 |
|
{ |
| 1046 |
|
byte[] bytes = new byte[30]; |
| 1047 |
|
int i = 0; |
| 1048 |
|
ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); |
| 1049 |
|
|
| 1050 |
|
dat.TextureEntry = new byte[0]; |
| 1051 |
|
|
| 1052 |
|
uint ID = localID; |
| 1053 |
|
bytes[i++] = (byte)(ID % 256); |
| 1054 |
|
bytes[i++] = (byte)((ID >> 8) % 256); |
| 1055 |
|
bytes[i++] = (byte)((ID >> 16) % 256); |
| 1056 |
|
bytes[i++] = (byte)((ID >> 24) % 256); |
| 1057 |
|
|
| 1058 |
|
// pos |
| 1059 |
|
byte[] pb = pos.GetBytes(); |
| 1060 |
|
Array.Copy(pb, 0, bytes, i, pb.Length); |
| 1061 |
|
i += 12; |
| 1062 |
|
|
| 1063 |
|
// velocity |
| 1064 |
|
velocity = velocity / 128.0f; |
| 1065 |
|
velocity.X += 1; |
| 1066 |
|
velocity.Y += 1; |
| 1067 |
|
velocity.Z += 1; |
| 1068 |
|
|
| 1069 |
|
ushort InternVelocityX = (ushort)(32768 * velocity.X); |
| 1070 |
|
ushort InternVelocityY = (ushort)(32768 * velocity.Y); |
| 1071 |
|
ushort InternVelocityZ = (ushort)(32768 * velocity.Z); |
| 1072 |
|
bytes[i++] = (byte)(InternVelocityX % 256); |
| 1073 |
|
bytes[i++] = (byte)((InternVelocityX >> 8) % 256); |
| 1074 |
|
bytes[i++] = (byte)(InternVelocityY % 256); |
| 1075 |
|
bytes[i++] = (byte)((InternVelocityY >> 8) % 256); |
| 1076 |
|
bytes[i++] = (byte)(InternVelocityZ % 256); |
| 1077 |
|
bytes[i++] = (byte)((InternVelocityZ >> 8) % 256); |
| 1078 |
|
|
| 1079 |
|
//rotation |
| 1080 |
|
ushort rw = (ushort)(32768 * (rotation.W + 1)); |
| 1081 |
|
ushort rx = (ushort)(32768 * (rotation.X + 1)); |
| 1082 |
|
ushort ry = (ushort)(32768 * (rotation.Y + 1)); |
| 1083 |
|
ushort rz = (ushort)(32768 * (rotation.Z + 1)); |
| 1084 |
|
|
| 1085 |
|
//rot |
| 1086 |
|
bytes[i++] = (byte)(rx % 256); |
| 1087 |
|
bytes[i++] = (byte)((rx >> 8) % 256); |
| 1088 |
|
bytes[i++] = (byte)(ry % 256); |
| 1089 |
|
bytes[i++] = (byte)((ry >> 8) % 256); |
| 1090 |
|
bytes[i++] = (byte)(rz % 256); |
| 1091 |
|
bytes[i++] = (byte)((rz >> 8) % 256); |
| 1092 |
|
bytes[i++] = (byte)(rw % 256); |
| 1093 |
|
bytes[i++] = (byte)((rw >> 8) % 256); |
| 1094 |
|
|
| 1095 |
|
dat.Data = bytes; |
| 1096 |
|
return (dat); |
| 1097 |
|
} |
| 1098 |
|
#endregion |
| 1099 |
} |
} |
| 1100 |
} |
} |