/* * Copyright (c) 2006, Second Life Reverse Engineering Team * All rights reserved. * * - 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. * - Neither the name of the Second Life Reverse Engineering Team 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR 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 libsecondlife.Packets; namespace libsecondlife { /// /// /// /// public delegate void ParcelCompleteCallback(Region region); /// /// Represents a region (also known as a sim) in Second Life. /// public class Region { /// public event ParcelCompleteCallback OnParcelCompletion; // FIXME: This whole setup is fscked in a really bad way. We can't be // locking on a publically accessible container, and we shouldn't have // publically accessible containers anyways because external programs // might be iterating through them or modifying them when internally // we are doing the opposite. The best way to fix this will be // privatizing and adding helper functions to access the dictionary public Dictionary Parcels; /// public LLUUID ID = LLUUID.Zero; /// public ulong Handle; /// public string Name = ""; /// public byte[] ParcelOverlay; /// public int ParcelOverlaysReceived; /// 64x64 Array of parcels which have been successfully downloaded /// (and their LocalID's, 0 = Null) public int[,] ParcelMarked; /// Flag to indicate whether we are downloading a sim's parcels public bool ParcelDownloading; /// Flag to indicate whether to get Dwell values automatically (NOT USED YET). Call Parcel.GetDwell() instead public bool ParcelDwell; /// public float TerrainHeightRange00; /// public float TerrainHeightRange01; /// public float TerrainHeightRange10; /// public float TerrainHeightRange11; /// public float TerrainStartHeight00; /// public float TerrainStartHeight01; /// public float TerrainStartHeight10; /// public float TerrainStartHeight11; /// public float WaterHeight; /// public LLUUID SimOwner = LLUUID.Zero; /// public LLUUID TerrainBase0 = LLUUID.Zero; /// public LLUUID TerrainBase1 = LLUUID.Zero; /// public LLUUID TerrainBase2 = LLUUID.Zero; /// public LLUUID TerrainBase3 = LLUUID.Zero; /// public LLUUID TerrainDetail0 = LLUUID.Zero; /// public LLUUID TerrainDetail1 = LLUUID.Zero; /// public LLUUID TerrainDetail2 = LLUUID.Zero; /// public LLUUID TerrainDetail3 = LLUUID.Zero; /// public bool IsEstateManager; /// public EstateTools Estate; /// /// This may cause your code to block while the GridRegion data is fetched for the 1st time. private GridRegion _GridRegionData = null; public GridRegion GridRegionData { get { if (_GridRegionData == null) { if ((Name != null) && (!Name.Equals(""))) { _GridRegionData = Client.Grid.GetGridRegion(Client.Network.CurrentSim.Region.Name); } } return _GridRegionData; } } private SecondLife Client; /// /// /// /// public Region(SecondLife client) { Estate = new EstateTools(client); Client = client; ParcelOverlay = new byte[4096]; ParcelMarked = new int[64, 64]; Parcels = new Dictionary(); } /// /// /// /// /// /// /// /// /// /// /// public Region(SecondLife client, LLUUID id, ulong handle, string name, float[] heightList, LLUUID simOwner, LLUUID[] terrainImages, bool isEstateManager) { Client = client; Estate = new EstateTools(client); ID = id; Handle = handle; Name = name; ParcelOverlay = new byte[4096]; ParcelMarked = new int[64, 64]; ParcelDownloading = false; ParcelDwell = false; TerrainHeightRange00 = heightList[0]; TerrainHeightRange01 = heightList[1]; TerrainHeightRange10 = heightList[2]; TerrainHeightRange11 = heightList[3]; TerrainStartHeight00 = heightList[4]; TerrainStartHeight01 = heightList[5]; TerrainStartHeight10 = heightList[6]; TerrainStartHeight11 = heightList[7]; WaterHeight = heightList[8]; SimOwner = simOwner; TerrainBase0 = terrainImages[0]; TerrainBase1 = terrainImages[1]; TerrainBase2 = terrainImages[2]; TerrainBase3 = terrainImages[3]; TerrainDetail0 = terrainImages[4]; TerrainDetail1 = terrainImages[5]; TerrainDetail2 = terrainImages[6]; TerrainDetail3 = terrainImages[7]; IsEstateManager = isEstateManager; } /// /// /// /// /// /// /// public void ParcelSubdivide(float west, float south, float east, float north) { ParcelDividePacket divide = new ParcelDividePacket(); divide.AgentData.AgentID = Client.Network.AgentID; divide.AgentData.SessionID = Client.Network.SessionID; divide.ParcelData.East = east; divide.ParcelData.North = north; divide.ParcelData.South = south; divide.ParcelData.West = west; // FIXME: Region needs a reference to it's parent Simulator //Client.Network.SendPacket((Packet)divide, this.Simulator); } /// /// /// /// /// /// /// public void ParcelJoin(float west, float south, float east, float north) { ParcelJoinPacket join = new ParcelJoinPacket(); join.AgentData.AgentID = Client.Network.AgentID; join.AgentData.SessionID = Client.Network.SessionID; join.ParcelData.East = east; join.ParcelData.North = north; join.ParcelData.South = south; join.ParcelData.West = west; // FIXME: Region needs a reference to it's parent Simulator //Client.Network.SendPacket((Packet)join, this.Simulator); } /// /// /// public void FillParcels() { // Begins filling parcels ParcelDownloading = true; ParcelPropertiesRequestPacket tPacket = new ParcelPropertiesRequestPacket(); tPacket.AgentData.AgentID = Client.Self.ID; tPacket.AgentData.SessionID = Client.Network.SessionID; tPacket.ParcelData.SequenceID = -10000; tPacket.ParcelData.West = 0.0f; tPacket.ParcelData.South = 0.0f; tPacket.ParcelData.East = 0.0f; tPacket.ParcelData.North = 0.0f; Client.Network.SendPacket((Packet)tPacket); } /// /// /// public void ResetParcelDownload() { Parcels = new Dictionary(); ParcelMarked = new int[64, 64]; } /// /// /// public void FilledParcels() { if (OnParcelCompletion != null) { OnParcelCompletion(this); } } /// /// /// /// public override int GetHashCode() { return ID.GetHashCode(); } } }