From 5fb81ab881adedb139369ef0bad19a80453ea129 Mon Sep 17 00:00:00 2001 From: Sean Dague Date: Wed, 28 Nov 2007 13:33:57 +0000 Subject: merged ClientView into a non partial class. Will make it easier to start breaking this up into more discreet functional classes --- OpenSim/Region/ClientStack/ClientView.cs | 3091 +++++++++++++++++++++++++++++- 1 file changed, 3090 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack/ClientView.cs') diff --git a/OpenSim/Region/ClientStack/ClientView.cs b/OpenSim/Region/ClientStack/ClientView.cs index 28692bb..0933453 100644 --- a/OpenSim/Region/ClientStack/ClientView.cs +++ b/OpenSim/Region/ClientStack/ClientView.cs @@ -28,9 +28,11 @@ using System; using System.Collections.Generic; using System.Net; +using System.Net.Sockets; using System.Text; using System.Threading; using System.Timers; +using Axiom.Math; using libsecondlife; using libsecondlife.Packets; using OpenSim.Framework; @@ -46,7 +48,7 @@ namespace OpenSim.Region.ClientStack /// Handles new client connections /// Constructor takes a single Packet and authenticates everything /// - public partial class ClientView : IClientAPI + public class ClientView : IClientAPI { public static TerrainManager TerrainManager; @@ -552,5 +554,3092 @@ namespace OpenSim.Region.ClientStack { ClientThread.Abort(); } + + // Previously ClientView.API partial class + public event Action OnLogout; + public event Action OnConnectionClosed; + public event ViewerEffectEventHandler OnViewerEffect; + public event ImprovedInstantMessage OnInstantMessage; + public event ChatFromViewer OnChatFromViewer; + public event TextureRequest OnRequestTexture; + public event RezObject OnRezObject; + public event GenericCall4 OnDeRezObject; + public event ModifyTerrain OnModifyTerrain; + public event Action OnRegionHandShakeReply; + public event GenericCall2 OnRequestWearables; + public event SetAppearance OnSetAppearance; + public event GenericCall2 OnCompleteMovementToRegion; + public event UpdateAgent OnAgentUpdate; + public event AgentRequestSit OnAgentRequestSit; + public event AgentSit OnAgentSit; + public event AvatarPickerRequest OnAvatarPickerRequest; + public event StartAnim OnStartAnim; + public event Action OnRequestAvatarsData; + public event LinkObjects OnLinkObjects; + public event DelinkObjects OnDelinkObjects; + public event UpdateVector OnGrabObject; + public event ObjectSelect OnDeGrabObject; + public event ObjectDuplicate OnObjectDuplicate; + public event MoveObject OnGrabUpdate; + public event AddNewPrim OnAddPrim; + public event RequestGodlikePowers OnRequestGodlikePowers; + public event GodKickUser OnGodKickUser; + public event ObjectExtraParams OnUpdateExtraParams; + public event UpdateShape OnUpdatePrimShape; + public event ObjectSelect OnObjectSelect; + public event ObjectDeselect OnObjectDeselect; + public event GenericCall7 OnObjectDescription; + public event GenericCall7 OnObjectName; + public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily; + public event UpdatePrimFlags OnUpdatePrimFlags; + public event UpdatePrimTexture OnUpdatePrimTexture; + public event UpdateVector OnUpdatePrimGroupPosition; + public event UpdateVector OnUpdatePrimSinglePosition; + public event UpdatePrimRotation OnUpdatePrimGroupRotation; + public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation; + public event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation; + public event UpdateVector OnUpdatePrimScale; + public event StatusChange OnChildAgentStatus; + public event GenericCall2 OnStopMovement; + public event Action OnRemoveAvatar; + public event RequestMapBlocks OnRequestMapBlocks; + public event RequestMapName OnMapNameRequest; + public event TeleportLocationRequest OnTeleportLocationRequest; + public event DisconnectUser OnDisconnectUser; + public event RequestAvatarProperties OnRequestAvatarProperties; + public event SetAlwaysRun OnSetAlwaysRun; + + public event CreateNewInventoryItem OnCreateNewInventoryItem; + public event CreateInventoryFolder OnCreateNewInventoryFolder; + public event FetchInventoryDescendents OnFetchInventoryDescendents; + public event FetchInventory OnFetchInventory; + public event RequestTaskInventory OnRequestTaskInventory; + public event UpdateInventoryItemTransaction OnUpdateInventoryItem; + public event CopyInventoryItem OnCopyInventoryItem; + public event UDPAssetUploadRequest OnAssetUploadRequest; + public event XferReceive OnXferReceive; + public event RequestXfer OnRequestXfer; + public event ConfirmXfer OnConfirmXfer; + public event RezScript OnRezScript; + public event UpdateTaskInventory OnUpdateTaskInventory; + public event RemoveTaskInventory OnRemoveTaskItem; + + public event UUIDNameRequest OnNameFromUUIDRequest; + + public event ParcelPropertiesRequest OnParcelPropertiesRequest; + public event ParcelDivideRequest OnParcelDivideRequest; + public event ParcelJoinRequest OnParcelJoinRequest; + public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; + public event ParcelSelectObjects OnParcelSelectObjects; + public event ParcelObjectOwnerRequest OnParcelObjectOwnerRequest; + public event EstateOwnerMessageRequest OnEstateOwnerMessage; + + /// + /// + /// + public LLVector3 StartPos + { + get { return startpos; } + set { startpos = value; } + } + + /// + /// + /// + private LLUUID m_agentId; + + public LLUUID AgentId + { + get { return m_agentId; } + } + + /// + /// + /// + public string FirstName + { + get { return firstName; } + } + + /// + /// + /// + public string LastName + { + get { return lastName; } + } + + #region Scene/Avatar to Client + + /// + /// + /// + /// + public void SendRegionHandshake(RegionInfo regionInfo) + { + Encoding _enc = Encoding.ASCII; + RegionHandshakePacket handshake = new RegionHandshakePacket(); + + handshake.RegionInfo.BillableFactor = regionInfo.EstateSettings.billableFactor; + handshake.RegionInfo.IsEstateManager = false; + handshake.RegionInfo.TerrainHeightRange00 = regionInfo.EstateSettings.terrainHeightRange0; + handshake.RegionInfo.TerrainHeightRange01 = regionInfo.EstateSettings.terrainHeightRange1; + handshake.RegionInfo.TerrainHeightRange10 = regionInfo.EstateSettings.terrainHeightRange2; + handshake.RegionInfo.TerrainHeightRange11 = regionInfo.EstateSettings.terrainHeightRange3; + handshake.RegionInfo.TerrainStartHeight00 = regionInfo.EstateSettings.terrainStartHeight0; + handshake.RegionInfo.TerrainStartHeight01 = regionInfo.EstateSettings.terrainStartHeight1; + handshake.RegionInfo.TerrainStartHeight10 = regionInfo.EstateSettings.terrainStartHeight2; + handshake.RegionInfo.TerrainStartHeight11 = regionInfo.EstateSettings.terrainStartHeight3; + handshake.RegionInfo.SimAccess = (byte) regionInfo.EstateSettings.simAccess; + handshake.RegionInfo.WaterHeight = regionInfo.EstateSettings.waterHeight; + + + handshake.RegionInfo.RegionFlags = (uint) regionInfo.EstateSettings.regionFlags; + + handshake.RegionInfo.SimName = _enc.GetBytes(regionInfo.RegionName + "\0"); + handshake.RegionInfo.SimOwner = regionInfo.MasterAvatarAssignedUUID; + handshake.RegionInfo.TerrainBase0 = regionInfo.EstateSettings.terrainBase0; + handshake.RegionInfo.TerrainBase1 = regionInfo.EstateSettings.terrainBase1; + handshake.RegionInfo.TerrainBase2 = regionInfo.EstateSettings.terrainBase2; + handshake.RegionInfo.TerrainBase3 = regionInfo.EstateSettings.terrainBase3; + handshake.RegionInfo.TerrainDetail0 = regionInfo.EstateSettings.terrainDetail0; + handshake.RegionInfo.TerrainDetail1 = regionInfo.EstateSettings.terrainDetail1; + handshake.RegionInfo.TerrainDetail2 = regionInfo.EstateSettings.terrainDetail2; + handshake.RegionInfo.TerrainDetail3 = regionInfo.EstateSettings.terrainDetail3; + handshake.RegionInfo.CacheID = LLUUID.Random(); //I guess this is for the client to remember an old setting? + + OutPacket(handshake, ThrottleOutPacketType.Task); + } + + /// + /// + /// + /// + public void MoveAgentIntoRegion(RegionInfo regInfo, LLVector3 pos, LLVector3 look) + { + AgentMovementCompletePacket mov = new AgentMovementCompletePacket(); + mov.AgentData.SessionID = m_sessionId; + mov.AgentData.AgentID = AgentId; + mov.Data.RegionHandle = regInfo.RegionHandle; + mov.Data.Timestamp = 1172750370; // TODO - dynamicalise this + + if ((pos.X == 0) && (pos.Y == 0) && (pos.Z == 0)) + { + mov.Data.Position = startpos; + } + else + { + mov.Data.Position = pos; + } + mov.Data.LookAt = look; + + OutPacket(mov, ThrottleOutPacketType.Task); + } + + /// + /// + /// + /// + /// + /// + /// + /// + public void SendChatMessage(string message, byte type, LLVector3 fromPos, string fromName, LLUUID fromAgentID) + { + SendChatMessage(Helpers.StringToField(message), type, fromPos, fromName, fromAgentID); + } + + + public void SendChatMessage(byte[] message, byte type, LLVector3 fromPos, string fromName, LLUUID fromAgentID) + { + Encoding enc = Encoding.ASCII; + ChatFromSimulatorPacket reply = new ChatFromSimulatorPacket(); + reply.ChatData.Audible = 1; + reply.ChatData.Message = message; + reply.ChatData.ChatType = type; + reply.ChatData.SourceType = 1; + reply.ChatData.Position = fromPos; + reply.ChatData.FromName = enc.GetBytes(fromName + "\0"); + reply.ChatData.OwnerID = fromAgentID; + reply.ChatData.SourceID = fromAgentID; + + OutPacket(reply, ThrottleOutPacketType.Task); + } + + /// + /// + /// + /// TODO + /// + /// + public void SendInstantMessage(LLUUID fromAgent, LLUUID fromAgentSession, string message, LLUUID toAgent, + LLUUID imSessionID, string fromName, byte dialog, uint timeStamp) + { + Encoding enc = Encoding.ASCII; + Encoding encUTF8 = Encoding.UTF8; + ImprovedInstantMessagePacket msg = new ImprovedInstantMessagePacket(); + msg.AgentData.AgentID = fromAgent; + msg.AgentData.SessionID = fromAgentSession; + msg.MessageBlock.FromAgentName = enc.GetBytes(fromName + " \0"); + msg.MessageBlock.Dialog = dialog; + msg.MessageBlock.FromGroup = false; + msg.MessageBlock.ID = imSessionID; + msg.MessageBlock.Offline = 0; + msg.MessageBlock.ParentEstateID = 0; + msg.MessageBlock.Position = new LLVector3(); + msg.MessageBlock.RegionID = LLUUID.Random(); + msg.MessageBlock.Timestamp = timeStamp; + msg.MessageBlock.ToAgentID = toAgent; + msg.MessageBlock.Message = encUTF8.GetBytes(message + "\0"); + msg.MessageBlock.BinaryBucket = new byte[0]; + + OutPacket(msg, ThrottleOutPacketType.Task); + } + + /// + /// Send the region heightmap to the client + /// + /// heightmap + public virtual void SendLayerData(float[] map) + { + try + { + int[] patches = new int[4]; + + for (int y = 0; y < 16; y++) + { + for (int x = 0; x < 16; x = x + 4) + { + patches[0] = x + 0 + y*16; + patches[1] = x + 1 + y*16; + patches[2] = x + 2 + y*16; + patches[3] = x + 3 + y*16; + + Packet layerpack = TerrainManager.CreateLandPacket(map, patches); + OutPacket(layerpack, ThrottleOutPacketType.Land); + } + } + } + catch (Exception e) + { + MainLog.Instance.Warn("client", + "ClientView.API.cs: SendLayerData() - Failed with exception " + e.ToString()); + } + } + + /// + /// Sends a specified patch to a client + /// + /// Patch coordinate (x) 0..16 + /// Patch coordinate (y) 0..16 + /// heightmap + public void SendLayerData(int px, int py, float[] map) + { + try + { + int[] patches = new int[1]; + int patchx, patchy; + patchx = px; + patchy = py; + + patches[0] = patchx + 0 + patchy*16; + + Packet layerpack = TerrainManager.CreateLandPacket(map, patches); + OutPacket(layerpack, ThrottleOutPacketType.Land); + } + catch (Exception e) + { + MainLog.Instance.Warn("client", + "ClientView.API.cs: SendLayerData() - Failed with exception " + e.ToString()); + } + } + + /// + /// + /// + /// + /// + /// + public void InformClientOfNeighbour(ulong neighbourHandle, IPEndPoint neighbourEndPoint) + { + IPAddress neighbourIP = neighbourEndPoint.Address; + ushort neighbourPort = (ushort) neighbourEndPoint.Port; + + EnableSimulatorPacket enablesimpacket = new EnableSimulatorPacket(); + enablesimpacket.SimulatorInfo = new EnableSimulatorPacket.SimulatorInfoBlock(); + enablesimpacket.SimulatorInfo.Handle = neighbourHandle; + + byte[] byteIP = neighbourIP.GetAddressBytes(); + enablesimpacket.SimulatorInfo.IP = (uint) byteIP[3] << 24; + enablesimpacket.SimulatorInfo.IP += (uint) byteIP[2] << 16; + enablesimpacket.SimulatorInfo.IP += (uint) byteIP[1] << 8; + enablesimpacket.SimulatorInfo.IP += (uint) byteIP[0]; + enablesimpacket.SimulatorInfo.Port = neighbourPort; + OutPacket(enablesimpacket, ThrottleOutPacketType.Task); + } + + /// + /// + /// + /// + public AgentCircuitData RequestClientInfo() + { + AgentCircuitData agentData = new AgentCircuitData(); + agentData.AgentID = AgentId; + agentData.SessionID = m_sessionId; + agentData.SecureSessionID = SecureSessionID; + agentData.circuitcode = m_circuitCode; + agentData.child = false; + agentData.firstname = firstName; + agentData.lastname = lastName; + agentData.CapsPath = ""; + return agentData; + } + + public void CrossRegion(ulong newRegionHandle, LLVector3 pos, LLVector3 lookAt, IPEndPoint externalIPEndPoint, + string capsURL) + { + LLVector3 look = new LLVector3(lookAt.X*10, lookAt.Y*10, lookAt.Z*10); + + CrossedRegionPacket newSimPack = new CrossedRegionPacket(); + newSimPack.AgentData = new CrossedRegionPacket.AgentDataBlock(); + newSimPack.AgentData.AgentID = AgentId; + newSimPack.AgentData.SessionID = m_sessionId; + newSimPack.Info = new CrossedRegionPacket.InfoBlock(); + newSimPack.Info.Position = pos; + newSimPack.Info.LookAt = look; + // new LLVector3(0.0f, 0.0f, 0.0f); // copied from Avatar.cs - SHOULD BE DYNAMIC!!!!!!!!!! + newSimPack.RegionData = new CrossedRegionPacket.RegionDataBlock(); + newSimPack.RegionData.RegionHandle = newRegionHandle; + byte[] byteIP = externalIPEndPoint.Address.GetAddressBytes(); + newSimPack.RegionData.SimIP = (uint) byteIP[3] << 24; + newSimPack.RegionData.SimIP += (uint) byteIP[2] << 16; + newSimPack.RegionData.SimIP += (uint) byteIP[1] << 8; + newSimPack.RegionData.SimIP += (uint) byteIP[0]; + newSimPack.RegionData.SimPort = (ushort) externalIPEndPoint.Port; + //newSimPack.RegionData.SeedCapability = new byte[0]; + newSimPack.RegionData.SeedCapability = Helpers.StringToField(capsURL); + + OutPacket(newSimPack, ThrottleOutPacketType.Task); + } + + public void SendMapBlock(List mapBlocks) + { + MapBlockReplyPacket mapReply = new MapBlockReplyPacket(); + mapReply.AgentData.AgentID = AgentId; + mapReply.Data = new MapBlockReplyPacket.DataBlock[mapBlocks.Count]; + mapReply.AgentData.Flags = 0; + + for (int i = 0; i < mapBlocks.Count; i++) + { + mapReply.Data[i] = new MapBlockReplyPacket.DataBlock(); + mapReply.Data[i].MapImageID = mapBlocks[i].MapImageId; + mapReply.Data[i].X = mapBlocks[i].X; + mapReply.Data[i].Y = mapBlocks[i].Y; + mapReply.Data[i].WaterHeight = mapBlocks[i].WaterHeight; + mapReply.Data[i].Name = Helpers.StringToField(mapBlocks[i].Name); + mapReply.Data[i].RegionFlags = mapBlocks[i].RegionFlags; + mapReply.Data[i].Access = mapBlocks[i].Access; + mapReply.Data[i].Agents = mapBlocks[i].Agents; + } + OutPacket(mapReply, ThrottleOutPacketType.Land); + } + + public void SendLocalTeleport(LLVector3 position, LLVector3 lookAt, uint flags) + { + TeleportLocalPacket tpLocal = new TeleportLocalPacket(); + tpLocal.Info.AgentID = AgentId; + tpLocal.Info.TeleportFlags = flags; + tpLocal.Info.LocationID = 2; + tpLocal.Info.LookAt = lookAt; + tpLocal.Info.Position = position; + OutPacket(tpLocal, ThrottleOutPacketType.Task); + } + + public void SendRegionTeleport(ulong regionHandle, byte simAccess, IPEndPoint newRegionEndPoint, uint locationID, + uint flags, string capsURL) + { + TeleportFinishPacket teleport = new TeleportFinishPacket(); + teleport.Info.AgentID = AgentId; + teleport.Info.RegionHandle = regionHandle; + teleport.Info.SimAccess = simAccess; + + teleport.Info.SeedCapability = Helpers.StringToField(capsURL); + //teleport.Info.SeedCapability = new byte[0]; + + IPAddress oIP = newRegionEndPoint.Address; + byte[] byteIP = oIP.GetAddressBytes(); + uint ip = (uint) byteIP[3] << 24; + ip += (uint) byteIP[2] << 16; + ip += (uint) byteIP[1] << 8; + ip += (uint) byteIP[0]; + + teleport.Info.SimIP = ip; + teleport.Info.SimPort = (ushort) newRegionEndPoint.Port; + teleport.Info.LocationID = 4; + teleport.Info.TeleportFlags = 1 << 4; + OutPacket(teleport, ThrottleOutPacketType.Task); + } + + /// + /// + /// + public void SendTeleportFailed() + { + TeleportFailedPacket tpFailed = new TeleportFailedPacket(); + tpFailed.Info.AgentID = this.AgentId; + tpFailed.Info.Reason = Helpers.StringToField("unknown failure of teleport"); + + OutPacket(tpFailed, ThrottleOutPacketType.Task); + } + + /// + /// + /// + public void SendTeleportLocationStart() + { + TeleportStartPacket tpStart = new TeleportStartPacket(); + tpStart.Info.TeleportFlags = 16; // Teleport via location + OutPacket(tpStart, ThrottleOutPacketType.Task); + } + + public void SendMoneyBalance(LLUUID transaction, bool success, byte[] description, int balance) + { + MoneyBalanceReplyPacket money = new MoneyBalanceReplyPacket(); + money.MoneyData.AgentID = AgentId; + money.MoneyData.TransactionID = transaction; + money.MoneyData.TransactionSuccess = success; + money.MoneyData.Description = description; + money.MoneyData.MoneyBalance = balance; + OutPacket(money, ThrottleOutPacketType.Task); + } + + public void SendStartPingCheck(byte seq) + { + StartPingCheckPacket pc = new StartPingCheckPacket(); + pc.PingID.PingID = seq; + pc.Header.Reliable = false; + OutPacket(pc, ThrottleOutPacketType.Task); + } + + public void SendKillObject(ulong regionHandle, uint localID) + { + KillObjectPacket kill = new KillObjectPacket(); + kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; + kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); + kill.ObjectData[0].ID = localID; + OutPacket(kill, ThrottleOutPacketType.Task); + } + + public void SendInventoryFolderDetails(LLUUID ownerID, LLUUID folderID, List items) + { + Encoding enc = Encoding.ASCII; + uint FULL_MASK_PERMISSIONS = 2147483647; + InventoryDescendentsPacket descend = CreateInventoryDescendentsPacket(ownerID, folderID); + + int count = 0; + if (items.Count < 40) + { + descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[items.Count]; + descend.AgentData.Descendents = items.Count; + } + else + { + descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[40]; + descend.AgentData.Descendents = 40; + } + int i = 0; + foreach (InventoryItemBase item in items) + { + descend.ItemData[i] = new InventoryDescendentsPacket.ItemDataBlock(); + descend.ItemData[i].ItemID = item.inventoryID; + descend.ItemData[i].AssetID = item.assetID; + descend.ItemData[i].CreatorID = item.creatorsID; + descend.ItemData[i].BaseMask = item.inventoryBasePermissions; + descend.ItemData[i].CreationDate = 1000; + descend.ItemData[i].Description = enc.GetBytes(item.inventoryDescription + "\0"); + descend.ItemData[i].EveryoneMask = item.inventoryEveryOnePermissions; + descend.ItemData[i].Flags = 1; + descend.ItemData[i].FolderID = item.parentFolderID; + descend.ItemData[i].GroupID = new LLUUID("00000000-0000-0000-0000-000000000000"); + descend.ItemData[i].GroupMask = 0; + descend.ItemData[i].InvType = (sbyte) item.invType; + descend.ItemData[i].Name = enc.GetBytes(item.inventoryName + "\0"); + descend.ItemData[i].NextOwnerMask = item.inventoryNextPermissions; + descend.ItemData[i].OwnerID = item.avatarID; + descend.ItemData[i].OwnerMask = item.inventoryCurrentPermissions; + descend.ItemData[i].SalePrice = 0; + descend.ItemData[i].SaleType = 0; + descend.ItemData[i].Type = (sbyte) item.assetType; + descend.ItemData[i].CRC = + Helpers.InventoryCRC(1000, 0, descend.ItemData[i].InvType, descend.ItemData[i].Type, + descend.ItemData[i].AssetID, descend.ItemData[i].GroupID, 100, + descend.ItemData[i].OwnerID, descend.ItemData[i].CreatorID, + descend.ItemData[i].ItemID, descend.ItemData[i].FolderID, FULL_MASK_PERMISSIONS, + 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS); + + i++; + count++; + if (i == 40) + { + OutPacket(descend, ThrottleOutPacketType.Asset); + + if ((items.Count - count) > 0) + { + descend = CreateInventoryDescendentsPacket(ownerID, folderID); + if ((items.Count - count) < 40) + { + descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[items.Count - count]; + descend.AgentData.Descendents = items.Count - count; + } + else + { + descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[40]; + descend.AgentData.Descendents = 40; + } + i = 0; + } + } + } + + if (i < 40) + { + OutPacket(descend, ThrottleOutPacketType.Asset); + } + } + + private InventoryDescendentsPacket CreateInventoryDescendentsPacket(LLUUID ownerID, LLUUID folderID) + { + InventoryDescendentsPacket descend = new InventoryDescendentsPacket(); + descend.AgentData.AgentID = AgentId; + descend.AgentData.OwnerID = ownerID; + descend.AgentData.FolderID = folderID; + descend.AgentData.Version = 0; + + return descend; + } + + public void SendInventoryItemDetails(LLUUID ownerID, InventoryItemBase item) + { + Encoding enc = Encoding.ASCII; + uint FULL_MASK_PERMISSIONS = 2147483647; + FetchInventoryReplyPacket inventoryReply = new FetchInventoryReplyPacket(); + inventoryReply.AgentData.AgentID = AgentId; + inventoryReply.InventoryData = new FetchInventoryReplyPacket.InventoryDataBlock[1]; + inventoryReply.InventoryData[0] = new FetchInventoryReplyPacket.InventoryDataBlock(); + inventoryReply.InventoryData[0].ItemID = item.inventoryID; + inventoryReply.InventoryData[0].AssetID = item.assetID; + inventoryReply.InventoryData[0].CreatorID = item.creatorsID; + inventoryReply.InventoryData[0].BaseMask = item.inventoryBasePermissions; + inventoryReply.InventoryData[0].CreationDate = + (int) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; + inventoryReply.InventoryData[0].Description = enc.GetBytes(item.inventoryDescription + "\0"); + inventoryReply.InventoryData[0].EveryoneMask = item.inventoryEveryOnePermissions; + inventoryReply.InventoryData[0].Flags = 0; + inventoryReply.InventoryData[0].FolderID = item.parentFolderID; + inventoryReply.InventoryData[0].GroupID = new LLUUID("00000000-0000-0000-0000-000000000000"); + inventoryReply.InventoryData[0].GroupMask = 0; + inventoryReply.InventoryData[0].InvType = (sbyte) item.invType; + inventoryReply.InventoryData[0].Name = enc.GetBytes(item.inventoryName + "\0"); + inventoryReply.InventoryData[0].NextOwnerMask = item.inventoryNextPermissions; + inventoryReply.InventoryData[0].OwnerID = item.avatarID; + inventoryReply.InventoryData[0].OwnerMask = item.inventoryCurrentPermissions; + inventoryReply.InventoryData[0].SalePrice = 0; + inventoryReply.InventoryData[0].SaleType = 0; + inventoryReply.InventoryData[0].Type = (sbyte) item.assetType; + inventoryReply.InventoryData[0].CRC = + Helpers.InventoryCRC(1000, 0, inventoryReply.InventoryData[0].InvType, + inventoryReply.InventoryData[0].Type, inventoryReply.InventoryData[0].AssetID, + inventoryReply.InventoryData[0].GroupID, 100, + inventoryReply.InventoryData[0].OwnerID, inventoryReply.InventoryData[0].CreatorID, + inventoryReply.InventoryData[0].ItemID, inventoryReply.InventoryData[0].FolderID, + FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS, + FULL_MASK_PERMISSIONS); + + OutPacket(inventoryReply, ThrottleOutPacketType.Asset); + } + + public void SendInventoryItemUpdate(InventoryItemBase Item) + { + Encoding enc = Encoding.ASCII; + uint FULL_MASK_PERMISSIONS = 2147483647; + UpdateCreateInventoryItemPacket InventoryReply = new UpdateCreateInventoryItemPacket(); + InventoryReply.AgentData.AgentID = AgentId; + InventoryReply.AgentData.SimApproved = true; + InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1]; + InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock(); + InventoryReply.InventoryData[0].ItemID = Item.inventoryID; + InventoryReply.InventoryData[0].AssetID = Item.assetID; + InventoryReply.InventoryData[0].CreatorID = Item.creatorsID; + InventoryReply.InventoryData[0].BaseMask = Item.inventoryBasePermissions; + InventoryReply.InventoryData[0].CreationDate = 1000; + InventoryReply.InventoryData[0].Description = enc.GetBytes(Item.inventoryDescription + "\0"); + InventoryReply.InventoryData[0].EveryoneMask = Item.inventoryEveryOnePermissions; + InventoryReply.InventoryData[0].Flags = 0; + InventoryReply.InventoryData[0].FolderID = Item.parentFolderID; + InventoryReply.InventoryData[0].GroupID = new LLUUID("00000000-0000-0000-0000-000000000000"); + InventoryReply.InventoryData[0].GroupMask = 0; + InventoryReply.InventoryData[0].InvType = (sbyte) Item.invType; + InventoryReply.InventoryData[0].Name = enc.GetBytes(Item.inventoryName + "\0"); + InventoryReply.InventoryData[0].NextOwnerMask = Item.inventoryNextPermissions; + InventoryReply.InventoryData[0].OwnerID = Item.avatarID; + InventoryReply.InventoryData[0].OwnerMask = Item.inventoryCurrentPermissions; + InventoryReply.InventoryData[0].SalePrice = 100; + InventoryReply.InventoryData[0].SaleType = 0; + InventoryReply.InventoryData[0].Type = (sbyte) Item.assetType; + InventoryReply.InventoryData[0].CRC = + Helpers.InventoryCRC(1000, 0, InventoryReply.InventoryData[0].InvType, + InventoryReply.InventoryData[0].Type, InventoryReply.InventoryData[0].AssetID, + InventoryReply.InventoryData[0].GroupID, 100, + InventoryReply.InventoryData[0].OwnerID, InventoryReply.InventoryData[0].CreatorID, + InventoryReply.InventoryData[0].ItemID, InventoryReply.InventoryData[0].FolderID, + FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS, + FULL_MASK_PERMISSIONS); + + OutPacket(InventoryReply, ThrottleOutPacketType.Asset); + } + + public void SendRemoveInventoryItem(LLUUID itemID) + { + RemoveInventoryItemPacket remove = new RemoveInventoryItemPacket(); + remove.AgentData.AgentID = AgentId; + remove.AgentData.SessionID = m_sessionId; + remove.InventoryData = new RemoveInventoryItemPacket.InventoryDataBlock[1]; + remove.InventoryData[0] = new RemoveInventoryItemPacket.InventoryDataBlock(); + remove.InventoryData[0].ItemID = itemID; + + OutPacket(remove, ThrottleOutPacketType.Asset); + } + + public void SendTaskInventory(LLUUID taskID, short serial, byte[] fileName) + { + ReplyTaskInventoryPacket replytask = new ReplyTaskInventoryPacket(); + replytask.InventoryData.TaskID = taskID; + replytask.InventoryData.Serial = serial; + replytask.InventoryData.Filename = fileName; + OutPacket(replytask, ThrottleOutPacketType.Asset); + } + + public void SendXferPacket(ulong xferID, uint packet, byte[] data) + { + SendXferPacketPacket sendXfer = new SendXferPacketPacket(); + sendXfer.XferID.ID = xferID; + sendXfer.XferID.Packet = packet; + sendXfer.DataPacket.Data = data; + OutPacket(sendXfer, ThrottleOutPacketType.Task); + } + public void SendAvatarPickerReply(AvatarPickerReplyPacket replyPacket) + { + OutPacket(replyPacket, ThrottleOutPacketType.Task); + } + + /// + /// + /// + /// + public void SendAlertMessage(string message) + { + AlertMessagePacket alertPack = new AlertMessagePacket(); + alertPack.AlertData.Message = Helpers.StringToField(message); + OutPacket(alertPack, ThrottleOutPacketType.Task); + } + + /// + /// + /// + /// + /// + public void SendAgentAlertMessage(string message, bool modal) + { + AgentAlertMessagePacket alertPack = new AgentAlertMessagePacket(); + alertPack.AgentData.AgentID = AgentId; + alertPack.AlertData.Message = Helpers.StringToField(message); + alertPack.AlertData.Modal = modal; + OutPacket(alertPack, ThrottleOutPacketType.Task); + } + + public void SendLoadURL(string objectname, LLUUID objectID, LLUUID ownerID, bool groupOwned, string message, + string url) + { + LoadURLPacket loadURL = new LoadURLPacket(); + loadURL.Data.ObjectName = Helpers.StringToField(objectname); + loadURL.Data.ObjectID = objectID; + loadURL.Data.OwnerID = ownerID; + loadURL.Data.OwnerIsGroup = groupOwned; + loadURL.Data.Message = Helpers.StringToField(message); + loadURL.Data.URL = Helpers.StringToField(url); + + OutPacket(loadURL, ThrottleOutPacketType.Task); + } + + + public void SendPreLoadSound(LLUUID objectID, LLUUID ownerID, LLUUID soundID) + { + PreloadSoundPacket preSound = new PreloadSoundPacket(); + preSound.DataBlock = new PreloadSoundPacket.DataBlockBlock[1]; + preSound.DataBlock[0] = new PreloadSoundPacket.DataBlockBlock(); + preSound.DataBlock[0].ObjectID = objectID; + preSound.DataBlock[0].OwnerID = ownerID; + preSound.DataBlock[0].SoundID = soundID; + OutPacket(preSound, ThrottleOutPacketType.Task); + } + + public void SendPlayAttachedSound(LLUUID soundID, LLUUID objectID, LLUUID ownerID, float gain, byte flags) + { + AttachedSoundPacket sound = new AttachedSoundPacket(); + sound.DataBlock.SoundID = soundID; + sound.DataBlock.ObjectID = objectID; + sound.DataBlock.OwnerID = ownerID; + sound.DataBlock.Gain = gain; + sound.DataBlock.Flags = flags; + + OutPacket(sound, ThrottleOutPacketType.Task); + } + + public void SendSunPos(LLVector3 sunPos, LLVector3 sunVel) + { + SimulatorViewerTimeMessagePacket viewertime = new SimulatorViewerTimeMessagePacket(); + viewertime.TimeInfo.SunDirection = sunPos; + viewertime.TimeInfo.SunAngVelocity = sunVel; + viewertime.TimeInfo.UsecSinceStart = (ulong) Util.UnixTimeSinceEpoch(); + OutPacket(viewertime, ThrottleOutPacketType.Task); + } + + public void SendViewerTime(int phase) + { + Console.WriteLine("SunPhase: {0}", phase); + SimulatorViewerTimeMessagePacket viewertime = new SimulatorViewerTimeMessagePacket(); + //viewertime.TimeInfo.SecPerDay = 86400; + // viewertime.TimeInfo.SecPerYear = 31536000; + viewertime.TimeInfo.SecPerDay = 1000; + viewertime.TimeInfo.SecPerYear = 365000; + viewertime.TimeInfo.SunPhase = 1; + int sunPhase = (phase + 2)/2; + if ((sunPhase < 6) || (sunPhase > 36)) + { + viewertime.TimeInfo.SunDirection = new LLVector3(0f, 0.8f, -0.8f); + Console.WriteLine("sending night"); + } + else + { + if (sunPhase < 12) + { + sunPhase = 12; + } + sunPhase = sunPhase - 12; + + float yValue = 0.1f*(sunPhase); + Console.WriteLine("Computed SunPhase: {0}, yValue: {1}", sunPhase, yValue); + if (yValue > 1.2f) + { + yValue = yValue - 1.2f; + } + if (yValue > 1) + { + yValue = 1; + } + if (yValue < 0) + { + yValue = 0; + } + if (sunPhase < 14) + { + yValue = 1 - yValue; + } + if (sunPhase < 12) + { + yValue *= -1; + } + viewertime.TimeInfo.SunDirection = new LLVector3(0f, yValue, 0.3f); + Console.WriteLine("sending sun update " + yValue); + } + viewertime.TimeInfo.SunAngVelocity = new LLVector3(0, 0.0f, 10.0f); + viewertime.TimeInfo.UsecSinceStart = (ulong) Util.UnixTimeSinceEpoch(); + OutPacket(viewertime, ThrottleOutPacketType.Task); + } + + public void SendAvatarProperties(LLUUID avatarID, string aboutText, string bornOn, string charterMember, + string flAbout, uint flags, LLUUID flImageID, LLUUID imageID, string profileURL, + LLUUID partnerID) + { + AvatarPropertiesReplyPacket avatarReply = new AvatarPropertiesReplyPacket(); + avatarReply.AgentData.AgentID = AgentId; + avatarReply.AgentData.AvatarID = avatarID; + avatarReply.PropertiesData.AboutText = Helpers.StringToField(aboutText); + avatarReply.PropertiesData.BornOn = Helpers.StringToField(bornOn); + avatarReply.PropertiesData.CharterMember = Helpers.StringToField(charterMember); + avatarReply.PropertiesData.FLAboutText = Helpers.StringToField(flAbout); + avatarReply.PropertiesData.Flags = 0; + avatarReply.PropertiesData.FLImageID = flImageID; + avatarReply.PropertiesData.ImageID = imageID; + avatarReply.PropertiesData.ProfileURL = Helpers.StringToField(profileURL); + avatarReply.PropertiesData.PartnerID = partnerID; + OutPacket(avatarReply, ThrottleOutPacketType.Task); + } + + #endregion + + #region Appearance/ Wearables Methods + + /// + /// + /// + /// + public void SendWearables(AvatarWearable[] wearables, int serial) + { + AgentWearablesUpdatePacket aw = new AgentWearablesUpdatePacket(); + aw.AgentData.AgentID = AgentId; + aw.AgentData.SerialNum = (uint) serial; + aw.AgentData.SessionID = m_sessionId; + + aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[13]; + AgentWearablesUpdatePacket.WearableDataBlock awb; + for (int i = 0; i < wearables.Length; i++) + { + awb = new AgentWearablesUpdatePacket.WearableDataBlock(); + awb.WearableType = (byte) i; + awb.AssetID = wearables[i].AssetID; + awb.ItemID = wearables[i].ItemID; + aw.WearableData[i] = awb; + } + + OutPacket(aw, ThrottleOutPacketType.Task); + } + + /// + /// + /// + /// + /// + /// + public void SendAppearance(LLUUID agentID, byte[] visualParams, byte[] textureEntry) + { + AvatarAppearancePacket avp = new AvatarAppearancePacket(); + avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218]; + avp.ObjectData.TextureEntry = textureEntry; + + AvatarAppearancePacket.VisualParamBlock avblock = null; + for (int i = 0; i < visualParams.Length; i++) + { + avblock = new AvatarAppearancePacket.VisualParamBlock(); + avblock.ParamValue = visualParams[i]; + avp.VisualParam[i] = avblock; + } + + avp.Sender.IsTrial = false; + avp.Sender.ID = agentID; + OutPacket(avp, ThrottleOutPacketType.Task); + } + + public void SendAnimation(LLUUID animID, int seq, LLUUID sourceAgentId) + { + AvatarAnimationPacket ani = new AvatarAnimationPacket(); + ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[1]; + ani.AnimationSourceList[0] = new AvatarAnimationPacket.AnimationSourceListBlock(); + ani.AnimationSourceList[0].ObjectID = sourceAgentId; + ani.Sender = new AvatarAnimationPacket.SenderBlock(); + ani.Sender.ID = sourceAgentId; + ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[1]; + ani.AnimationList[0] = new AvatarAnimationPacket.AnimationListBlock(); + ani.AnimationList[0].AnimID = animID; + ani.AnimationList[0].AnimSequenceID = seq; + OutPacket(ani, ThrottleOutPacketType.Task); + } + + #endregion + + #region Avatar Packet/data sending Methods + + /// + /// send a objectupdate packet with information about the clients avatar + /// + /// + /// + /// + /// + /// + /// + public void SendAvatarData(ulong regionHandle, string firstName, string lastName, LLUUID avatarID, + uint avatarLocalID, LLVector3 Pos, byte[] textureEntry, uint parentID) + { + ObjectUpdatePacket objupdate = new ObjectUpdatePacket(); + objupdate.RegionData.RegionHandle = regionHandle; + objupdate.RegionData.TimeDilation = 64096; + objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; + objupdate.ObjectData[0] = CreateDefaultAvatarPacket(textureEntry); + + //give this avatar object a local id and assign the user a name + objupdate.ObjectData[0].ID = avatarLocalID; + objupdate.ObjectData[0].FullID = avatarID; + objupdate.ObjectData[0].ParentID = parentID; + objupdate.ObjectData[0].NameValue = + Helpers.StringToField("FirstName STRING RW SV " + firstName + "\nLastName STRING RW SV " + lastName); + LLVector3 pos2 = new LLVector3((float) Pos.X, (float) Pos.Y, (float) Pos.Z); + byte[] pb = pos2.GetBytes(); + Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length); + + OutPacket(objupdate, ThrottleOutPacketType.Task); + } + + /// + /// + /// + /// + /// + /// + /// + /// + public void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position, + LLVector3 velocity, LLQuaternion rotation) + { + ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = + CreateAvatarImprovedBlock(localID, position, velocity, rotation); + ImprovedTerseObjectUpdatePacket terse = new ImprovedTerseObjectUpdatePacket(); + terse.RegionData.RegionHandle = regionHandle; + terse.RegionData.TimeDilation = timeDilation; + terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; + terse.ObjectData[0] = terseBlock; + + OutPacket(terse, ThrottleOutPacketType.Task); + } + + public void SendCoarseLocationUpdate(List CoarseLocations) + { + CoarseLocationUpdatePacket loc = new CoarseLocationUpdatePacket(); + int total = CoarseLocations.Count; + CoarseLocationUpdatePacket.IndexBlock ib = + new CoarseLocationUpdatePacket.IndexBlock(); + loc.Location = new CoarseLocationUpdatePacket.LocationBlock[total]; + for (int i = 0; i < total; i++) + { + CoarseLocationUpdatePacket.LocationBlock lb = + new CoarseLocationUpdatePacket.LocationBlock(); + lb.X = (byte) CoarseLocations[i].X; + lb.Y = (byte) CoarseLocations[i].Y; + lb.Z = (byte) (CoarseLocations[i].Z/4); + loc.Location[i] = lb; + } + ib.You = -1; + ib.Prey = -1; + loc.Index = ib; + OutPacket(loc, ThrottleOutPacketType.Task); + } + + #endregion + + #region Primitive Packet/data Sending Methods + + /// + /// + /// + /// + /// + /// + public void AttachObject(uint localID, LLQuaternion rotation, byte attachPoint) + { + ObjectAttachPacket attach = new ObjectAttachPacket(); + attach.AgentData.AgentID = AgentId; + attach.AgentData.SessionID = m_sessionId; + attach.AgentData.AttachmentPoint = attachPoint; + attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1]; + attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock(); + attach.ObjectData[0].ObjectLocalID = localID; + attach.ObjectData[0].Rotation = rotation; + + OutPacket(attach, ThrottleOutPacketType.Task); + } + + public void SendPrimitiveToClient( + ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, LLVector3 pos, + uint flags, + LLUUID objectID, LLUUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, LLQuaternion rotation, byte clickAction) + { + ObjectUpdatePacket outPacket = new ObjectUpdatePacket(); + outPacket.RegionData.RegionHandle = regionHandle; + outPacket.RegionData.TimeDilation = timeDilation; + outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; + + outPacket.ObjectData[0] = CreatePrimUpdateBlock(primShape, flags); + + outPacket.ObjectData[0].ID = localID; + outPacket.ObjectData[0].FullID = objectID; + outPacket.ObjectData[0].OwnerID = ownerID; + outPacket.ObjectData[0].Text = Helpers.StringToField(text); + outPacket.ObjectData[0].TextColor[0] = color[0]; + outPacket.ObjectData[0].TextColor[1] = color[1]; + outPacket.ObjectData[0].TextColor[2] = color[2]; + outPacket.ObjectData[0].TextColor[3] = color[3]; + outPacket.ObjectData[0].ParentID = parentID; + outPacket.ObjectData[0].PSBlock = particleSystem; + outPacket.ObjectData[0].ClickAction = clickAction; + //outPacket.ObjectData[0].Flags = 0; + outPacket.ObjectData[0].Radius = 20; + + byte[] pb = pos.GetBytes(); + Array.Copy(pb, 0, outPacket.ObjectData[0].ObjectData, 0, pb.Length); + + byte[] rot = rotation.GetBytes(); + Array.Copy(rot, 0, outPacket.ObjectData[0].ObjectData, 36, rot.Length); + + OutPacket(outPacket, ThrottleOutPacketType.Task); + } + + /// + /// + /// + /// + /// + /// + /// + /// + public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position, + LLQuaternion rotation) + { + LLVector3 velocity = new LLVector3(0f,0f,0f); + LLVector3 rotationalvelocity = new LLVector3(0f,0f,0f); + ImprovedTerseObjectUpdatePacket terse = new ImprovedTerseObjectUpdatePacket(); + terse.RegionData.RegionHandle = regionHandle; + terse.RegionData.TimeDilation = timeDilation; + terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; + terse.ObjectData[0] = CreatePrimImprovedBlock(localID, position, rotation, velocity, rotationalvelocity); + + OutPacket(terse, ThrottleOutPacketType.Task); + } + public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position, + LLQuaternion rotation, LLVector3 velocity, LLVector3 rotationalvelocity) + { + + ImprovedTerseObjectUpdatePacket terse = new ImprovedTerseObjectUpdatePacket(); + terse.RegionData.RegionHandle = regionHandle; + terse.RegionData.TimeDilation = timeDilation; + terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; + terse.ObjectData[0] = CreatePrimImprovedBlock(localID, position, rotation, velocity, rotationalvelocity); + + OutPacket(terse, ThrottleOutPacketType.Task); + } + + + #endregion + + #region Helper Methods + + protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateAvatarImprovedBlock(uint localID, LLVector3 pos, + LLVector3 velocity, + LLQuaternion rotation) + { + byte[] bytes = new byte[60]; + int i = 0; + ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); + + dat.TextureEntry = new byte[0]; // AvatarTemplate.TextureEntry; + + uint ID = localID; + + bytes[i++] = (byte) (ID%256); + bytes[i++] = (byte) ((ID >> 8)%256); + bytes[i++] = (byte) ((ID >> 16)%256); + bytes[i++] = (byte) ((ID >> 24)%256); + bytes[i++] = 0; + bytes[i++] = 1; + i += 14; + bytes[i++] = 128; + bytes[i++] = 63; + + byte[] pb = pos.GetBytes(); + Array.Copy(pb, 0, bytes, i, pb.Length); + i += 12; + ushort InternVelocityX; + ushort InternVelocityY; + ushort InternVelocityZ; + Vector3 internDirec = new Vector3(0, 0, 0); + + internDirec = new Vector3(velocity.X, velocity.Y, velocity.Z); + + internDirec = internDirec/128.0f; + internDirec.x += 1; + internDirec.y += 1; + internDirec.z += 1; + + InternVelocityX = (ushort) (32768*internDirec.x); + InternVelocityY = (ushort) (32768*internDirec.y); + InternVelocityZ = (ushort) (32768*internDirec.z); + + ushort ac = 32767; + bytes[i++] = (byte) (InternVelocityX%256); + bytes[i++] = (byte) ((InternVelocityX >> 8)%256); + bytes[i++] = (byte) (InternVelocityY%256); + bytes[i++] = (byte) ((InternVelocityY >> 8)%256); + bytes[i++] = (byte) (InternVelocityZ%256); + bytes[i++] = (byte) ((InternVelocityZ >> 8)%256); + + //accel + bytes[i++] = (byte) (ac%256); + bytes[i++] = (byte) ((ac >> 8)%256); + bytes[i++] = (byte) (ac%256); + bytes[i++] = (byte) ((ac >> 8)%256); + bytes[i++] = (byte) (ac%256); + bytes[i++] = (byte) ((ac >> 8)%256); + + //rotation + ushort rw, rx, ry, rz; + rw = (ushort) (32768*(rotation.W + 1)); + rx = (ushort) (32768*(rotation.X + 1)); + ry = (ushort) (32768*(rotation.Y + 1)); + rz = (ushort) (32768*(rotation.Z + 1)); + + //rot + bytes[i++] = (byte) (rx%256); + bytes[i++] = (byte) ((rx >> 8)%256); + bytes[i++] = (byte) (ry%256); + bytes[i++] = (byte) ((ry >> 8)%256); + bytes[i++] = (byte) (rz%256); + bytes[i++] = (byte) ((rz >> 8)%256); + bytes[i++] = (byte) (rw%256); + bytes[i++] = (byte) ((rw >> 8)%256); + + //rotation vel + bytes[i++] = (byte) (ac%256); + bytes[i++] = (byte) ((ac >> 8)%256); + bytes[i++] = (byte) (ac%256); + bytes[i++] = (byte) ((ac >> 8)%256); + bytes[i++] = (byte) (ac%256); + bytes[i++] = (byte) ((ac >> 8)%256); + + dat.Data = bytes; + + return (dat); + } + + /// + /// + /// + /// + /// + /// + /// + protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreatePrimImprovedBlock(uint localID, + LLVector3 position, + LLQuaternion rotation, LLVector3 velocity, LLVector3 rotationalvelocity) + { + uint ID = localID; + byte[] bytes = new byte[60]; + + int i = 0; + ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); + dat.TextureEntry = new byte[0]; + bytes[i++] = (byte) (ID%256); + bytes[i++] = (byte) ((ID >> 8)%256); + bytes[i++] = (byte) ((ID >> 16)%256); + bytes[i++] = (byte) ((ID >> 24)%256); + bytes[i++] = 0; + bytes[i++] = 0; + + byte[] pb = position.GetBytes(); + Array.Copy(pb, 0, bytes, i, pb.Length); + i += 12; + ushort ac = 32767; + + ushort velx, vely, velz; + Vector3 vel = new Vector3(velocity.X, velocity.Y, velocity.Z); + + vel = vel/128.0f; + vel.x += 1; + vel.y += 1; + vel.z += 1; + //vel + velx = (ushort)(32768 * (vel.x)); + vely = (ushort)(32768 * (vel.y)); + velz = (ushort)(32768 * (vel.z)); + + bytes[i++] = (byte) (velx % 256); + bytes[i++] = (byte) ((velx >> 8) % 256); + bytes[i++] = (byte) (vely % 256); + bytes[i++] = (byte) ((vely >> 8) % 256); + bytes[i++] = (byte) (velz % 256); + bytes[i++] = (byte) ((velz >> 8) % 256); + + //accel + bytes[i++] = (byte) (ac%256); + bytes[i++] = (byte) ((ac >> 8)%256); + bytes[i++] = (byte) (ac%256); + bytes[i++] = (byte) ((ac >> 8)%256); + bytes[i++] = (byte) (ac%256); + bytes[i++] = (byte) ((ac >> 8)%256); + + ushort rw, rx, ry, rz; + rw = (ushort) (32768*(rotation.W + 1)); + rx = (ushort) (32768*(rotation.X + 1)); + ry = (ushort) (32768*(rotation.Y + 1)); + rz = (ushort) (32768*(rotation.Z + 1)); + + //rot + bytes[i++] = (byte) (rx%256); + bytes[i++] = (byte) ((rx >> 8)%256); + bytes[i++] = (byte) (ry%256); + bytes[i++] = (byte) ((ry >> 8)%256); + bytes[i++] = (byte) (rz%256); + bytes[i++] = (byte) ((rz >> 8)%256); + bytes[i++] = (byte) (rw%256); + bytes[i++] = (byte) ((rw >> 8)%256); + + //rotation vel + ushort rvelx, rvely, rvelz; + Vector3 rvel = new Vector3(rotationalvelocity.X, rotationalvelocity.Y, rotationalvelocity.Z); + + rvel = rvel / 128.0f; + rvel.x += 1; + rvel.y += 1; + rvel.z += 1; + //vel + rvelx = (ushort)(32768 * (rvel.x)); + rvely = (ushort)(32768 * (rvel.y)); + rvelz = (ushort)(32768 * (rvel.z)); + + bytes[i++] = (byte)(rvelx % 256); + bytes[i++] = (byte)((rvelx >> 8) % 256); + bytes[i++] = (byte)(rvely % 256); + bytes[i++] = (byte)((rvely >> 8) % 256); + bytes[i++] = (byte)(rvelz % 256); + bytes[i++] = (byte)((rvelz >> 8) % 256); + + dat.Data = bytes; + return dat; + } + + /// + /// Create the ObjectDataBlock for a ObjectUpdatePacket (for a Primitive) + /// + /// + /// + protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(PrimitiveBaseShape primShape, uint flags) + { + ObjectUpdatePacket.ObjectDataBlock objupdate = new ObjectUpdatePacket.ObjectDataBlock(); + SetDefaultPrimPacketValues(objupdate); + objupdate.UpdateFlags = flags; + SetPrimPacketShapeData(objupdate, primShape); + + return objupdate; + } + + protected void SetPrimPacketShapeData(ObjectUpdatePacket.ObjectDataBlock objectData, PrimitiveBaseShape primData) + { + objectData.TextureEntry = primData.TextureEntry; + objectData.PCode = primData.PCode; + objectData.PathBegin = primData.PathBegin; + objectData.PathEnd = primData.PathEnd; + objectData.PathScaleX = primData.PathScaleX; + objectData.PathScaleY = primData.PathScaleY; + objectData.PathShearX = primData.PathShearX; + objectData.PathShearY = primData.PathShearY; + objectData.PathSkew = primData.PathSkew; + objectData.ProfileBegin = primData.ProfileBegin; + objectData.ProfileEnd = primData.ProfileEnd; + objectData.Scale = primData.Scale; + objectData.PathCurve = primData.PathCurve; + objectData.ProfileCurve = primData.ProfileCurve; + objectData.ProfileHollow = primData.ProfileHollow; + objectData.PathRadiusOffset = primData.PathRadiusOffset; + objectData.PathRevolutions = primData.PathRevolutions; + objectData.PathTaperX = primData.PathTaperX; + objectData.PathTaperY = primData.PathTaperY; + objectData.PathTwist = primData.PathTwist; + objectData.PathTwistBegin = primData.PathTwistBegin; + objectData.ExtraParams = primData.ExtraParams; + } + + /// + /// Set some default values in a ObjectUpdatePacket + /// + /// + protected void SetDefaultPrimPacketValues(ObjectUpdatePacket.ObjectDataBlock objdata) + { + objdata.PSBlock = new byte[0]; + objdata.ExtraParams = new byte[1]; + objdata.MediaURL = new byte[0]; + objdata.NameValue = new byte[0]; + objdata.Text = new byte[0]; + objdata.TextColor = new byte[4]; + objdata.JointAxisOrAnchor = new LLVector3(0, 0, 0); + objdata.JointPivot = new LLVector3(0, 0, 0); + objdata.Material = 3; + objdata.TextureAnim = new byte[0]; + objdata.Sound = LLUUID.Zero; + objdata.State = 0; + objdata.Data = new byte[0]; + + objdata.ObjectData = new byte[60]; + objdata.ObjectData[46] = 128; + objdata.ObjectData[47] = 63; + } + + + /// + /// + /// + /// + protected ObjectUpdatePacket.ObjectDataBlock CreateDefaultAvatarPacket(byte[] textureEntry) + { + ObjectUpdatePacket.ObjectDataBlock objdata = new ObjectUpdatePacket.ObjectDataBlock(); + // new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock(data1, ref i); + + SetDefaultAvatarPacketValues(ref objdata); + objdata.UpdateFlags = 61 + (9 << 8) + (130 << 16) + (16 << 24); + objdata.PathCurve = 16; + objdata.ProfileCurve = 1; + objdata.PathScaleX = 100; + objdata.PathScaleY = 100; + objdata.ParentID = 0; + objdata.OwnerID = LLUUID.Zero; + objdata.Scale = new LLVector3(1, 1, 1); + objdata.PCode = 47; + if (textureEntry != null) + { + objdata.TextureEntry = textureEntry; + } + Encoding enc = Encoding.ASCII; + LLVector3 pos = new LLVector3(objdata.ObjectData, 16); + pos.X = 100f; + objdata.ID = 8880000; + objdata.NameValue = enc.GetBytes("FirstName STRING RW SV Test \nLastName STRING RW SV User \0"); + //LLVector3 pos2 = new LLVector3(100f, 100f, 23f); + //objdata.FullID=user.AgentId; + byte[] pb = pos.GetBytes(); + Array.Copy(pb, 0, objdata.ObjectData, 16, pb.Length); + + return objdata; + } + + /// + /// + /// + /// + protected void SetDefaultAvatarPacketValues(ref ObjectUpdatePacket.ObjectDataBlock objdata) + { + objdata.PSBlock = new byte[0]; + objdata.ExtraParams = new byte[1]; + objdata.MediaURL = new byte[0]; + objdata.NameValue = new byte[0]; + objdata.Text = new byte[0]; + objdata.TextColor = new byte[4]; + objdata.JointAxisOrAnchor = new LLVector3(0, 0, 0); + objdata.JointPivot = new LLVector3(0, 0, 0); + objdata.Material = 4; + objdata.TextureAnim = new byte[0]; + objdata.Sound = LLUUID.Zero; + LLObject.TextureEntry ntex = new LLObject.TextureEntry(new LLUUID("00000000-0000-0000-5005-000000000005")); + objdata.TextureEntry = ntex.ToBytes(); + objdata.State = 0; + objdata.Data = new byte[0]; + + objdata.ObjectData = new byte[76]; + objdata.ObjectData[15] = 128; + objdata.ObjectData[16] = 63; + objdata.ObjectData[56] = 128; + objdata.ObjectData[61] = 102; + objdata.ObjectData[62] = 40; + objdata.ObjectData[63] = 61; + objdata.ObjectData[64] = 189; + } + + public void SendNameReply(LLUUID profileId, string firstname, string lastname) + { + UUIDNameReplyPacket packet = new UUIDNameReplyPacket(); + + packet.UUIDNameBlock = new UUIDNameReplyPacket.UUIDNameBlockBlock[1]; + packet.UUIDNameBlock[0] = new UUIDNameReplyPacket.UUIDNameBlockBlock(); + packet.UUIDNameBlock[0].ID = profileId; + packet.UUIDNameBlock[0].FirstName = Helpers.StringToField(firstname); + packet.UUIDNameBlock[0].LastName = Helpers.StringToField(lastname); + + OutPacket(packet, ThrottleOutPacketType.Task); + } + + #endregion + + protected virtual void RegisterLocalPacketHandlers() + { + AddLocalPacketHandler(PacketType.LogoutRequest, Logout); + AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect); + AddLocalPacketHandler(PacketType.AgentCachedTexture, AgentTextureCached); + AddLocalPacketHandler(PacketType.MultipleObjectUpdate, MultipleObjUpdate); + } + + private bool HandleViewerEffect(IClientAPI sender, Packet Pack) + { + ViewerEffectPacket viewer = (ViewerEffectPacket) Pack; + + if (OnViewerEffect != null) + { + OnViewerEffect(sender, viewer.Effect); + } + + return true; + } + + protected virtual bool Logout(IClientAPI client, Packet packet) + { + MainLog.Instance.Verbose("CLIENT", "Got a logout request"); + + if (OnLogout != null) + { + OnLogout(client); + } + + return true; + } + + protected bool AgentTextureCached(IClientAPI simclient, Packet packet) + { + //System.Console.WriteLine("texture cached: " + packet.ToString()); + AgentCachedTexturePacket chechedtex = (AgentCachedTexturePacket) packet; + AgentCachedTextureResponsePacket cachedresp = new AgentCachedTextureResponsePacket(); + cachedresp.AgentData.AgentID = AgentId; + cachedresp.AgentData.SessionID = m_sessionId; + cachedresp.AgentData.SerialNum = cachedtextureserial; + cachedtextureserial++; + cachedresp.WearableData = + new AgentCachedTextureResponsePacket.WearableDataBlock[chechedtex.WearableData.Length]; + for (int i = 0; i < chechedtex.WearableData.Length; i++) + { + cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); + cachedresp.WearableData[i].TextureIndex = chechedtex.WearableData[i].TextureIndex; + cachedresp.WearableData[i].TextureID = LLUUID.Zero; + cachedresp.WearableData[i].HostName = new byte[0]; + } + OutPacket(cachedresp, ThrottleOutPacketType.Texture); + return true; + } + + protected bool MultipleObjUpdate(IClientAPI simClient, Packet packet) + { + MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket) packet; + // System.Console.WriteLine("new multi update packet " + multipleupdate.ToString()); + for (int i = 0; i < multipleupdate.ObjectData.Length; i++) + { + #region position + + if (multipleupdate.ObjectData[i].Type == 9) //change position + { + if (OnUpdatePrimGroupPosition != null) + { + LLVector3 pos = new LLVector3(multipleupdate.ObjectData[i].Data, 0); + OnUpdatePrimGroupPosition(multipleupdate.ObjectData[i].ObjectLocalID, pos, this); + } + } + else if (multipleupdate.ObjectData[i].Type == 1) //single item of group change position + { + if (OnUpdatePrimSinglePosition != null) + { + LLVector3 pos = new LLVector3(multipleupdate.ObjectData[i].Data, 0); + // System.Console.WriteLine("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); + OnUpdatePrimSinglePosition(multipleupdate.ObjectData[i].ObjectLocalID, pos, this); + } + } + #endregion position + #region rotation + + else if (multipleupdate.ObjectData[i].Type == 2) // single item of group rotation from tab + { + if (OnUpdatePrimSingleRotation != null) + { + LLQuaternion rot = new LLQuaternion(multipleupdate.ObjectData[i].Data, 0, true); + //System.Console.WriteLine("new tab rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W); + OnUpdatePrimSingleRotation(multipleupdate.ObjectData[i].ObjectLocalID, rot, this); + } + } + else if (multipleupdate.ObjectData[i].Type == 3) // single item of group rotation from mouse + { + if (OnUpdatePrimSingleRotation != null) + { + LLQuaternion rot = new LLQuaternion(multipleupdate.ObjectData[i].Data, 12, true); + //System.Console.WriteLine("new mouse rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W); + OnUpdatePrimSingleRotation(multipleupdate.ObjectData[i].ObjectLocalID, rot, this); + } + } + else if (multipleupdate.ObjectData[i].Type == 10) //group rotation from object tab + { + if (OnUpdatePrimGroupRotation != null) + { + LLQuaternion rot = new LLQuaternion(multipleupdate.ObjectData[i].Data, 0, true); + // Console.WriteLine("new rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W); + OnUpdatePrimGroupRotation(multipleupdate.ObjectData[i].ObjectLocalID, rot, this); + } + } + else if (multipleupdate.ObjectData[i].Type == 11) //group rotation from mouse + { + if (OnUpdatePrimGroupMouseRotation != null) + { + LLVector3 pos = new LLVector3(multipleupdate.ObjectData[i].Data, 0); + LLQuaternion rot = new LLQuaternion(multipleupdate.ObjectData[i].Data, 12, true); + //Console.WriteLine("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z); + // Console.WriteLine("new rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W); + OnUpdatePrimGroupMouseRotation(multipleupdate.ObjectData[i].ObjectLocalID, pos, rot, this); + } + } + #endregion + #region scale + + else if (multipleupdate.ObjectData[i].Type == 13) //group scale from object tab + { + if (OnUpdatePrimScale != null) + { + LLVector3 scale = new LLVector3(multipleupdate.ObjectData[i].Data, 12); + //Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + OnUpdatePrimScale(multipleupdate.ObjectData[i].ObjectLocalID, scale, this); + + // Change the position based on scale (for bug number 246) + LLVector3 pos = new LLVector3(multipleupdate.ObjectData[i].Data, 0); + // System.Console.WriteLine("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); + OnUpdatePrimSinglePosition(multipleupdate.ObjectData[i].ObjectLocalID, pos, this); + } + } + else if (multipleupdate.ObjectData[i].Type == 29) //group scale from mouse + { + if (OnUpdatePrimScale != null) + { + LLVector3 scale = new LLVector3(multipleupdate.ObjectData[i].Data, 12); + // Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z ); + OnUpdatePrimScale(multipleupdate.ObjectData[i].ObjectLocalID, scale, this); + LLVector3 pos = new LLVector3(multipleupdate.ObjectData[i].Data, 0); + OnUpdatePrimSinglePosition(multipleupdate.ObjectData[i].ObjectLocalID, pos, this); + } + } + else if (multipleupdate.ObjectData[i].Type == 5) //single prim scale from object tab + { + if (OnUpdatePrimScale != null) + { + LLVector3 scale = new LLVector3(multipleupdate.ObjectData[i].Data, 12); + // Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + OnUpdatePrimScale(multipleupdate.ObjectData[i].ObjectLocalID, scale, this); + } + } + else if (multipleupdate.ObjectData[i].Type == 21) //single prim scale from mouse + { + if (OnUpdatePrimScale != null) + { + LLVector3 scale = new LLVector3(multipleupdate.ObjectData[i].Data, 12); + // Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + OnUpdatePrimScale(multipleupdate.ObjectData[i].ObjectLocalID, scale, this); + } + } + + #endregion + } + return true; + } + + public void RequestMapLayer() + { + //should be getting the map layer from the grid server + //send a layer covering the 800,800 - 1200,1200 area (should be covering the requested area) + MapLayerReplyPacket mapReply = new MapLayerReplyPacket(); + mapReply.AgentData.AgentID = AgentId; + mapReply.AgentData.Flags = 0; + mapReply.LayerData = new MapLayerReplyPacket.LayerDataBlock[1]; + mapReply.LayerData[0] = new MapLayerReplyPacket.LayerDataBlock(); + mapReply.LayerData[0].Bottom = 0; + mapReply.LayerData[0].Left = 0; + mapReply.LayerData[0].Top = 30000; + mapReply.LayerData[0].Right = 30000; + mapReply.LayerData[0].ImageID = new LLUUID("00000000-0000-0000-9999-000000000006"); + OutPacket(mapReply, ThrottleOutPacketType.Land); + } + + public void RequestMapBlocks(int minX, int minY, int maxX, int maxY) + { + /* + IList simMapProfiles = m_gridServer.RequestMapBlocks(minX, minY, maxX, maxY); + MapBlockReplyPacket mbReply = new MapBlockReplyPacket(); + mbReply.AgentData.AgentId = this.AgentId; + int len; + if (simMapProfiles == null) + len = 0; + else + len = simMapProfiles.Count; + + mbReply.Data = new MapBlockReplyPacket.DataBlock[len]; + int iii; + for (iii = 0; iii < len; iii++) + { + Hashtable mp = (Hashtable)simMapProfiles[iii]; + mbReply.Data[iii] = new MapBlockReplyPacket.DataBlock(); + mbReply.Data[iii].Name = System.Text.Encoding.UTF8.GetBytes((string)mp["name"]); + mbReply.Data[iii].Access = System.Convert.ToByte(mp["access"]); + mbReply.Data[iii].Agents = System.Convert.ToByte(mp["agents"]); + mbReply.Data[iii].MapImageID = new LLUUID((string)mp["map-image-id"]); + mbReply.Data[iii].RegionFlags = System.Convert.ToUInt32(mp["region-flags"]); + mbReply.Data[iii].WaterHeight = System.Convert.ToByte(mp["water-height"]); + mbReply.Data[iii].X = System.Convert.ToUInt16(mp["x"]); + mbReply.Data[iii].Y = System.Convert.ToUInt16(mp["y"]); + } + this.OutPacket(mbReply, ThrottleOutPacketType.Land); + */ + } + + // Previously ClientView.PacketQueue + protected BlockingQueue PacketQueue; + + protected Queue IncomingPacketQueue; + protected Queue OutgoingPacketQueue; + protected Queue ResendOutgoingPacketQueue; + protected Queue LandOutgoingPacketQueue; + protected Queue WindOutgoingPacketQueue; + protected Queue CloudOutgoingPacketQueue; + protected Queue TaskOutgoingPacketQueue; + protected Queue TextureOutgoingPacketQueue; + protected Queue AssetOutgoingPacketQueue; + + protected Dictionary PendingAcks = new Dictionary(); + protected Dictionary NeedAck = new Dictionary(); + + protected Timer AckTimer; + protected uint Sequence = 0; + protected object SequenceLock = new object(); + protected const int MAX_APPENDED_ACKS = 10; + protected const int RESEND_TIMEOUT = 4000; + protected const int MAX_SEQUENCE = 0xFFFFFF; + + private uint m_circuitCode; + public EndPoint userEP; + + protected PacketServer m_networkServer; + + public uint CircuitCode + { + get { return m_circuitCode; } + set { m_circuitCode = value; } + } + + protected virtual void ProcessOutPacket(Packet Pack) + { + // Keep track of when this packet was sent out + Pack.TickCount = System.Environment.TickCount; + + if (!Pack.Header.Resent) + { + // Set the sequence number + lock (SequenceLock) + { + if (Sequence >= MAX_SEQUENCE) + { + Sequence = 1; + } + else + { + Sequence++; + } + + Pack.Header.Sequence = Sequence; + } + + if (Pack.Header.Reliable) //DIRTY HACK + { + lock (NeedAck) + { + if (!NeedAck.ContainsKey(Pack.Header.Sequence)) + { + try + { + NeedAck.Add(Pack.Header.Sequence, Pack); + } + catch (Exception e) // HACKY + { + e.ToString(); + // Ignore + // Seems to throw a exception here occasionally + // of 'duplicate key' despite being locked. + // !?!?!? + } + } + else + { + // Client.Log("Attempted to add a duplicate sequence number (" + + // packet.Header.Sequence + ") to the NeedAck dictionary for packet type " + + // packet.Type.ToString(), Helpers.LogLevel.Warning); + } + } + + // Don't append ACKs to resent packets, in case that's what was causing the + // delivery to fail + if (!Pack.Header.Resent) + { + // Append any ACKs that need to be sent out to this packet + lock (PendingAcks) + { + if (PendingAcks.Count > 0 && PendingAcks.Count < MAX_APPENDED_ACKS && + Pack.Type != PacketType.PacketAck && + Pack.Type != PacketType.LogoutRequest) + { + Pack.Header.AckList = new uint[PendingAcks.Count]; + int i = 0; + + foreach (uint ack in PendingAcks.Values) + { + Pack.Header.AckList[i] = ack; + i++; + } + + PendingAcks.Clear(); + Pack.Header.AppendedAcks = true; + } + } + } + } + } + + byte[] ZeroOutBuffer = new byte[4096]; + byte[] sendbuffer; + sendbuffer = Pack.ToBytes(); + + try + { + if (Pack.Header.Zerocoded) + { + int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer); + m_networkServer.SendPacketTo(ZeroOutBuffer, packetsize, SocketFlags.None, m_circuitCode); //userEP); + } + else + { + m_networkServer.SendPacketTo(sendbuffer, sendbuffer.Length, SocketFlags.None, m_circuitCode); + //userEP); + } + } + catch (Exception e) + { + MainLog.Instance.Warn("client", + "ClientView.PacketQueue.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " + + userEP.ToString() + " - killing thread"); + MainLog.Instance.Error(e.ToString()); + KillThread(); + } + } + + public virtual void InPacket(Packet NewPack) + { + // Handle appended ACKs + if (NewPack.Header.AppendedAcks) + { + lock (NeedAck) + { + foreach (uint ack in NewPack.Header.AckList) + { + NeedAck.Remove(ack); + } + } + } + + // Handle PacketAck packets + if (NewPack.Type == PacketType.PacketAck) + { + PacketAckPacket ackPacket = (PacketAckPacket) NewPack; + + lock (NeedAck) + { + foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets) + { + NeedAck.Remove(block.ID); + } + } + } + else if ((NewPack.Type == PacketType.StartPingCheck)) + { + //reply to pingcheck + StartPingCheckPacket startPing = (StartPingCheckPacket) NewPack; + CompletePingCheckPacket endPing = new CompletePingCheckPacket(); + endPing.PingID.PingID = startPing.PingID.PingID; + OutPacket(endPing, ThrottleOutPacketType.Task); + } + else + { + QueItem item = new QueItem(); + item.Packet = NewPack; + item.Incoming = true; + PacketQueue.Enqueue(item); + } + } + + private void ThrottleCheck(ref int TypeBytesSent, int Throttle, Queue q, QueItem item) + { + // The idea.. is if the packet throttle queues are empty + // and the client is under throttle for the type. Queue + // it up directly. This basically short cuts having to + // wait for the timer to fire to put things into the + // output queue + + if(q.Count == 0 && TypeBytesSent <= ((int)(Throttle / throttleTimeDivisor))) + { + bytesSent += item.Packet.ToBytes().Length; + TypeBytesSent += item.Packet.ToBytes().Length; + PacketQueue.Enqueue(item); + } + else + { + q.Enqueue(item); + } + } + + public virtual void OutPacket(Packet NewPack, ThrottleOutPacketType throttlePacketType) + { + QueItem item = new QueItem(); + item.Packet = NewPack; + item.Incoming = false; + item.throttleType = throttlePacketType; // Packet throttle type + + // The idea.. is if the packet throttle queues are empty and the client is under throttle for the type. + // Queue it up directly. + switch (throttlePacketType) + { + case ThrottleOutPacketType.Resend: + ThrottleCheck(ref ResendBytesSent, ResendthrottleOutbound, ResendOutgoingPacketQueue, item); + break; + case ThrottleOutPacketType.Texture: + ThrottleCheck(ref TextureBytesSent, TexturethrottleOutbound, TextureOutgoingPacketQueue, item); + break; + case ThrottleOutPacketType.Task: + ThrottleCheck(ref TaskBytesSent, TaskthrottleOutbound, TaskOutgoingPacketQueue, item); + break; + case ThrottleOutPacketType.Land: + ThrottleCheck(ref LandBytesSent, LandthrottleOutbound, LandOutgoingPacketQueue, item); + break; + case ThrottleOutPacketType.Asset: + ThrottleCheck(ref AssetBytesSent, AssetthrottleOutbound, AssetOutgoingPacketQueue, item); + break; + case ThrottleOutPacketType.Cloud: + ThrottleCheck(ref CloudBytesSent, CloudthrottleOutbound, CloudOutgoingPacketQueue, item); + break; + case ThrottleOutPacketType.Wind: + ThrottleCheck(ref WindBytesSent, WindthrottleOutbound, WindOutgoingPacketQueue, item); + break; + + default: + // Acknowledgements and other such stuff should go directly to the blocking Queue + // Throttling them may and likely 'will' be problematic + PacketQueue.Enqueue(item); + break; + } + //OutgoingPacketQueue.Enqueue(item); + } + + # region Low Level Packet Methods + + protected void ack_pack(Packet Pack) + { + if (Pack.Header.Reliable) + { + PacketAckPacket ack_it = new PacketAckPacket(); + ack_it.Packets = new PacketAckPacket.PacketsBlock[1]; + ack_it.Packets[0] = new PacketAckPacket.PacketsBlock(); + ack_it.Packets[0].ID = Pack.Header.Sequence; + ack_it.Header.Reliable = false; + + OutPacket(ack_it, ThrottleOutPacketType.Unknown); + } + /* + if (Pack.Header.Reliable) + { + lock (PendingAcks) + { + uint sequence = (uint)Pack.Header.Sequence; + if (!PendingAcks.ContainsKey(sequence)) { PendingAcks[sequence] = sequence; } + } + }*/ + } + + protected void ResendUnacked() + { + int now = System.Environment.TickCount; + + lock (NeedAck) + { + foreach (Packet packet in NeedAck.Values) + { + if ((now - packet.TickCount > RESEND_TIMEOUT) && (!packet.Header.Resent)) + { + MainLog.Instance.Verbose("Resending " + packet.Type.ToString() + " packet, " + + (now - packet.TickCount) + "ms have passed"); + + packet.Header.Resent = true; + OutPacket(packet, ThrottleOutPacketType.Resend); + } + } + } + } + + protected void SendAcks() + { + lock (PendingAcks) + { + if (PendingAcks.Count > 0) + { + if (PendingAcks.Count > 250) + { + // FIXME: Handle the odd case where we have too many pending ACKs queued up + MainLog.Instance.Verbose("Too many ACKs queued up!"); + return; + } + + //OpenSim.Framework.Console.MainLog.Instance.WriteLine("Sending PacketAck"); + + + int i = 0; + PacketAckPacket acks = new PacketAckPacket(); + acks.Packets = new PacketAckPacket.PacketsBlock[PendingAcks.Count]; + + foreach (uint ack in PendingAcks.Values) + { + acks.Packets[i] = new PacketAckPacket.PacketsBlock(); + acks.Packets[i].ID = ack; + i++; + } + + acks.Header.Reliable = false; + OutPacket(acks, ThrottleOutPacketType.Unknown); + + PendingAcks.Clear(); + } + } + } + + protected void AckTimer_Elapsed(object sender, ElapsedEventArgs ea) + { + SendAcks(); + ResendUnacked(); + } + + #endregion + // Previously ClientView.ProcessPackets + private int m_moneyBalance; + + public int MoneyBalance + { + get { return m_moneyBalance; } + } + + public bool AddMoney(int debit) + { + if (m_moneyBalance + debit >= 0) + { + m_moneyBalance += debit; + SendMoneyBalance(LLUUID.Zero, true, Helpers.StringToField("Poof Poof!"), m_moneyBalance); + return true; + } + else + { + return false; + } + } + + protected void ProcessInPacket(Packet Pack) + { + ack_pack(Pack); + + if (ProcessPacketMethod(Pack)) + { + //there is a handler registered that handled this packet type + return; + } + else + { + Encoding _enc = Encoding.ASCII; + + switch (Pack.Type) + { + #region Scene/Avatar + + case PacketType.AvatarPropertiesRequest: + AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket) Pack; + if (OnRequestAvatarProperties != null) + { + OnRequestAvatarProperties(this, avatarProperties.AgentData.AvatarID); + } + break; + case PacketType.ChatFromViewer: + ChatFromViewerPacket inchatpack = (ChatFromViewerPacket) Pack; + + string fromName = ""; //ClientAvatar.firstname + " " + ClientAvatar.lastname; + byte[] message = inchatpack.ChatData.Message; + byte type = inchatpack.ChatData.Type; + LLVector3 fromPos = new LLVector3(); // ClientAvatar.Pos; + LLUUID fromAgentID = AgentId; + + int channel = inchatpack.ChatData.Channel; + + if (OnChatFromViewer != null) + { + ChatFromViewerArgs args = new ChatFromViewerArgs(); + args.Channel = channel; + args.From = fromName; + args.Message = Helpers.FieldToUTF8String(message); + args.Type = (ChatTypeEnum) type; + args.Position = fromPos; + + args.Scene = Scene; + args.Sender = this; + + OnChatFromViewer(this, args); + } + break; + case PacketType.ImprovedInstantMessage: + ImprovedInstantMessagePacket msgpack = (ImprovedInstantMessagePacket) Pack; + string IMfromName = Util.FieldToString(msgpack.MessageBlock.FromAgentName); + string IMmessage = Helpers.FieldToUTF8String(msgpack.MessageBlock.Message); + if (OnInstantMessage != null) + { + OnInstantMessage(msgpack.AgentData.AgentID, msgpack.AgentData.SessionID, + msgpack.MessageBlock.ToAgentID, msgpack.MessageBlock.ID, + msgpack.MessageBlock.Timestamp, IMfromName, IMmessage, + msgpack.MessageBlock.Dialog); + } + break; + case PacketType.RezObject: + RezObjectPacket rezPacket = (RezObjectPacket) Pack; + if (OnRezObject != null) + { + OnRezObject(this, rezPacket.InventoryData.ItemID, rezPacket.RezData.RayEnd); + } + break; + case PacketType.DeRezObject: + if (OnDeRezObject != null) + { + OnDeRezObject(Pack, this); + } + break; + case PacketType.ModifyLand: + ModifyLandPacket modify = (ModifyLandPacket) Pack; + if (modify.ParcelData.Length > 0) + { + if (OnModifyTerrain != null) + { + OnModifyTerrain(modify.ModifyBlock.Height, modify.ModifyBlock.Seconds, + modify.ModifyBlock.BrushSize, + modify.ModifyBlock.Action, modify.ParcelData[0].North, + modify.ParcelData[0].West, this); + } + } + break; + case PacketType.RegionHandshakeReply: + if (OnRegionHandShakeReply != null) + { + OnRegionHandShakeReply(this); + } + break; + case PacketType.AgentWearablesRequest: + if (OnRequestWearables != null) + { + OnRequestWearables( ); + } + if (OnRequestAvatarsData != null) + { + OnRequestAvatarsData(this); + } + break; + case PacketType.AgentSetAppearance: + //OpenSim.Framework.Console.MainLog.Instance.Verbose("set appear", Pack.ToString()); + AgentSetAppearancePacket appear = (AgentSetAppearancePacket) Pack; + if (OnSetAppearance != null) + { + OnSetAppearance(appear.ObjectData.TextureEntry, appear.VisualParam); + } + break; + case PacketType.SetAlwaysRun: + SetAlwaysRunPacket run = (SetAlwaysRunPacket)Pack; + + if (OnSetAlwaysRun != null) + OnSetAlwaysRun(this,run.AgentData.AlwaysRun); + + break; + case PacketType.CompleteAgentMovement: + if (OnCompleteMovementToRegion != null) + { + OnCompleteMovementToRegion(); + } + break; + case PacketType.AgentUpdate: + if (OnAgentUpdate != null) + { + AgentUpdatePacket agenUpdate = (AgentUpdatePacket) Pack; + + OnAgentUpdate(this, agenUpdate); //agenUpdate.AgentData.ControlFlags, agenUpdate.AgentData.BodyRotationa); + } + break; + case PacketType.AgentAnimation: + AgentAnimationPacket AgentAni = (AgentAnimationPacket) Pack; + for (int i = 0; i < AgentAni.AnimationList.Length; i++) + { + if (AgentAni.AnimationList[i].StartAnim) + { + if (OnStartAnim != null) + { + OnStartAnim(this, AgentAni.AnimationList[i].AnimID, 1); + } + } + } + break; + case PacketType.AgentRequestSit: + if (OnAgentRequestSit != null) + { + AgentRequestSitPacket agentRequestSit = (AgentRequestSitPacket) Pack; + OnAgentRequestSit(this, agentRequestSit.AgentData.AgentID, + agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset); + } + break; + case PacketType.AgentSit: + if (OnAgentSit != null) + { + AgentSitPacket agentSit = (AgentSitPacket) Pack; + OnAgentSit(this, agentSit.AgentData.AgentID); + } + break; + case PacketType.AvatarPickerRequest: + AvatarPickerRequestPacket avRequestQuery = (AvatarPickerRequestPacket)Pack; + AvatarPickerRequestPacket.AgentDataBlock Requestdata = avRequestQuery.AgentData; + AvatarPickerRequestPacket.DataBlock querydata = avRequestQuery.Data; + //System.Console.WriteLine("Agent Sends:" + Helpers.FieldToUTF8String(querydata.Name)); + if (OnAvatarPickerRequest != null) + { + OnAvatarPickerRequest(this, Requestdata.AgentID, Requestdata.QueryID, Helpers.FieldToUTF8String(querydata.Name)); + } + break; + #endregion + + #region Objects/m_sceneObjects + + case PacketType.ObjectLink: + //OpenSim.Framework.Console.MainLog.Instance.Verbose( Pack.ToString()); + ObjectLinkPacket link = (ObjectLinkPacket) Pack; + uint parentprimid = 0; + List childrenprims = new List(); + if (link.ObjectData.Length > 1) + { + parentprimid = link.ObjectData[0].ObjectLocalID; + + for (int i = 1; i < link.ObjectData.Length; i++) + { + childrenprims.Add(link.ObjectData[i].ObjectLocalID); + } + } + if (OnLinkObjects != null) + { + OnLinkObjects(parentprimid, childrenprims); + } + break; + case PacketType.ObjectDelink: + //OpenSim.Framework.Console.MainLog.Instance.Verbose( Pack.ToString()); + ObjectDelinkPacket delink = (ObjectDelinkPacket) Pack; + + // It appears the prim at index 0 is not always the root prim (for + // instance, when one prim of a link set has been edited independently + // of the others). Therefore, we'll pass all the ids onto the delink + // method for it to decide which is the root. + List prims = new List(); + for (int i = 0; i < delink.ObjectData.Length; i++) + { + prims.Add(delink.ObjectData[i].ObjectLocalID); + } + + if (OnDelinkObjects != null) + { + OnDelinkObjects(prims); + } + + break; + case PacketType.ObjectAdd: + if (OnAddPrim != null) + { + ObjectAddPacket addPacket = (ObjectAddPacket) Pack; + PrimitiveBaseShape shape = GetShapeFromAddPacket(addPacket); + OnAddPrim(AgentId, addPacket.ObjectData.RayEnd, addPacket.ObjectData.Rotation, shape); + } + break; + case PacketType.ObjectShape: + ObjectShapePacket shapePacket = (ObjectShapePacket) Pack; + for (int i = 0; i < shapePacket.ObjectData.Length; i++) + { + if (OnUpdatePrimShape != null) + { + OnUpdatePrimShape(shapePacket.ObjectData[i].ObjectLocalID, shapePacket.ObjectData[i]); + } + } + break; + case PacketType.ObjectExtraParams: + ObjectExtraParamsPacket extraPar = (ObjectExtraParamsPacket) Pack; + if (OnUpdateExtraParams != null) + { + OnUpdateExtraParams(extraPar.ObjectData[0].ObjectLocalID, extraPar.ObjectData[0].ParamType, + extraPar.ObjectData[0].ParamInUse, extraPar.ObjectData[0].ParamData); + } + break; + case PacketType.ObjectDuplicate: + ObjectDuplicatePacket dupe = (ObjectDuplicatePacket) Pack; + ObjectDuplicatePacket.AgentDataBlock AgentandGroupData = dupe.AgentData; + for (int i = 0; i < dupe.ObjectData.Length; i++) + { + if (OnObjectDuplicate != null) + { + OnObjectDuplicate(dupe.ObjectData[i].ObjectLocalID, dupe.SharedData.Offset, + dupe.SharedData.DuplicateFlags, AgentandGroupData.AgentID, AgentandGroupData.GroupID); + } + } + + break; + + case PacketType.ObjectSelect: + ObjectSelectPacket incomingselect = (ObjectSelectPacket) Pack; + for (int i = 0; i < incomingselect.ObjectData.Length; i++) + { + if (OnObjectSelect != null) + { + OnObjectSelect(incomingselect.ObjectData[i].ObjectLocalID, this); + } + } + break; + case PacketType.ObjectDeselect: + ObjectDeselectPacket incomingdeselect = (ObjectDeselectPacket) Pack; + for (int i = 0; i < incomingdeselect.ObjectData.Length; i++) + { + if (OnObjectDeselect != null) + { + OnObjectDeselect(incomingdeselect.ObjectData[i].ObjectLocalID, this); + } + } + break; + case PacketType.ObjectFlagUpdate: + ObjectFlagUpdatePacket flags = (ObjectFlagUpdatePacket) Pack; + if (OnUpdatePrimFlags != null) + { + OnUpdatePrimFlags(flags.AgentData.ObjectLocalID, Pack, this); + } + break; + case PacketType.ObjectImage: + ObjectImagePacket imagePack = (ObjectImagePacket) Pack; + for (int i = 0; i < imagePack.ObjectData.Length; i++) + { + if (OnUpdatePrimTexture != null) + { + OnUpdatePrimTexture(imagePack.ObjectData[i].ObjectLocalID, + imagePack.ObjectData[i].TextureEntry, this); + } + } + break; + case PacketType.ObjectGrab: + ObjectGrabPacket grab = (ObjectGrabPacket) Pack; + if (OnGrabObject != null) + { + OnGrabObject(grab.ObjectData.LocalID, grab.ObjectData.GrabOffset, this); + } + break; + case PacketType.ObjectGrabUpdate: + ObjectGrabUpdatePacket grabUpdate = (ObjectGrabUpdatePacket) Pack; + if (OnGrabUpdate != null) + { + OnGrabUpdate(grabUpdate.ObjectData.ObjectID, grabUpdate.ObjectData.GrabOffsetInitial, + grabUpdate.ObjectData.GrabPosition, this); + } + break; + case PacketType.ObjectDeGrab: + ObjectDeGrabPacket deGrab = (ObjectDeGrabPacket) Pack; + if (OnDeGrabObject != null) + { + OnDeGrabObject(deGrab.ObjectData.LocalID, this); + } + break; + case PacketType.ObjectDescription: + ObjectDescriptionPacket objDes = (ObjectDescriptionPacket) Pack; + for (int i = 0; i < objDes.ObjectData.Length; i++) + { + if (OnObjectDescription != null) + { + OnObjectDescription(objDes.ObjectData[i].LocalID, + enc.GetString(objDes.ObjectData[i].Description)); + } + } + break; + case PacketType.ObjectName: + ObjectNamePacket objName = (ObjectNamePacket) Pack; + for (int i = 0; i < objName.ObjectData.Length; i++) + { + if (OnObjectName != null) + { + OnObjectName(objName.ObjectData[i].LocalID, enc.GetString(objName.ObjectData[i].Name)); + } + } + break; + case PacketType.ObjectPermissions: + OpenSim.Framework.Console.MainLog.Instance.Verbose("CLIENT", "unhandled packet " + Pack.ToString()); + break; + + case PacketType.RequestObjectPropertiesFamily: + //This powers the little tooltip that appears when you move your mouse over an object + RequestObjectPropertiesFamilyPacket packToolTip = (RequestObjectPropertiesFamilyPacket)Pack; + + + RequestObjectPropertiesFamilyPacket.ObjectDataBlock packObjBlock = packToolTip.ObjectData; + + if (OnRequestObjectPropertiesFamily != null) + { + OnRequestObjectPropertiesFamily(this, this.m_agentId, packObjBlock.RequestFlags, packObjBlock.ObjectID); + + + } + + break; + + #endregion + + #region Inventory/Asset/Other related packets + + case PacketType.RequestImage: + RequestImagePacket imageRequest = (RequestImagePacket) Pack; + //Console.WriteLine("image request: " + Pack.ToString()); + for (int i = 0; i < imageRequest.RequestImage.Length; i++) + { + // still working on the Texture download module so for now using old method + // TextureRequestArgs args = new TextureRequestArgs(); + // args.RequestedAssetID = imageRequest.RequestImage[i].Image; + // args.DiscardLevel = imageRequest.RequestImage[i].DiscardLevel; + // args.PacketNumber = imageRequest.RequestImage[i].Packet; + + // if (OnRequestTexture != null) + // { + // OnRequestTexture(this, args); + // } + + m_assetCache.AddTextureRequest(this, imageRequest.RequestImage[i].Image, + imageRequest.RequestImage[i].Packet, + imageRequest.RequestImage[i].DiscardLevel); + } + break; + case PacketType.TransferRequest: + //Console.WriteLine("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request"); + TransferRequestPacket transfer = (TransferRequestPacket) Pack; + m_assetCache.AddAssetRequest(this, transfer); + break; + case PacketType.AssetUploadRequest: + AssetUploadRequestPacket request = (AssetUploadRequestPacket) Pack; + // Console.WriteLine("upload request " + Pack.ToString()); + // Console.WriteLine("upload request was for assetid: " + request.AssetBlock.TransactionID.Combine(this.SecureSessionID).ToStringHyphenated()); + if (OnAssetUploadRequest != null) + { + OnAssetUploadRequest(this, request.AssetBlock.TransactionID.Combine(SecureSessionID), + request.AssetBlock.TransactionID, request.AssetBlock.Type, + request.AssetBlock.AssetData, request.AssetBlock.StoreLocal); + } + break; + case PacketType.RequestXfer: + RequestXferPacket xferReq = (RequestXferPacket) Pack; + if (OnRequestXfer != null) + { + OnRequestXfer(this, xferReq.XferID.ID, Util.FieldToString(xferReq.XferID.Filename)); + } + break; + case PacketType.SendXferPacket: + SendXferPacketPacket xferRec = (SendXferPacketPacket) Pack; + if (OnXferReceive != null) + { + OnXferReceive(this, xferRec.XferID.ID, xferRec.XferID.Packet, xferRec.DataPacket.Data); + } + break; + case PacketType.ConfirmXferPacket: + ConfirmXferPacketPacket confirmXfer = (ConfirmXferPacketPacket) Pack; + if (OnConfirmXfer != null) + { + OnConfirmXfer(this, confirmXfer.XferID.ID, confirmXfer.XferID.Packet); + } + break; + case PacketType.CreateInventoryFolder: + if (OnCreateNewInventoryFolder != null) + { + CreateInventoryFolderPacket invFolder = (CreateInventoryFolderPacket) Pack; + OnCreateNewInventoryFolder(this, invFolder.FolderData.FolderID, + (ushort) invFolder.FolderData.Type, + Util.FieldToString(invFolder.FolderData.Name), + invFolder.FolderData.ParentID); + } + break; + case PacketType.CreateInventoryItem: + CreateInventoryItemPacket createItem = (CreateInventoryItemPacket) Pack; + if (OnCreateNewInventoryItem != null) + { + OnCreateNewInventoryItem(this, createItem.InventoryBlock.TransactionID, + createItem.InventoryBlock.FolderID, + createItem.InventoryBlock.CallbackID, + Util.FieldToString(createItem.InventoryBlock.Description), + Util.FieldToString(createItem.InventoryBlock.Name), + createItem.InventoryBlock.InvType, + createItem.InventoryBlock.Type, + createItem.InventoryBlock.WearableType, + createItem.InventoryBlock.NextOwnerMask); + } + break; + case PacketType.FetchInventory: + if (OnFetchInventory != null) + { + FetchInventoryPacket FetchInventory = (FetchInventoryPacket) Pack; + for (int i = 0; i < FetchInventory.InventoryData.Length; i++) + { + OnFetchInventory(this, FetchInventory.InventoryData[i].ItemID, + FetchInventory.InventoryData[i].OwnerID); + } + } + break; + case PacketType.FetchInventoryDescendents: + if (OnFetchInventoryDescendents != null) + { + FetchInventoryDescendentsPacket Fetch = (FetchInventoryDescendentsPacket) Pack; + OnFetchInventoryDescendents(this, Fetch.InventoryData.FolderID, Fetch.InventoryData.OwnerID, + Fetch.InventoryData.FetchFolders, Fetch.InventoryData.FetchItems, + Fetch.InventoryData.SortOrder); + } + break; + case PacketType.UpdateInventoryItem: + UpdateInventoryItemPacket update = (UpdateInventoryItemPacket) Pack; + if (OnUpdateInventoryItem != null) + { + for (int i = 0; i < update.InventoryData.Length; i++) + { + if (update.InventoryData[i].TransactionID != LLUUID.Zero) + { + OnUpdateInventoryItem(this, update.InventoryData[i].TransactionID, + update.InventoryData[i].TransactionID.Combine(SecureSessionID), + update.InventoryData[i].ItemID); + } + } + } + //Console.WriteLine(Pack.ToString()); + /*for (int i = 0; i < update.InventoryData.Length; i++) + { + if (update.InventoryData[i].TransactionID != LLUUID.Zero) + { + AssetBase asset = m_assetCache.GetAsset(update.InventoryData[i].TransactionID.Combine(this.SecureSessionID)); + if (asset != null) + { + // Console.WriteLine("updating inventory item, found asset" + asset.FullID.ToStringHyphenated() + " already in cache"); + m_inventoryCache.UpdateInventoryItemAsset(this, update.InventoryData[i].ItemID, asset); + } + else + { + asset = this.UploadAssets.AddUploadToAssetCache(update.InventoryData[i].TransactionID); + if (asset != null) + { + //Console.WriteLine("updating inventory item, adding asset" + asset.FullID.ToStringHyphenated() + " to cache"); + m_inventoryCache.UpdateInventoryItemAsset(this, update.InventoryData[i].ItemID, asset); + } + else + { + //Console.WriteLine("trying to update inventory item, but asset is null"); + } + } + } + else + { + m_inventoryCache.UpdateInventoryItemDetails(this, update.InventoryData[i].ItemID, update.InventoryData[i]); ; + } + }*/ + break; + case PacketType.CopyInventoryItem: + CopyInventoryItemPacket copyitem = (CopyInventoryItemPacket) Pack; + if (OnCopyInventoryItem != null) + { + foreach (CopyInventoryItemPacket.InventoryDataBlock datablock in copyitem.InventoryData) + { + OnCopyInventoryItem(this, datablock.CallbackID, datablock.OldAgentID, datablock.OldItemID, datablock.NewFolderID, Util.FieldToString(datablock.NewName)); + } + } + break; + case PacketType.RequestTaskInventory: + RequestTaskInventoryPacket requesttask = (RequestTaskInventoryPacket) Pack; + if (OnRequestTaskInventory != null) + { + OnRequestTaskInventory(this, requesttask.InventoryData.LocalID); + } + break; + case PacketType.UpdateTaskInventory: + //Console.WriteLine(Pack.ToString()); + UpdateTaskInventoryPacket updatetask = (UpdateTaskInventoryPacket) Pack; + if (OnUpdateTaskInventory != null) + { + if (updatetask.UpdateData.Key == 0) + { + OnUpdateTaskInventory(this, updatetask.InventoryData.ItemID, + updatetask.InventoryData.FolderID, updatetask.UpdateData.LocalID); + } + } + break; + case PacketType.RemoveTaskInventory: + RemoveTaskInventoryPacket removeTask = (RemoveTaskInventoryPacket) Pack; + if (OnRemoveTaskItem != null) + { + OnRemoveTaskItem(this, removeTask.InventoryData.ItemID, removeTask.InventoryData.LocalID); + } + break; + case PacketType.MoveTaskInventory: + OpenSim.Framework.Console.MainLog.Instance.Verbose("CLIENT", "unhandled packet " + Pack.ToString()); + break; + case PacketType.RezScript: + //Console.WriteLine(Pack.ToString()); + RezScriptPacket rezScript = (RezScriptPacket) Pack; + if (OnRezScript != null) + { + OnRezScript(this, rezScript.InventoryBlock.ItemID, rezScript.UpdateBlock.ObjectLocalID); + } + break; + case PacketType.MapLayerRequest: + RequestMapLayer(); + break; + case PacketType.MapBlockRequest: + MapBlockRequestPacket MapRequest = (MapBlockRequestPacket) Pack; + if (OnRequestMapBlocks != null) + { + OnRequestMapBlocks(this, MapRequest.PositionData.MinX, MapRequest.PositionData.MinY, + MapRequest.PositionData.MaxX, MapRequest.PositionData.MaxY); + } + break; + case PacketType.MapNameRequest: + MapNameRequestPacket map = (MapNameRequestPacket) Pack; + string mapName = UTF8Encoding.UTF8.GetString(map.NameData.Name, 0, + map.NameData.Name.Length - 1); + if (OnMapNameRequest != null) + { + OnMapNameRequest(this, mapName); + } + break; + case PacketType.TeleportLandmarkRequest: + TeleportLandmarkRequestPacket tpReq = (TeleportLandmarkRequestPacket) Pack; + + TeleportStartPacket tpStart = new TeleportStartPacket(); + tpStart.Info.TeleportFlags = 8; // tp via lm + OutPacket(tpStart, ThrottleOutPacketType.Task); + + TeleportProgressPacket tpProgress = new TeleportProgressPacket(); + tpProgress.Info.Message = (new ASCIIEncoding()).GetBytes("sending_landmark"); + tpProgress.Info.TeleportFlags = 8; + tpProgress.AgentData.AgentID = tpReq.Info.AgentID; + OutPacket(tpProgress, ThrottleOutPacketType.Task); + + // Fetch landmark + LLUUID lmid = tpReq.Info.LandmarkID; + AssetBase lma = m_assetCache.GetAsset(lmid); + if (lma != null) + { + AssetLandmark lm = new AssetLandmark(lma); + + if (lm.RegionID == m_scene.RegionInfo.RegionID) + { + TeleportLocalPacket tpLocal = new TeleportLocalPacket(); + + tpLocal.Info.AgentID = tpReq.Info.AgentID; + tpLocal.Info.TeleportFlags = 8; // Teleport via landmark + tpLocal.Info.LocationID = 2; + tpLocal.Info.Position = lm.Position; + OutPacket(tpLocal, ThrottleOutPacketType.Task); + } + else + { + TeleportCancelPacket tpCancel = new TeleportCancelPacket(); + tpCancel.Info.AgentID = tpReq.Info.AgentID; + tpCancel.Info.SessionID = tpReq.Info.SessionID; + OutPacket(tpCancel, ThrottleOutPacketType.Task); + } + } + else + { + Console.WriteLine("Cancelling Teleport - fetch asset not yet implemented"); + + TeleportCancelPacket tpCancel = new TeleportCancelPacket(); + tpCancel.Info.AgentID = tpReq.Info.AgentID; + tpCancel.Info.SessionID = tpReq.Info.SessionID; + OutPacket(tpCancel, ThrottleOutPacketType.Task); + } + break; + case PacketType.TeleportLocationRequest: + TeleportLocationRequestPacket tpLocReq = (TeleportLocationRequestPacket) Pack; + // Console.WriteLine(tpLocReq.ToString()); + + if (OnTeleportLocationRequest != null) + { + OnTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position, + tpLocReq.Info.LookAt, 16); + } + else + { + //no event handler so cancel request + TeleportCancelPacket tpCancel = new TeleportCancelPacket(); + tpCancel.Info.SessionID = tpLocReq.AgentData.SessionID; + tpCancel.Info.AgentID = tpLocReq.AgentData.AgentID; + OutPacket(tpCancel, ThrottleOutPacketType.Task); + } + break; + + #endregion + + case PacketType.MoneyBalanceRequest: + SendMoneyBalance(LLUUID.Zero, true, new byte[0], MoneyBalance); + break; + case PacketType.UUIDNameRequest: + UUIDNameRequestPacket incoming = (UUIDNameRequestPacket) Pack; + foreach (UUIDNameRequestPacket.UUIDNameBlockBlock UUIDBlock in incoming.UUIDNameBlock) + { + OnNameFromUUIDRequest(UUIDBlock.ID, this); + } + break; + + #region Parcel related packets + + case PacketType.ParcelPropertiesRequest: + ParcelPropertiesRequestPacket propertiesRequest = (ParcelPropertiesRequestPacket) Pack; + if (OnParcelPropertiesRequest != null) + { + OnParcelPropertiesRequest((int) Math.Round(propertiesRequest.ParcelData.West), + (int) Math.Round(propertiesRequest.ParcelData.South), + (int) Math.Round(propertiesRequest.ParcelData.East), + (int) Math.Round(propertiesRequest.ParcelData.North), + propertiesRequest.ParcelData.SequenceID, + propertiesRequest.ParcelData.SnapSelection, this); + } + break; + case PacketType.ParcelDivide: + ParcelDividePacket landDivide = (ParcelDividePacket) Pack; + if (OnParcelDivideRequest != null) + { + OnParcelDivideRequest((int) Math.Round(landDivide.ParcelData.West), + (int) Math.Round(landDivide.ParcelData.South), + (int) Math.Round(landDivide.ParcelData.East), + (int) Math.Round(landDivide.ParcelData.North), this); + } + break; + case PacketType.ParcelJoin: + ParcelJoinPacket landJoin = (ParcelJoinPacket) Pack; + if (OnParcelJoinRequest != null) + { + OnParcelJoinRequest((int) Math.Round(landJoin.ParcelData.West), + (int) Math.Round(landJoin.ParcelData.South), + (int) Math.Round(landJoin.ParcelData.East), + (int) Math.Round(landJoin.ParcelData.North), this); + } + break; + case PacketType.ParcelPropertiesUpdate: + ParcelPropertiesUpdatePacket updatePacket = (ParcelPropertiesUpdatePacket) Pack; + if (OnParcelPropertiesUpdateRequest != null) + { + OnParcelPropertiesUpdateRequest(updatePacket, this); + } + break; + case PacketType.ParcelSelectObjects: + ParcelSelectObjectsPacket selectPacket = (ParcelSelectObjectsPacket) Pack; + if (OnParcelSelectObjects != null) + { + OnParcelSelectObjects(selectPacket.ParcelData.LocalID, + Convert.ToInt32(selectPacket.ParcelData.ReturnType), this); + } + break; + case PacketType.ParcelObjectOwnersRequest: + //System.Console.WriteLine(Pack.ToString()); + ParcelObjectOwnersRequestPacket reqPacket = (ParcelObjectOwnersRequestPacket) Pack; + if (OnParcelObjectOwnerRequest != null) + { + OnParcelObjectOwnerRequest(reqPacket.ParcelData.LocalID, this); + } + break; + + #endregion + + #region Estate Packets + + case PacketType.EstateOwnerMessage: + EstateOwnerMessagePacket messagePacket = (EstateOwnerMessagePacket) Pack; + if (OnEstateOwnerMessage != null) + { + OnEstateOwnerMessage(messagePacket, this); + } + break; + + case PacketType.AgentThrottle: + + //OpenSim.Framework.Console.MainLog.Instance.Verbose("CLIENT", "unhandled packet " + Pack.ToString()); + + AgentThrottlePacket atpack = (AgentThrottlePacket)Pack; + + byte[] throttle = atpack.Throttle.Throttles; + int tResend = -1; + int tLand = -1; + int tWind = -1; + int tCloud = -1; + int tTask = -1; + int tTexture = -1; + int tAsset = -1; + int tall = -1; + int singlefloat = 4; + + //Agent Throttle Block contains 7 single floatingpoint values. + int j = 0; + + // Some Systems may be big endian... + // it might be smart to do this check more often... + if (!BitConverter.IsLittleEndian) + for (int i = 0; i < 7; i++) + Array.Reverse(throttle, j + i * singlefloat, singlefloat); + + // values gotten from libsecondlife.org/wiki/Throttle. Thanks MW_ + // bytes + // Convert to integer, since.. the full fp space isn't used. + tResend = (int)BitConverter.ToSingle(throttle, j); + j += singlefloat; + tLand = (int)BitConverter.ToSingle(throttle, j); + j += singlefloat; + tWind = (int)BitConverter.ToSingle(throttle, j); + j += singlefloat; + tCloud = (int)BitConverter.ToSingle(throttle, j); + j += singlefloat; + tTask = (int)BitConverter.ToSingle(throttle, j); + j += singlefloat; + tTexture = (int)BitConverter.ToSingle(throttle, j); + j += singlefloat; + tAsset = (int)BitConverter.ToSingle(throttle, j); + + tall = tResend + tLand + tWind + tCloud + tTask + tTexture + tAsset; + /* + OpenSim.Framework.Console.MainLog.Instance.Verbose("CLIENT", "Client AgentThrottle - Got throttle:resendbytes=" + tResend + + " landbytes=" + tLand + + " windbytes=" + tWind + + " cloudbytes=" + tCloud + + " taskbytes=" + tTask + + " texturebytes=" + tTexture + + " Assetbytes=" + tAsset + + " Allbytes=" + tall); + */ + + // Total Sanity + // Make sure that the client sent sane total values. + + // If the client didn't send acceptable values.... + // Scale the clients values down until they are acceptable. + + if (tall <= throttleOutboundMax) + { + // Sanity + // Making sure the client sends sane values + // This gives us a measure of control of the comms + // Check Max of Type + // Then Check Min of type + + // Resend throttle + if (tResend <= ResendthrottleMAX) + ResendthrottleOutbound = tResend; + + if (tResend < ResendthrottleMin) + ResendthrottleOutbound = ResendthrottleMin; + + // Land throttle + if (tLand <= LandthrottleMax) + LandthrottleOutbound = tLand; + + if (tLand < LandthrottleMin) + LandthrottleOutbound = LandthrottleMin; + + // Wind throttle + if (tWind <= WindthrottleMax) + WindthrottleOutbound = tWind; + + if (tWind < WindthrottleMin) + WindthrottleOutbound = WindthrottleMin; + + // Cloud throttle + if (tCloud <= CloudthrottleMax) + CloudthrottleOutbound = tCloud; + + if (tCloud < CloudthrottleMin) + CloudthrottleOutbound = CloudthrottleMin; + + // Task throttle + if (tTask <= TaskthrottleMax) + TaskthrottleOutbound = tTask; + + if (tTask < TaskthrottleMin) + TaskthrottleOutbound = TaskthrottleMin; + + // Texture throttle + if (tTexture <= TexturethrottleMax) + TexturethrottleOutbound = tTexture; + + if (tTexture < TexturethrottleMin) + TexturethrottleOutbound = TexturethrottleMin; + + //Asset throttle + if (tAsset <= AssetthrottleMax) + AssetthrottleOutbound = tAsset; + + if (tAsset < AssetthrottleMin) + AssetthrottleOutbound = AssetthrottleMin; + + /* OpenSim.Framework.Console.MainLog.Instance.Verbose("THROTTLE", "Using:resendbytes=" + ResendthrottleOutbound + + " landbytes=" + LandthrottleOutbound + + " windbytes=" + WindthrottleOutbound + + " cloudbytes=" + CloudthrottleOutbound + + " taskbytes=" + TaskthrottleOutbound + + " texturebytes=" + TexturethrottleOutbound + + " Assetbytes=" + AssetthrottleOutbound + + " Allbytes=" + tall); + */ + } + else + { + // The client didn't send acceptable values.. + // so it's our job now to turn them into acceptable values + // We're going to first scale the values down + // After that we're going to check if the scaled values are sane + + // We're going to be dividing by a user value.. so make sure + // we don't get a divide by zero error. + if (tall > 0) + { + // Find out the percentage of all communications + // the client requests for each type. We'll keep resend at + // it's client recommended level (won't scale it down) + // unless it's beyond sane values itself. + + if (tResend <= ResendthrottleMAX) + { + // This is nexted because we only want to re-set the values + // the packet throttler uses once. + + if (tResend >= ResendthrottleMin) + { + ResendthrottleOutbound = tResend; + } + else + { + ResendthrottleOutbound = ResendthrottleMin; + } + } + else + { + ResendthrottleOutbound = ResendthrottleMAX; + } + + + // Getting Percentages of communication for each type of data + float LandPercent = (float)(tLand / tall); + float WindPercent = (float)(tWind / tall); + float CloudPercent = (float)(tCloud / tall); + float TaskPercent = (float)(tTask / tall); + float TexturePercent = (float)(tTexture / tall); + float AssetPercent = (float)(tAsset / tall); + + // Okay.. now we've got the percentages of total communication. + // Apply them to a new max total + + int tLandResult = (int)(LandPercent * throttleOutboundMax); + int tWindResult = (int)(WindPercent * throttleOutboundMax); + int tCloudResult = (int)(CloudPercent * throttleOutboundMax); + int tTaskResult = (int)(TaskPercent * throttleOutboundMax); + int tTextureResult = (int)(TexturePercent * throttleOutboundMax); + int tAssetResult = (int)(AssetPercent * throttleOutboundMax); + + // Now we have to check our scaled values for sanity + + // Check Max of Type + // Then Check Min of type + + // Land throttle + if (tLandResult <= LandthrottleMax) + LandthrottleOutbound = tLandResult; + + if (tLandResult < LandthrottleMin) + LandthrottleOutbound = LandthrottleMin; + + // Wind throttle + if (tWindResult <= WindthrottleMax) + WindthrottleOutbound = tWindResult; + + if (tWindResult < WindthrottleMin) + WindthrottleOutbound = WindthrottleMin; + + // Cloud throttle + if (tCloudResult <= CloudthrottleMax) + CloudthrottleOutbound = tCloudResult; + + if (tCloudResult < CloudthrottleMin) + CloudthrottleOutbound = CloudthrottleMin; + + // Task throttle + if (tTaskResult <= TaskthrottleMax) + TaskthrottleOutbound = tTaskResult; + + if (tTaskResult < TaskthrottleMin) + TaskthrottleOutbound = TaskthrottleMin; + + // Texture throttle + if (tTextureResult <= TexturethrottleMax) + TexturethrottleOutbound = tTextureResult; + + if (tTextureResult < TexturethrottleMin) + TexturethrottleOutbound = TexturethrottleMin; + + //Asset throttle + if (tAssetResult <= AssetthrottleMax) + AssetthrottleOutbound = tAssetResult; + + if (tAssetResult < AssetthrottleMin) + AssetthrottleOutbound = AssetthrottleMin; + + /* OpenSim.Framework.Console.MainLog.Instance.Verbose("THROTTLE", "Using:resendbytes=" + ResendthrottleOutbound + + " landbytes=" + LandthrottleOutbound + + " windbytes=" + WindthrottleOutbound + + " cloudbytes=" + CloudthrottleOutbound + + " taskbytes=" + TaskthrottleOutbound + + " texturebytes=" + TexturethrottleOutbound + + " Assetbytes=" + AssetthrottleOutbound + + " Allbytes=" + tall); + */ + + } + else + { + + // The client sent a stupid value.. + // We're going to set the throttles to the minimum possible + ResendthrottleOutbound = ResendthrottleMin; + LandthrottleOutbound = LandthrottleMin; + WindthrottleOutbound = WindthrottleMin; + CloudthrottleOutbound = CloudthrottleMin; + TaskthrottleOutbound = TaskthrottleMin; + TexturethrottleOutbound = TexturethrottleMin; + AssetthrottleOutbound = AssetthrottleMin; + OpenSim.Framework.Console.MainLog.Instance.Verbose("THROTTLE", "ClientSentBadThrottle Using:resendbytes=" + ResendthrottleOutbound + + " landbytes=" + LandthrottleOutbound + + " windbytes=" + WindthrottleOutbound + + " cloudbytes=" + CloudthrottleOutbound + + " taskbytes=" + TaskthrottleOutbound + + " texturebytes=" + TexturethrottleOutbound + + " Assetbytes=" + AssetthrottleOutbound + + " Allbytes=" + tall); + } + + } + // Reset Client Throttles + // This has the effect of 'wiggling the slider + // causes prim and stuck textures that didn't download to download + + ResendBytesSent = 0; + LandBytesSent = 0; + WindBytesSent = 0; + CloudBytesSent = 0; + TaskBytesSent = 0; + AssetBytesSent = 0; + TextureBytesSent = 0; + + //Yay, we've finally handled the agent Throttle packet! + + + + break; + + #endregion + + #region unimplemented handlers + case PacketType.RequestGodlikePowers: + RequestGodlikePowersPacket rglpPack = (RequestGodlikePowersPacket) Pack; + RequestGodlikePowersPacket.RequestBlockBlock rblock = rglpPack.RequestBlock; + LLUUID token = rblock.Token; + RequestGodlikePowersPacket.AgentDataBlock ablock = rglpPack.AgentData; + + OnRequestGodlikePowers(ablock.AgentID, ablock.SessionID, token, this); + + break; + case PacketType.GodKickUser: + OpenSim.Framework.Console.MainLog.Instance.Verbose("CLIENT", "unhandled packet " + Pack.ToString()); + + GodKickUserPacket gkupack = (GodKickUserPacket) Pack; + + if (gkupack.UserInfo.GodSessionID == SessionId && this.AgentId == gkupack.UserInfo.GodID) + { + OnGodKickUser(gkupack.UserInfo.GodID, gkupack.UserInfo.GodSessionID, gkupack.UserInfo.AgentID, (uint) 0, gkupack.UserInfo.Reason); + } + else + { + SendAgentAlertMessage("Kick request denied", false); + } + //KickUserPacket kupack = new KickUserPacket(); + //KickUserPacket.UserInfoBlock kupackib = kupack.UserInfo; + + //kupack.UserInfo.AgentID = gkupack.UserInfo.AgentID; + //kupack.UserInfo.SessionID = gkupack.UserInfo.GodSessionID; + + //kupack.TargetBlock.TargetIP = (uint)0; + //kupack.TargetBlock.TargetPort = (ushort)0; + //kupack.UserInfo.Reason = gkupack.UserInfo.Reason; + + + //OutPacket(kupack, ThrottleOutPacketType.Task); + break; + + case PacketType.StartPingCheck: + // Send the client the ping response back + // Pass the same PingID in the matching packet + // Handled In the packet processing + OpenSim.Framework.Console.MainLog.Instance.Debug("CLIENT", "possibly unhandled packet " + Pack.ToString()); + break; + case PacketType.CompletePingCheck: + // Parhaps this should be processed on the Sim to determine whether or not to drop a dead client + // Dumping it to the verbose console until it's handled properly. + + OpenSim.Framework.Console.MainLog.Instance.Verbose("CLIENT", "unhandled packet " + Pack.ToString()); + break; + case PacketType.AgentIsNowWearing: + // AgentIsNowWearingPacket wear = (AgentIsNowWearingPacket)Pack; + OpenSim.Framework.Console.MainLog.Instance.Verbose("CLIENT", "unhandled packet " + Pack.ToString()); + break; + case PacketType.ObjectScale: + OpenSim.Framework.Console.MainLog.Instance.Verbose("CLIENT", "unhandled packet " + Pack.ToString()); + break; + default: + OpenSim.Framework.Console.MainLog.Instance.Verbose("CLIENT", "unhandled packet " + Pack.ToString()); + break; + + #endregion + } + } + } + + private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) + { + PrimitiveBaseShape shape = new PrimitiveBaseShape(); + + shape.PCode = addPacket.ObjectData.PCode; + shape.PathBegin = addPacket.ObjectData.PathBegin; + shape.PathEnd = addPacket.ObjectData.PathEnd; + shape.PathScaleX = addPacket.ObjectData.PathScaleX; + shape.PathScaleY = addPacket.ObjectData.PathScaleY; + shape.PathShearX = addPacket.ObjectData.PathShearX; + shape.PathShearY = addPacket.ObjectData.PathShearY; + shape.PathSkew = addPacket.ObjectData.PathSkew; + shape.ProfileBegin = addPacket.ObjectData.ProfileBegin; + shape.ProfileEnd = addPacket.ObjectData.ProfileEnd; + shape.Scale = addPacket.ObjectData.Scale; + shape.PathCurve = addPacket.ObjectData.PathCurve; + shape.ProfileCurve = addPacket.ObjectData.ProfileCurve; + shape.ProfileHollow = addPacket.ObjectData.ProfileHollow; + shape.PathRadiusOffset = addPacket.ObjectData.PathRadiusOffset; + shape.PathRevolutions = addPacket.ObjectData.PathRevolutions; + shape.PathTaperX = addPacket.ObjectData.PathTaperX; + shape.PathTaperY = addPacket.ObjectData.PathTaperY; + shape.PathTwist = addPacket.ObjectData.PathTwist; + shape.PathTwistBegin = addPacket.ObjectData.PathTwistBegin; + LLObject.TextureEntry ntex = new LLObject.TextureEntry(new LLUUID("00000000-0000-0000-9999-000000000005")); + shape.TextureEntry = ntex.ToBytes(); + return shape; + } + + public void SendLogoutPacket() + { + LogoutReplyPacket logReply = new LogoutReplyPacket(); + logReply.AgentData.AgentID = AgentId; + logReply.AgentData.SessionID = SessionId; + logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1]; + logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock(); + logReply.InventoryData[0].ItemID = LLUUID.Zero; + + OutPacket(logReply, ThrottleOutPacketType.Task); + } } } \ No newline at end of file -- cgit v1.1