/// <summary> /// Where we send the ParcelOverlay packet to the client /// </summary> /// <param name="remote_client">The object representing the client</param> public void SendParcelOverlay(IClientAPI remote_client) { if (m_hasSentParcelOverLay.Contains(remote_client.AgentId)) return; //Already sent m_hasSentParcelOverLay.Add(remote_client.AgentId); Util.FireAndForget(delegate { const int LAND_BLOCKS_PER_PACKET = 1024; byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; int byteArrayCount = 0; int sequenceID = 0; for (int y = 0; y < (LAND_OVERLAY_CHUNKS*m_scene.RegionInfo.RegionSizeY/ Constants.TerrainPatchSize); y++) { for (int x = 0; x < (LAND_OVERLAY_CHUNKS*m_scene.RegionInfo.RegionSizeX/ Constants.TerrainPatchSize); x++) { byte tempByte = 0; //This represents the byte for the current 4x4 ILandObject currentParcelBlock = GetLandObject(x*LAND_OVERLAY_CHUNKS, y*LAND_OVERLAY_CHUNKS); if (currentParcelBlock != null) { if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId) { //Owner Flag tempByte = Convert.ToByte(tempByte | (byte) ParcelOverlayType.OwnedBySelf); } else if (currentParcelBlock.LandData.SalePrice > 0 && (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero || currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId)) { //Sale Flag tempByte = Convert.ToByte(tempByte | (byte) ParcelOverlayType.ForSale); } else if (currentParcelBlock.LandData.OwnerID == UUID.Zero) { //Public Flag tempByte = Convert.ToByte(tempByte | (byte) ParcelOverlayType.Public); } else if (currentParcelBlock.LandData.GroupID != UUID.Zero && m_scene.Permissions.IsInGroup(remote_client.AgentId, currentParcelBlock.LandData. GroupID)) { tempByte = Convert.ToByte(tempByte | (byte) ParcelOverlayType.OwnedByGroup); } else { //Other Flag tempByte = Convert.ToByte(tempByte | (byte) ParcelOverlayType.OwnedByOther); } if (currentParcelBlock.LandData.Private) { //Public Flag tempByte = Convert.ToByte(tempByte | (byte) ParcelOverlayType.Private); } //Now for border control ILandObject westParcel = null; ILandObject southParcel = null; if (x > 0) { if (currentParcelBlock.ContainsPoint( (x - 1)*LAND_OVERLAY_CHUNKS, y*LAND_OVERLAY_CHUNKS)) westParcel = currentParcelBlock; else westParcel = GetLandObject((x - 1)*LAND_OVERLAY_CHUNKS, y*LAND_OVERLAY_CHUNKS); } if (y > 0) { if (currentParcelBlock.ContainsPoint(x*LAND_OVERLAY_CHUNKS, (y - 1)*LAND_OVERLAY_CHUNKS)) southParcel = currentParcelBlock; else southParcel = GetLandObject(x*LAND_OVERLAY_CHUNKS, (y - 1)*LAND_OVERLAY_CHUNKS); } if (x == 0) { tempByte = Convert.ToByte(tempByte | (byte) ParcelOverlayType.BorderWest); } else if (westParcel != null && westParcel != currentParcelBlock) { tempByte = Convert.ToByte(tempByte | (byte) ParcelOverlayType.BorderWest); } if (y == 0) { tempByte = Convert.ToByte(tempByte | (byte) ParcelOverlayType.BorderSouth); } else if (southParcel != null && southParcel != currentParcelBlock) { tempByte = Convert.ToByte(tempByte | (byte) ParcelOverlayType.BorderSouth); } byteArray[byteArrayCount] = tempByte; byteArrayCount++; if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) { remote_client.SendLandParcelOverlay(byteArray, sequenceID); byteArrayCount = 0; sequenceID++; } } } } byteArray = null; } ); }
/// <summary> /// Where we send the ParcelOverlay packet to the client /// </summary> /// <param name="remote_client">The object representing the client</param> public void SendParcelOverlay(IClientAPI remote_client) { const int LAND_BLOCKS_PER_PACKET = 1024; byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; int byteArrayCount = 0; int sequenceID = 0; int blockmeters = 4 * (int) Constants.RegionSize/(int)Constants.TerrainPatchSize; for (int y = 0; y < blockmeters; y++) { for (int x = 0; x < blockmeters; x++) { byte tempByte = 0; //This represents the byte for the current 4x4 ILandObject currentParcelBlock = GetLandObject(x * 4, y * 4); if (currentParcelBlock != null) { if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId) { //Owner Flag tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER); } else if (currentParcelBlock.LandData.SalePrice > 0 && (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero || currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId)) { //Sale Flag tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_IS_FOR_SALE); } else if (currentParcelBlock.LandData.OwnerID == UUID.Zero) { //Public Flag tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_PUBLIC); } else { //Other Flag tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_OTHER); } //Now for border control ILandObject westParcel = null; ILandObject southParcel = null; if (x > 0) { westParcel = GetLandObject((x - 1) * 4, y * 4); } if (y > 0) { southParcel = GetLandObject(x * 4, (y - 1) * 4); } if (x == 0) { tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST); } else if (westParcel != null && westParcel != currentParcelBlock) { tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST); } if (y == 0) { tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); } else if (southParcel != null && southParcel != currentParcelBlock) { tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); } byteArray[byteArrayCount] = tempByte; byteArrayCount++; if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) { remote_client.SendLandParcelOverlay(byteArray, sequenceID); byteArrayCount = 0; sequenceID++; byteArray = new byte[LAND_BLOCKS_PER_PACKET]; } } } } }
/// <summary> /// Where we send the ParcelOverlay packet to the client /// </summary> /// <param name="remote_client">The object representing the client</param> public void SendParcelOverlay(IClientAPI remote_client) { const int LAND_BLOCKS_PER_PACKET = 1024; byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; int byteArrayCount = 0; int sequenceID = 0; // Layer data is in landUnit (4m) chunks for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++) { for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++) { byteArray[byteArrayCount] = BuildLayerByte(GetLandObject(x * LandUnit, y * LandUnit), x, y, remote_client); byteArrayCount++; if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) { remote_client.SendLandParcelOverlay(byteArray, sequenceID); byteArrayCount = 0; sequenceID++; byteArray = new byte[LAND_BLOCKS_PER_PACKET]; } } } if (byteArrayCount != 0) { remote_client.SendLandParcelOverlay(byteArray, sequenceID); } }
/// <summary> /// Send the parcel overlay blocks to the client. We send the overlay packets /// around a location and limited by the 'parcelLayerViewDistance'. This number /// is usually 128 and the code is arranged so it sends all the parcel overlay /// information for a whole region if the region is legacy sized (256x256). If /// the region is larger, only the parcel layer information is sent around /// the point specified. This reduces the problem of parcel layer information /// blocks increasing exponentially as region size increases. /// </summary> /// <param name="remote_client">The object representing the client</param> /// <param name="xPlace">X position in the region to send surrounding parcel layer info</param> /// <param name="yPlace">y position in the region to send surrounding parcel layer info</param> /// <param name="layerViewDistance">Distance from x,y position to send parcel layer info</param> public void SendParcelOverlay(IClientAPI remote_client) { if (remote_client.SceneAgent.PresenceType == PresenceType.Npc) return; const int LAND_BLOCKS_PER_PACKET = 1024; byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; int byteArrayCount = 0; int sequenceID = 0; // Layer data is in LandUnit (4m) chunks for (int y = 0; y < m_scene.RegionInfo.RegionSizeY; y += LandUnit) { for (int x = 0; x < m_scene.RegionInfo.RegionSizeX; x += LandUnit) { byte tempByte = 0; //This represents the byte for the current 4x4 ILandObject currentParcelBlock = GetLandObject(x, y); if (currentParcelBlock != null) { // types if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId) { //Owner Flag tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_REQUESTER; } else if (currentParcelBlock.LandData.IsGroupOwned && remote_client.IsGroupMember(currentParcelBlock.LandData.GroupID)) { tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_GROUP; } else if (currentParcelBlock.LandData.SalePrice > 0 && (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero || currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId)) { //Sale type tempByte = (byte)LandChannel.LAND_TYPE_IS_FOR_SALE; } else if (currentParcelBlock.LandData.OwnerID == UUID.Zero) { //Public type tempByte = (byte)LandChannel.LAND_TYPE_PUBLIC; // this does nothing, its zero } // LAND_TYPE_IS_BEING_AUCTIONED still unsuported else { //Other Flag tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_OTHER; } // now flags // border control ILandObject westParcel = null; ILandObject southParcel = null; if (x > 0) { westParcel = GetLandObject((x - 1), y); } if (y > 0) { southParcel = GetLandObject(x, (y - 1)); } if (x == 0) { tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST; } else if (westParcel != null && westParcel != currentParcelBlock) { tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST; } if (y == 0) { tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH; } else if (southParcel != null && southParcel != currentParcelBlock) { tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH; } // local sound if ((currentParcelBlock.LandData.Flags & (uint)ParcelFlags.SoundLocal) != 0) tempByte |= (byte)LandChannel.LAND_FLAG_LOCALSOUND; // hide avatars if (!currentParcelBlock.LandData.SeeAVs) tempByte |= (byte)LandChannel.LAND_FLAG_HIDEAVATARS; byteArray[byteArrayCount] = tempByte; byteArrayCount++; if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) { remote_client.SendLandParcelOverlay(byteArray, sequenceID); byteArrayCount = 0; sequenceID++; byteArray = new byte[LAND_BLOCKS_PER_PACKET]; } } } } if (byteArrayCount > 0) { remote_client.SendLandParcelOverlay(byteArray, sequenceID); } }
/// <summary> /// Where we send the ParcelOverlay packet to the client /// </summary> /// <param name="remote_client">The object representing the client</param> public void SendParcelOverlay(IClientAPI remote_client) { if (m_hasSentParcelOverLay.Contains(remote_client.AgentId)) return; //Already sent m_hasSentParcelOverLay.Add(remote_client.AgentId); Util.FireAndForget(delegate(object o) { const int LAND_BLOCKS_PER_PACKET = 1024; byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; int byteArrayCount = 0; int sequenceID = 0; for (int y = 0; y < (ParcelManagementModule.LAND_OVERLAY_CHUNKS * m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize); y++) { for (int x = 0; x < (ParcelManagementModule.LAND_OVERLAY_CHUNKS * m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize); x++) { byte tempByte = 0; //This represents the byte for the current 4x4 ILandObject currentParcelBlock = GetLandObject(x * 4, y * 4); if (currentParcelBlock != null) { if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId) { //Owner Flag tempByte = Convert.ToByte(tempByte | ParcelManagementModule.LAND_TYPE_OWNED_BY_REQUESTER); } else if (currentParcelBlock.LandData.SalePrice > 0 && (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero || currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId)) { //Sale Flag tempByte = Convert.ToByte(tempByte | ParcelManagementModule.LAND_TYPE_IS_FOR_SALE); } else if (currentParcelBlock.LandData.OwnerID == UUID.Zero) { //Public Flag tempByte = Convert.ToByte(tempByte | ParcelManagementModule.LAND_TYPE_PUBLIC); } else if (currentParcelBlock.LandData.GroupID != UUID.Zero) { tempByte = Convert.ToByte(tempByte | ParcelManagementModule.LAND_TYPE_OWNED_BY_GROUP); } else { //Other Flag tempByte = Convert.ToByte(tempByte | ParcelManagementModule.LAND_TYPE_OWNED_BY_OTHER); } //Now for border control ILandObject westParcel = null; ILandObject southParcel = null; if (x > 0) { westParcel = GetLandObject((x - 1) * 4, y * 4); } if (y > 0) { southParcel = GetLandObject(x * 4, (y - 1) * 4); } if (x == 0) { tempByte = Convert.ToByte(tempByte | ParcelManagementModule.LAND_FLAG_PROPERTY_BORDER_WEST); } else if (westParcel != null && westParcel != currentParcelBlock) { tempByte = Convert.ToByte(tempByte | ParcelManagementModule.LAND_FLAG_PROPERTY_BORDER_WEST); } if (y == 0) { tempByte = Convert.ToByte(tempByte | ParcelManagementModule.LAND_FLAG_PROPERTY_BORDER_SOUTH); } else if (southParcel != null && southParcel != currentParcelBlock) { tempByte = Convert.ToByte(tempByte | ParcelManagementModule.LAND_FLAG_PROPERTY_BORDER_SOUTH); } byteArray[byteArrayCount] = tempByte; byteArrayCount++; if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) { remote_client.SendLandParcelOverlay(byteArray, sequenceID); byteArrayCount = 0; sequenceID++; byteArray = new byte[LAND_BLOCKS_PER_PACKET]; } } } } }); }
/// <summary> /// Send the parcel overlay blocks to the client. We send the overlay packets /// around a location and limited by the 'parcelLayerViewDistance'. This number /// is usually 128 and the code is arranged so it sends all the parcel overlay /// information for a whole region if the region is legacy sized (256x256). If /// the region is larger, only the parcel layer information is sent around /// the point specified. This reduces the problem of parcel layer information /// blocks increasing exponentially as region size increases. /// </summary> /// <param name="remote_client">The object representing the client</param> /// <param name="xPlace">X position in the region to send surrounding parcel layer info</param> /// <param name="yPlace">y position in the region to send surrounding parcel layer info</param> /// <param name="layerViewDistance">Distance from x,y position to send parcel layer info</param> private void SendParcelOverlay(IClientAPI remote_client, int xPlace, int yPlace, int layerViewDistance) { const int LAND_BLOCKS_PER_PACKET = 1024; byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; int byteArrayCount = 0; int sequenceID = 0; int xLow = 0; int xHigh = (int)m_scene.RegionInfo.RegionSizeX; int yLow = 0; int yHigh = (int)m_scene.RegionInfo.RegionSizeY; if (shouldLimitParcelLayerInfoToViewDistance) { // Compute view distance around the given point int txLow = xPlace - layerViewDistance; int txHigh = xPlace + layerViewDistance; // If the distance is outside the region area, move the view distance to ba all in the region if (txLow < xLow) { txLow = xLow; txHigh = Math.Min(yLow + (layerViewDistance * 2), xHigh); } if (txHigh > xHigh) { txLow = Math.Max(xLow, xHigh - (layerViewDistance * 2)); txHigh = xHigh; } xLow = txLow; xHigh = txHigh; int tyLow = yPlace - layerViewDistance; int tyHigh = yPlace + layerViewDistance; if (tyLow < yLow) { tyLow = yLow; tyHigh = Math.Min(yLow + (layerViewDistance * 2), yHigh); } if (tyHigh > yHigh) { tyLow = Math.Max(yLow, yHigh - (layerViewDistance * 2)); tyHigh = yHigh; } yLow = tyLow; yHigh = tyHigh; } // m_log.DebugFormat("{0} SendParcelOverlay: place=<{1},{2}>, vDist={3}, xLH=<{4},{5}, yLH=<{6},{7}>", // LogHeader, xPlace, yPlace, layerViewDistance, xLow, xHigh, yLow, yHigh); // Layer data is in landUnit (4m) chunks for (int y = yLow; y < yHigh / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++) { for (int x = xLow; x < xHigh / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++) { byteArray[byteArrayCount] = BuildLayerByte(GetLandObject(x * LandUnit, y * LandUnit), x, y, remote_client); byteArrayCount++; if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) { // m_log.DebugFormat("{0} SendParcelOverlay, sending packet, bytes={1}", LogHeader, byteArray.Length); remote_client.SendLandParcelOverlay(byteArray, sequenceID); byteArrayCount = 0; sequenceID++; byteArray = new byte[LAND_BLOCKS_PER_PACKET]; } } } if (byteArrayCount != 0) { remote_client.SendLandParcelOverlay(byteArray, sequenceID); // m_log.DebugFormat("{0} SendParcelOverlay, complete sending packet, bytes={1}", LogHeader, byteArray.Length); } }