/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the OpenSim Project nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ using System; using System.Collections.Generic; using System.Net; using System.Text; using Axiom.Math; using libsecondlife; using libsecondlife.Packets; using OpenSim.Framework; using OpenSim.Framework.Console; namespace OpenSim.Region.ClientStack { partial class ClientView { public event Action<IClientAPI> OnLogout; public event Action<IClientAPI> 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<IClientAPI> 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<IClientAPI> 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 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<LLUUID> OnRemoveAvatar; public event RequestMapBlocks OnRequestMapBlocks; 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 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; /// <summary> /// /// </summary> public LLVector3 StartPos { get { return startpos; } set { startpos = value; } } /// <summary> /// /// </summary> private LLUUID m_agentId; public LLUUID AgentId { get { return m_agentId; } } /// <summary> /// /// </summary> public string FirstName { get { return firstName; } } /// <summary> /// /// </summary> public string LastName { get { return lastName; } } #region Scene/Avatar to Client /// <summary> /// /// </summary> /// <param name="regionInfo"></param> 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); } /// <summary> /// /// </summary> /// <param name="regInfo"></param> 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); } /// <summary> /// /// </summary> /// <param name="message"></param> /// <param name="type"></param> /// <param name="fromPos"></param> /// <param name="fromName"></param> /// <param name="fromAgentID"></param> 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); } /// <summary> /// /// </summary> /// <remarks>TODO</remarks> /// <param name="message"></param> /// <param name="target"></param> 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); } /// <summary> /// Send the region heightmap to the client /// </summary> /// <param name="map">heightmap</param> 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); } } } catch (Exception e) { MainLog.Instance.Warn("client", "ClientView.API.cs: SendLayerData() - Failed with exception " + e.ToString()); } } /// <summary> /// Sends a specified patch to a client /// </summary> /// <param name="px">Patch coordinate (x) 0..16</param> /// <param name="py">Patch coordinate (y) 0..16</param> /// <param name="map">heightmap</param> 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); } catch (Exception e) { MainLog.Instance.Warn("client", "ClientView.API.cs: SendLayerData() - Failed with exception " + e.ToString()); } } /// <summary> /// /// </summary> /// <param name="neighbourHandle"></param> /// <param name="neighbourIP"></param> /// <param name="neighbourPort"></param> 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); } /// <summary> /// /// </summary> /// <returns></returns> 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); } public void SendMapBlock(List<MapBlockData> 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); } 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); } 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); } /// <summary> /// /// </summary> public void SendTeleportCancel() { TeleportCancelPacket tpCancel = new TeleportCancelPacket(); tpCancel.Info.SessionID = m_sessionId; tpCancel.Info.AgentID = AgentId; OutPacket(tpCancel); } /// <summary> /// /// </summary> public void SendTeleportLocationStart() { TeleportStartPacket tpStart = new TeleportStartPacket(); tpStart.Info.TeleportFlags = 16; // Teleport via location OutPacket(tpStart); } 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); } public void SendStartPingCheck(byte seq) { StartPingCheckPacket pc = new StartPingCheckPacket(); pc.PingID.PingID = seq; pc.Header.Reliable = false; OutPacket(pc); } 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); } public void SendInventoryFolderDetails(LLUUID ownerID, LLUUID folderID, List<InventoryItemBase> 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); 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); } } 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); } 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); } 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); } 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); } 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); } public void SendAvatarPickerReply(AvatarPickerReplyPacket replyPacket) { OutPacket(replyPacket); } /// <summary> /// /// </summary> /// <param name="message"></param> public void SendAlertMessage(string message) { AlertMessagePacket alertPack = new AlertMessagePacket(); alertPack.AlertData.Message = Helpers.StringToField(message); OutPacket(alertPack); } /// <summary> /// /// </summary> /// <param name="message"></param> /// <param name="modal"></param> 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); } 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); } 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); } 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); } 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); } 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); } 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); } #endregion #region Appearance/ Wearables Methods /// <summary> /// /// </summary> /// <param name="wearables"></param> 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); } /// <summary> /// /// </summary> /// <param name="agentID"></param> /// <param name="visualParams"></param> /// <param name="textureEntry"></param> 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); } 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); } #endregion #region Avatar Packet/data sending Methods /// <summary> /// send a objectupdate packet with information about the clients avatar /// </summary> /// <param name="regionInfo"></param> /// <param name="firstName"></param> /// <param name="lastName"></param> /// <param name="avatarID"></param> /// <param name="avatarLocalID"></param> /// <param name="Pos"></param> 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); } /// <summary> /// /// </summary> /// <param name="regionHandle"></param> /// <param name="timeDilation"></param> /// <param name="localID"></param> /// <param name="position"></param> /// <param name="velocity"></param> 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); } public void SendCoarseLocationUpdate(List<LLVector3> 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); } #endregion #region Primitive Packet/data Sending Methods /// <summary> /// /// </summary> /// <param name="localID"></param> /// <param name="rotation"></param> /// <param name="attachPoint"></param> 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); } 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); } /// <summary> /// /// </summary> /// <param name="regionHandle"></param> /// <param name="timeDilation"></param> /// <param name="localID"></param> /// <param name="position"></param> /// <param name="rotation"></param> 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); } 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); } #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); } /// <summary> /// /// </summary> /// <param name="localID"></param> /// <param name="position"></param> /// <param name="rotation"></param> /// <returns></returns> 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; } /// <summary> /// Create the ObjectDataBlock for a ObjectUpdatePacket (for a Primitive) /// </summary> /// <param name="primData"></param> /// <returns></returns> 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; } /// <summary> /// Set some default values in a ObjectUpdatePacket /// </summary> /// <param name="objdata"></param> 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; } /// <summary> /// /// </summary> /// <returns></returns> 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; } /// <summary> /// /// </summary> /// <param name="objdata"></param> 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); } #endregion } }